Extra files to distribute in sysdeps/posix.
[glibc/history.git] / sysdeps / posix / getaddrinfo.c
blob46c66a8f7eeb36e6ac8b5bc403db571ab571f6e7
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 <errno.h>
40 #include <ifaddrs.h>
41 #include <netdb.h>
42 #include <resolv.h>
43 #include <stdbool.h>
44 #include <stdio.h>
45 #include <stdlib.h>
46 #include <string.h>
47 #include <unistd.h>
48 #include <arpa/inet.h>
49 #include <sys/socket.h>
50 #include <netinet/in.h>
51 #include <sys/types.h>
52 #include <sys/un.h>
53 #include <sys/utsname.h>
54 #include <net/if.h>
55 #include <nsswitch.h>
56 #include <not-cancel.h>
57 #include <nscd/nscd-client.h>
58 #include <nscd/nscd_proto.h>
60 #ifdef HAVE_LIBIDN
61 extern int __idna_to_ascii_lz (const char *input, char **output, int flags);
62 extern int __idna_to_unicode_lzlz (const char *input, char **output,
63 int flags);
64 # include <libidn/idna.h>
65 #endif
67 #define GAIH_OKIFUNSPEC 0x0100
68 #define GAIH_EAI ~(GAIH_OKIFUNSPEC)
70 #ifndef UNIX_PATH_MAX
71 #define UNIX_PATH_MAX 108
72 #endif
74 struct gaih_service
76 const char *name;
77 int num;
80 struct gaih_servtuple
82 struct gaih_servtuple *next;
83 int socktype;
84 int protocol;
85 int port;
88 static const struct gaih_servtuple nullserv;
90 struct gaih_addrtuple
92 struct gaih_addrtuple *next;
93 char *name;
94 int family;
95 uint32_t addr[4];
96 uint32_t scopeid;
99 struct gaih_typeproto
101 int socktype;
102 int protocol;
103 char name[4];
104 int protoflag;
107 /* Values for `protoflag'. */
108 #define GAI_PROTO_NOSERVICE 1
109 #define GAI_PROTO_PROTOANY 2
111 static const struct gaih_typeproto gaih_inet_typeproto[] =
113 { 0, 0, "", 0 },
114 { SOCK_STREAM, IPPROTO_TCP, "tcp", 0 },
115 { SOCK_DGRAM, IPPROTO_UDP, "udp", 0 },
116 { SOCK_RAW, 0, "raw", GAI_PROTO_PROTOANY|GAI_PROTO_NOSERVICE },
117 { 0, 0, "", 0 }
120 struct gaih
122 int family;
123 int (*gaih)(const char *name, const struct gaih_service *service,
124 const struct addrinfo *req, struct addrinfo **pai,
125 unsigned int *naddrs);
128 static const struct addrinfo default_hints =
130 .ai_flags = AI_DEFAULT,
131 .ai_family = PF_UNSPEC,
132 .ai_socktype = 0,
133 .ai_protocol = 0,
134 .ai_addrlen = 0,
135 .ai_addr = NULL,
136 .ai_canonname = NULL,
137 .ai_next = NULL
141 #if 0
142 /* Using Unix sockets this way is a security risk. */
143 static int
144 gaih_local (const char *name, const struct gaih_service *service,
145 const struct addrinfo *req, struct addrinfo **pai)
147 struct utsname utsname;
149 if ((name != NULL) && (req->ai_flags & AI_NUMERICHOST))
150 return GAIH_OKIFUNSPEC | -EAI_NONAME;
152 if ((name != NULL) || (req->ai_flags & AI_CANONNAME))
153 if (uname (&utsname) < 0)
154 return -EAI_SYSTEM;
156 if (name != NULL)
158 if (strcmp(name, "localhost") &&
159 strcmp(name, "local") &&
160 strcmp(name, "unix") &&
161 strcmp(name, utsname.nodename))
162 return GAIH_OKIFUNSPEC | -EAI_NONAME;
165 if (req->ai_protocol || req->ai_socktype)
167 const struct gaih_typeproto *tp = gaih_inet_typeproto + 1;
169 while (tp->name[0]
170 && ((tp->protoflag & GAI_PROTO_NOSERVICE) != 0
171 || (req->ai_socktype != 0 && req->ai_socktype != tp->socktype)
172 || (req->ai_protocol != 0
173 && !(tp->protoflag & GAI_PROTO_PROTOANY)
174 && req->ai_protocol != tp->protocol)))
175 ++tp;
177 if (! tp->name[0])
179 if (req->ai_socktype)
180 return (GAIH_OKIFUNSPEC | -EAI_SOCKTYPE);
181 else
182 return (GAIH_OKIFUNSPEC | -EAI_SERVICE);
186 *pai = malloc (sizeof (struct addrinfo) + sizeof (struct sockaddr_un)
187 + ((req->ai_flags & AI_CANONNAME)
188 ? (strlen(utsname.nodename) + 1): 0));
189 if (*pai == NULL)
190 return -EAI_MEMORY;
192 (*pai)->ai_next = NULL;
193 (*pai)->ai_flags = req->ai_flags;
194 (*pai)->ai_family = AF_LOCAL;
195 (*pai)->ai_socktype = req->ai_socktype ? req->ai_socktype : SOCK_STREAM;
196 (*pai)->ai_protocol = req->ai_protocol;
197 (*pai)->ai_addrlen = sizeof (struct sockaddr_un);
198 (*pai)->ai_addr = (void *) (*pai) + sizeof (struct addrinfo);
200 #ifdef _HAVE_SA_LEN
201 ((struct sockaddr_un *) (*pai)->ai_addr)->sun_len =
202 sizeof (struct sockaddr_un);
203 #endif /* _HAVE_SA_LEN */
205 ((struct sockaddr_un *)(*pai)->ai_addr)->sun_family = AF_LOCAL;
206 memset(((struct sockaddr_un *)(*pai)->ai_addr)->sun_path, 0, UNIX_PATH_MAX);
208 if (service)
210 struct sockaddr_un *sunp = (struct sockaddr_un *) (*pai)->ai_addr;
212 if (strchr (service->name, '/') != NULL)
214 if (strlen (service->name) >= sizeof (sunp->sun_path))
215 return GAIH_OKIFUNSPEC | -EAI_SERVICE;
217 strcpy (sunp->sun_path, service->name);
219 else
221 if (strlen (P_tmpdir "/") + 1 + strlen (service->name) >=
222 sizeof (sunp->sun_path))
223 return GAIH_OKIFUNSPEC | -EAI_SERVICE;
225 __stpcpy (__stpcpy (sunp->sun_path, P_tmpdir "/"), service->name);
228 else
230 /* This is a dangerous use of the interface since there is a time
231 window between the test for the file and the actual creation
232 (done by the caller) in which a file with the same name could
233 be created. */
234 char *buf = ((struct sockaddr_un *) (*pai)->ai_addr)->sun_path;
236 if (__builtin_expect (__path_search (buf, L_tmpnam, NULL, NULL, 0),
237 0) != 0
238 || __builtin_expect (__gen_tempname (buf, __GT_NOCREATE), 0) != 0)
239 return -EAI_SYSTEM;
242 if (req->ai_flags & AI_CANONNAME)
243 (*pai)->ai_canonname = strcpy ((char *) *pai + sizeof (struct addrinfo)
244 + sizeof (struct sockaddr_un),
245 utsname.nodename);
246 else
247 (*pai)->ai_canonname = NULL;
248 return 0;
250 #endif /* 0 */
252 static int
253 gaih_inet_serv (const char *servicename, const struct gaih_typeproto *tp,
254 const struct addrinfo *req, struct gaih_servtuple *st)
256 struct servent *s;
257 size_t tmpbuflen = 1024;
258 struct servent ts;
259 char *tmpbuf;
260 int r;
264 tmpbuf = __alloca (tmpbuflen);
266 r = __getservbyname_r (servicename, tp->name, &ts, tmpbuf, tmpbuflen,
267 &s);
268 if (r != 0 || s == NULL)
270 if (r == ERANGE)
271 tmpbuflen *= 2;
272 else
273 return GAIH_OKIFUNSPEC | -EAI_SERVICE;
276 while (r);
278 st->next = NULL;
279 st->socktype = tp->socktype;
280 st->protocol = ((tp->protoflag & GAI_PROTO_PROTOANY)
281 ? req->ai_protocol : tp->protocol);
282 st->port = s->s_port;
284 return 0;
287 #define gethosts(_family, _type) \
289 int i; \
290 int herrno; \
291 struct hostent th; \
292 struct hostent *h; \
293 char *localcanon = NULL; \
294 no_data = 0; \
295 while (1) { \
296 rc = 0; \
297 status = DL_CALL_FCT (fct, (name, _family, &th, tmpbuf, tmpbuflen, \
298 &rc, &herrno, NULL, &localcanon)); \
299 if (rc != ERANGE || herrno != NETDB_INTERNAL) \
300 break; \
301 tmpbuf = extend_alloca (tmpbuf, tmpbuflen, 2 * tmpbuflen); \
303 if (status == NSS_STATUS_SUCCESS && rc == 0) \
304 h = &th; \
305 else \
306 h = NULL; \
307 if (rc != 0) \
309 if (herrno == NETDB_INTERNAL) \
311 __set_h_errno (herrno); \
312 return -EAI_SYSTEM; \
314 if (herrno == TRY_AGAIN) \
315 no_data = EAI_AGAIN; \
316 else \
317 no_data = herrno == NO_DATA; \
319 else if (h != NULL) \
321 for (i = 0; h->h_addr_list[i]; i++) \
323 if (*pat == NULL) \
325 *pat = __alloca (sizeof (struct gaih_addrtuple)); \
326 (*pat)->scopeid = 0; \
328 uint32_t *addr = (*pat)->addr; \
329 (*pat)->next = NULL; \
330 (*pat)->name = i == 0 ? strdupa (h->h_name) : NULL; \
331 if (_family == AF_INET && req->ai_family == AF_INET6) \
333 (*pat)->family = AF_INET6; \
334 addr[3] = *(uint32_t *) h->h_addr_list[i]; \
335 addr[2] = htonl (0xffff); \
336 addr[1] = 0; \
337 addr[0] = 0; \
339 else \
341 (*pat)->family = _family; \
342 memcpy (addr, h->h_addr_list[i], sizeof(_type)); \
344 pat = &((*pat)->next); \
347 if (localcanon != NULL && canon == NULL) \
348 canon = strdupa (localcanon); \
350 if (_family == AF_INET6 && i > 0) \
351 got_ipv6 = true; \
356 typedef enum nss_status (*nss_gethostbyname3_r)
357 (const char *name, int af, struct hostent *host,
358 char *buffer, size_t buflen, int *errnop,
359 int *h_errnop, int32_t *ttlp, char **canonp);
360 typedef enum nss_status (*nss_getcanonname_r)
361 (const char *name, char *buffer, size_t buflen, char **result,
362 int *errnop, int *h_errnop);
363 extern service_user *__nss_hosts_database attribute_hidden;
365 static int
366 gaih_inet (const char *name, const struct gaih_service *service,
367 const struct addrinfo *req, struct addrinfo **pai,
368 unsigned int *naddrs)
370 const struct gaih_typeproto *tp = gaih_inet_typeproto;
371 struct gaih_servtuple *st = (struct gaih_servtuple *) &nullserv;
372 struct gaih_addrtuple *at = NULL;
373 int rc;
374 bool got_ipv6 = false;
375 const char *canon = NULL;
376 const char *orig_name = name;
378 if (req->ai_protocol || req->ai_socktype)
380 ++tp;
382 while (tp->name[0]
383 && ((req->ai_socktype != 0 && req->ai_socktype != tp->socktype)
384 || (req->ai_protocol != 0
385 && !(tp->protoflag & GAI_PROTO_PROTOANY)
386 && req->ai_protocol != tp->protocol)))
387 ++tp;
389 if (! tp->name[0])
391 if (req->ai_socktype)
392 return (GAIH_OKIFUNSPEC | -EAI_SOCKTYPE);
393 else
394 return (GAIH_OKIFUNSPEC | -EAI_SERVICE);
398 int port = 0;
399 if (service != NULL)
401 if ((tp->protoflag & GAI_PROTO_NOSERVICE) != 0)
402 return (GAIH_OKIFUNSPEC | -EAI_SERVICE);
404 if (service->num < 0)
406 if (tp->name[0])
408 st = (struct gaih_servtuple *)
409 __alloca (sizeof (struct gaih_servtuple));
411 if ((rc = gaih_inet_serv (service->name, tp, req, st)))
412 return rc;
414 else
416 struct gaih_servtuple **pst = &st;
417 for (tp++; tp->name[0]; tp++)
419 struct gaih_servtuple *newp;
421 if ((tp->protoflag & GAI_PROTO_NOSERVICE) != 0)
422 continue;
424 if (req->ai_socktype != 0
425 && req->ai_socktype != tp->socktype)
426 continue;
427 if (req->ai_protocol != 0
428 && !(tp->protoflag & GAI_PROTO_PROTOANY)
429 && req->ai_protocol != tp->protocol)
430 continue;
432 newp = (struct gaih_servtuple *)
433 __alloca (sizeof (struct gaih_servtuple));
435 if ((rc = gaih_inet_serv (service->name, tp, req, newp)))
437 if (rc & GAIH_OKIFUNSPEC)
438 continue;
439 return rc;
442 *pst = newp;
443 pst = &(newp->next);
445 if (st == (struct gaih_servtuple *) &nullserv)
446 return (GAIH_OKIFUNSPEC | -EAI_SERVICE);
449 else
451 port = htons (service->num);
452 goto got_port;
455 else
457 got_port:
459 if (req->ai_socktype || req->ai_protocol)
461 st = __alloca (sizeof (struct gaih_servtuple));
462 st->next = NULL;
463 st->socktype = tp->socktype;
464 st->protocol = ((tp->protoflag & GAI_PROTO_PROTOANY)
465 ? req->ai_protocol : tp->protocol);
466 st->port = port;
468 else
470 /* Neither socket type nor protocol is set. Return all socket types
471 we know about. */
472 struct gaih_servtuple **lastp = &st;
473 for (++tp; tp->name[0]; ++tp)
475 struct gaih_servtuple *newp;
477 newp = __alloca (sizeof (struct gaih_servtuple));
478 newp->next = NULL;
479 newp->socktype = tp->socktype;
480 newp->protocol = tp->protocol;
481 newp->port = port;
483 *lastp = newp;
484 lastp = &newp->next;
489 if (name != NULL)
491 at = __alloca (sizeof (struct gaih_addrtuple));
493 at->family = AF_UNSPEC;
494 at->scopeid = 0;
495 at->next = NULL;
497 #ifdef HAVE_LIBIDN
498 if (req->ai_flags & AI_IDN)
500 int idn_flags = 0;
501 if (req->ai_flags & AI_IDN_ALLOW_UNASSIGNED)
502 idn_flags |= IDNA_ALLOW_UNASSIGNED;
503 if (req->ai_flags & AI_IDN_USE_STD3_ASCII_RULES)
504 idn_flags |= IDNA_USE_STD3_ASCII_RULES;
506 char *p = NULL;
507 rc = __idna_to_ascii_lz (name, &p, idn_flags);
508 if (rc != IDNA_SUCCESS)
510 if (rc == IDNA_MALLOC_ERROR)
511 return -EAI_MEMORY;
512 if (rc == IDNA_DLOPEN_ERROR)
513 return -EAI_SYSTEM;
514 return -EAI_IDN_ENCODE;
516 /* In case the output string is the same as the input string
517 no new string has been allocated. */
518 if (p != name)
520 name = strdupa (p);
521 free (p);
524 #endif
526 if (__inet_aton (name, (struct in_addr *) at->addr) != 0)
528 if (req->ai_family == AF_UNSPEC || req->ai_family == AF_INET)
529 at->family = AF_INET;
530 else if (req->ai_family == AF_INET6 && req->ai_flags & AI_V4MAPPED)
532 at->addr[3] = at->addr[0];
533 at->addr[2] = htonl (0xffff);
534 at->addr[1] = 0;
535 at->addr[0] = 0;
536 at->family = AF_INET6;
538 else
539 return -EAI_ADDRFAMILY;
541 dupname:
542 if (req->ai_flags & AI_CANONNAME)
544 canon = strdup (name);
545 if (canon == NULL)
546 return -EAI_MEMORY;
550 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 goto dupname;
602 if (at->family == AF_UNSPEC && (req->ai_flags & AI_NUMERICHOST) == 0)
604 struct gaih_addrtuple **pat = &at;
605 int no_data = 0;
606 int no_inet6_data = 0;
607 service_user *nip = NULL;
608 enum nss_status inet6_status = NSS_STATUS_UNAVAIL;
609 enum nss_status status = NSS_STATUS_UNAVAIL;
610 int no_more;
611 int old_res_options;
613 /* If we do not have to look for IPv4 and IPv6 together, use
614 the simple, old functions. */
615 if (req->ai_family == AF_INET
616 || (req->ai_family == AF_INET6
617 && ((req->ai_flags & AI_V4MAPPED) == 0
618 || (req->ai_flags & AI_ALL) == 0)))
620 int family = req->ai_family;
621 size_t tmpbuflen = 512;
622 char *tmpbuf = alloca (tmpbuflen);
623 int rc;
624 struct hostent th;
625 struct hostent *h;
626 int herrno;
628 simple_again:
629 while (1)
631 rc = __gethostbyname2_r (name, family, &th, tmpbuf,
632 tmpbuflen, &h, &herrno);
633 if (rc != ERANGE || herrno != NETDB_INTERNAL)
634 break;
635 tmpbuf = extend_alloca (tmpbuf, tmpbuflen, 2 * tmpbuflen);
638 if (rc == 0)
640 if (h == NULL)
642 if (req->ai_family == AF_INET6
643 && (req->ai_flags & AI_V4MAPPED)
644 && family == AF_INET6)
646 /* Try again, this time looking for IPv4
647 addresses. */
648 family = AF_INET;
649 goto simple_again;
652 else
654 /* We found data, now convert it into the list. */
655 for (int i = 0; h->h_addr_list[i]; ++i)
657 if (*pat == NULL)
659 *pat = __alloca (sizeof (struct gaih_addrtuple));
660 (*pat)->scopeid = 0;
662 (*pat)->next = NULL;
663 (*pat)->family = req->ai_family;
664 if (family == req->ai_family)
665 memcpy ((*pat)->addr, h->h_addr_list[i],
666 h->h_length);
667 else
669 uint32_t *addr = (uint32_t *) (*pat)->addr;
670 addr[3] = *(uint32_t *) h->h_addr_list[i];
671 addr[2] = htonl (0xffff);
672 addr[1] = 0;
673 addr[0] = 0;
675 pat = &((*pat)->next);
679 else
681 if (herrno == NETDB_INTERNAL)
683 __set_h_errno (herrno);
684 return -EAI_SYSTEM;
686 if (herrno == TRY_AGAIN)
688 return -EAI_AGAIN;
690 /* We made requests but they turned out no data.
691 The name is known, though. */
692 return (GAIH_OKIFUNSPEC | -EAI_NODATA);
695 goto process_list;
698 #ifdef USE_NSCD
699 if (__nss_not_use_nscd_hosts > 0
700 && ++__nss_not_use_nscd_hosts > NSS_NSCD_RETRY)
701 __nss_not_use_nscd_hosts = 0;
703 if (!__nss_not_use_nscd_hosts)
705 /* Try to use nscd. */
706 struct nscd_ai_result *air = NULL;
707 int herrno;
708 int err = __nscd_getai (name, &air, &herrno);
709 if (air != NULL)
711 /* Transform into gaih_addrtuple list. */
712 bool added_canon = (req->ai_flags & AI_CANONNAME) == 0;
713 char *addrs = air->addrs;
715 for (int i = 0; i < air->naddrs; ++i)
717 socklen_t size = (air->family[i] == AF_INET
718 ? INADDRSZ : IN6ADDRSZ);
719 if (*pat == NULL)
721 *pat = __alloca (sizeof (struct gaih_addrtuple));
722 (*pat)->scopeid = 0;
724 uint32_t *pataddr = (*pat)->addr;
725 (*pat)->next = NULL;
726 if (added_canon || air->canon == NULL)
727 (*pat)->name = NULL;
728 else
729 canon = (*pat)->name = strdupa (air->canon);
731 if (air->family[i] == AF_INET
732 && req->ai_family == AF_INET6
733 && (req->ai_flags & AI_V4MAPPED))
735 (*pat)->family = AF_INET6;
736 pataddr[3] = *(uint32_t *) addrs;
737 pataddr[2] = htonl (0xffff);
738 pataddr[1] = 0;
739 pataddr[0] = 0;
740 pat = &((*pat)->next);
741 added_canon = true;
743 else if (req->ai_family == AF_UNSPEC
744 || air->family[i] == req->ai_family)
746 (*pat)->family = air->family[i];
747 memcpy (pataddr, addrs, size);
748 pat = &((*pat)->next);
749 added_canon = true;
750 if (air->family[i] == AF_INET6)
751 got_ipv6 = true;
753 addrs += size;
756 free (air);
758 if (at->family == AF_UNSPEC)
759 return (GAIH_OKIFUNSPEC | -EAI_NONAME);
761 goto process_list;
763 else if (err != 0 && __nss_not_use_nscd_hosts == 0)
765 if (herrno == NETDB_INTERNAL && errno == ENOMEM)
766 return -EAI_MEMORY;
767 if (herrno == TRY_AGAIN)
768 return -EAI_AGAIN;
769 return -EAI_SYSTEM;
772 #endif
774 if (__nss_hosts_database != NULL)
776 no_more = 0;
777 nip = __nss_hosts_database;
779 else
780 no_more = __nss_database_lookup ("hosts", NULL,
781 "dns [!UNAVAIL=return] files",
782 &nip);
784 if (__res_maybe_init (&_res, 0) == -1)
785 no_more = 1;
787 /* If we are looking for both IPv4 and IPv6 address we don't
788 want the lookup functions to automatically promote IPv4
789 addresses to IPv6 addresses. Currently this is decided
790 by setting the RES_USE_INET6 bit in _res.options. */
791 old_res_options = _res.options;
792 _res.options &= ~RES_USE_INET6;
794 size_t tmpbuflen = 512;
795 char *tmpbuf = alloca (tmpbuflen);
797 while (!no_more)
799 nss_gethostbyname3_r fct = NULL;
800 if (req->ai_flags & AI_CANONNAME)
801 /* No need to use this function if we do not look for
802 the canonical name. The function does not exist in
803 all NSS modules and therefore the lookup would
804 often fail. */
805 fct = __nss_lookup_function (nip, "gethostbyname3_r");
806 if (fct == NULL)
807 /* We are cheating here. The gethostbyname2_r function does
808 not have the same interface as gethostbyname3_r but the
809 extra arguments the latter takes are added at the end.
810 So the gethostbyname2_r code will just ignore them. */
811 fct = __nss_lookup_function (nip, "gethostbyname2_r");
813 if (fct != NULL)
815 if (req->ai_family == AF_INET6
816 || req->ai_family == AF_UNSPEC)
818 gethosts (AF_INET6, struct in6_addr);
819 no_inet6_data = no_data;
820 inet6_status = status;
822 if (req->ai_family == AF_INET
823 || req->ai_family == AF_UNSPEC
824 || (req->ai_family == AF_INET6
825 && (req->ai_flags & AI_V4MAPPED)
826 /* Avoid generating the mapped addresses if we
827 know we are not going to need them. */
828 && ((req->ai_flags & AI_ALL) || !got_ipv6)))
830 gethosts (AF_INET, struct in_addr);
832 if (req->ai_family == AF_INET)
834 no_inet6_data = no_data;
835 inet6_status = status;
839 /* If we found one address for AF_INET or AF_INET6,
840 don't continue the search. */
841 if (inet6_status == NSS_STATUS_SUCCESS
842 || status == NSS_STATUS_SUCCESS)
844 if ((req->ai_flags & AI_CANONNAME) != 0 && canon == NULL)
846 /* If we need the canonical name, get it
847 from the same service as the result. */
848 nss_getcanonname_r cfct;
849 int herrno;
851 cfct = __nss_lookup_function (nip, "getcanonname_r");
852 if (cfct != NULL)
854 const size_t max_fqdn_len = 256;
855 char *buf = alloca (max_fqdn_len);
856 char *s;
858 if (DL_CALL_FCT (cfct, (at->name ?: name, buf,
859 max_fqdn_len, &s, &rc,
860 &herrno))
861 == NSS_STATUS_SUCCESS)
862 canon = s;
863 else
864 /* Set to name now to avoid using
865 gethostbyaddr. */
866 canon = name;
870 break;
873 /* We can have different states for AF_INET and
874 AF_INET6. Try to find a useful one for both. */
875 if (inet6_status == NSS_STATUS_TRYAGAIN)
876 status = NSS_STATUS_TRYAGAIN;
877 else if (status == NSS_STATUS_UNAVAIL
878 && inet6_status != NSS_STATUS_UNAVAIL)
879 status = inet6_status;
882 if (nss_next_action (nip, status) == NSS_ACTION_RETURN)
883 break;
885 if (nip->next == NULL)
886 no_more = -1;
887 else
888 nip = nip->next;
891 _res.options = old_res_options;
893 if (no_data != 0 && no_inet6_data != 0)
895 /* If both requests timed out report this. */
896 if (no_data == EAI_AGAIN && no_inet6_data == EAI_AGAIN)
897 return -EAI_AGAIN;
899 /* We made requests but they turned out no data. The name
900 is known, though. */
901 return (GAIH_OKIFUNSPEC | -EAI_NODATA);
905 process_list:
906 if (at->family == AF_UNSPEC)
907 return (GAIH_OKIFUNSPEC | -EAI_NONAME);
909 else
911 struct gaih_addrtuple *atr;
912 atr = at = __alloca (sizeof (struct gaih_addrtuple));
913 memset (at, '\0', sizeof (struct gaih_addrtuple));
915 if (req->ai_family == AF_UNSPEC)
917 at->next = __alloca (sizeof (struct gaih_addrtuple));
918 memset (at->next, '\0', sizeof (struct gaih_addrtuple));
921 if (req->ai_family == AF_UNSPEC || req->ai_family == AF_INET6)
923 at->family = AF_INET6;
924 if ((req->ai_flags & AI_PASSIVE) == 0)
925 memcpy (at->addr, &in6addr_loopback, sizeof (struct in6_addr));
926 atr = at->next;
929 if (req->ai_family == AF_UNSPEC || req->ai_family == AF_INET)
931 atr->family = AF_INET;
932 if ((req->ai_flags & AI_PASSIVE) == 0)
933 atr->addr[0] = htonl (INADDR_LOOPBACK);
937 if (pai == NULL)
938 return 0;
941 struct gaih_servtuple *st2;
942 struct gaih_addrtuple *at2 = at;
943 size_t socklen;
944 sa_family_t family;
947 buffer is the size of an unformatted IPv6 address in printable format.
949 while (at2 != NULL)
951 /* Only the first entry gets the canonical name. */
952 if (at2 == at && (req->ai_flags & AI_CANONNAME) != 0)
954 if (canon == NULL)
956 struct hostent *h = NULL;
957 int herrno;
958 struct hostent th;
959 size_t tmpbuflen = 512;
960 char *tmpbuf = NULL;
964 tmpbuf = extend_alloca (tmpbuf, tmpbuflen, tmpbuflen * 2);
965 rc = __gethostbyaddr_r (at2->addr,
966 ((at2->family == AF_INET6)
967 ? sizeof (struct in6_addr)
968 : sizeof (struct in_addr)),
969 at2->family, &th, tmpbuf,
970 tmpbuflen, &h, &herrno);
972 while (rc == ERANGE && herrno == NETDB_INTERNAL);
974 if (rc != 0 && herrno == NETDB_INTERNAL)
976 __set_h_errno (herrno);
977 return -EAI_SYSTEM;
980 if (h != NULL)
981 canon = h->h_name;
982 else
984 assert (orig_name != NULL);
985 /* If the canonical name cannot be determined, use
986 the passed in string. */
987 canon = orig_name;
991 #ifdef HAVE_LIBIDN
992 if (req->ai_flags & AI_CANONIDN)
994 int idn_flags = 0;
995 if (req->ai_flags & AI_IDN_ALLOW_UNASSIGNED)
996 idn_flags |= IDNA_ALLOW_UNASSIGNED;
997 if (req->ai_flags & AI_IDN_USE_STD3_ASCII_RULES)
998 idn_flags |= IDNA_USE_STD3_ASCII_RULES;
1000 char *out;
1001 int rc = __idna_to_unicode_lzlz (canon, &out, idn_flags);
1002 if (rc != IDNA_SUCCESS)
1004 if (rc == IDNA_MALLOC_ERROR)
1005 return -EAI_MEMORY;
1006 if (rc == IDNA_DLOPEN_ERROR)
1007 return -EAI_SYSTEM;
1008 return -EAI_IDN_ENCODE;
1010 /* In case the output string is the same as the input
1011 string no new string has been allocated. Otherwise
1012 make a copy. */
1013 if (out == canon)
1014 goto make_copy;
1016 else
1017 #endif
1019 #ifdef HAVE_LIBIDN
1020 make_copy:
1021 #endif
1022 canon = strdup (canon);
1023 if (canon == NULL)
1024 return -EAI_MEMORY;
1028 family = at2->family;
1029 if (family == AF_INET6)
1031 socklen = sizeof (struct sockaddr_in6);
1033 /* If we looked up IPv4 mapped address discard them here if
1034 the caller isn't interested in all address and we have
1035 found at least one IPv6 address. */
1036 if (got_ipv6
1037 && (req->ai_flags & (AI_V4MAPPED|AI_ALL)) == AI_V4MAPPED
1038 && IN6_IS_ADDR_V4MAPPED (at2->addr))
1039 goto ignore;
1041 else
1042 socklen = sizeof (struct sockaddr_in);
1044 for (st2 = st; st2 != NULL; st2 = st2->next)
1046 struct addrinfo *ai;
1047 ai = *pai = malloc (sizeof (struct addrinfo) + socklen);
1048 if (ai == NULL)
1049 return -EAI_MEMORY;
1051 ai->ai_flags = req->ai_flags;
1052 ai->ai_family = family;
1053 ai->ai_socktype = st2->socktype;
1054 ai->ai_protocol = st2->protocol;
1055 ai->ai_addrlen = socklen;
1056 ai->ai_addr = (void *) (ai + 1);
1058 /* We only add the canonical name once. */
1059 ai->ai_canonname = (char *) canon;
1060 canon = NULL;
1062 #ifdef _HAVE_SA_LEN
1063 ai->ai_addr->sa_len = socklen;
1064 #endif /* _HAVE_SA_LEN */
1065 ai->ai_addr->sa_family = family;
1067 if (family == AF_INET6)
1069 struct sockaddr_in6 *sin6p =
1070 (struct sockaddr_in6 *) ai->ai_addr;
1072 sin6p->sin6_port = st2->port;
1073 sin6p->sin6_flowinfo = 0;
1074 memcpy (&sin6p->sin6_addr,
1075 at2->addr, sizeof (struct in6_addr));
1076 sin6p->sin6_scope_id = at2->scopeid;
1078 else
1080 struct sockaddr_in *sinp =
1081 (struct sockaddr_in *) ai->ai_addr;
1082 sinp->sin_port = st2->port;
1083 memcpy (&sinp->sin_addr,
1084 at2->addr, sizeof (struct in_addr));
1085 memset (sinp->sin_zero, '\0', sizeof (sinp->sin_zero));
1088 pai = &(ai->ai_next);
1090 *pai = NULL;
1092 ++*naddrs;
1094 ignore:
1095 at2 = at2->next;
1098 return 0;
1101 static const struct gaih gaih[] =
1103 { PF_INET6, gaih_inet },
1104 { PF_INET, gaih_inet },
1105 #if 0
1106 { PF_LOCAL, gaih_local },
1107 #endif
1108 { PF_UNSPEC, NULL }
1111 struct sort_result
1113 struct addrinfo *dest_addr;
1114 struct sockaddr_storage source_addr;
1115 uint8_t source_addr_len;
1116 bool got_source_addr;
1120 static int
1121 get_scope (const struct sockaddr_storage *ss)
1123 int scope;
1124 if (ss->ss_family == PF_INET6)
1126 const struct sockaddr_in6 *in6 = (const struct sockaddr_in6 *) ss;
1128 if (! IN6_IS_ADDR_MULTICAST (&in6->sin6_addr))
1130 if (IN6_IS_ADDR_LINKLOCAL (&in6->sin6_addr))
1131 scope = 2;
1132 else if (IN6_IS_ADDR_SITELOCAL (&in6->sin6_addr))
1133 scope = 5;
1134 else
1135 /* XXX Is this the correct default behavior? */
1136 scope = 14;
1138 else
1139 scope = in6->sin6_addr.s6_addr[1] & 0xf;
1141 else if (ss->ss_family == PF_INET)
1143 const struct sockaddr_in *in = (const struct sockaddr_in *) ss;
1144 const uint8_t *addr = (const uint8_t *) &in->sin_addr;
1146 /* RFC 3484 specifies how to map IPv6 addresses to scopes.
1147 169.254/16 and 127/8 are link-local. */
1148 if ((addr[0] == 169 && addr[1] == 254) || addr[0] == 127)
1149 scope = 2;
1150 else if (addr[0] == 10 || (addr[0] == 172 && addr[1] == 16)
1151 || (addr[0] == 192 && addr[1] == 168))
1152 scope = 5;
1153 else
1154 scope = 14;
1156 else
1157 /* XXX What is a good default? */
1158 scope = 15;
1160 return scope;
1164 /* XXX The system administrator should be able to install other
1165 tables. We need to make this configurable. The problem is that
1166 the kernel is also involved since it needs the same table. */
1167 static const struct prefixlist
1169 struct in6_addr prefix;
1170 unsigned int bits;
1171 int val;
1172 } default_labels[] =
1174 /* See RFC 3484 for the details. */
1175 { { .in6_u = { .u6_addr16 = { 0x0000, 0x0000, 0x0000, 0x0000,
1176 0x0000, 0x0000, 0x0000, 0x0001 } } },
1177 128, 0 },
1178 { { .in6_u = { .u6_addr16 = { 0x2002, 0x0000, 0x0000, 0x0000,
1179 0x0000, 0x0000, 0x0000, 0x0000 } } },
1180 16, 2 },
1181 { { .in6_u = { .u6_addr16 = { 0x0000, 0x0000, 0x0000, 0x0000,
1182 0x0000, 0x0000, 0x0000, 0x0000 } } },
1183 96, 3 },
1184 { { .in6_u = { .u6_addr16 = { 0x0000, 0x0000, 0x0000, 0x0000,
1185 0x0000, 0xffff, 0x0000, 0x0000 } } },
1186 96, 4 },
1187 { { .in6_u = { .u6_addr16 = { 0x0000, 0x0000, 0x0000, 0x0000,
1188 0x0000, 0x0000, 0x0000, 0x0000 } } },
1189 0, 1 }
1193 static const struct prefixlist default_precedence[] =
1195 /* See RFC 3484 for the details. */
1196 { { .in6_u = { .u6_addr16 = { 0x0000, 0x0000, 0x0000, 0x0000,
1197 0x0000, 0x0000, 0x0000, 0x0001 } } },
1198 128, 50 },
1199 { { .in6_u = { .u6_addr16 = { 0x2002, 0x0000, 0x0000, 0x0000,
1200 0x0000, 0x0000, 0x0000, 0x0000 } } },
1201 16, 30 },
1202 { { .in6_u = { .u6_addr16 = { 0x0000, 0x0000, 0x0000, 0x0000,
1203 0x0000, 0x0000, 0x0000, 0x0000 } } },
1204 96, 20 },
1205 { { .in6_u = { .u6_addr16 = { 0x0000, 0x0000, 0x0000, 0x0000,
1206 0x0000, 0xffff, 0x0000, 0x0000 } } },
1207 96, 10 },
1208 { { .in6_u = { .u6_addr16 = { 0x0000, 0x0000, 0x0000, 0x0000,
1209 0x0000, 0x0000, 0x0000, 0x0000 } } },
1210 0, 40 }
1214 static int
1215 match_prefix (const struct sockaddr_storage *ss, const struct prefixlist *list,
1216 int default_val)
1218 int idx;
1219 struct sockaddr_in6 in6_mem;
1220 const struct sockaddr_in6 *in6;
1222 if (ss->ss_family == PF_INET6)
1223 in6 = (const struct sockaddr_in6 *) ss;
1224 else if (ss->ss_family == PF_INET)
1226 const struct sockaddr_in *in = (const struct sockaddr_in *) ss;
1228 /* Convert to IPv6 address. */
1229 in6_mem.sin6_family = PF_INET6;
1230 in6_mem.sin6_port = in->sin_port;
1231 in6_mem.sin6_flowinfo = 0;
1232 if (in->sin_addr.s_addr == htonl (0x7f000001))
1233 in6_mem.sin6_addr = (struct in6_addr) IN6ADDR_LOOPBACK_INIT;
1234 else
1236 /* Construct a V4-to-6 mapped address. */
1237 memset (&in6_mem.sin6_addr, '\0', sizeof (in6_mem.sin6_addr));
1238 in6_mem.sin6_addr.s6_addr16[5] = 0xffff;
1239 in6_mem.sin6_addr.s6_addr32[3] = in->sin_addr.s_addr;
1240 in6_mem.sin6_scope_id = 0;
1243 in6 = &in6_mem;
1245 else
1246 return default_val;
1248 for (idx = 0; ; ++idx)
1250 unsigned int bits = list[idx].bits;
1251 uint8_t *mask = list[idx].prefix.s6_addr;
1252 uint8_t *val = in6->sin6_addr.s6_addr;
1254 while (bits >= 8)
1256 if (*mask != *val)
1257 break;
1259 ++mask;
1260 ++val;
1261 bits -= 8;
1264 if (bits < 8)
1266 if ((*mask & (0xff00 >> bits)) == (*val & (0xff00 >> bits)))
1267 /* Match! */
1268 break;
1272 return list[idx].val;
1276 static int
1277 get_label (const struct sockaddr_storage *ss)
1279 /* XXX What is a good default value? */
1280 return match_prefix (ss, default_labels, INT_MAX);
1284 static int
1285 get_precedence (const struct sockaddr_storage *ss)
1287 /* XXX What is a good default value? */
1288 return match_prefix (ss, default_precedence, 0);
1292 /* Find last bit set in a word. */
1293 static int
1294 fls (uint32_t a)
1296 uint32_t mask;
1297 int n = 0;
1298 for (n = 0, mask = 1 << 31; n < 32; mask >>= 1, ++n)
1299 if ((a & mask) != 0)
1300 break;
1301 return n;
1305 static int
1306 rfc3484_sort (const void *p1, const void *p2)
1308 const struct sort_result *a1 = (const struct sort_result *) p1;
1309 const struct sort_result *a2 = (const struct sort_result *) p2;
1311 /* Rule 1: Avoid unusable destinations.
1312 We have the got_source_addr flag set if the destination is reachable. */
1313 if (a1->got_source_addr && ! a2->got_source_addr)
1314 return -1;
1315 if (! a1->got_source_addr && a2->got_source_addr)
1316 return 1;
1319 /* Rule 2: Prefer matching scope. Only interesting if both
1320 destination addresses are IPv6. */
1321 int a1_dst_scope
1322 = get_scope ((struct sockaddr_storage *) a1->dest_addr->ai_addr);
1324 int a2_dst_scope
1325 = get_scope ((struct sockaddr_storage *) a2->dest_addr->ai_addr);
1327 if (a1->got_source_addr)
1329 int a1_src_scope = get_scope (&a1->source_addr);
1330 int a2_src_scope = get_scope (&a2->source_addr);
1332 if (a1_dst_scope == a1_src_scope && a2_dst_scope != a2_src_scope)
1333 return -1;
1334 if (a1_dst_scope != a1_src_scope && a2_dst_scope == a2_src_scope)
1335 return 1;
1339 /* Rule 3: Avoid deprecated addresses.
1340 That's something only the kernel could decide. */
1342 /* Rule 4: Prefer home addresses.
1343 Another thing only the kernel can decide. */
1345 /* Rule 5: Prefer matching label. */
1346 if (a1->got_source_addr)
1348 int a1_dst_label
1349 = get_label ((struct sockaddr_storage *) a1->dest_addr->ai_addr);
1350 int a1_src_label = get_label (&a1->source_addr);
1352 int a2_dst_label
1353 = get_label ((struct sockaddr_storage *) a2->dest_addr->ai_addr);
1354 int a2_src_label = get_label (&a2->source_addr);
1356 if (a1_dst_label == a1_src_label && a2_dst_label != a2_src_label)
1357 return -1;
1358 if (a1_dst_label != a1_src_label && a2_dst_label == a2_src_label)
1359 return 1;
1363 /* Rule 6: Prefer higher precedence. */
1364 int a1_prec
1365 = get_precedence ((struct sockaddr_storage *) a1->dest_addr->ai_addr);
1366 int a2_prec
1367 = get_precedence ((struct sockaddr_storage *) a2->dest_addr->ai_addr);
1369 if (a1_prec > a2_prec)
1370 return -1;
1371 if (a1_prec < a2_prec)
1372 return 1;
1375 /* Rule 7: Prefer native transport.
1376 XXX How to recognize tunnels? */
1379 /* Rule 8: Prefer smaller scope. */
1380 if (a1_dst_scope < a2_dst_scope)
1381 return -1;
1382 if (a1_dst_scope > a2_dst_scope)
1383 return 1;
1386 /* Rule 9: Use longest matching prefix. */
1387 if (a1->got_source_addr
1388 && a1->dest_addr->ai_family == a2->dest_addr->ai_family)
1390 int bit1 = 0;
1391 int bit2 = 0;
1393 if (a1->dest_addr->ai_family == PF_INET)
1395 assert (a1->source_addr.ss_family == PF_INET);
1396 assert (a2->source_addr.ss_family == PF_INET);
1398 struct sockaddr_in *in1_dst;
1399 struct sockaddr_in *in1_src;
1400 struct sockaddr_in *in2_dst;
1401 struct sockaddr_in *in2_src;
1403 in1_dst = (struct sockaddr_in *) a1->dest_addr->ai_addr;
1404 in1_src = (struct sockaddr_in *) &a1->source_addr;
1405 in2_dst = (struct sockaddr_in *) a2->dest_addr->ai_addr;
1406 in2_src = (struct sockaddr_in *) &a2->source_addr;
1408 bit1 = fls (ntohl (in1_dst->sin_addr.s_addr
1409 ^ in1_src->sin_addr.s_addr));
1410 bit2 = fls (ntohl (in2_dst->sin_addr.s_addr
1411 ^ in2_src->sin_addr.s_addr));
1413 else if (a1->dest_addr->ai_family == PF_INET6)
1415 assert (a1->source_addr.ss_family == PF_INET6);
1416 assert (a2->source_addr.ss_family == PF_INET6);
1418 struct sockaddr_in6 *in1_dst;
1419 struct sockaddr_in6 *in1_src;
1420 struct sockaddr_in6 *in2_dst;
1421 struct sockaddr_in6 *in2_src;
1423 in1_dst = (struct sockaddr_in6 *) a1->dest_addr->ai_addr;
1424 in1_src = (struct sockaddr_in6 *) &a1->source_addr;
1425 in2_dst = (struct sockaddr_in6 *) a2->dest_addr->ai_addr;
1426 in2_src = (struct sockaddr_in6 *) &a2->source_addr;
1428 int i;
1429 for (i = 0; i < 4; ++i)
1430 if (in1_dst->sin6_addr.s6_addr32[i]
1431 != in1_src->sin6_addr.s6_addr32[i]
1432 || (in2_dst->sin6_addr.s6_addr32[i]
1433 != in2_src->sin6_addr.s6_addr32[i]))
1434 break;
1436 if (i < 4)
1438 bit1 = fls (ntohl (in1_dst->sin6_addr.s6_addr32[i]
1439 ^ in1_src->sin6_addr.s6_addr32[i]));
1440 bit2 = fls (ntohl (in2_dst->sin6_addr.s6_addr32[i]
1441 ^ in2_src->sin6_addr.s6_addr32[i]));
1445 if (bit1 > bit2)
1446 return -1;
1447 if (bit1 < bit2)
1448 return 1;
1452 /* Rule 10: Otherwise, leave the order unchanged. */
1453 return 0;
1458 getaddrinfo (const char *name, const char *service,
1459 const struct addrinfo *hints, struct addrinfo **pai)
1461 int i = 0, j = 0, last_i = 0;
1462 int nresults = 0;
1463 struct addrinfo *p = NULL, **end;
1464 const struct gaih *g = gaih;
1465 const struct gaih *pg = NULL;
1466 struct gaih_service gaih_service, *pservice;
1467 struct addrinfo local_hints;
1469 if (name != NULL && name[0] == '*' && name[1] == 0)
1470 name = NULL;
1472 if (service != NULL && service[0] == '*' && service[1] == 0)
1473 service = NULL;
1475 if (name == NULL && service == NULL)
1476 return EAI_NONAME;
1478 if (hints == NULL)
1479 hints = &default_hints;
1481 if (hints->ai_flags
1482 & ~(AI_PASSIVE|AI_CANONNAME|AI_NUMERICHOST|AI_ADDRCONFIG|AI_V4MAPPED
1483 #ifdef HAVE_LIBIDN
1484 |AI_IDN|AI_CANONIDN|AI_IDN_ALLOW_UNASSIGNED
1485 |AI_IDN_USE_STD3_ASCII_RULES
1486 #endif
1487 |AI_NUMERICSERV|AI_ALL))
1488 return EAI_BADFLAGS;
1490 if ((hints->ai_flags & AI_CANONNAME) && name == NULL)
1491 return EAI_BADFLAGS;
1493 if (hints->ai_flags & AI_ADDRCONFIG)
1495 /* Determine whether we have IPv4 or IPv6 interfaces or both.
1496 We cannot cache the results since new interfaces could be
1497 added at any time. */
1498 bool seen_ipv4;
1499 bool seen_ipv6;
1500 __check_pf (&seen_ipv4, &seen_ipv6);
1502 /* Now make a decision on what we return, if anything. */
1503 if (hints->ai_family == PF_UNSPEC && (seen_ipv4 || seen_ipv6))
1505 /* If we haven't seen both IPv4 and IPv6 interfaces we can
1506 narrow down the search. */
1507 if (! seen_ipv4 || ! seen_ipv6)
1509 local_hints = *hints;
1510 local_hints.ai_family = seen_ipv4 ? PF_INET : PF_INET6;
1511 hints = &local_hints;
1514 else if ((hints->ai_family == PF_INET && ! seen_ipv4)
1515 || (hints->ai_family == PF_INET6 && ! seen_ipv6))
1516 /* We cannot possibly return a valid answer. */
1517 return EAI_NONAME;
1520 if (service && service[0])
1522 char *c;
1523 gaih_service.name = service;
1524 gaih_service.num = strtoul (gaih_service.name, &c, 10);
1525 if (*c != '\0')
1527 if (hints->ai_flags & AI_NUMERICSERV)
1528 return EAI_NONAME;
1530 gaih_service.num = -1;
1533 pservice = &gaih_service;
1535 else
1536 pservice = NULL;
1538 if (pai)
1539 end = &p;
1540 else
1541 end = NULL;
1543 unsigned int naddrs = 0;
1544 while (g->gaih)
1546 if (hints->ai_family == g->family || hints->ai_family == AF_UNSPEC)
1548 j++;
1549 if (pg == NULL || pg->gaih != g->gaih)
1551 pg = g;
1552 i = g->gaih (name, pservice, hints, end, &naddrs);
1553 if (i != 0)
1555 /* EAI_NODATA is a more specific result as it says that
1556 we found a result but it is not usable. */
1557 if (last_i != (GAIH_OKIFUNSPEC | -EAI_NODATA))
1558 last_i = i;
1560 if (hints->ai_family == AF_UNSPEC && (i & GAIH_OKIFUNSPEC))
1562 ++g;
1563 continue;
1566 freeaddrinfo (p);
1568 return -(i & GAIH_EAI);
1570 if (end)
1571 while (*end)
1573 end = &((*end)->ai_next);
1574 ++nresults;
1578 ++g;
1581 if (j == 0)
1582 return EAI_FAMILY;
1584 if (naddrs > 1)
1586 /* Sort results according to RFC 3484. */
1587 struct sort_result results[nresults];
1588 struct addrinfo *q;
1589 struct addrinfo *last = NULL;
1590 char *canonname = NULL;
1592 for (i = 0, q = p; q != NULL; ++i, last = q, q = q->ai_next)
1594 results[i].dest_addr = q;
1595 results[i].got_source_addr = false;
1597 /* If we just looked up the address for a different
1598 protocol, reuse the result. */
1599 if (last != NULL && last->ai_addrlen == q->ai_addrlen
1600 && memcmp (last->ai_addr, q->ai_addr, q->ai_addrlen) == 0)
1602 memcpy (&results[i].source_addr, &results[i - 1].source_addr,
1603 results[i - 1].source_addr_len);
1604 results[i].source_addr_len = results[i - 1].source_addr_len;
1605 results[i].got_source_addr = results[i - 1].got_source_addr;
1607 else
1609 /* We overwrite the type with SOCK_DGRAM since we do not
1610 want connect() to connect to the other side. If we
1611 cannot determine the source address remember this
1612 fact. */
1613 int fd = __socket (q->ai_family, SOCK_DGRAM, IPPROTO_IP);
1614 socklen_t sl = sizeof (results[i].source_addr);
1615 if (fd != -1
1616 && __connect (fd, q->ai_addr, q->ai_addrlen) == 0
1617 && __getsockname (fd,
1618 (struct sockaddr *) &results[i].source_addr,
1619 &sl) == 0)
1621 results[i].source_addr_len = sl;
1622 results[i].got_source_addr = true;
1624 else
1625 /* Just make sure that if we have to process the same
1626 address again we do not copy any memory. */
1627 results[i].source_addr_len = 0;
1629 if (fd != -1)
1630 close_not_cancel_no_status (fd);
1633 /* Remember the canonical name. */
1634 if (q->ai_canonname != NULL)
1636 assert (canonname == NULL);
1637 canonname = q->ai_canonname;
1638 q->ai_canonname = NULL;
1642 /* We got all the source addresses we can get, now sort using
1643 the information. */
1644 qsort (results, nresults, sizeof (results[0]), rfc3484_sort);
1646 /* Queue the results up as they come out of sorting. */
1647 q = p = results[0].dest_addr;
1648 for (i = 1; i < nresults; ++i)
1649 q = q->ai_next = results[i].dest_addr;
1650 q->ai_next = NULL;
1652 /* Fill in the canonical name into the new first entry. */
1653 p->ai_canonname = canonname;
1656 if (p)
1658 *pai = p;
1659 return 0;
1662 if (pai == NULL && last_i == 0)
1663 return 0;
1665 return last_i ? -(last_i & GAIH_EAI) : EAI_NONAME;
1667 libc_hidden_def (getaddrinfo)
1669 static_link_warning (getaddrinfo)
1671 void
1672 freeaddrinfo (struct addrinfo *ai)
1674 struct addrinfo *p;
1676 while (ai != NULL)
1678 p = ai;
1679 ai = ai->ai_next;
1680 free (p->ai_canonname);
1681 free (p);
1684 libc_hidden_def (freeaddrinfo)