(CFLAGS-tst-align.c): Add -mpreferred-stack-boundary=4.
[glibc.git] / sysdeps / posix / getaddrinfo.c
blobc9081345aba22f1d510fbce848903ef05c4119fe
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);
127 static const struct addrinfo default_hints =
129 .ai_flags = AI_DEFAULT,
130 .ai_family = PF_UNSPEC,
131 .ai_socktype = 0,
132 .ai_protocol = 0,
133 .ai_addrlen = 0,
134 .ai_addr = NULL,
135 .ai_canonname = NULL,
136 .ai_next = NULL
140 #if 0
141 /* Using Unix sockets this way is a security risk. */
142 static int
143 gaih_local (const char *name, const struct gaih_service *service,
144 const struct addrinfo *req, struct addrinfo **pai)
146 struct utsname utsname;
148 if ((name != NULL) && (req->ai_flags & AI_NUMERICHOST))
149 return GAIH_OKIFUNSPEC | -EAI_NONAME;
151 if ((name != NULL) || (req->ai_flags & AI_CANONNAME))
152 if (uname (&utsname) < 0)
153 return -EAI_SYSTEM;
155 if (name != NULL)
157 if (strcmp(name, "localhost") &&
158 strcmp(name, "local") &&
159 strcmp(name, "unix") &&
160 strcmp(name, utsname.nodename))
161 return GAIH_OKIFUNSPEC | -EAI_NONAME;
164 if (req->ai_protocol || req->ai_socktype)
166 const struct gaih_typeproto *tp = gaih_inet_typeproto + 1;
168 while (tp->name[0]
169 && ((tp->protoflag & GAI_PROTO_NOSERVICE) != 0
170 || (req->ai_socktype != 0 && req->ai_socktype != tp->socktype)
171 || (req->ai_protocol != 0
172 && !(tp->protoflag & GAI_PROTO_PROTOANY)
173 && req->ai_protocol != tp->protocol)))
174 ++tp;
176 if (! tp->name[0])
178 if (req->ai_socktype)
179 return (GAIH_OKIFUNSPEC | -EAI_SOCKTYPE);
180 else
181 return (GAIH_OKIFUNSPEC | -EAI_SERVICE);
185 *pai = malloc (sizeof (struct addrinfo) + sizeof (struct sockaddr_un)
186 + ((req->ai_flags & AI_CANONNAME)
187 ? (strlen(utsname.nodename) + 1): 0));
188 if (*pai == NULL)
189 return -EAI_MEMORY;
191 (*pai)->ai_next = NULL;
192 (*pai)->ai_flags = req->ai_flags;
193 (*pai)->ai_family = AF_LOCAL;
194 (*pai)->ai_socktype = req->ai_socktype ? req->ai_socktype : SOCK_STREAM;
195 (*pai)->ai_protocol = req->ai_protocol;
196 (*pai)->ai_addrlen = sizeof (struct sockaddr_un);
197 (*pai)->ai_addr = (void *) (*pai) + sizeof (struct addrinfo);
199 #if SALEN
200 ((struct sockaddr_un *) (*pai)->ai_addr)->sun_len =
201 sizeof (struct sockaddr_un);
202 #endif /* SALEN */
204 ((struct sockaddr_un *)(*pai)->ai_addr)->sun_family = AF_LOCAL;
205 memset(((struct sockaddr_un *)(*pai)->ai_addr)->sun_path, 0, UNIX_PATH_MAX);
207 if (service)
209 struct sockaddr_un *sunp = (struct sockaddr_un *) (*pai)->ai_addr;
211 if (strchr (service->name, '/') != NULL)
213 if (strlen (service->name) >= sizeof (sunp->sun_path))
214 return GAIH_OKIFUNSPEC | -EAI_SERVICE;
216 strcpy (sunp->sun_path, service->name);
218 else
220 if (strlen (P_tmpdir "/") + 1 + strlen (service->name) >=
221 sizeof (sunp->sun_path))
222 return GAIH_OKIFUNSPEC | -EAI_SERVICE;
224 __stpcpy (__stpcpy (sunp->sun_path, P_tmpdir "/"), service->name);
227 else
229 /* This is a dangerous use of the interface since there is a time
230 window between the test for the file and the actual creation
231 (done by the caller) in which a file with the same name could
232 be created. */
233 char *buf = ((struct sockaddr_un *) (*pai)->ai_addr)->sun_path;
235 if (__builtin_expect (__path_search (buf, L_tmpnam, NULL, NULL, 0),
236 0) != 0
237 || __builtin_expect (__gen_tempname (buf, __GT_NOCREATE), 0) != 0)
238 return -EAI_SYSTEM;
241 if (req->ai_flags & AI_CANONNAME)
242 (*pai)->ai_canonname = strcpy ((char *) *pai + sizeof (struct addrinfo)
243 + sizeof (struct sockaddr_un),
244 utsname.nodename);
245 else
246 (*pai)->ai_canonname = NULL;
247 return 0;
249 #endif /* 0 */
251 static int
252 gaih_inet_serv (const char *servicename, const struct gaih_typeproto *tp,
253 const struct addrinfo *req, struct gaih_servtuple *st)
255 struct servent *s;
256 size_t tmpbuflen = 1024;
257 struct servent ts;
258 char *tmpbuf;
259 int r;
263 tmpbuf = __alloca (tmpbuflen);
265 r = __getservbyname_r (servicename, tp->name, &ts, tmpbuf, tmpbuflen,
266 &s);
267 if (r != 0 || s == NULL)
269 if (r == ERANGE)
270 tmpbuflen *= 2;
271 else
272 return GAIH_OKIFUNSPEC | -EAI_SERVICE;
275 while (r);
277 st->next = NULL;
278 st->socktype = tp->socktype;
279 st->protocol = ((tp->protoflag & GAI_PROTO_PROTOANY)
280 ? req->ai_protocol : tp->protocol);
281 st->port = s->s_port;
283 return 0;
286 #define gethosts(_family, _type) \
288 int i; \
289 int herrno; \
290 struct hostent th; \
291 struct hostent *h; \
292 char *localcanon = NULL; \
293 no_data = 0; \
294 while (1) { \
295 rc = 0; \
296 status = DL_CALL_FCT (fct, (name, _family, &th, tmpbuf, tmpbuflen, \
297 &rc, &herrno, NULL, &localcanon)); \
298 if (rc != ERANGE || herrno != NETDB_INTERNAL) \
299 break; \
300 tmpbuf = extend_alloca (tmpbuf, tmpbuflen, 2 * tmpbuflen); \
302 if (status == NSS_STATUS_SUCCESS && rc == 0) \
303 h = &th; \
304 else \
305 h = NULL; \
306 if (rc != 0) \
308 if (herrno == NETDB_INTERNAL) \
310 __set_h_errno (herrno); \
311 return -EAI_SYSTEM; \
313 if (herrno == TRY_AGAIN) \
314 no_data = EAI_AGAIN; \
315 else \
316 no_data = herrno == NO_DATA; \
318 else if (h != NULL) \
320 for (i = 0; h->h_addr_list[i]; i++) \
322 if (*pat == NULL) \
324 *pat = __alloca (sizeof (struct gaih_addrtuple)); \
325 (*pat)->scopeid = 0; \
327 uint32_t *addr = (*pat)->addr; \
328 (*pat)->next = NULL; \
329 (*pat)->name = i == 0 ? strdupa (h->h_name) : NULL; \
330 if (_family == AF_INET && req->ai_family == AF_INET6) \
332 (*pat)->family = AF_INET6; \
333 addr[3] = *(uint32_t *) h->h_addr_list[i]; \
334 addr[2] = htonl (0xffff); \
335 addr[1] = 0; \
336 addr[0] = 0; \
338 else \
340 (*pat)->family = _family; \
341 memcpy (addr, h->h_addr_list[i], sizeof(_type)); \
343 pat = &((*pat)->next); \
346 if (localcanon != NULL && canon == NULL) \
347 canon = strdupa (localcanon); \
349 if (_family == AF_INET6 && i > 0) \
350 got_ipv6 = true; \
355 typedef enum nss_status (*nss_gethostbyname3_r)
356 (const char *name, int af, struct hostent *host,
357 char *buffer, size_t buflen, int *errnop,
358 int *h_errnop, int32_t *ttlp, char **canonp);
359 typedef enum nss_status (*nss_getcanonname_r)
360 (const char *name, char *buffer, size_t buflen, char **result,
361 int *errnop, int *h_errnop);
362 extern service_user *__nss_hosts_database attribute_hidden;
364 static int
365 gaih_inet (const char *name, const struct gaih_service *service,
366 const struct addrinfo *req, struct addrinfo **pai)
368 const struct gaih_typeproto *tp = gaih_inet_typeproto;
369 struct gaih_servtuple *st = (struct gaih_servtuple *) &nullserv;
370 struct gaih_addrtuple *at = NULL;
371 int rc;
372 bool got_ipv6 = false;
373 const char *canon = NULL;
374 const char *orig_name = name;
376 if (req->ai_protocol || req->ai_socktype)
378 ++tp;
380 while (tp->name[0]
381 && ((req->ai_socktype != 0 && req->ai_socktype != tp->socktype)
382 || (req->ai_protocol != 0
383 && !(tp->protoflag & GAI_PROTO_PROTOANY)
384 && req->ai_protocol != tp->protocol)))
385 ++tp;
387 if (! tp->name[0])
389 if (req->ai_socktype)
390 return (GAIH_OKIFUNSPEC | -EAI_SOCKTYPE);
391 else
392 return (GAIH_OKIFUNSPEC | -EAI_SERVICE);
396 if (service != NULL)
398 if ((tp->protoflag & GAI_PROTO_NOSERVICE) != 0)
399 return (GAIH_OKIFUNSPEC | -EAI_SERVICE);
401 if (service->num < 0)
403 if (tp->name[0])
405 st = (struct gaih_servtuple *)
406 __alloca (sizeof (struct gaih_servtuple));
408 if ((rc = gaih_inet_serv (service->name, tp, req, st)))
409 return rc;
411 else
413 struct gaih_servtuple **pst = &st;
414 for (tp++; tp->name[0]; tp++)
416 struct gaih_servtuple *newp;
418 if ((tp->protoflag & GAI_PROTO_NOSERVICE) != 0)
419 continue;
421 if (req->ai_socktype != 0
422 && req->ai_socktype != tp->socktype)
423 continue;
424 if (req->ai_protocol != 0
425 && !(tp->protoflag & GAI_PROTO_PROTOANY)
426 && req->ai_protocol != tp->protocol)
427 continue;
429 newp = (struct gaih_servtuple *)
430 __alloca (sizeof (struct gaih_servtuple));
432 if ((rc = gaih_inet_serv (service->name, tp, req, newp)))
434 if (rc & GAIH_OKIFUNSPEC)
435 continue;
436 return rc;
439 *pst = newp;
440 pst = &(newp->next);
442 if (st == (struct gaih_servtuple *) &nullserv)
443 return (GAIH_OKIFUNSPEC | -EAI_SERVICE);
446 else
448 if (req->ai_socktype || req->ai_protocol)
450 st = __alloca (sizeof (struct gaih_servtuple));
451 st->next = NULL;
452 st->socktype = tp->socktype;
453 st->protocol = ((tp->protoflag & GAI_PROTO_PROTOANY)
454 ? req->ai_protocol : tp->protocol);
455 st->port = htons (service->num);
457 else
459 /* Neither socket type nor protocol is set. Return all
460 socket types we know about. */
461 struct gaih_servtuple **lastp = &st;
462 for (tp = gaih_inet_typeproto + 1; tp->name[0]; ++tp)
463 if ((tp->protoflag & GAI_PROTO_NOSERVICE) == 0)
465 struct gaih_servtuple *newp;
467 newp = __alloca (sizeof (struct gaih_servtuple));
468 newp->next = NULL;
469 newp->socktype = tp->socktype;
470 newp->protocol = tp->protocol;
471 newp->port = htons (service->num);
473 *lastp = newp;
474 lastp = &newp->next;
479 else if (req->ai_socktype || req->ai_protocol)
481 st = __alloca (sizeof (struct gaih_servtuple));
482 st->next = NULL;
483 st->socktype = tp->socktype;
484 st->protocol = ((tp->protoflag & GAI_PROTO_PROTOANY)
485 ? req->ai_protocol : tp->protocol);
486 st->port = 0;
488 else
490 /* Neither socket type nor protocol is set. Return all socket types
491 we know about. */
492 struct gaih_servtuple **lastp = &st;
493 for (++tp; tp->name[0]; ++tp)
495 struct gaih_servtuple *newp;
497 newp = __alloca (sizeof (struct gaih_servtuple));
498 newp->next = NULL;
499 newp->socktype = tp->socktype;
500 newp->protocol = tp->protocol;
501 newp->port = 0;
503 *lastp = newp;
504 lastp = &newp->next;
508 if (name != NULL)
510 at = __alloca (sizeof (struct gaih_addrtuple));
512 at->family = AF_UNSPEC;
513 at->scopeid = 0;
514 at->next = NULL;
516 #ifdef HAVE_LIBIDN
517 if (req->ai_flags & AI_IDN)
519 int idn_flags = 0;
520 if (req->ai_flags & AI_IDN_ALLOW_UNASSIGNED)
521 idn_flags |= IDNA_ALLOW_UNASSIGNED;
522 if (req->ai_flags & AI_IDN_USE_STD3_ASCII_RULES)
523 idn_flags |= IDNA_USE_STD3_ASCII_RULES;
525 char *p = NULL;
526 rc = __idna_to_ascii_lz (name, &p, idn_flags);
527 if (rc != IDNA_SUCCESS)
529 if (rc == IDNA_MALLOC_ERROR)
530 return -EAI_MEMORY;
531 if (rc == IDNA_DLOPEN_ERROR)
532 return -EAI_SYSTEM;
533 return -EAI_IDN_ENCODE;
535 /* In case the output string is the same as the input string
536 no new string has been allocated. */
537 if (p != name)
539 name = strdupa (p);
540 free (p);
543 #endif
545 if (__inet_aton (name, (struct in_addr *) at->addr) != 0)
547 if (req->ai_family == AF_UNSPEC || req->ai_family == AF_INET)
548 at->family = AF_INET;
549 else if (req->ai_family == AF_INET6 && req->ai_flags & AI_V4MAPPED)
551 at->addr[3] = at->addr[0];
552 at->addr[2] = htonl (0xffff);
553 at->addr[1] = 0;
554 at->addr[0] = 0;
555 at->family = AF_INET6;
557 else
558 return -EAI_ADDRFAMILY;
560 dupname:
561 if (req->ai_flags & AI_CANONNAME)
563 canon = strdup (name);
564 if (canon == NULL)
565 return -EAI_MEMORY;
569 if (at->family == AF_UNSPEC)
571 char *namebuf = strdupa (name);
572 char *scope_delim;
574 scope_delim = strchr (namebuf, SCOPE_DELIMITER);
575 if (scope_delim != NULL)
576 *scope_delim = '\0';
578 if (inet_pton (AF_INET6, namebuf, at->addr) > 0)
580 if (req->ai_family == AF_UNSPEC || req->ai_family == AF_INET6)
581 at->family = AF_INET6;
582 else if (req->ai_family == AF_INET
583 && IN6_IS_ADDR_V4MAPPED (at->addr))
585 at->addr[0] = at->addr[3];
586 at->family = AF_INET;
588 else
589 return -EAI_ADDRFAMILY;
591 if (scope_delim != NULL)
593 int try_numericscope = 0;
594 if (IN6_IS_ADDR_LINKLOCAL (at->addr)
595 || IN6_IS_ADDR_MC_LINKLOCAL (at->addr))
597 at->scopeid = if_nametoindex (scope_delim + 1);
598 if (at->scopeid == 0)
599 try_numericscope = 1;
601 else
602 try_numericscope = 1;
604 if (try_numericscope != 0)
606 char *end;
607 assert (sizeof (uint32_t) <= sizeof (unsigned long));
608 at->scopeid = (uint32_t) strtoul (scope_delim + 1, &end,
609 10);
610 if (*end != '\0')
611 return GAIH_OKIFUNSPEC | -EAI_NONAME;
615 goto dupname;
619 if (at->family == AF_UNSPEC && (req->ai_flags & AI_NUMERICHOST) == 0)
621 struct gaih_addrtuple **pat = &at;
622 int no_data = 0;
623 int no_inet6_data = 0;
624 service_user *nip = NULL;
625 enum nss_status inet6_status = NSS_STATUS_UNAVAIL;
626 enum nss_status status = NSS_STATUS_UNAVAIL;
627 int no_more;
628 int old_res_options;
630 /* If we do not have to look for IPv4 and IPv6 together, use
631 the simple, old functions. */
632 if (req->ai_family == AF_INET || req->ai_family == AF_INET6)
634 int family = req->ai_family;
635 size_t tmpbuflen = 512;
636 char *tmpbuf = alloca (tmpbuflen);
637 int rc;
638 struct hostent th;
639 struct hostent *h;
640 int herrno;
642 simple_again:
643 while (1)
645 rc = __gethostbyname2_r (name, family, &th, tmpbuf,
646 tmpbuflen, &h, &herrno);
647 if (rc != ERANGE || herrno != NETDB_INTERNAL)
648 break;
649 tmpbuf = extend_alloca (tmpbuf, tmpbuflen, 2 * tmpbuflen);
652 if (rc == 0)
654 if (h == NULL)
656 if (req->ai_family == AF_INET6
657 && (req->ai_flags & AI_V4MAPPED)
658 && family == AF_INET6)
660 /* Try again, this time looking for IPv4
661 addresses. */
662 family = AF_INET;
663 goto simple_again;
666 else
668 /* We found data, now convert it into the list. */
669 for (int i = 0; h->h_addr_list[i]; ++i)
671 if (*pat == NULL)
673 *pat = __alloca (sizeof (struct gaih_addrtuple));
674 (*pat)->scopeid = 0;
676 (*pat)->next = NULL;
677 (*pat)->family = req->ai_family;
678 if (family == req->ai_family)
679 memcpy ((*pat)->addr, h->h_addr_list[i],
680 h->h_length);
681 else
683 int32_t *addr = (uint32_t *) (*pat)->addr;
684 addr[3] = *(uint32_t *) h->h_addr_list[i];
685 addr[2] = htonl (0xffff);
686 addr[1] = 0;
687 addr[0] = 0;
689 pat = &((*pat)->next);
693 else
695 if (herrno == NETDB_INTERNAL)
697 __set_h_errno (herrno);
698 return -EAI_SYSTEM;
700 if (herrno == TRY_AGAIN)
702 return -EAI_AGAIN;
704 /* We made requests but they turned out no data.
705 The name is known, though. */
706 return (GAIH_OKIFUNSPEC | -EAI_NODATA);
709 goto process_list;
712 #ifdef USE_NSCD
713 if (__nss_not_use_nscd_hosts > 0
714 && ++__nss_not_use_nscd_hosts > NSS_NSCD_RETRY)
715 __nss_not_use_nscd_hosts = 0;
717 if (!__nss_not_use_nscd_hosts)
719 /* Try to use nscd. */
720 struct nscd_ai_result *air = NULL;
721 int herrno;
722 int err = __nscd_getai (name, &air, &herrno);
723 if (air != NULL)
725 /* Transform into gaih_addrtuple list. */
726 bool added_canon = (req->ai_flags & AI_CANONNAME) == 0;
727 char *addrs = air->addrs;
729 for (int i = 0; i < air->naddrs; ++i)
731 socklen_t size = (air->family[i] == AF_INET
732 ? INADDRSZ : IN6ADDRSZ);
733 if (*pat == NULL)
735 *pat = __alloca (sizeof (struct gaih_addrtuple));
736 (*pat)->scopeid = 0;
738 uint32_t *pataddr = (*pat)->addr;
739 (*pat)->next = NULL;
740 if (added_canon || air->canon == NULL)
741 (*pat)->name = NULL;
742 else
743 canon = (*pat)->name = strdupa (air->canon);
745 if (air->family[i] == AF_INET
746 && req->ai_family == AF_INET6
747 && (req->ai_flags & AI_V4MAPPED))
749 (*pat)->family = AF_INET6;
750 pataddr[3] = *(uint32_t *) addrs;
751 pataddr[2] = htonl (0xffff);
752 pataddr[1] = 0;
753 pataddr[0] = 0;
754 pat = &((*pat)->next);
755 added_canon = true;
757 else if (req->ai_family == AF_UNSPEC
758 || air->family[i] == req->ai_family)
760 (*pat)->family = air->family[i];
761 memcpy (pataddr, addrs, size);
762 pat = &((*pat)->next);
763 added_canon = true;
764 if (air->family[i] == AF_INET6)
765 got_ipv6 = true;
767 addrs += size;
770 free (air);
772 if (at->family == AF_UNSPEC)
773 return (GAIH_OKIFUNSPEC | -EAI_NONAME);
775 goto process_list;
777 else if (err != 0 && __nss_not_use_nscd_hosts == 0)
779 if (herrno == NETDB_INTERNAL && errno == ENOMEM)
780 return -EAI_MEMORY;
781 if (herrno == TRY_AGAIN)
782 return -EAI_AGAIN;
783 return -EAI_SYSTEM;
786 #endif
788 if (__nss_hosts_database != NULL)
790 no_more = 0;
791 nip = __nss_hosts_database;
793 else
794 no_more = __nss_database_lookup ("hosts", NULL,
795 "dns [!UNAVAIL=return] files",
796 &nip);
798 if (__res_maybe_init (&_res, 0) == -1)
799 no_more = 1;
801 /* If we are looking for both IPv4 and IPv6 address we don't
802 want the lookup functions to automatically promote IPv4
803 addresses to IPv6 addresses. Currently this is decided
804 by setting the RES_USE_INET6 bit in _res.options. */
805 old_res_options = _res.options;
806 _res.options &= ~RES_USE_INET6;
808 size_t tmpbuflen = 512;
809 char *tmpbuf = alloca (tmpbuflen);
811 while (!no_more)
813 nss_gethostbyname3_r fct = NULL;
814 if (req->ai_flags & AI_CANONNAME)
815 /* No need to use this function if we do not look for
816 the canonical name. The function does not exist in
817 all NSS modules and therefore the lookup would
818 often fail. */
819 fct = __nss_lookup_function (nip, "gethostbyname3_r");
820 if (fct == NULL)
821 /* We are cheating here. The gethostbyname2_r function does
822 not have the same interface as gethostbyname3_r but the
823 extra arguments the latter takes are added at the end.
824 So the gethostbyname2_r code will just ignore them. */
825 fct = __nss_lookup_function (nip, "gethostbyname2_r");
827 if (fct != NULL)
829 if (req->ai_family == AF_INET6
830 || req->ai_family == AF_UNSPEC)
832 gethosts (AF_INET6, struct in6_addr);
833 no_inet6_data = no_data;
834 inet6_status = status;
836 if (req->ai_family == AF_INET
837 || req->ai_family == AF_UNSPEC
838 || (req->ai_family == AF_INET6
839 && (req->ai_flags & AI_V4MAPPED)
840 /* Avoid generating the mapped addresses if we
841 know we are not going to need them. */
842 && ((req->ai_flags & AI_ALL) || !got_ipv6)))
844 gethosts (AF_INET, struct in_addr);
846 if (req->ai_family == AF_INET)
848 no_inet6_data = no_data;
849 inet6_status = status;
853 /* If we found one address for AF_INET or AF_INET6,
854 don't continue the search. */
855 if (inet6_status == NSS_STATUS_SUCCESS
856 || status == NSS_STATUS_SUCCESS)
858 if ((req->ai_flags & AI_CANONNAME) != 0 && canon == NULL)
860 /* If we need the canonical name, get it
861 from the same service as the result. */
862 nss_getcanonname_r cfct;
863 int herrno;
865 cfct = __nss_lookup_function (nip, "getcanonname_r");
866 if (cfct != NULL)
868 const size_t max_fqdn_len = 256;
869 char *buf = alloca (max_fqdn_len);
870 char *s;
872 if (DL_CALL_FCT (cfct, (at->name ?: name, buf,
873 max_fqdn_len, &s, &rc,
874 &herrno))
875 == NSS_STATUS_SUCCESS)
876 canon = s;
877 else
878 /* Set to name now to avoid using
879 gethostbyaddr. */
880 canon = name;
884 break;
887 /* We can have different states for AF_INET and
888 AF_INET6. Try to find a useful one for both. */
889 if (inet6_status == NSS_STATUS_TRYAGAIN)
890 status = NSS_STATUS_TRYAGAIN;
891 else if (status == NSS_STATUS_UNAVAIL &&
892 inet6_status != NSS_STATUS_UNAVAIL)
893 status = inet6_status;
896 if (nss_next_action (nip, status) == NSS_ACTION_RETURN)
897 break;
899 if (nip->next == NULL)
900 no_more = -1;
901 else
902 nip = nip->next;
905 _res.options = old_res_options;
907 if (no_data != 0 && no_inet6_data != 0)
909 /* If both requests timed out report this. */
910 if (no_data == EAI_AGAIN && no_inet6_data == EAI_AGAIN)
911 return -EAI_AGAIN;
913 /* We made requests but they turned out no data. The name
914 is known, though. */
915 return (GAIH_OKIFUNSPEC | -EAI_NODATA);
919 process_list:
920 if (at->family == AF_UNSPEC)
921 return (GAIH_OKIFUNSPEC | -EAI_NONAME);
923 else
925 struct gaih_addrtuple *atr;
926 atr = at = __alloca (sizeof (struct gaih_addrtuple));
927 memset (at, '\0', sizeof (struct gaih_addrtuple));
929 if (req->ai_family == AF_UNSPEC)
931 at->next = __alloca (sizeof (struct gaih_addrtuple));
932 memset (at->next, '\0', sizeof (struct gaih_addrtuple));
935 if (req->ai_family == AF_UNSPEC || req->ai_family == AF_INET6)
937 at->family = AF_INET6;
938 if ((req->ai_flags & AI_PASSIVE) == 0)
939 memcpy (at->addr, &in6addr_loopback, sizeof (struct in6_addr));
940 atr = at->next;
943 if (req->ai_family == AF_UNSPEC || req->ai_family == AF_INET)
945 atr->family = AF_INET;
946 if ((req->ai_flags & AI_PASSIVE) == 0)
947 atr->addr[0] = htonl (INADDR_LOOPBACK);
951 if (pai == NULL)
952 return 0;
955 struct gaih_servtuple *st2;
956 struct gaih_addrtuple *at2 = at;
957 size_t socklen;
958 sa_family_t family;
961 buffer is the size of an unformatted IPv6 address in printable format.
963 while (at2 != NULL)
965 /* Only the first entry gets the canonical name. */
966 if (at2 == at && (req->ai_flags & AI_CANONNAME) != 0)
968 if (canon == NULL)
970 struct hostent *h = NULL;
971 int herrno;
972 struct hostent th;
973 size_t tmpbuflen = 512;
974 char *tmpbuf = NULL;
978 tmpbuf = extend_alloca (tmpbuf, tmpbuflen, tmpbuflen * 2);
979 rc = __gethostbyaddr_r (at2->addr,
980 ((at2->family == AF_INET6)
981 ? sizeof (struct in6_addr)
982 : sizeof (struct in_addr)),
983 at2->family, &th, tmpbuf,
984 tmpbuflen, &h, &herrno);
986 while (rc == ERANGE && herrno == NETDB_INTERNAL);
988 if (rc != 0 && herrno == NETDB_INTERNAL)
990 __set_h_errno (herrno);
991 return -EAI_SYSTEM;
994 if (h != NULL)
995 canon = h->h_name;
996 else
998 assert (orig_name != NULL);
999 /* If the canonical name cannot be determined, use
1000 the passed in string. */
1001 canon = orig_name;
1005 #ifdef HAVE_LIBIDN
1006 if (req->ai_flags & AI_CANONIDN)
1008 int idn_flags = 0;
1009 if (req->ai_flags & AI_IDN_ALLOW_UNASSIGNED)
1010 idn_flags |= IDNA_ALLOW_UNASSIGNED;
1011 if (req->ai_flags & AI_IDN_USE_STD3_ASCII_RULES)
1012 idn_flags |= IDNA_USE_STD3_ASCII_RULES;
1014 char *out;
1015 int rc = __idna_to_unicode_lzlz (canon, &out, idn_flags);
1016 if (rc != IDNA_SUCCESS)
1018 if (rc == IDNA_MALLOC_ERROR)
1019 return -EAI_MEMORY;
1020 if (rc == IDNA_DLOPEN_ERROR)
1021 return -EAI_SYSTEM;
1022 return -EAI_IDN_ENCODE;
1024 /* In case the output string is the same as the input
1025 string no new string has been allocated. Otherwise
1026 make a copy. */
1027 if (out == canon)
1028 goto make_copy;
1030 else
1031 #endif
1033 #ifdef HAVE_LIBIDN
1034 make_copy:
1035 #endif
1036 canon = strdup (canon);
1037 if (canon == NULL)
1038 return -EAI_MEMORY;
1042 if (at2->family == AF_INET6)
1044 family = AF_INET6;
1045 socklen = sizeof (struct sockaddr_in6);
1047 /* If we looked up IPv4 mapped address discard them here if
1048 the caller isn't interested in all address and we have
1049 found at least one IPv6 address. */
1050 if (got_ipv6
1051 && (req->ai_flags & (AI_V4MAPPED|AI_ALL)) == AI_V4MAPPED
1052 && IN6_IS_ADDR_V4MAPPED (at2->addr))
1053 goto ignore;
1055 else
1057 family = AF_INET;
1058 socklen = sizeof (struct sockaddr_in);
1061 for (st2 = st; st2 != NULL; st2 = st2->next)
1063 struct addrinfo *ai;
1064 ai = *pai = malloc (sizeof (struct addrinfo) + socklen);
1065 if (ai == NULL)
1066 return -EAI_MEMORY;
1068 ai->ai_flags = req->ai_flags;
1069 ai->ai_family = family;
1070 ai->ai_socktype = st2->socktype;
1071 ai->ai_protocol = st2->protocol;
1072 ai->ai_addrlen = socklen;
1073 ai->ai_addr = (void *) (ai + 1);
1075 /* We only add the canonical name once. */
1076 ai->ai_canonname = (char *) canon;
1077 canon = NULL;
1079 #if SALEN
1080 ai->ai_addr->sa_len = socklen;
1081 #endif /* SALEN */
1082 ai->ai_addr->sa_family = family;
1084 if (family == AF_INET6)
1086 struct sockaddr_in6 *sin6p =
1087 (struct sockaddr_in6 *) ai->ai_addr;
1089 sin6p->sin6_port = st2->port;
1090 sin6p->sin6_flowinfo = 0;
1091 memcpy (&sin6p->sin6_addr,
1092 at2->addr, sizeof (struct in6_addr));
1093 sin6p->sin6_scope_id = at2->scopeid;
1095 else
1097 struct sockaddr_in *sinp =
1098 (struct sockaddr_in *) ai->ai_addr;
1099 sinp->sin_port = st2->port;
1100 memcpy (&sinp->sin_addr,
1101 at2->addr, sizeof (struct in_addr));
1102 memset (sinp->sin_zero, '\0', sizeof (sinp->sin_zero));
1105 pai = &(ai->ai_next);
1107 *pai = NULL;
1109 ignore:
1110 at2 = at2->next;
1113 return 0;
1116 static struct gaih gaih[] =
1118 { PF_INET6, gaih_inet },
1119 { PF_INET, gaih_inet },
1120 #if 0
1121 { PF_LOCAL, gaih_local },
1122 #endif
1123 { PF_UNSPEC, NULL }
1126 struct sort_result
1128 struct addrinfo *dest_addr;
1129 struct sockaddr_storage source_addr;
1130 uint8_t source_addr_len;
1131 bool got_source_addr;
1135 static int
1136 get_scope (const struct sockaddr_storage *ss)
1138 int scope;
1139 if (ss->ss_family == PF_INET6)
1141 const struct sockaddr_in6 *in6 = (const struct sockaddr_in6 *) ss;
1143 if (! IN6_IS_ADDR_MULTICAST (&in6->sin6_addr))
1145 if (IN6_IS_ADDR_LINKLOCAL (&in6->sin6_addr))
1146 scope = 2;
1147 else if (IN6_IS_ADDR_SITELOCAL (&in6->sin6_addr))
1148 scope = 5;
1149 else
1150 /* XXX Is this the correct default behavior? */
1151 scope = 14;
1153 else
1154 scope = in6->sin6_addr.s6_addr[1] & 0xf;
1156 else if (ss->ss_family == PF_INET)
1158 const struct sockaddr_in *in = (const struct sockaddr_in *) ss;
1159 const uint8_t *addr = (const uint8_t *) &in->sin_addr;
1161 /* RFC 3484 specifies how to map IPv6 addresses to scopes.
1162 169.254/16 and 127/8 are link-local. */
1163 if ((addr[0] == 169 && addr[1] == 254) || addr[0] == 127)
1164 scope = 2;
1165 else if (addr[0] == 10 || (addr[0] == 172 && addr[1] == 16)
1166 || (addr[0] == 192 && addr[1] == 168))
1167 scope = 5;
1168 else
1169 scope = 14;
1171 else
1172 /* XXX What is a good default? */
1173 scope = 15;
1175 return scope;
1179 /* XXX The system administrator should be able to install other
1180 tables. We need to make this configurable. The problem is that
1181 the kernel is also involved since it needs the same table. */
1182 static const struct prefixlist
1184 struct in6_addr prefix;
1185 unsigned int bits;
1186 int val;
1187 } default_labels[] =
1189 /* See RFC 3484 for the details. */
1190 { { .in6_u = { .u6_addr16 = { 0x0000, 0x0000, 0x0000, 0x0000,
1191 0x0000, 0x0000, 0x0000, 0x0001 } } },
1192 128, 0 },
1193 { { .in6_u = { .u6_addr16 = { 0x2002, 0x0000, 0x0000, 0x0000,
1194 0x0000, 0x0000, 0x0000, 0x0000 } } },
1195 16, 2 },
1196 { { .in6_u = { .u6_addr16 = { 0x0000, 0x0000, 0x0000, 0x0000,
1197 0x0000, 0x0000, 0x0000, 0x0000 } } },
1198 96, 3 },
1199 { { .in6_u = { .u6_addr16 = { 0x0000, 0x0000, 0x0000, 0x0000,
1200 0x0000, 0xffff, 0x0000, 0x0000 } } },
1201 96, 4 },
1202 { { .in6_u = { .u6_addr16 = { 0x0000, 0x0000, 0x0000, 0x0000,
1203 0x0000, 0x0000, 0x0000, 0x0000 } } },
1204 0, 1 }
1208 static const struct prefixlist default_precedence[] =
1210 /* See RFC 3484 for the details. */
1211 { { .in6_u = { .u6_addr16 = { 0x0000, 0x0000, 0x0000, 0x0000,
1212 0x0000, 0x0000, 0x0000, 0x0001 } } },
1213 128, 50 },
1214 { { .in6_u = { .u6_addr16 = { 0x2002, 0x0000, 0x0000, 0x0000,
1215 0x0000, 0x0000, 0x0000, 0x0000 } } },
1216 16, 30 },
1217 { { .in6_u = { .u6_addr16 = { 0x0000, 0x0000, 0x0000, 0x0000,
1218 0x0000, 0x0000, 0x0000, 0x0000 } } },
1219 96, 20 },
1220 { { .in6_u = { .u6_addr16 = { 0x0000, 0x0000, 0x0000, 0x0000,
1221 0x0000, 0xffff, 0x0000, 0x0000 } } },
1222 96, 10 },
1223 { { .in6_u = { .u6_addr16 = { 0x0000, 0x0000, 0x0000, 0x0000,
1224 0x0000, 0x0000, 0x0000, 0x0000 } } },
1225 0, 40 }
1229 static int
1230 match_prefix (const struct sockaddr_storage *ss, const struct prefixlist *list,
1231 int default_val)
1233 int idx;
1234 struct sockaddr_in6 in6_mem;
1235 const struct sockaddr_in6 *in6;
1237 if (ss->ss_family == PF_INET6)
1238 in6 = (const struct sockaddr_in6 *) ss;
1239 else if (ss->ss_family == PF_INET)
1241 const struct sockaddr_in *in = (const struct sockaddr_in *) ss;
1243 /* Convert to IPv6 address. */
1244 in6_mem.sin6_family = PF_INET6;
1245 in6_mem.sin6_port = in->sin_port;
1246 in6_mem.sin6_flowinfo = 0;
1247 if (in->sin_addr.s_addr == htonl (0x7f000001))
1248 in6_mem.sin6_addr = (struct in6_addr) IN6ADDR_LOOPBACK_INIT;
1249 else
1251 /* Construct a V4-to-6 mapped address. */
1252 memset (&in6_mem.sin6_addr, '\0', sizeof (in6_mem.sin6_addr));
1253 in6_mem.sin6_addr.s6_addr16[5] = 0xffff;
1254 in6_mem.sin6_addr.s6_addr32[3] = in->sin_addr.s_addr;
1255 in6_mem.sin6_scope_id = 0;
1258 in6 = &in6_mem;
1260 else
1261 return default_val;
1263 for (idx = 0; ; ++idx)
1265 unsigned int bits = list[idx].bits;
1266 uint8_t *mask = list[idx].prefix.s6_addr;
1267 uint8_t *val = in6->sin6_addr.s6_addr;
1269 while (bits > 8)
1271 if (*mask != *val)
1272 break;
1274 ++mask;
1275 ++val;
1276 bits -= 8;
1279 if (bits < 8)
1281 if ((*mask & (0xff00 >> bits)) == (*val & (0xff00 >> bits)))
1282 /* Match! */
1283 break;
1287 return list[idx].val;
1291 static int
1292 get_label (const struct sockaddr_storage *ss)
1294 /* XXX What is a good default value? */
1295 return match_prefix (ss, default_labels, INT_MAX);
1299 static int
1300 get_precedence (const struct sockaddr_storage *ss)
1302 /* XXX What is a good default value? */
1303 return match_prefix (ss, default_precedence, 0);
1307 static int
1308 rfc3484_sort (const void *p1, const void *p2)
1310 const struct sort_result *a1 = (const struct sort_result *) p1;
1311 const struct sort_result *a2 = (const struct sort_result *) p2;
1313 /* Rule 1: Avoid unusable destinations.
1314 We have the got_source_addr flag set if the destination is reachable. */
1315 if (a1->got_source_addr && ! a2->got_source_addr)
1316 return -1;
1317 if (! a1->got_source_addr && a2->got_source_addr)
1318 return 1;
1321 /* Rule 2: Prefer matching scope. Only interesting if both
1322 destination addresses are IPv6. */
1323 int a1_dst_scope
1324 = get_scope ((struct sockaddr_storage *) a1->dest_addr->ai_addr);
1326 int a2_dst_scope
1327 = get_scope ((struct sockaddr_storage *) a2->dest_addr->ai_addr);
1329 if (a1->got_source_addr)
1331 int a1_src_scope = get_scope (&a1->source_addr);
1332 int a2_src_scope = get_scope (&a2->source_addr);
1334 if (a1_dst_scope == a1_src_scope && a2_dst_scope != a2_src_scope)
1335 return -1;
1336 if (a1_dst_scope != a1_src_scope && a2_dst_scope == a2_src_scope)
1337 return 1;
1341 /* Rule 3: Avoid deprecated addresses.
1342 That's something only the kernel could decide. */
1344 /* Rule 4: Prefer home addresses.
1345 Another thing only the kernel can decide. */
1347 /* Rule 5: Prefer matching label. */
1348 if (a1->got_source_addr)
1350 int a1_dst_label
1351 = get_label ((struct sockaddr_storage *) a1->dest_addr->ai_addr);
1352 int a1_src_label = get_label (&a1->source_addr);
1354 int a2_dst_label
1355 = get_label ((struct sockaddr_storage *) a2->dest_addr->ai_addr);
1356 int a2_src_label = get_label (&a2->source_addr);
1358 if (a1_dst_label == a1_src_label && a2_dst_label != a2_src_label)
1359 return -1;
1360 if (a1_dst_label != a1_src_label && a2_dst_label == a2_src_label)
1361 return 1;
1365 /* Rule 6: Prefer higher precedence. */
1366 int a1_prec
1367 = get_precedence ((struct sockaddr_storage *) a1->dest_addr->ai_addr);
1368 int a2_prec
1369 = get_precedence ((struct sockaddr_storage *) a2->dest_addr->ai_addr);
1371 if (a1_prec > a2_prec)
1372 return -1;
1373 if (a1_prec < a2_prec)
1374 return 1;
1377 /* Rule 7: Prefer native transport.
1378 XXX How to recognize tunnels? */
1381 /* Rule 8: Prefer smaller scope. */
1382 if (a1_dst_scope < a2_dst_scope)
1383 return -1;
1384 if (a1_dst_scope > a2_dst_scope)
1385 return 1;
1388 /* Rule 9: Use longest matching prefix. */
1389 if (a1->got_source_addr
1390 && a1->dest_addr->ai_family == a2->dest_addr->ai_family)
1392 int bit1 = 0;
1393 int bit2 = 0;
1395 if (a1->dest_addr->ai_family == PF_INET)
1397 assert (a1->source_addr.ss_family == PF_INET);
1398 assert (a2->source_addr.ss_family == PF_INET);
1400 struct sockaddr_in *in1_dst;
1401 struct sockaddr_in *in1_src;
1402 struct sockaddr_in *in2_dst;
1403 struct sockaddr_in *in2_src;
1405 in1_dst = (struct sockaddr_in *) a1->dest_addr->ai_addr;
1406 in1_src = (struct sockaddr_in *) &a1->source_addr;
1407 in2_dst = (struct sockaddr_in *) a2->dest_addr->ai_addr;
1408 in2_src = (struct sockaddr_in *) &a2->source_addr;
1410 bit1 = ffs (in1_dst->sin_addr.s_addr ^ in1_src->sin_addr.s_addr);
1411 bit2 = ffs (in2_dst->sin_addr.s_addr ^ 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 = ffs (in1_dst->sin6_addr.s6_addr32[i]
1439 ^ in1_src->sin6_addr.s6_addr32[i]);
1440 bit2 = ffs (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 struct gaih *g = gaih, *pg = NULL;
1465 struct gaih_service gaih_service, *pservice;
1466 struct addrinfo local_hints;
1468 if (name != NULL && name[0] == '*' && name[1] == 0)
1469 name = NULL;
1471 if (service != NULL && service[0] == '*' && service[1] == 0)
1472 service = NULL;
1474 if (name == NULL && service == NULL)
1475 return EAI_NONAME;
1477 if (hints == NULL)
1478 hints = &default_hints;
1480 if (hints->ai_flags
1481 & ~(AI_PASSIVE|AI_CANONNAME|AI_NUMERICHOST|AI_ADDRCONFIG|AI_V4MAPPED
1482 #ifdef HAVE_LIBIDN
1483 |AI_IDN|AI_CANONIDN|AI_IDN_ALLOW_UNASSIGNED
1484 |AI_IDN_USE_STD3_ASCII_RULES
1485 #endif
1486 |AI_NUMERICSERV|AI_ALL))
1487 return EAI_BADFLAGS;
1489 if ((hints->ai_flags & AI_CANONNAME) && name == NULL)
1490 return EAI_BADFLAGS;
1492 if (hints->ai_flags & AI_ADDRCONFIG)
1494 /* Determine whether we have IPv4 or IPv6 interfaces or both.
1495 We cannot cache the results since new interfaces could be
1496 added at any time. */
1497 bool seen_ipv4;
1498 bool seen_ipv6;
1499 __check_pf (&seen_ipv4, &seen_ipv6);
1501 /* Now make a decision on what we return, if anything. */
1502 if (hints->ai_family == PF_UNSPEC && (seen_ipv4 || seen_ipv6))
1504 /* If we haven't seen both IPv4 and IPv6 interfaces we can
1505 narrow down the search. */
1506 if (! seen_ipv4 || ! seen_ipv6)
1508 local_hints = *hints;
1509 local_hints.ai_family = seen_ipv4 ? PF_INET : PF_INET6;
1510 hints = &local_hints;
1513 else if ((hints->ai_family == PF_INET && ! seen_ipv4)
1514 || (hints->ai_family == PF_INET6 && ! seen_ipv6))
1515 /* We cannot possibly return a valid answer. */
1516 return EAI_NONAME;
1519 if (service && service[0])
1521 char *c;
1522 gaih_service.name = service;
1523 gaih_service.num = strtoul (gaih_service.name, &c, 10);
1524 if (*c != '\0')
1526 if (hints->ai_flags & AI_NUMERICSERV)
1527 return EAI_NONAME;
1529 gaih_service.num = -1;
1532 pservice = &gaih_service;
1534 else
1535 pservice = NULL;
1537 if (pai)
1538 end = &p;
1539 else
1540 end = NULL;
1542 while (g->gaih)
1544 if (hints->ai_family == g->family || hints->ai_family == AF_UNSPEC)
1546 j++;
1547 if (pg == NULL || pg->gaih != g->gaih)
1549 pg = g;
1550 i = g->gaih (name, pservice, hints, end);
1551 if (i != 0)
1553 /* EAI_NODATA is a more specific result as it says that
1554 we found a result but it is not usable. */
1555 if (last_i != (GAIH_OKIFUNSPEC | -EAI_NODATA))
1556 last_i = i;
1558 if (hints->ai_family == AF_UNSPEC && (i & GAIH_OKIFUNSPEC))
1560 ++g;
1561 continue;
1564 freeaddrinfo (p);
1566 return -(i & GAIH_EAI);
1568 if (end)
1569 while (*end)
1571 end = &((*end)->ai_next);
1572 ++nresults;
1576 ++g;
1579 if (j == 0)
1580 return EAI_FAMILY;
1582 if (nresults > 1)
1584 /* Sort results according to RFC 3484. */
1585 struct sort_result results[nresults];
1586 struct addrinfo *q;
1587 struct addrinfo *last = NULL;
1588 char *canonname = NULL;
1590 for (i = 0, q = p; q != NULL; ++i, last = q, q = q->ai_next)
1592 results[i].dest_addr = q;
1593 results[i].got_source_addr = false;
1595 /* If we just looked up the address for a different
1596 protocol, reuse the result. */
1597 if (last != NULL && last->ai_addrlen == q->ai_addrlen
1598 && memcmp (last->ai_addr, q->ai_addr, q->ai_addrlen) == 0)
1600 memcpy (&results[i].source_addr, &results[i - 1].source_addr,
1601 results[i - 1].source_addr_len);
1602 results[i].source_addr_len = results[i - 1].source_addr_len;
1603 results[i].got_source_addr = results[i - 1].got_source_addr;
1605 else
1607 /* We overwrite the type with SOCK_DGRAM since we do not
1608 want connect() to connect to the other side. If we
1609 cannot determine the source address remember this
1610 fact. */
1611 int fd = __socket (q->ai_family, SOCK_DGRAM, IPPROTO_IP);
1612 socklen_t sl = sizeof (results[i].source_addr);
1613 if (fd != -1
1614 && __connect (fd, q->ai_addr, q->ai_addrlen) == 0
1615 && __getsockname (fd,
1616 (struct sockaddr *) &results[i].source_addr,
1617 &sl) == 0)
1619 results[i].source_addr_len = sl;
1620 results[i].got_source_addr = true;
1622 else
1623 /* Just make sure that if we have to process the same
1624 address again we do not copy any memory. */
1625 results[i].source_addr_len = 0;
1627 if (fd != -1)
1628 close_not_cancel_no_status (fd);
1631 /* Remember the canonical name. */
1632 if (q->ai_canonname != NULL)
1634 assert (canonname == NULL);
1635 canonname = q->ai_canonname;
1636 q->ai_canonname = NULL;
1640 /* We got all the source addresses we can get, now sort using
1641 the information. */
1642 qsort (results, nresults, sizeof (results[0]), rfc3484_sort);
1644 /* Queue the results up as they come out of sorting. */
1645 q = p = results[0].dest_addr;
1646 for (i = 1; i < nresults; ++i)
1647 q = q->ai_next = results[i].dest_addr;
1648 q->ai_next = NULL;
1650 /* Fill in the canonical name into the new first entry. */
1651 p->ai_canonname = canonname;
1654 if (p)
1656 *pai = p;
1657 return 0;
1660 if (pai == NULL && last_i == 0)
1661 return 0;
1663 return last_i ? -(last_i & GAIH_EAI) : EAI_NONAME;
1665 libc_hidden_def (getaddrinfo)
1667 static_link_warning (getaddrinfo)
1669 void
1670 freeaddrinfo (struct addrinfo *ai)
1672 struct addrinfo *p;
1674 while (ai != NULL)
1676 p = ai;
1677 ai = ai->ai_next;
1678 free (p->ai_canonname);
1679 free (p);
1682 libc_hidden_def (freeaddrinfo)