2 * Copyright 1996 by Craig Metz
3 * Copyright (C) 2000-2006 Erik Andersen <andersen@uclibc.org>
4 * Portions from the GNU C library,
5 * Copyright (C) 2003, 2006 Free Software Foundation, Inc.
7 * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
10 /* $USAGI: getaddrinfo.c,v 1.16 2001/10/04 09:52:03 sekiya Exp $ */
12 /* The Inner Net License, Version 2.00
14 The author(s) grant permission for redistribution and use in source and
15 binary forms, with or without modification, of the software and documentation
16 provided that the following conditions are met:
18 0. If you receive a version of the software that is specifically labelled
19 as not being for redistribution (check the version message and/or README),
20 you are not permitted to redistribute that version of the software in any
22 1. All terms of the all other applicable copyrights and licenses must be
24 2. Redistributions of source code must retain the authors' copyright
25 notice(s), this list of conditions, and the following disclaimer.
26 3. Redistributions in binary form must reproduce the authors' copyright
27 notice(s), this list of conditions, and the following disclaimer in the
28 documentation and/or other materials provided with the distribution.
29 4. All advertising materials mentioning features or use of this software
30 must display the following acknowledgement with the name(s) of the
31 authors as specified in the copyright notice(s) substituted where
34 This product includes software developed by <name(s)>, The Inner
35 Net, and other contributors.
37 5. Neither the name(s) of the author(s) nor the names of its contributors
38 may be used to endorse or promote products derived from this software
39 without specific prior written permission.
41 THIS SOFTWARE IS PROVIDED BY ITS AUTHORS AND CONTRIBUTORS ``AS IS'' AND ANY
42 EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
43 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
44 DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR ANY
45 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
46 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
47 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
48 ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
49 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
50 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
52 If these license terms cause you a real problem, contact the author. */
64 #include <arpa/inet.h>
65 #include <sys/socket.h>
66 #include <netinet/in.h>
67 #include <sys/types.h>
69 #include <sys/utsname.h>
73 #define GAIH_OKIFUNSPEC 0x0100
74 #define GAIH_EAI ~(GAIH_OKIFUNSPEC)
77 #define UNIX_PATH_MAX 108
80 /* Useful for having small structure members/global variables */
81 typedef int8_t socktype_t;
82 typedef int8_t family_t;
83 typedef int8_t protocol_t;
84 struct BUG_too_small {
85 char BUG_socktype_t_too_small[(0
90 char BUG_family_t_too_small[(0
95 char BUG_protocol_t_too_small[(0
101 struct gaih_service {
106 struct gaih_servtuple {
107 struct gaih_servtuple *next;
113 struct gaih_addrtuple {
114 struct gaih_addrtuple *next;
120 struct gaih_typeproto {
126 /* Values for `protoflag'. */
127 #define GAI_PROTO_NOSERVICE 1
128 #define GAI_PROTO_PROTOANY 2
130 static const struct gaih_typeproto gaih_inet_typeproto[] = {
132 { SOCK_STREAM, IPPROTO_TCP, 0, "tcp" },
133 { SOCK_DGRAM , IPPROTO_UDP, 0, "udp" },
134 { SOCK_RAW , 0 , GAI_PROTO_PROTOANY|GAI_PROTO_NOSERVICE, "raw" },
140 int (*gaih)(const char *name, const struct gaih_service *service,
141 const struct addrinfo *req, struct addrinfo **pai);
147 static unsigned __check_pf(void)
151 #if defined __UCLIBC_SUPPORT_AI_ADDRCONFIG__
154 struct ifaddrs *runp;
156 /* Get the interface list via getifaddrs. */
157 if (getifaddrs(&ifa) != 0) {
158 /* We cannot determine what interfaces are available.
160 #if defined __UCLIBC_HAS_IPV4__
163 #if defined __UCLIBC_HAS_IPV6__
169 for (runp = ifa; runp != NULL; runp = runp->ifa_next) {
170 if (runp->ifa_addr == NULL)
172 #if defined __UCLIBC_HAS_IPV4__
173 if (runp->ifa_addr->sa_family == PF_INET)
176 #if defined __UCLIBC_HAS_IPV6__
177 if (runp->ifa_addr->sa_family == PF_INET6)
185 /* AI_ADDRCONFIG is disabled, assume both ipv4 and ipv6 available. */
186 #if defined __UCLIBC_HAS_IPV4__
189 #if defined __UCLIBC_HAS_IPV6__
193 #endif /* __UCLIBC_SUPPORT_AI_ADDRCONFIG__ */
198 static int addrconfig(sa_family_t af)
202 int saved_errno = errno;
206 #if defined __UCLIBC_HAS_IPV4__
208 ret = seen & SEEN_IPV4;
211 #if defined __UCLIBC_HAS_IPV6__
213 ret = seen & SEEN_IPV6;
217 s = socket(af, SOCK_DGRAM, 0);
218 ret = 1; /* Assume PF_UNIX. */
225 __set_errno(saved_errno);
230 /* Using Unix sockets this way is a security risk. */
232 gaih_local(const char *name, const struct gaih_service *service,
233 const struct addrinfo *req, struct addrinfo **pai)
235 struct utsname utsname;
236 struct addrinfo *ai = *pai;
238 if ((name != NULL) && (req->ai_flags & AI_NUMERICHOST))
239 return (GAIH_OKIFUNSPEC | -EAI_NONAME);
241 if ((name != NULL) || (req->ai_flags & AI_CANONNAME))
242 if (uname(&utsname) < 0)
246 if (strcmp(name, "localhost") &&
247 strcmp(name, "local") &&
248 strcmp(name, "unix") &&
249 strcmp(name, utsname.nodename))
250 return (GAIH_OKIFUNSPEC | -EAI_NONAME);
253 if (req->ai_protocol || req->ai_socktype) {
254 const struct gaih_typeproto *tp = gaih_inet_typeproto + 1;
257 && ((tp->protoflag & GAI_PROTO_NOSERVICE) != 0
258 || (req->ai_socktype != 0 && req->ai_socktype != tp->socktype)
259 || (req->ai_protocol != 0 && !(tp->protoflag & GAI_PROTO_PROTOANY) && req->ai_protocol != tp->protocol))
264 if (req->ai_socktype)
265 return (GAIH_OKIFUNSPEC | -EAI_SOCKTYPE);
266 return (GAIH_OKIFUNSPEC | -EAI_SERVICE);
270 *pai = ai = malloc(sizeof(struct addrinfo) + sizeof(struct sockaddr_un)
271 + ((req->ai_flags & AI_CANONNAME)
272 ? (strlen(utsname.nodename) + 1) : 0));
277 ai->ai_flags = req->ai_flags;
278 ai->ai_family = AF_LOCAL;
279 ai->ai_socktype = req->ai_socktype ? req->ai_socktype : SOCK_STREAM;
280 ai->ai_protocol = req->ai_protocol;
281 ai->ai_addrlen = sizeof(struct sockaddr_un);
282 ai->ai_addr = (void *)ai + sizeof(struct addrinfo);
284 ((struct sockaddr_un *)ai->ai_addr)->sun_len = sizeof(struct sockaddr_un);
287 ((struct sockaddr_un *)ai->ai_addr)->sun_family = AF_LOCAL;
288 memset(((struct sockaddr_un *)ai->ai_addr)->sun_path, 0, UNIX_PATH_MAX);
291 struct sockaddr_un *sunp = (struct sockaddr_un *)ai->ai_addr;
293 if (strchr(service->name, '/') != NULL) {
294 if (strlen(service->name) >= sizeof(sunp->sun_path))
295 return GAIH_OKIFUNSPEC | -EAI_SERVICE;
296 strcpy(sunp->sun_path, service->name);
298 if (strlen(P_tmpdir "/") + 1 + strlen(service->name) >= sizeof(sunp->sun_path))
299 return (GAIH_OKIFUNSPEC | -EAI_SERVICE);
300 stpcpy(stpcpy(sunp->sun_path, P_tmpdir "/"), service->name);
303 /* This is a dangerous use of the interface since there is a time
304 window between the test for the file and the actual creation
305 (done by the caller) in which a file with the same name could
307 char *buf = ((struct sockaddr_un *)ai->ai_addr)->sun_path;
309 if (__path_search(buf, L_tmpnam, NULL, NULL, 0) != 0
310 || __gen_tempname(buf, __GT_NOCREATE) != 0
316 ai->ai_canonname = NULL;
317 if (req->ai_flags & AI_CANONNAME)
318 ai->ai_canonname = strcpy((char *)(ai + 1) + sizeof(struct sockaddr_un),
325 gaih_inet_serv(const char *servicename, const struct gaih_typeproto *tp,
326 const struct addrinfo *req, struct gaih_servtuple *st)
329 size_t tmpbuflen = 1024;
335 tmpbuf = alloca(tmpbuflen);
336 r = getservbyname_r(servicename, tp->name, &ts, tmpbuf, tmpbuflen, &s);
337 if (r == 0 && s != NULL)
340 return (GAIH_OKIFUNSPEC | -EAI_SERVICE);
344 st->socktype = tp->socktype;
345 st->protocol = ((tp->protoflag & GAI_PROTO_PROTOANY) ? req->ai_protocol : tp->protocol);
346 st->port = s->s_port;
350 /* NB: also uses h,pat,rc,no_data variables */
351 #define gethosts(_family, _type) \
362 tmpbuf = alloca(tmpbuflen); \
363 rc = gethostbyname2_r(name, _family, &th, tmpbuf, \
364 tmpbuflen, &h, &herrno); \
365 } while (rc == ERANGE && herrno == NETDB_INTERNAL); \
367 if (herrno == NETDB_INTERNAL) { \
368 __set_h_errno(herrno); \
369 return -EAI_SYSTEM; \
371 if (herrno == TRY_AGAIN) \
372 no_data = EAI_AGAIN; \
374 no_data = (herrno == NO_DATA); \
375 } else if (h != NULL) { \
376 for (i = 0; h->h_addr_list[i]; i++) { \
377 if (*pat == NULL) { \
378 *pat = alloca(sizeof(struct gaih_addrtuple)); \
379 (*pat)->scopeid = 0; \
381 (*pat)->next = NULL; \
382 (*pat)->family = _family; \
383 memcpy((*pat)->addr, h->h_addr_list[i], sizeof(_type)); \
384 pat = &((*pat)->next); \
390 gaih_inet(const char *name, const struct gaih_service *service,
391 const struct addrinfo *req, struct addrinfo **pai)
393 struct gaih_servtuple nullserv;
395 const struct gaih_typeproto *tp = gaih_inet_typeproto;
396 struct gaih_servtuple *st = &nullserv;
397 struct gaih_addrtuple *at = NULL;
399 int v4mapped = (req->ai_family == PF_UNSPEC || req->ai_family == PF_INET6)
400 && (req->ai_flags & AI_V4MAPPED);
401 unsigned seen = __check_pf();
403 memset(&nullserv, 0, sizeof(nullserv));
405 if (req->ai_protocol || req->ai_socktype) {
408 && ((req->ai_socktype != 0 && req->ai_socktype != tp->socktype)
409 || (req->ai_protocol != 0 && !(tp->protoflag & GAI_PROTO_PROTOANY) && req->ai_protocol != tp->protocol)
415 if (req->ai_socktype)
416 return (GAIH_OKIFUNSPEC | -EAI_SOCKTYPE);
417 return (GAIH_OKIFUNSPEC | -EAI_SERVICE);
421 if (service != NULL) {
422 if ((tp->protoflag & GAI_PROTO_NOSERVICE) != 0)
423 return (GAIH_OKIFUNSPEC | -EAI_SERVICE);
425 if (service->num < 0) {
427 st = alloca(sizeof(struct gaih_servtuple));
428 rc = gaih_inet_serv(service->name, tp, req, st);
432 struct gaih_servtuple **pst = &st;
433 for (tp++; tp->name[0]; tp++) {
434 struct gaih_servtuple *newp;
436 if ((tp->protoflag & GAI_PROTO_NOSERVICE) != 0)
439 if (req->ai_socktype != 0 && req->ai_socktype != tp->socktype)
441 if (req->ai_protocol != 0
442 && !(tp->protoflag & GAI_PROTO_PROTOANY)
443 && req->ai_protocol != tp->protocol)
446 newp = alloca(sizeof(struct gaih_servtuple));
447 rc = gaih_inet_serv(service->name, tp, req, newp);
449 if (rc & GAIH_OKIFUNSPEC)
458 return (GAIH_OKIFUNSPEC | -EAI_SERVICE);
461 st = alloca(sizeof(struct gaih_servtuple));
463 st->socktype = tp->socktype;
464 st->protocol = ((tp->protoflag & GAI_PROTO_PROTOANY)
465 ? req->ai_protocol : tp->protocol);
466 st->port = htons(service->num);
468 } else if (req->ai_socktype || req->ai_protocol) {
469 st = alloca(sizeof(struct gaih_servtuple));
471 st->socktype = tp->socktype;
472 st->protocol = ((tp->protoflag & GAI_PROTO_PROTOANY)
473 ? req->ai_protocol : tp->protocol);
477 * Neither socket type nor protocol is set. Return all socket types
480 struct gaih_servtuple **lastp = &st;
481 for (++tp; tp->name[0]; ++tp) {
482 struct gaih_servtuple *newp;
484 newp = alloca(sizeof(struct gaih_servtuple));
486 newp->socktype = tp->socktype;
487 newp->protocol = tp->protocol;
496 at = alloca(sizeof(struct gaih_addrtuple));
497 at->family = AF_UNSPEC;
501 if (inet_pton(AF_INET, name, at->addr) > 0) {
502 if (req->ai_family == AF_UNSPEC || req->ai_family == AF_INET || v4mapped)
503 at->family = AF_INET;
508 #if defined __UCLIBC_HAS_IPV6__
509 if (at->family == AF_UNSPEC) {
510 char *namebuf = strdupa(name);
513 scope_delim = strchr(namebuf, SCOPE_DELIMITER);
514 if (scope_delim != NULL)
517 if (inet_pton(AF_INET6, namebuf, at->addr) > 0) {
518 if (req->ai_family == AF_UNSPEC || req->ai_family == AF_INET6)
519 at->family = AF_INET6;
523 if (scope_delim != NULL) {
524 int try_numericscope = 0;
525 uint32_t *a32 = (uint32_t*)at->addr;
526 if (IN6_IS_ADDR_LINKLOCAL(a32) || IN6_IS_ADDR_MC_LINKLOCAL(at->addr)) {
527 at->scopeid = if_nametoindex(scope_delim + 1);
528 if (at->scopeid == 0)
529 try_numericscope = 1;
531 try_numericscope = 1;
533 if (try_numericscope != 0) {
535 assert(sizeof(uint32_t) <= sizeof(unsigned long));
536 at->scopeid = (uint32_t)strtoul(scope_delim + 1, &end, 10);
538 return (GAIH_OKIFUNSPEC | -EAI_NONAME);
545 if (at->family == AF_UNSPEC && (req->ai_flags & AI_NUMERICHOST) == 0) {
547 struct gaih_addrtuple **pat = &at;
552 * If we are looking for both IPv4 and IPv6 address we don't want
553 * the lookup functions to automatically promote IPv4 addresses to
556 #if defined __UCLIBC_HAS_IPV6__
557 if (req->ai_family == AF_UNSPEC || req->ai_family == AF_INET6)
558 if (!(req->ai_flags & AI_ADDRCONFIG) || (seen & SEEN_IPV6))
559 gethosts(AF_INET6, struct in6_addr);
561 no_inet6_data = no_data;
563 if (req->ai_family == AF_INET
564 || (!v4mapped && req->ai_family == AF_UNSPEC)
565 || (v4mapped && (no_inet6_data != 0 || (req->ai_flags & AI_ALL)))
567 if (!(req->ai_flags & AI_ADDRCONFIG) || (seen & SEEN_IPV4))
568 gethosts(AF_INET, struct in_addr);
571 if (no_data != 0 && no_inet6_data != 0) {
572 /* If both requests timed out report this. */
573 if (no_data == EAI_AGAIN && no_inet6_data == EAI_AGAIN)
576 * We made requests but they turned out no data.
577 * The name is known, though.
579 return (GAIH_OKIFUNSPEC | -EAI_AGAIN);
583 if (at->family == AF_UNSPEC)
584 return (GAIH_OKIFUNSPEC | -EAI_NONAME);
586 struct gaih_addrtuple *atr;
588 atr = at = alloca(sizeof(struct gaih_addrtuple));
589 memset(at, '\0', sizeof(struct gaih_addrtuple));
590 if (req->ai_family == 0) {
591 at->next = alloca(sizeof(struct gaih_addrtuple));
592 memset(at->next, '\0', sizeof(struct gaih_addrtuple));
594 #if defined __UCLIBC_HAS_IPV6__
595 if (req->ai_family == 0 || req->ai_family == AF_INET6) {
596 at->family = AF_INET6;
597 if ((req->ai_flags & AI_PASSIVE) == 0)
598 memcpy(at->addr, &in6addr_loopback, sizeof(struct in6_addr));
602 if (req->ai_family == 0 || req->ai_family == AF_INET) {
603 atr->family = AF_INET;
604 if ((req->ai_flags & AI_PASSIVE) == 0) {
605 uint32_t *a = (uint32_t*)atr->addr;
606 *a = htonl(INADDR_LOOPBACK);
615 const char *c = NULL;
616 struct gaih_servtuple *st2;
617 struct gaih_addrtuple *at2 = at;
618 size_t socklen, namelen;
622 * buffer is the size of an unformatted IPv6 address in
625 char buffer[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255")];
627 while (at2 != NULL) {
628 if (req->ai_flags & AI_CANONNAME) {
629 struct hostent *h = NULL;
632 size_t tmpbuflen = 512;
637 tmpbuf = alloca(tmpbuflen);
638 rc = gethostbyaddr_r(at2->addr,
639 ((at2->family == AF_INET6)
640 ? sizeof(struct in6_addr)
641 : sizeof(struct in_addr)),
643 &th, tmpbuf, tmpbuflen,
645 } while (rc == errno && herrno == NETDB_INTERNAL);
647 if (rc != 0 && herrno == NETDB_INTERNAL) {
648 __set_h_errno(herrno);
653 c = inet_ntop(at2->family, at2->addr, buffer, sizeof(buffer));
658 return (GAIH_OKIFUNSPEC | -EAI_NONAME);
660 namelen = strlen(c) + 1;
664 #if defined __UCLIBC_HAS_IPV6__
665 if (at2->family == AF_INET6 || v4mapped) {
667 socklen = sizeof(struct sockaddr_in6);
670 #if defined __UCLIBC_HAS_IPV4__ && defined __UCLIBC_HAS_IPV6__
673 #if defined __UCLIBC_HAS_IPV4__
676 socklen = sizeof(struct sockaddr_in);
679 for (st2 = st; st2 != NULL; st2 = st2->next) {
680 if (req->ai_flags & AI_ADDRCONFIG) {
681 if (family == AF_INET && !(seen & SEEN_IPV4))
683 #if defined __UCLIBC_HAS_IPV6__
684 else if (family == AF_INET6 && !(seen & SEEN_IPV6))
688 *pai = malloc(sizeof(struct addrinfo) + socklen + namelen);
692 (*pai)->ai_flags = req->ai_flags;
693 (*pai)->ai_family = family;
694 (*pai)->ai_socktype = st2->socktype;
695 (*pai)->ai_protocol = st2->protocol;
696 (*pai)->ai_addrlen = socklen;
697 (*pai)->ai_addr = (void *) (*pai) + sizeof(struct addrinfo);
699 (*pai)->ai_addr->sa_len = socklen;
701 (*pai)->ai_addr->sa_family = family;
703 #if defined __UCLIBC_HAS_IPV6__
704 if (family == AF_INET6) {
705 struct sockaddr_in6 *sin6p = (struct sockaddr_in6 *) (*pai)->ai_addr;
707 sin6p->sin6_flowinfo = 0;
708 if (at2->family == AF_INET6) {
709 memcpy(&sin6p->sin6_addr,
710 at2->addr, sizeof(struct in6_addr));
712 sin6p->sin6_addr.s6_addr32[0] = 0;
713 sin6p->sin6_addr.s6_addr32[1] = 0;
714 sin6p->sin6_addr.s6_addr32[2] = htonl(0x0000ffff);
715 memcpy(&sin6p->sin6_addr.s6_addr32[3],
716 at2->addr, sizeof(sin6p->sin6_addr.s6_addr32[3]));
718 sin6p->sin6_port = st2->port;
719 sin6p->sin6_scope_id = at2->scopeid;
722 #if defined __UCLIBC_HAS_IPV4__ && defined __UCLIBC_HAS_IPV6__
725 #if defined __UCLIBC_HAS_IPV4__
727 struct sockaddr_in *sinp = (struct sockaddr_in *) (*pai)->ai_addr;
729 memcpy(&sinp->sin_addr, at2->addr, sizeof(struct in_addr));
730 sinp->sin_port = st2->port;
731 memset(sinp->sin_zero, '\0', sizeof(sinp->sin_zero));
735 (*pai)->ai_canonname = ((void *) (*pai) +
736 sizeof(struct addrinfo) + socklen);
737 strcpy((*pai)->ai_canonname, c);
739 (*pai)->ai_canonname = NULL;
741 (*pai)->ai_next = NULL;
742 pai = &((*pai)->ai_next);
751 static const struct gaih gaih[] = {
752 #if defined __UCLIBC_HAS_IPV6__
753 { PF_INET6, gaih_inet },
755 { PF_INET, gaih_inet },
757 { PF_LOCAL, gaih_local },
763 freeaddrinfo(struct addrinfo *ai)
773 libc_hidden_def(freeaddrinfo)
776 getaddrinfo(const char *name, const char *service,
777 const struct addrinfo *hints, struct addrinfo **pai)
779 int i = 0, j, last_i = 0;
780 struct addrinfo *p = NULL, **end;
781 const struct gaih *g = gaih, *pg = NULL;
782 struct gaih_service gaih_service, *pservice;
783 struct addrinfo default_hints;
785 if (name != NULL && name[0] == '*' && name[1] == 0)
788 if (service != NULL && service[0] == '*' && service[1] == 0)
791 if (name == NULL && service == NULL)
795 memset(&default_hints, 0, sizeof(default_hints));
797 default_hints.ai_family = AF_UNSPEC;
798 hints = &default_hints;
801 if (hints->ai_flags & ~(AI_PASSIVE|AI_CANONNAME|AI_NUMERICHOST|
802 AI_ADDRCONFIG|AI_V4MAPPED|AI_NUMERICSERV|AI_ALL))
805 if ((hints->ai_flags & AI_CANONNAME) && name == NULL)
808 if (service && service[0]) {
810 gaih_service.name = service;
811 gaih_service.num = strtoul(gaih_service.name, &c, 10);
813 if (hints->ai_flags & AI_NUMERICSERV)
815 gaih_service.num = -1;
818 * Can't specify a numerical socket unless a protocol
821 if (hints->ai_socktype == 0 && hints->ai_protocol == 0)
824 pservice = &gaih_service;
834 if (hints->ai_family == g->family || hints->ai_family == AF_UNSPEC) {
835 if ((hints->ai_flags & AI_ADDRCONFIG) && !addrconfig(g->family)) {
840 if (pg == NULL || pg->gaih != g->gaih) {
842 i = g->gaih(name, pservice, hints, end);
845 if (hints->ai_family == AF_UNSPEC && (i & GAIH_OKIFUNSPEC))
849 return -(i & GAIH_EAI);
853 end = &((*end)->ai_next);
867 if (pai == NULL && last_i == 0)
870 /* if (p) - never happens, see above */
871 /* freeaddrinfo(p); */
873 return last_i ? -(last_i & GAIH_EAI) : EAI_NONAME;
875 libc_hidden_def(getaddrinfo)