2.5-18.1
[glibc.git] / sysdeps / posix / getaddrinfo.c
bloba7e1459c9ca2809e21656dbf8a3ad0b2811c1c58
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 <resolv.h>
44 #include <stdbool.h>
45 #include <stdio.h>
46 #include <stdio_ext.h>
47 #include <stdlib.h>
48 #include <string.h>
49 #include <arpa/inet.h>
50 #include <net/if.h>
51 #include <netinet/in.h>
52 #include <sys/socket.h>
53 #include <sys/stat.h>
54 #include <sys/types.h>
55 #include <sys/un.h>
56 #include <sys/utsname.h>
57 #include <unistd.h>
58 #include <nsswitch.h>
59 #include <bits/libc-lock.h>
60 #include <not-cancel.h>
61 #include <nscd/nscd-client.h>
62 #include <nscd/nscd_proto.h>
64 #ifdef HAVE_LIBIDN
65 extern int __idna_to_ascii_lz (const char *input, char **output, int flags);
66 extern int __idna_to_unicode_lzlz (const char *input, char **output,
67 int flags);
68 # include <libidn/idna.h>
69 #endif
71 #define GAIH_OKIFUNSPEC 0x0100
72 #define GAIH_EAI ~(GAIH_OKIFUNSPEC)
74 #ifndef UNIX_PATH_MAX
75 # define UNIX_PATH_MAX 108
76 #endif
78 struct gaih_service
80 const char *name;
81 int num;
84 struct gaih_servtuple
86 struct gaih_servtuple *next;
87 int socktype;
88 int protocol;
89 int port;
92 static const struct gaih_servtuple nullserv;
94 struct gaih_addrtuple
96 struct gaih_addrtuple *next;
97 char *name;
98 int family;
99 uint32_t addr[4];
100 uint32_t scopeid;
103 struct gaih_typeproto
105 int socktype;
106 int protocol;
107 char name[4];
108 int protoflag;
111 /* Values for `protoflag'. */
112 #define GAI_PROTO_NOSERVICE 1
113 #define GAI_PROTO_PROTOANY 2
115 static const struct gaih_typeproto gaih_inet_typeproto[] =
117 { 0, 0, "", 0 },
118 { SOCK_STREAM, IPPROTO_TCP, "tcp", 0 },
119 { SOCK_DGRAM, IPPROTO_UDP, "udp", 0 },
120 { SOCK_RAW, 0, "raw", GAI_PROTO_PROTOANY|GAI_PROTO_NOSERVICE },
121 { 0, 0, "", 0 }
124 struct gaih
126 int family;
127 int (*gaih)(const char *name, const struct gaih_service *service,
128 const struct addrinfo *req, struct addrinfo **pai,
129 unsigned int *naddrs);
132 static const struct addrinfo default_hints =
134 .ai_flags = AI_DEFAULT,
135 .ai_family = PF_UNSPEC,
136 .ai_socktype = 0,
137 .ai_protocol = 0,
138 .ai_addrlen = 0,
139 .ai_addr = NULL,
140 .ai_canonname = NULL,
141 .ai_next = NULL
145 #if 0
146 /* Using Unix sockets this way is a security risk. */
147 static int
148 gaih_local (const char *name, const struct gaih_service *service,
149 const struct addrinfo *req, struct addrinfo **pai)
151 struct utsname utsname;
153 if ((name != NULL) && (req->ai_flags & AI_NUMERICHOST))
154 return GAIH_OKIFUNSPEC | -EAI_NONAME;
156 if ((name != NULL) || (req->ai_flags & AI_CANONNAME))
157 if (uname (&utsname) < 0)
158 return -EAI_SYSTEM;
160 if (name != NULL)
162 if (strcmp(name, "localhost") &&
163 strcmp(name, "local") &&
164 strcmp(name, "unix") &&
165 strcmp(name, utsname.nodename))
166 return GAIH_OKIFUNSPEC | -EAI_NONAME;
169 if (req->ai_protocol || req->ai_socktype)
171 const struct gaih_typeproto *tp = gaih_inet_typeproto + 1;
173 while (tp->name[0]
174 && ((tp->protoflag & GAI_PROTO_NOSERVICE) != 0
175 || (req->ai_socktype != 0 && req->ai_socktype != tp->socktype)
176 || (req->ai_protocol != 0
177 && !(tp->protoflag & GAI_PROTO_PROTOANY)
178 && req->ai_protocol != tp->protocol)))
179 ++tp;
181 if (! tp->name[0])
183 if (req->ai_socktype)
184 return GAIH_OKIFUNSPEC | -EAI_SOCKTYPE;
185 else
186 return GAIH_OKIFUNSPEC | -EAI_SERVICE;
190 *pai = malloc (sizeof (struct addrinfo) + sizeof (struct sockaddr_un)
191 + ((req->ai_flags & AI_CANONNAME)
192 ? (strlen(utsname.nodename) + 1): 0));
193 if (*pai == NULL)
194 return -EAI_MEMORY;
196 (*pai)->ai_next = NULL;
197 (*pai)->ai_flags = req->ai_flags;
198 (*pai)->ai_family = AF_LOCAL;
199 (*pai)->ai_socktype = req->ai_socktype ? req->ai_socktype : SOCK_STREAM;
200 (*pai)->ai_protocol = req->ai_protocol;
201 (*pai)->ai_addrlen = sizeof (struct sockaddr_un);
202 (*pai)->ai_addr = (void *) (*pai) + sizeof (struct addrinfo);
204 #ifdef _HAVE_SA_LEN
205 ((struct sockaddr_un *) (*pai)->ai_addr)->sun_len =
206 sizeof (struct sockaddr_un);
207 #endif /* _HAVE_SA_LEN */
209 ((struct sockaddr_un *)(*pai)->ai_addr)->sun_family = AF_LOCAL;
210 memset(((struct sockaddr_un *)(*pai)->ai_addr)->sun_path, 0, UNIX_PATH_MAX);
212 if (service)
214 struct sockaddr_un *sunp = (struct sockaddr_un *) (*pai)->ai_addr;
216 if (strchr (service->name, '/') != NULL)
218 if (strlen (service->name) >= sizeof (sunp->sun_path))
219 return GAIH_OKIFUNSPEC | -EAI_SERVICE;
221 strcpy (sunp->sun_path, service->name);
223 else
225 if (strlen (P_tmpdir "/") + 1 + strlen (service->name) >=
226 sizeof (sunp->sun_path))
227 return GAIH_OKIFUNSPEC | -EAI_SERVICE;
229 __stpcpy (__stpcpy (sunp->sun_path, P_tmpdir "/"), service->name);
232 else
234 /* This is a dangerous use of the interface since there is a time
235 window between the test for the file and the actual creation
236 (done by the caller) in which a file with the same name could
237 be created. */
238 char *buf = ((struct sockaddr_un *) (*pai)->ai_addr)->sun_path;
240 if (__builtin_expect (__path_search (buf, L_tmpnam, NULL, NULL, 0),
241 0) != 0
242 || __builtin_expect (__gen_tempname (buf, __GT_NOCREATE), 0) != 0)
243 return -EAI_SYSTEM;
246 if (req->ai_flags & AI_CANONNAME)
247 (*pai)->ai_canonname = strcpy ((char *) *pai + sizeof (struct addrinfo)
248 + sizeof (struct sockaddr_un),
249 utsname.nodename);
250 else
251 (*pai)->ai_canonname = NULL;
252 return 0;
254 #endif /* 0 */
257 static int
258 gaih_inet_serv (const char *servicename, const struct gaih_typeproto *tp,
259 const struct addrinfo *req, struct gaih_servtuple *st)
261 struct servent *s;
262 size_t tmpbuflen = 1024;
263 struct servent ts;
264 char *tmpbuf;
265 int r;
269 tmpbuf = __alloca (tmpbuflen);
271 r = __getservbyname_r (servicename, tp->name, &ts, tmpbuf, tmpbuflen,
272 &s);
273 if (r != 0 || s == NULL)
275 if (r == ERANGE)
276 tmpbuflen *= 2;
277 else
278 return GAIH_OKIFUNSPEC | -EAI_SERVICE;
281 while (r);
283 st->next = NULL;
284 st->socktype = tp->socktype;
285 st->protocol = ((tp->protoflag & GAI_PROTO_PROTOANY)
286 ? req->ai_protocol : tp->protocol);
287 st->port = s->s_port;
289 return 0;
292 #define gethosts(_family, _type) \
294 int i; \
295 int herrno; \
296 struct hostent th; \
297 struct hostent *h; \
298 char *localcanon = NULL; \
299 no_data = 0; \
300 while (1) { \
301 rc = 0; \
302 status = DL_CALL_FCT (fct, (name, _family, &th, tmpbuf, tmpbuflen, \
303 &rc, &herrno, NULL, &localcanon)); \
304 if (rc != ERANGE || herrno != NETDB_INTERNAL) \
305 break; \
306 tmpbuf = extend_alloca (tmpbuf, tmpbuflen, 2 * tmpbuflen); \
308 if (status == NSS_STATUS_SUCCESS && rc == 0) \
309 h = &th; \
310 else \
311 h = NULL; \
312 if (rc != 0) \
314 if (herrno == NETDB_INTERNAL) \
316 __set_h_errno (herrno); \
317 return -EAI_SYSTEM; \
319 if (herrno == TRY_AGAIN) \
320 no_data = EAI_AGAIN; \
321 else \
322 no_data = herrno == NO_DATA; \
324 else if (h != NULL) \
326 for (i = 0; h->h_addr_list[i]; i++) \
328 if (*pat == NULL) \
330 *pat = __alloca (sizeof (struct gaih_addrtuple)); \
331 (*pat)->scopeid = 0; \
333 uint32_t *addr = (*pat)->addr; \
334 (*pat)->next = NULL; \
335 (*pat)->name = i == 0 ? strdupa (h->h_name) : NULL; \
336 if (_family == AF_INET && req->ai_family == AF_INET6) \
338 (*pat)->family = AF_INET6; \
339 addr[3] = *(uint32_t *) h->h_addr_list[i]; \
340 addr[2] = htonl (0xffff); \
341 addr[1] = 0; \
342 addr[0] = 0; \
344 else \
346 (*pat)->family = _family; \
347 memcpy (addr, h->h_addr_list[i], sizeof(_type)); \
349 pat = &((*pat)->next); \
352 if (localcanon != NULL && canon == NULL) \
353 canon = strdupa (localcanon); \
355 if (_family == AF_INET6 && i > 0) \
356 got_ipv6 = true; \
361 typedef enum nss_status (*nss_gethostbyname3_r)
362 (const char *name, int af, struct hostent *host,
363 char *buffer, size_t buflen, int *errnop,
364 int *h_errnop, int32_t *ttlp, char **canonp);
365 typedef enum nss_status (*nss_getcanonname_r)
366 (const char *name, char *buffer, size_t buflen, char **result,
367 int *errnop, int *h_errnop);
368 extern service_user *__nss_hosts_database attribute_hidden;
371 static int
372 gaih_inet (const char *name, const struct gaih_service *service,
373 const struct addrinfo *req, struct addrinfo **pai,
374 unsigned int *naddrs)
376 const struct gaih_typeproto *tp = gaih_inet_typeproto;
377 struct gaih_servtuple *st = (struct gaih_servtuple *) &nullserv;
378 struct gaih_addrtuple *at = NULL;
379 int rc;
380 bool got_ipv6 = false;
381 const char *canon = NULL;
382 const char *orig_name = name;
384 if (req->ai_protocol || req->ai_socktype)
386 ++tp;
388 while (tp->name[0]
389 && ((req->ai_socktype != 0 && req->ai_socktype != tp->socktype)
390 || (req->ai_protocol != 0
391 && !(tp->protoflag & GAI_PROTO_PROTOANY)
392 && req->ai_protocol != tp->protocol)))
393 ++tp;
395 if (! tp->name[0])
397 if (req->ai_socktype)
398 return GAIH_OKIFUNSPEC | -EAI_SOCKTYPE;
399 else
400 return GAIH_OKIFUNSPEC | -EAI_SERVICE;
404 int port = 0;
405 if (service != NULL)
407 if ((tp->protoflag & GAI_PROTO_NOSERVICE) != 0)
408 return GAIH_OKIFUNSPEC | -EAI_SERVICE;
410 if (service->num < 0)
412 if (tp->name[0])
414 st = (struct gaih_servtuple *)
415 __alloca (sizeof (struct gaih_servtuple));
417 if ((rc = gaih_inet_serv (service->name, tp, req, st)))
418 return rc;
420 else
422 struct gaih_servtuple **pst = &st;
423 for (tp++; tp->name[0]; tp++)
425 struct gaih_servtuple *newp;
427 if ((tp->protoflag & GAI_PROTO_NOSERVICE) != 0)
428 continue;
430 if (req->ai_socktype != 0
431 && req->ai_socktype != tp->socktype)
432 continue;
433 if (req->ai_protocol != 0
434 && !(tp->protoflag & GAI_PROTO_PROTOANY)
435 && req->ai_protocol != tp->protocol)
436 continue;
438 newp = (struct gaih_servtuple *)
439 __alloca (sizeof (struct gaih_servtuple));
441 if ((rc = gaih_inet_serv (service->name, tp, req, newp)))
443 if (rc & GAIH_OKIFUNSPEC)
444 continue;
445 return rc;
448 *pst = newp;
449 pst = &(newp->next);
451 if (st == (struct gaih_servtuple *) &nullserv)
452 return GAIH_OKIFUNSPEC | -EAI_SERVICE;
455 else
457 port = htons (service->num);
458 goto got_port;
461 else
463 got_port:
465 if (req->ai_socktype || req->ai_protocol)
467 st = __alloca (sizeof (struct gaih_servtuple));
468 st->next = NULL;
469 st->socktype = tp->socktype;
470 st->protocol = ((tp->protoflag & GAI_PROTO_PROTOANY)
471 ? req->ai_protocol : tp->protocol);
472 st->port = port;
474 else
476 /* Neither socket type nor protocol is set. Return all socket types
477 we know about. */
478 struct gaih_servtuple **lastp = &st;
479 for (++tp; tp->name[0]; ++tp)
481 struct gaih_servtuple *newp;
483 newp = __alloca (sizeof (struct gaih_servtuple));
484 newp->next = NULL;
485 newp->socktype = tp->socktype;
486 newp->protocol = tp->protocol;
487 newp->port = port;
489 *lastp = newp;
490 lastp = &newp->next;
495 if (name != NULL)
497 at = __alloca (sizeof (struct gaih_addrtuple));
499 at->family = AF_UNSPEC;
500 at->scopeid = 0;
501 at->next = NULL;
503 #ifdef HAVE_LIBIDN
504 if (req->ai_flags & AI_IDN)
506 int idn_flags = 0;
507 if (req->ai_flags & AI_IDN_ALLOW_UNASSIGNED)
508 idn_flags |= IDNA_ALLOW_UNASSIGNED;
509 if (req->ai_flags & AI_IDN_USE_STD3_ASCII_RULES)
510 idn_flags |= IDNA_USE_STD3_ASCII_RULES;
512 char *p = NULL;
513 rc = __idna_to_ascii_lz (name, &p, idn_flags);
514 if (rc != IDNA_SUCCESS)
516 if (rc == IDNA_MALLOC_ERROR)
517 return -EAI_MEMORY;
518 if (rc == IDNA_DLOPEN_ERROR)
519 return -EAI_SYSTEM;
520 return -EAI_IDN_ENCODE;
522 /* In case the output string is the same as the input string
523 no new string has been allocated. */
524 if (p != name)
526 name = strdupa (p);
527 free (p);
530 #endif
532 if (__inet_aton (name, (struct in_addr *) at->addr) != 0)
534 if (req->ai_family == AF_UNSPEC || req->ai_family == AF_INET)
535 at->family = AF_INET;
536 else if (req->ai_family == AF_INET6 && (req->ai_flags & AI_V4MAPPED))
538 at->addr[3] = at->addr[0];
539 at->addr[2] = htonl (0xffff);
540 at->addr[1] = 0;
541 at->addr[0] = 0;
542 at->family = AF_INET6;
544 else
545 return -EAI_ADDRFAMILY;
547 if (req->ai_flags & AI_CANONNAME)
548 canon = name;
550 else if (at->family == AF_UNSPEC)
552 char *namebuf = (char *) name;
553 char *scope_delim = strchr (name, SCOPE_DELIMITER);
555 if (__builtin_expect (scope_delim != NULL, 0))
557 namebuf = alloca (scope_delim - name + 1);
558 *((char *) __mempcpy (namebuf, name, scope_delim - name)) = '\0';
561 if (inet_pton (AF_INET6, namebuf, at->addr) > 0)
563 if (req->ai_family == AF_UNSPEC || req->ai_family == AF_INET6)
564 at->family = AF_INET6;
565 else if (req->ai_family == AF_INET
566 && IN6_IS_ADDR_V4MAPPED (at->addr))
568 at->addr[0] = at->addr[3];
569 at->family = AF_INET;
571 else
572 return -EAI_ADDRFAMILY;
574 if (scope_delim != NULL)
576 int try_numericscope = 0;
577 if (IN6_IS_ADDR_LINKLOCAL (at->addr)
578 || IN6_IS_ADDR_MC_LINKLOCAL (at->addr))
580 at->scopeid = if_nametoindex (scope_delim + 1);
581 if (at->scopeid == 0)
582 try_numericscope = 1;
584 else
585 try_numericscope = 1;
587 if (try_numericscope != 0)
589 char *end;
590 assert (sizeof (uint32_t) <= sizeof (unsigned long));
591 at->scopeid = (uint32_t) strtoul (scope_delim + 1, &end,
592 10);
593 if (*end != '\0')
594 return GAIH_OKIFUNSPEC | -EAI_NONAME;
598 if (req->ai_flags & AI_CANONNAME)
599 canon = name;
603 if (at->family == AF_UNSPEC && (req->ai_flags & AI_NUMERICHOST) == 0)
605 struct gaih_addrtuple **pat = &at;
606 int no_data = 0;
607 int no_inet6_data = 0;
608 service_user *nip = NULL;
609 enum nss_status inet6_status = NSS_STATUS_UNAVAIL;
610 enum nss_status status = NSS_STATUS_UNAVAIL;
611 int no_more;
612 int old_res_options;
614 /* If we do not have to look for IPv4 and IPv6 together, use
615 the simple, old functions. */
616 if (req->ai_family == AF_INET
617 || (req->ai_family == AF_INET6
618 && ((req->ai_flags & AI_V4MAPPED) == 0
619 || (req->ai_flags & AI_ALL) == 0)))
621 int family = req->ai_family;
622 size_t tmpbuflen = 512;
623 char *tmpbuf = alloca (tmpbuflen);
624 int rc;
625 struct hostent th;
626 struct hostent *h;
627 int herrno;
629 simple_again:
630 while (1)
632 rc = __gethostbyname2_r (name, family, &th, tmpbuf,
633 tmpbuflen, &h, &herrno);
634 if (rc != ERANGE || herrno != NETDB_INTERNAL)
635 break;
636 tmpbuf = extend_alloca (tmpbuf, tmpbuflen, 2 * tmpbuflen);
639 if (rc == 0)
641 if (h == NULL)
643 if (req->ai_family == AF_INET6
644 && (req->ai_flags & AI_V4MAPPED)
645 && family == AF_INET6)
647 /* Try again, this time looking for IPv4
648 addresses. */
649 family = AF_INET;
650 goto simple_again;
653 else
655 /* We found data, now convert it into the list. */
656 for (int i = 0; h->h_addr_list[i]; ++i)
658 if (*pat == NULL)
660 *pat = __alloca (sizeof (struct gaih_addrtuple));
661 (*pat)->scopeid = 0;
663 (*pat)->next = NULL;
664 (*pat)->family = req->ai_family;
665 if (family == req->ai_family)
666 memcpy ((*pat)->addr, h->h_addr_list[i],
667 h->h_length);
668 else
670 uint32_t *addr = (uint32_t *) (*pat)->addr;
671 addr[3] = *(uint32_t *) h->h_addr_list[i];
672 addr[2] = htonl (0xffff);
673 addr[1] = 0;
674 addr[0] = 0;
676 pat = &((*pat)->next);
680 else
682 if (herrno == NETDB_INTERNAL)
684 __set_h_errno (herrno);
685 return -EAI_SYSTEM;
687 if (herrno == TRY_AGAIN)
689 return -EAI_AGAIN;
691 /* We made requests but they turned out no data.
692 The name is known, though. */
693 return GAIH_OKIFUNSPEC | -EAI_NODATA;
696 goto process_list;
699 #ifdef USE_NSCD
700 if (__nss_not_use_nscd_hosts > 0
701 && ++__nss_not_use_nscd_hosts > NSS_NSCD_RETRY)
702 __nss_not_use_nscd_hosts = 0;
704 if (!__nss_not_use_nscd_hosts)
706 /* Try to use nscd. */
707 struct nscd_ai_result *air = NULL;
708 int herrno;
709 int err = __nscd_getai (name, &air, &herrno);
710 if (air != NULL)
712 /* Transform into gaih_addrtuple list. */
713 bool added_canon = (req->ai_flags & AI_CANONNAME) == 0;
714 char *addrs = air->addrs;
716 for (int i = 0; i < air->naddrs; ++i)
718 socklen_t size = (air->family[i] == AF_INET
719 ? INADDRSZ : IN6ADDRSZ);
720 if (*pat == NULL)
722 *pat = __alloca (sizeof (struct gaih_addrtuple));
723 (*pat)->scopeid = 0;
725 uint32_t *pataddr = (*pat)->addr;
726 (*pat)->next = NULL;
727 if (added_canon || air->canon == NULL)
728 (*pat)->name = NULL;
729 else
730 canon = (*pat)->name = strdupa (air->canon);
732 if (air->family[i] == AF_INET
733 && req->ai_family == AF_INET6
734 && (req->ai_flags & AI_V4MAPPED))
736 (*pat)->family = AF_INET6;
737 pataddr[3] = *(uint32_t *) addrs;
738 pataddr[2] = htonl (0xffff);
739 pataddr[1] = 0;
740 pataddr[0] = 0;
741 pat = &((*pat)->next);
742 added_canon = true;
744 else if (req->ai_family == AF_UNSPEC
745 || air->family[i] == req->ai_family)
747 (*pat)->family = air->family[i];
748 memcpy (pataddr, addrs, size);
749 pat = &((*pat)->next);
750 added_canon = true;
751 if (air->family[i] == AF_INET6)
752 got_ipv6 = true;
754 addrs += size;
757 free (air);
759 if (at->family == AF_UNSPEC)
760 return GAIH_OKIFUNSPEC | -EAI_NONAME;
762 goto process_list;
764 else if (err != 0 && __nss_not_use_nscd_hosts == 0)
766 if (herrno == NETDB_INTERNAL && errno == ENOMEM)
767 return -EAI_MEMORY;
768 if (herrno == TRY_AGAIN)
769 return -EAI_AGAIN;
770 return -EAI_SYSTEM;
773 #endif
775 if (__nss_hosts_database != NULL)
777 no_more = 0;
778 nip = __nss_hosts_database;
780 else
781 no_more = __nss_database_lookup ("hosts", NULL,
782 "dns [!UNAVAIL=return] files",
783 &nip);
785 if (__res_maybe_init (&_res, 0) == -1)
786 no_more = 1;
788 /* If we are looking for both IPv4 and IPv6 address we don't
789 want the lookup functions to automatically promote IPv4
790 addresses to IPv6 addresses. Currently this is decided
791 by setting the RES_USE_INET6 bit in _res.options. */
792 old_res_options = _res.options;
793 _res.options &= ~RES_USE_INET6;
795 size_t tmpbuflen = 512;
796 char *tmpbuf = alloca (tmpbuflen);
798 while (!no_more)
800 nss_gethostbyname3_r fct = NULL;
801 if (req->ai_flags & AI_CANONNAME)
802 /* No need to use this function if we do not look for
803 the canonical name. The function does not exist in
804 all NSS modules and therefore the lookup would
805 often fail. */
806 fct = __nss_lookup_function (nip, "gethostbyname3_r");
807 if (fct == NULL)
808 /* We are cheating here. The gethostbyname2_r function does
809 not have the same interface as gethostbyname3_r but the
810 extra arguments the latter takes are added at the end.
811 So the gethostbyname2_r code will just ignore them. */
812 fct = __nss_lookup_function (nip, "gethostbyname2_r");
814 if (fct != NULL)
816 if (req->ai_family == AF_INET6
817 || req->ai_family == AF_UNSPEC)
819 gethosts (AF_INET6, struct in6_addr);
820 no_inet6_data = no_data;
821 inet6_status = status;
823 if (req->ai_family == AF_INET
824 || req->ai_family == AF_UNSPEC
825 || (req->ai_family == AF_INET6
826 && (req->ai_flags & AI_V4MAPPED)
827 /* Avoid generating the mapped addresses if we
828 know we are not going to need them. */
829 && ((req->ai_flags & AI_ALL) || !got_ipv6)))
831 gethosts (AF_INET, struct in_addr);
833 if (req->ai_family == AF_INET)
835 no_inet6_data = no_data;
836 inet6_status = status;
840 /* If we found one address for AF_INET or AF_INET6,
841 don't continue the search. */
842 if (inet6_status == NSS_STATUS_SUCCESS
843 || status == NSS_STATUS_SUCCESS)
845 if ((req->ai_flags & AI_CANONNAME) != 0 && canon == NULL)
847 /* If we need the canonical name, get it
848 from the same service as the result. */
849 nss_getcanonname_r cfct;
850 int herrno;
852 cfct = __nss_lookup_function (nip, "getcanonname_r");
853 if (cfct != NULL)
855 const size_t max_fqdn_len = 256;
856 char *buf = alloca (max_fqdn_len);
857 char *s;
859 if (DL_CALL_FCT (cfct, (at->name ?: name, buf,
860 max_fqdn_len, &s, &rc,
861 &herrno))
862 == NSS_STATUS_SUCCESS)
863 canon = s;
864 else
865 /* Set to name now to avoid using
866 gethostbyaddr. */
867 canon = name;
871 break;
874 /* We can have different states for AF_INET and
875 AF_INET6. Try to find a useful one for both. */
876 if (inet6_status == NSS_STATUS_TRYAGAIN)
877 status = NSS_STATUS_TRYAGAIN;
878 else if (status == NSS_STATUS_UNAVAIL
879 && inet6_status != NSS_STATUS_UNAVAIL)
880 status = inet6_status;
883 if (nss_next_action (nip, status) == NSS_ACTION_RETURN)
884 break;
886 if (nip->next == NULL)
887 no_more = -1;
888 else
889 nip = nip->next;
892 _res.options = old_res_options;
894 if (no_data != 0 && no_inet6_data != 0)
896 /* If both requests timed out report this. */
897 if (no_data == EAI_AGAIN && no_inet6_data == EAI_AGAIN)
898 return -EAI_AGAIN;
900 /* We made requests but they turned out no data. The name
901 is known, though. */
902 return GAIH_OKIFUNSPEC | -EAI_NODATA;
906 process_list:
907 if (at->family == AF_UNSPEC)
908 return GAIH_OKIFUNSPEC | -EAI_NONAME;
910 else
912 struct gaih_addrtuple *atr;
913 atr = at = __alloca (sizeof (struct gaih_addrtuple));
914 memset (at, '\0', sizeof (struct gaih_addrtuple));
916 if (req->ai_family == AF_UNSPEC)
918 at->next = __alloca (sizeof (struct gaih_addrtuple));
919 memset (at->next, '\0', sizeof (struct gaih_addrtuple));
922 if (req->ai_family == AF_UNSPEC || req->ai_family == AF_INET6)
924 at->family = AF_INET6;
925 if ((req->ai_flags & AI_PASSIVE) == 0)
926 memcpy (at->addr, &in6addr_loopback, sizeof (struct in6_addr));
927 atr = at->next;
930 if (req->ai_family == AF_UNSPEC || req->ai_family == AF_INET)
932 atr->family = AF_INET;
933 if ((req->ai_flags & AI_PASSIVE) == 0)
934 atr->addr[0] = htonl (INADDR_LOOPBACK);
938 if (pai == NULL)
939 return 0;
942 struct gaih_servtuple *st2;
943 struct gaih_addrtuple *at2 = at;
944 size_t socklen;
945 sa_family_t family;
948 buffer is the size of an unformatted IPv6 address in printable format.
950 while (at2 != NULL)
952 /* Only the first entry gets the canonical name. */
953 if (at2 == at && (req->ai_flags & AI_CANONNAME) != 0)
955 if (canon == NULL)
957 struct hostent *h = NULL;
958 int herrno;
959 struct hostent th;
960 size_t tmpbuflen = 512;
961 char *tmpbuf = NULL;
965 tmpbuf = extend_alloca (tmpbuf, tmpbuflen, tmpbuflen * 2);
966 rc = __gethostbyaddr_r (at2->addr,
967 ((at2->family == AF_INET6)
968 ? sizeof (struct in6_addr)
969 : sizeof (struct in_addr)),
970 at2->family, &th, tmpbuf,
971 tmpbuflen, &h, &herrno);
973 while (rc == ERANGE && herrno == NETDB_INTERNAL);
975 if (rc != 0 && herrno == NETDB_INTERNAL)
977 __set_h_errno (herrno);
978 return -EAI_SYSTEM;
981 if (h != NULL)
982 canon = h->h_name;
983 else
985 assert (orig_name != NULL);
986 /* If the canonical name cannot be determined, use
987 the passed in string. */
988 canon = orig_name;
992 #ifdef HAVE_LIBIDN
993 if (req->ai_flags & AI_CANONIDN)
995 int idn_flags = 0;
996 if (req->ai_flags & AI_IDN_ALLOW_UNASSIGNED)
997 idn_flags |= IDNA_ALLOW_UNASSIGNED;
998 if (req->ai_flags & AI_IDN_USE_STD3_ASCII_RULES)
999 idn_flags |= IDNA_USE_STD3_ASCII_RULES;
1001 char *out;
1002 int rc = __idna_to_unicode_lzlz (canon, &out, idn_flags);
1003 if (rc != IDNA_SUCCESS)
1005 if (rc == IDNA_MALLOC_ERROR)
1006 return -EAI_MEMORY;
1007 if (rc == IDNA_DLOPEN_ERROR)
1008 return -EAI_SYSTEM;
1009 return -EAI_IDN_ENCODE;
1011 /* In case the output string is the same as the input
1012 string no new string has been allocated. Otherwise
1013 make a copy. */
1014 if (out == canon)
1015 goto make_copy;
1017 else
1018 #endif
1020 #ifdef HAVE_LIBIDN
1021 make_copy:
1022 #endif
1023 canon = strdup (canon);
1024 if (canon == NULL)
1025 return -EAI_MEMORY;
1029 family = at2->family;
1030 if (family == AF_INET6)
1032 socklen = sizeof (struct sockaddr_in6);
1034 /* If we looked up IPv4 mapped address discard them here if
1035 the caller isn't interested in all address and we have
1036 found at least one IPv6 address. */
1037 if (got_ipv6
1038 && (req->ai_flags & (AI_V4MAPPED|AI_ALL)) == AI_V4MAPPED
1039 && IN6_IS_ADDR_V4MAPPED (at2->addr))
1040 goto ignore;
1042 else
1043 socklen = sizeof (struct sockaddr_in);
1045 for (st2 = st; st2 != NULL; st2 = st2->next)
1047 struct addrinfo *ai;
1048 ai = *pai = malloc (sizeof (struct addrinfo) + socklen);
1049 if (ai == NULL)
1051 free ((char *) canon);
1052 return -EAI_MEMORY;
1055 ai->ai_flags = req->ai_flags;
1056 ai->ai_family = family;
1057 ai->ai_socktype = st2->socktype;
1058 ai->ai_protocol = st2->protocol;
1059 ai->ai_addrlen = socklen;
1060 ai->ai_addr = (void *) (ai + 1);
1062 /* We only add the canonical name once. */
1063 ai->ai_canonname = (char *) canon;
1064 canon = NULL;
1066 #ifdef _HAVE_SA_LEN
1067 ai->ai_addr->sa_len = socklen;
1068 #endif /* _HAVE_SA_LEN */
1069 ai->ai_addr->sa_family = family;
1071 /* In case of an allocation error the list must be NULL
1072 terminated. */
1073 ai->ai_next = NULL;
1075 if (family == AF_INET6)
1077 struct sockaddr_in6 *sin6p =
1078 (struct sockaddr_in6 *) ai->ai_addr;
1080 sin6p->sin6_port = st2->port;
1081 sin6p->sin6_flowinfo = 0;
1082 memcpy (&sin6p->sin6_addr,
1083 at2->addr, sizeof (struct in6_addr));
1084 sin6p->sin6_scope_id = at2->scopeid;
1086 else
1088 struct sockaddr_in *sinp =
1089 (struct sockaddr_in *) ai->ai_addr;
1090 sinp->sin_port = st2->port;
1091 memcpy (&sinp->sin_addr,
1092 at2->addr, sizeof (struct in_addr));
1093 memset (sinp->sin_zero, '\0', sizeof (sinp->sin_zero));
1096 pai = &(ai->ai_next);
1099 ++*naddrs;
1101 ignore:
1102 at2 = at2->next;
1105 return 0;
1108 #if 0
1109 static const struct gaih gaih[] =
1111 { PF_INET6, gaih_inet },
1112 { PF_INET, gaih_inet },
1113 #if 0
1114 { PF_LOCAL, gaih_local },
1115 #endif
1116 { PF_UNSPEC, NULL }
1118 #endif
1120 struct sort_result
1122 struct addrinfo *dest_addr;
1123 struct sockaddr_storage source_addr;
1124 uint8_t source_addr_len;
1125 bool got_source_addr;
1126 uint8_t source_addr_flags;
1130 static int
1131 get_scope (const struct sockaddr_storage *ss)
1133 int scope;
1134 if (ss->ss_family == PF_INET6)
1136 const struct sockaddr_in6 *in6 = (const struct sockaddr_in6 *) ss;
1138 if (! IN6_IS_ADDR_MULTICAST (&in6->sin6_addr))
1140 if (IN6_IS_ADDR_LINKLOCAL (&in6->sin6_addr))
1141 scope = 2;
1142 else if (IN6_IS_ADDR_SITELOCAL (&in6->sin6_addr))
1143 scope = 5;
1144 else
1145 /* XXX Is this the correct default behavior? */
1146 scope = 14;
1148 else
1149 scope = in6->sin6_addr.s6_addr[1] & 0xf;
1151 else if (ss->ss_family == PF_INET)
1153 const struct sockaddr_in *in = (const struct sockaddr_in *) ss;
1154 const uint8_t *addr = (const uint8_t *) &in->sin_addr;
1156 /* RFC 3484 specifies how to map IPv6 addresses to scopes.
1157 169.254/16 and 127/8 are link-local. */
1158 if ((addr[0] == 169 && addr[1] == 254) || addr[0] == 127)
1159 scope = 2;
1160 else if (addr[0] == 10 || (addr[0] == 172 && (addr[1] & 0xf0) == 16)
1161 || (addr[0] == 192 && addr[1] == 168))
1162 scope = 5;
1163 else
1164 scope = 14;
1166 else
1167 /* XXX What is a good default? */
1168 scope = 15;
1170 return scope;
1174 struct prefixentry
1176 struct in6_addr prefix;
1177 unsigned int bits;
1178 int val;
1182 /* The label table. */
1183 static const struct prefixentry *labels;
1185 /* Default labels. */
1186 static const struct prefixentry default_labels[] =
1188 /* See RFC 3484 for the details. */
1189 { { .in6_u
1190 = { .u6_addr8 = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1191 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 } } },
1192 128, 0 },
1193 { { .in6_u
1194 = { .u6_addr8 = { 0x20, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1195 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
1196 16, 2 },
1197 { { .in6_u
1198 = { .u6_addr8 = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1199 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
1200 96, 3 },
1201 { { .in6_u
1202 = { .u6_addr8 = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1203 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00 } } },
1204 96, 4 },
1205 /* The next two entries differ from RFC 3484. We need to treat
1206 IPv6 site-local addresses special because they are never NATed,
1207 unlike site-locale IPv4 addresses. If this would not happen, on
1208 machines which have only IPv4 and IPv6 site-local addresses, the
1209 sorting would prefer the IPv6 site-local addresses, causing
1210 unnecessary delays when trying to connect to a global IPv6 address
1211 through a site-local IPv6 address. */
1212 { { .in6_u
1213 = { .u6_addr8 = { 0xfe, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1214 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
1215 10, 5 },
1216 { { .in6_u
1217 = { .u6_addr8 = { 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1218 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
1219 7, 6 },
1220 { { .in6_u
1221 = { .u6_addr8 = { 0x20, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1222 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
1223 32, 7 },
1224 { { .in6_u
1225 = { .u6_addr8 = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1226 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
1227 0, 1 }
1231 /* The precedence table. */
1232 static const struct prefixentry *precedence;
1234 /* The default precedences. */
1235 static const struct prefixentry default_precedence[] =
1237 /* See RFC 3484 for the details. */
1238 { { .in6_u
1239 = { .u6_addr8 = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1240 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 } } },
1241 128, 50 },
1242 { { .in6_u
1243 = { .u6_addr8 = { 0x20, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1244 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
1245 16, 30 },
1246 { { .in6_u
1247 = { .u6_addr8 = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1248 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
1249 96, 20 },
1250 { { .in6_u
1251 = { .u6_addr8 = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1252 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00 } } },
1253 96, 10 },
1254 { { .in6_u
1255 = { .u6_addr8 = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1256 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
1257 0, 40 }
1261 static int
1262 match_prefix (const struct sockaddr_storage *ss,
1263 const struct prefixentry *list, int default_val)
1265 int idx;
1266 struct sockaddr_in6 in6_mem;
1267 const struct sockaddr_in6 *in6;
1269 if (ss->ss_family == PF_INET6)
1270 in6 = (const struct sockaddr_in6 *) ss;
1271 else if (ss->ss_family == PF_INET)
1273 const struct sockaddr_in *in = (const struct sockaddr_in *) ss;
1275 /* Convert to IPv6 address. */
1276 in6_mem.sin6_family = PF_INET6;
1277 in6_mem.sin6_port = in->sin_port;
1278 in6_mem.sin6_flowinfo = 0;
1279 if (in->sin_addr.s_addr == htonl (0x7f000001))
1280 in6_mem.sin6_addr = (struct in6_addr) IN6ADDR_LOOPBACK_INIT;
1281 else
1283 /* Construct a V4-to-6 mapped address. */
1284 memset (&in6_mem.sin6_addr, '\0', sizeof (in6_mem.sin6_addr));
1285 in6_mem.sin6_addr.s6_addr16[5] = 0xffff;
1286 in6_mem.sin6_addr.s6_addr32[3] = in->sin_addr.s_addr;
1287 in6_mem.sin6_scope_id = 0;
1290 in6 = &in6_mem;
1292 else
1293 return default_val;
1295 for (idx = 0; ; ++idx)
1297 unsigned int bits = list[idx].bits;
1298 const uint8_t *mask = list[idx].prefix.s6_addr;
1299 const uint8_t *val = in6->sin6_addr.s6_addr;
1301 while (bits >= 8)
1303 if (*mask != *val)
1304 break;
1306 ++mask;
1307 ++val;
1308 bits -= 8;
1311 if (bits < 8)
1313 if ((*mask & (0xff00 >> bits)) == (*val & (0xff00 >> bits)))
1314 /* Match! */
1315 break;
1319 return list[idx].val;
1323 static int
1324 get_label (const struct sockaddr_storage *ss)
1326 /* XXX What is a good default value? */
1327 return match_prefix (ss, labels, INT_MAX);
1331 static int
1332 get_precedence (const struct sockaddr_storage *ss)
1334 /* XXX What is a good default value? */
1335 return match_prefix (ss, precedence, 0);
1339 /* Find last bit set in a word. */
1340 static int
1341 fls (uint32_t a)
1343 uint32_t mask;
1344 int n = 0;
1345 for (n = 0, mask = 1 << 31; n < 32; mask >>= 1, ++n)
1346 if ((a & mask) != 0)
1347 break;
1348 return n;
1352 static int
1353 rfc3484_sort (const void *p1, const void *p2)
1355 const struct sort_result *a1 = (const struct sort_result *) p1;
1356 const struct sort_result *a2 = (const struct sort_result *) p2;
1358 /* Rule 1: Avoid unusable destinations.
1359 We have the got_source_addr flag set if the destination is reachable. */
1360 if (a1->got_source_addr && ! a2->got_source_addr)
1361 return -1;
1362 if (! a1->got_source_addr && a2->got_source_addr)
1363 return 1;
1366 /* Rule 2: Prefer matching scope. Only interesting if both
1367 destination addresses are IPv6. */
1368 int a1_dst_scope
1369 = get_scope ((struct sockaddr_storage *) a1->dest_addr->ai_addr);
1371 int a2_dst_scope
1372 = get_scope ((struct sockaddr_storage *) a2->dest_addr->ai_addr);
1374 if (a1->got_source_addr)
1376 int a1_src_scope = get_scope (&a1->source_addr);
1377 int a2_src_scope = get_scope (&a2->source_addr);
1379 if (a1_dst_scope == a1_src_scope && a2_dst_scope != a2_src_scope)
1380 return -1;
1381 if (a1_dst_scope != a1_src_scope && a2_dst_scope == a2_src_scope)
1382 return 1;
1386 /* Rule 3: Avoid deprecated addresses. */
1387 if (a1->got_source_addr)
1389 if (!(a1->source_addr_flags & in6ai_deprecated)
1390 && (a2->source_addr_flags & in6ai_deprecated))
1391 return -1;
1392 if ((a1->source_addr_flags & in6ai_deprecated)
1393 && !(a2->source_addr_flags & in6ai_deprecated))
1394 return 1;
1397 /* Rule 4: Prefer home addresses. */
1398 if (a1->got_source_addr)
1400 if (!(a1->source_addr_flags & in6ai_homeaddress)
1401 && (a2->source_addr_flags & in6ai_homeaddress))
1402 return 1;
1403 if ((a1->source_addr_flags & in6ai_homeaddress)
1404 && !(a2->source_addr_flags & in6ai_homeaddress))
1405 return -1;
1408 /* Rule 5: Prefer matching label. */
1409 if (a1->got_source_addr)
1411 int a1_dst_label
1412 = get_label ((struct sockaddr_storage *) a1->dest_addr->ai_addr);
1413 int a1_src_label = get_label (&a1->source_addr);
1415 int a2_dst_label
1416 = get_label ((struct sockaddr_storage *) a2->dest_addr->ai_addr);
1417 int a2_src_label = get_label (&a2->source_addr);
1419 if (a1_dst_label == a1_src_label && a2_dst_label != a2_src_label)
1420 return -1;
1421 if (a1_dst_label != a1_src_label && a2_dst_label == a2_src_label)
1422 return 1;
1426 /* Rule 6: Prefer higher precedence. */
1427 int a1_prec
1428 = get_precedence ((struct sockaddr_storage *) a1->dest_addr->ai_addr);
1429 int a2_prec
1430 = get_precedence ((struct sockaddr_storage *) a2->dest_addr->ai_addr);
1432 if (a1_prec > a2_prec)
1433 return -1;
1434 if (a1_prec < a2_prec)
1435 return 1;
1438 /* Rule 7: Prefer native transport. */
1439 if (a1->got_source_addr)
1441 if (!(a1->source_addr_flags & in6ai_temporary)
1442 && (a2->source_addr_flags & in6ai_temporary))
1443 return -1;
1444 if ((a1->source_addr_flags & in6ai_temporary)
1445 && !(a2->source_addr_flags & in6ai_temporary))
1446 return 1;
1448 /* XXX Do we need to check anything beside temporary addresses? */
1452 /* Rule 8: Prefer smaller scope. */
1453 if (a1_dst_scope < a2_dst_scope)
1454 return -1;
1455 if (a1_dst_scope > a2_dst_scope)
1456 return 1;
1459 /* Rule 9: Use longest matching prefix. */
1460 if (a1->got_source_addr
1461 && a1->dest_addr->ai_family == a2->dest_addr->ai_family)
1463 int bit1 = 0;
1464 int bit2 = 0;
1466 if (a1->dest_addr->ai_family == PF_INET)
1468 assert (a1->source_addr.ss_family == PF_INET);
1469 assert (a2->source_addr.ss_family == PF_INET);
1471 struct sockaddr_in *in1_dst;
1472 struct sockaddr_in *in1_src;
1473 struct sockaddr_in *in2_dst;
1474 struct sockaddr_in *in2_src;
1476 in1_dst = (struct sockaddr_in *) a1->dest_addr->ai_addr;
1477 in1_src = (struct sockaddr_in *) &a1->source_addr;
1478 in2_dst = (struct sockaddr_in *) a2->dest_addr->ai_addr;
1479 in2_src = (struct sockaddr_in *) &a2->source_addr;
1481 bit1 = fls (ntohl (in1_dst->sin_addr.s_addr
1482 ^ in1_src->sin_addr.s_addr));
1483 bit2 = fls (ntohl (in2_dst->sin_addr.s_addr
1484 ^ in2_src->sin_addr.s_addr));
1486 else if (a1->dest_addr->ai_family == PF_INET6)
1488 assert (a1->source_addr.ss_family == PF_INET6);
1489 assert (a2->source_addr.ss_family == PF_INET6);
1491 struct sockaddr_in6 *in1_dst;
1492 struct sockaddr_in6 *in1_src;
1493 struct sockaddr_in6 *in2_dst;
1494 struct sockaddr_in6 *in2_src;
1496 in1_dst = (struct sockaddr_in6 *) a1->dest_addr->ai_addr;
1497 in1_src = (struct sockaddr_in6 *) &a1->source_addr;
1498 in2_dst = (struct sockaddr_in6 *) a2->dest_addr->ai_addr;
1499 in2_src = (struct sockaddr_in6 *) &a2->source_addr;
1501 int i;
1502 for (i = 0; i < 4; ++i)
1503 if (in1_dst->sin6_addr.s6_addr32[i]
1504 != in1_src->sin6_addr.s6_addr32[i]
1505 || (in2_dst->sin6_addr.s6_addr32[i]
1506 != in2_src->sin6_addr.s6_addr32[i]))
1507 break;
1509 if (i < 4)
1511 bit1 = fls (ntohl (in1_dst->sin6_addr.s6_addr32[i]
1512 ^ in1_src->sin6_addr.s6_addr32[i]));
1513 bit2 = fls (ntohl (in2_dst->sin6_addr.s6_addr32[i]
1514 ^ in2_src->sin6_addr.s6_addr32[i]));
1518 if (bit1 > bit2)
1519 return -1;
1520 if (bit1 < bit2)
1521 return 1;
1525 /* Rule 10: Otherwise, leave the order unchanged. */
1526 return 0;
1530 static int
1531 in6aicmp (const void *p1, const void *p2)
1533 struct in6addrinfo *a1 = (struct in6addrinfo *) p1;
1534 struct in6addrinfo *a2 = (struct in6addrinfo *) p2;
1536 return memcmp (a1->addr, a2->addr, sizeof (a1->addr));
1540 /* Name of the config file for RFC 3484 sorting (for now). */
1541 #define GAICONF_FNAME "/etc/gai.conf"
1544 /* Nozero if we are supposed to reload the config file automatically
1545 whenever it changed. */
1546 static int gaiconf_reload_flag;
1548 /* Last modification time. */
1549 static struct timespec gaiconf_mtime;
1552 libc_freeres_fn(fini)
1554 if (labels != default_labels)
1556 const struct prefixentry *old = labels;
1557 labels = default_labels;
1558 free ((void *) old);
1561 if (precedence != default_precedence)
1563 const struct prefixentry *old = precedence;
1564 precedence = default_precedence;
1565 free ((void *) old);
1570 struct prefixlist
1572 struct prefixentry entry;
1573 struct prefixlist *next;
1577 static void
1578 free_prefixlist (struct prefixlist *list)
1580 while (list != NULL)
1582 struct prefixlist *oldp = list;
1583 list = list->next;
1584 free (oldp);
1589 static int
1590 prefixcmp (const void *p1, const void *p2)
1592 const struct prefixentry *e1 = (const struct prefixentry *) p1;
1593 const struct prefixentry *e2 = (const struct prefixentry *) p2;
1595 if (e1->bits < e2->bits)
1596 return 1;
1597 if (e1->bits == e2->bits)
1598 return 0;
1599 return -1;
1603 static void
1604 gaiconf_init (void)
1606 struct prefixlist *labellist = NULL;
1607 size_t nlabellist = 0;
1608 bool labellist_nullbits = false;
1609 struct prefixlist *precedencelist = NULL;
1610 size_t nprecedencelist = 0;
1611 bool precedencelist_nullbits = false;
1613 FILE *fp = fopen (GAICONF_FNAME, "rc");
1614 if (fp != NULL)
1616 struct stat64 st;
1617 if (__fxstat64 (_STAT_VER, fileno (fp), &st) != 0)
1619 fclose (fp);
1620 goto no_file;
1623 char *line = NULL;
1624 size_t linelen = 0;
1626 __fsetlocking (fp, FSETLOCKING_BYCALLER);
1628 while (!feof_unlocked (fp))
1630 ssize_t n = __getline (&line, &linelen, fp);
1631 if (n <= 0)
1632 break;
1634 /* Handle comments. No escaping possible so this is easy. */
1635 char *cp = strchr (line, '#');
1636 if (cp != NULL)
1637 *cp = '\0';
1639 cp = line;
1640 while (isspace (*cp))
1641 ++cp;
1643 char *cmd = cp;
1644 while (*cp != '\0' && !isspace (*cp))
1645 ++cp;
1646 size_t cmdlen = cp - cmd;
1648 if (*cp != '\0')
1649 *cp++ = '\0';
1650 while (isspace (*cp))
1651 ++cp;
1653 char *val1 = cp;
1654 while (*cp != '\0' && !isspace (*cp))
1655 ++cp;
1656 size_t val1len = cp - cmd;
1658 /* We always need at least two values. */
1659 if (val1len == 0)
1660 continue;
1662 if (*cp != '\0')
1663 *cp++ = '\0';
1664 while (isspace (*cp))
1665 ++cp;
1667 char *val2 = cp;
1668 while (*cp != '\0' && !isspace (*cp))
1669 ++cp;
1671 /* Ignore the rest of the line. */
1672 *cp = '\0';
1674 struct prefixlist **listp;
1675 size_t *lenp;
1676 bool *nullbitsp;
1677 switch (cmdlen)
1679 case 5:
1680 if (strcmp (cmd, "label") == 0)
1682 struct in6_addr prefix;
1683 unsigned long int bits;
1684 unsigned long int val;
1685 char *endp;
1687 listp = &labellist;
1688 lenp = &nlabellist;
1689 nullbitsp = &labellist_nullbits;
1691 new_elem:
1692 bits = 128;
1693 __set_errno (0);
1694 cp = strchr (val1, '/');
1695 if (cp != NULL)
1696 *cp++ = '\0';
1697 if (inet_pton (AF_INET6, val1, &prefix)
1698 && (cp == NULL
1699 || (bits = strtoul (cp, &endp, 10)) != ULONG_MAX
1700 || errno != ERANGE)
1701 && *endp == '\0'
1702 && bits <= INT_MAX
1703 && ((val = strtoul (val2, &endp, 10)) != ULONG_MAX
1704 || errno != ERANGE)
1705 && *endp == '\0'
1706 && val <= INT_MAX)
1708 struct prefixlist *newp = malloc (sizeof (*newp));
1709 if (newp == NULL)
1711 free (line);
1712 fclose (fp);
1713 goto no_file;
1716 memcpy (&newp->entry.prefix, &prefix, sizeof (prefix));
1717 newp->entry.bits = bits;
1718 newp->entry.val = val;
1719 newp->next = *listp;
1720 *listp = newp;
1721 ++*lenp;
1722 *nullbitsp |= bits == 0;
1725 break;
1727 case 6:
1728 if (strcmp (cmd, "reload") == 0)
1729 gaiconf_reload_flag = strcmp (val1, "yes") == 0;
1730 break;
1732 case 10:
1733 if (strcmp (cmd, "precedence") == 0)
1735 listp = &precedencelist;
1736 lenp = &nprecedencelist;
1737 nullbitsp = &precedencelist_nullbits;
1738 goto new_elem;
1740 break;
1744 free (line);
1746 fclose (fp);
1748 /* Create the array for the labels. */
1749 struct prefixentry *new_labels;
1750 if (nlabellist > 0)
1752 if (!labellist_nullbits)
1753 ++nlabellist;
1754 new_labels = malloc (nlabellist * sizeof (*new_labels));
1755 if (new_labels == NULL)
1756 goto no_file;
1758 int i = nlabellist;
1759 if (!labellist_nullbits)
1761 --i;
1762 memset (&new_labels[i].prefix, '\0', sizeof (struct in6_addr));
1763 new_labels[i].bits = 0;
1764 new_labels[i].val = 1;
1767 struct prefixlist *l = labellist;
1768 while (i-- > 0)
1770 new_labels[i] = l->entry;
1771 l = l->next;
1773 free_prefixlist (labellist);
1775 /* Sort the entries so that the most specific ones are at
1776 the beginning. */
1777 qsort (new_labels, nlabellist, sizeof (*new_labels), prefixcmp);
1779 else
1780 new_labels = (struct prefixentry *) default_labels;
1782 struct prefixentry *new_precedence;
1783 if (nprecedencelist > 0)
1785 if (!precedencelist_nullbits)
1786 ++nprecedencelist;
1787 new_precedence = malloc (nprecedencelist * sizeof (*new_precedence));
1788 if (new_precedence == NULL)
1790 if (new_labels != default_labels)
1791 free (new_labels);
1792 goto no_file;
1795 int i = nprecedencelist;
1796 if (!precedencelist_nullbits)
1798 --i;
1799 memset (&new_precedence[i].prefix, '\0',
1800 sizeof (struct in6_addr));
1801 new_precedence[i].bits = 0;
1802 new_precedence[i].val = 40;
1805 struct prefixlist *l = precedencelist;
1806 while (i-- > 0)
1808 new_precedence[i] = l->entry;
1809 l = l->next;
1811 free_prefixlist (precedencelist);
1813 /* Sort the entries so that the most specific ones are at
1814 the beginning. */
1815 qsort (new_precedence, nprecedencelist, sizeof (*new_labels),
1816 prefixcmp);
1818 else
1819 new_precedence = (struct prefixentry *) default_precedence;
1821 /* Now we are ready to replace the values. */
1822 const struct prefixentry *old = labels;
1823 labels = new_labels;
1824 if (old != default_labels)
1825 free ((void *) old);
1827 old = precedence;
1828 precedence = new_precedence;
1829 if (old != default_precedence)
1830 free ((void *) old);
1832 gaiconf_mtime = st.st_mtim;
1834 else
1836 no_file:
1837 free_prefixlist (labellist);
1838 free_prefixlist (precedencelist);
1840 /* If we previously read the file but it is gone now, free the
1841 old data and use the builtin one. Leave the reload flag
1842 alone. */
1843 fini ();
1848 static void
1849 gaiconf_reload (void)
1851 struct stat64 st;
1852 if (__xstat64 (_STAT_VER, GAICONF_FNAME, &st) != 0
1853 || memcmp (&st.st_mtim, &gaiconf_mtime, sizeof (gaiconf_mtime)) != 0)
1854 gaiconf_init ();
1859 getaddrinfo (const char *name, const char *service,
1860 const struct addrinfo *hints, struct addrinfo **pai)
1862 int i = 0, last_i = 0;
1863 int nresults = 0;
1864 struct addrinfo *p = NULL;
1865 struct gaih_service gaih_service, *pservice;
1866 struct addrinfo local_hints;
1868 if (name != NULL && name[0] == '*' && name[1] == 0)
1869 name = NULL;
1871 if (service != NULL && service[0] == '*' && service[1] == 0)
1872 service = NULL;
1874 if (name == NULL && service == NULL)
1875 return EAI_NONAME;
1877 if (hints == NULL)
1878 hints = &default_hints;
1880 if (hints->ai_flags
1881 & ~(AI_PASSIVE|AI_CANONNAME|AI_NUMERICHOST|AI_ADDRCONFIG|AI_V4MAPPED
1882 #ifdef HAVE_LIBIDN
1883 |AI_IDN|AI_CANONIDN|AI_IDN_ALLOW_UNASSIGNED
1884 |AI_IDN_USE_STD3_ASCII_RULES
1885 #endif
1886 |AI_NUMERICSERV|AI_ALL))
1887 return EAI_BADFLAGS;
1889 if ((hints->ai_flags & AI_CANONNAME) && name == NULL)
1890 return EAI_BADFLAGS;
1892 struct in6addrinfo *in6ai = NULL;
1893 size_t in6ailen;
1894 bool seen_ipv4 = false;
1895 bool seen_ipv6 = false;
1896 /* We might need information about what kind of interfaces are available.
1897 But even if AI_ADDRCONFIG is not used, if the user requested IPv6
1898 addresses we have to know whether an address is deprecated or
1899 temporary. */
1900 if ((hints->ai_flags & AI_ADDRCONFIG) || hints->ai_family == PF_UNSPEC
1901 || hints->ai_family == PF_INET6)
1902 /* Determine whether we have IPv4 or IPv6 interfaces or both. We
1903 cannot cache the results since new interfaces could be added at
1904 any time. */
1905 __check_pf (&seen_ipv4, &seen_ipv6, &in6ai, &in6ailen);
1907 if (hints->ai_flags & AI_ADDRCONFIG)
1909 /* Now make a decision on what we return, if anything. */
1910 if (hints->ai_family == PF_UNSPEC && (seen_ipv4 || seen_ipv6))
1912 /* If we haven't seen both IPv4 and IPv6 interfaces we can
1913 narrow down the search. */
1914 if (! seen_ipv4 || ! seen_ipv6)
1916 local_hints = *hints;
1917 local_hints.ai_family = seen_ipv4 ? PF_INET : PF_INET6;
1918 hints = &local_hints;
1921 else if ((hints->ai_family == PF_INET && ! seen_ipv4)
1922 || (hints->ai_family == PF_INET6 && ! seen_ipv6))
1924 /* We cannot possibly return a valid answer. */
1925 free (in6ai);
1926 return EAI_NONAME;
1930 if (service && service[0])
1932 char *c;
1933 gaih_service.name = service;
1934 gaih_service.num = strtoul (gaih_service.name, &c, 10);
1935 if (*c != '\0')
1937 if (hints->ai_flags & AI_NUMERICSERV)
1939 free (in6ai);
1940 return EAI_NONAME;
1943 gaih_service.num = -1;
1946 pservice = &gaih_service;
1948 else
1949 pservice = NULL;
1951 struct addrinfo **end;
1952 if (pai)
1953 end = &p;
1954 else
1955 end = NULL;
1957 unsigned int naddrs = 0;
1958 #if 0
1959 /* If we would support more protocols than just IPv4 and IPv6 we
1960 would iterate over a table with appropriate callback functions.
1961 Since we currently only handle IPv4 and IPv6 this is not
1962 necessary. */
1963 const struct gaih *g = gaih;
1964 const struct gaih *pg = NULL;
1965 int j = 0;
1966 while (g->gaih)
1968 if (hints->ai_family == g->family || hints->ai_family == AF_UNSPEC)
1970 j++;
1971 if (pg == NULL || pg->gaih != g->gaih)
1973 pg = g;
1974 i = g->gaih (name, pservice, hints, end, &naddrs);
1975 if (i != 0)
1977 /* EAI_NODATA is a more specific result as it says that
1978 we found a result but it is not usable. */
1979 if (last_i != (GAIH_OKIFUNSPEC | -EAI_NODATA))
1980 last_i = i;
1982 if (hints->ai_family == AF_UNSPEC && (i & GAIH_OKIFUNSPEC))
1984 ++g;
1985 continue;
1988 freeaddrinfo (p);
1989 free (in6ai);
1991 return -(i & GAIH_EAI);
1993 if (end)
1994 while (*end)
1996 end = &((*end)->ai_next);
1997 ++nresults;
2001 ++g;
2004 if (j == 0)
2006 free (in6ai);
2007 return EAI_FAMILY;
2009 #else
2010 if (hints->ai_family == AF_UNSPEC || hints->ai_family == AF_INET
2011 || hints->ai_family == AF_INET6)
2013 last_i = gaih_inet (name, pservice, hints, end, &naddrs);
2014 if (last_i != 0)
2016 freeaddrinfo (p);
2017 free (in6ai);
2019 return -(last_i & GAIH_EAI);
2021 if (end)
2022 while (*end)
2024 end = &((*end)->ai_next);
2025 ++nresults;
2028 else
2030 free (in6ai);
2031 return EAI_FAMILY;
2033 #endif
2035 if (naddrs > 1)
2037 /* Read the config file. */
2038 __libc_once_define (static, once);
2039 __typeof (once) old_once = once;
2040 __libc_once (once, gaiconf_init);
2041 if (old_once && gaiconf_reload_flag)
2042 gaiconf_reload ();
2044 /* Sort results according to RFC 3484. */
2045 struct sort_result results[nresults];
2046 struct addrinfo *q;
2047 struct addrinfo *last = NULL;
2048 char *canonname = NULL;
2050 /* If we have information about deprecated and temporary address
2051 sort the array now. */
2052 if (in6ai != NULL)
2053 qsort (in6ai, in6ailen, sizeof (*in6ai), in6aicmp);
2055 for (i = 0, q = p; q != NULL; ++i, last = q, q = q->ai_next)
2057 results[i].dest_addr = q;
2058 results[i].got_source_addr = false;
2060 /* If we just looked up the address for a different
2061 protocol, reuse the result. */
2062 if (last != NULL && last->ai_addrlen == q->ai_addrlen
2063 && memcmp (last->ai_addr, q->ai_addr, q->ai_addrlen) == 0)
2065 memcpy (&results[i].source_addr, &results[i - 1].source_addr,
2066 results[i - 1].source_addr_len);
2067 results[i].source_addr_len = results[i - 1].source_addr_len;
2068 results[i].got_source_addr = results[i - 1].got_source_addr;
2069 results[i].source_addr_flags = results[i - 1].source_addr_flags;
2071 else
2073 results[i].source_addr_flags = 0;
2075 /* We overwrite the type with SOCK_DGRAM since we do not
2076 want connect() to connect to the other side. If we
2077 cannot determine the source address remember this
2078 fact. */
2079 int fd = __socket (q->ai_family, SOCK_DGRAM, IPPROTO_IP);
2080 socklen_t sl = sizeof (results[i].source_addr);
2081 if (fd != -1
2082 && __connect (fd, q->ai_addr, q->ai_addrlen) == 0
2083 && __getsockname (fd,
2084 (struct sockaddr *) &results[i].source_addr,
2085 &sl) == 0)
2087 results[i].source_addr_len = sl;
2088 results[i].got_source_addr = true;
2090 if (q->ai_family == PF_INET6 && in6ai != NULL)
2092 /* See whether the address is the list of deprecated
2093 or temporary addresses. */
2094 struct in6addrinfo tmp;
2095 memcpy (tmp.addr, q->ai_addr, IN6ADDRSZ);
2097 struct in6addrinfo *found
2098 = bsearch (&tmp, in6ai, in6ailen, sizeof (*in6ai),
2099 in6aicmp);
2100 if (found != NULL)
2101 results[i].source_addr_flags = found->flags;
2104 else
2105 /* Just make sure that if we have to process the same
2106 address again we do not copy any memory. */
2107 results[i].source_addr_len = 0;
2109 if (fd != -1)
2110 close_not_cancel_no_status (fd);
2113 /* Remember the canonical name. */
2114 if (q->ai_canonname != NULL)
2116 assert (canonname == NULL);
2117 canonname = q->ai_canonname;
2118 q->ai_canonname = NULL;
2122 /* We got all the source addresses we can get, now sort using
2123 the information. */
2124 qsort (results, nresults, sizeof (results[0]), rfc3484_sort);
2126 /* Queue the results up as they come out of sorting. */
2127 q = p = results[0].dest_addr;
2128 for (i = 1; i < nresults; ++i)
2129 q = q->ai_next = results[i].dest_addr;
2130 q->ai_next = NULL;
2132 /* Fill in the canonical name into the new first entry. */
2133 p->ai_canonname = canonname;
2136 free (in6ai);
2138 if (p)
2140 *pai = p;
2141 return 0;
2144 if (pai == NULL && last_i == 0)
2145 return 0;
2147 return last_i ? -(last_i & GAIH_EAI) : EAI_NONAME;
2149 libc_hidden_def (getaddrinfo)
2151 static_link_warning (getaddrinfo)
2153 void
2154 freeaddrinfo (struct addrinfo *ai)
2156 struct addrinfo *p;
2158 while (ai != NULL)
2160 p = ai;
2161 ai = ai->ai_next;
2162 free (p->ai_canonname);
2163 free (p);
2166 libc_hidden_def (freeaddrinfo)