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. */
65 #include <arpa/inet.h>
66 #include <sys/socket.h>
67 #include <netinet/in.h>
68 #include <sys/types.h>
70 #include <sys/utsname.h>
74 #define GAIH_OKIFUNSPEC 0x0100
75 #define GAIH_EAI ~(GAIH_OKIFUNSPEC)
78 #define UNIX_PATH_MAX 108
81 /* Useful for having small structure members/global variables */
82 typedef int8_t socktype_t;
83 typedef int8_t family_t;
84 typedef int8_t protocol_t;
85 struct BUG_too_small {
86 char BUG_socktype_t_too_small[(0
91 char BUG_family_t_too_small[(0
96 char BUG_protocol_t_too_small[(0
102 struct gaih_service {
107 struct gaih_servtuple {
108 struct gaih_servtuple *next;
114 struct gaih_addrtuple {
115 struct gaih_addrtuple *next;
121 struct gaih_typeproto {
127 /* Values for `protoflag'. */
128 #define GAI_PROTO_NOSERVICE 1
129 #define GAI_PROTO_PROTOANY 2
131 static const struct gaih_typeproto gaih_inet_typeproto[] = {
133 { SOCK_STREAM, IPPROTO_TCP, 0, "tcp" },
134 { SOCK_DGRAM , IPPROTO_UDP, 0, "udp" },
135 { SOCK_RAW , 0 , GAI_PROTO_PROTOANY|GAI_PROTO_NOSERVICE, "raw" },
141 int (*gaih)(const char *name, const struct gaih_service *service,
142 const struct addrinfo *req, struct addrinfo **pai);
148 static unsigned __check_pf(void)
152 #if defined __UCLIBC_SUPPORT_AI_ADDRCONFIG__
155 struct ifaddrs *runp;
157 /* Get the interface list via getifaddrs. */
158 if (getifaddrs(&ifa) != 0) {
159 /* We cannot determine what interfaces are available.
161 #if defined __UCLIBC_HAS_IPV4__
164 #if defined __UCLIBC_HAS_IPV6__
170 for (runp = ifa; runp != NULL; runp = runp->ifa_next) {
171 if (runp->ifa_addr == NULL)
173 #if defined __UCLIBC_HAS_IPV4__
174 if (runp->ifa_addr->sa_family == PF_INET)
177 #if defined __UCLIBC_HAS_IPV6__
178 if (runp->ifa_addr->sa_family == PF_INET6)
186 /* AI_ADDRCONFIG is disabled, assume both ipv4 and ipv6 available. */
187 #if defined __UCLIBC_HAS_IPV4__
190 #if defined __UCLIBC_HAS_IPV6__
194 #endif /* __UCLIBC_SUPPORT_AI_ADDRCONFIG__ */
199 static int addrconfig(sa_family_t af)
203 int saved_errno = errno;
207 #if defined __UCLIBC_HAS_IPV4__
209 ret = seen & SEEN_IPV4;
212 #if defined __UCLIBC_HAS_IPV6__
214 ret = seen & SEEN_IPV6;
218 s = socket(af, SOCK_DGRAM, 0);
219 ret = 1; /* Assume PF_UNIX. */
226 __set_errno(saved_errno);
231 /* Using Unix sockets this way is a security risk. */
233 gaih_local(const char *name, const struct gaih_service *service,
234 const struct addrinfo *req, struct addrinfo **pai)
236 struct utsname utsname;
237 struct addrinfo *ai = *pai;
239 if ((name != NULL) && (req->ai_flags & AI_NUMERICHOST))
240 return (GAIH_OKIFUNSPEC | -EAI_NONAME);
242 if ((name != NULL) || (req->ai_flags & AI_CANONNAME))
243 if (uname(&utsname) < 0)
247 if (strcmp(name, "localhost") &&
248 strcmp(name, "local") &&
249 strcmp(name, "unix") &&
250 strcmp(name, utsname.nodename))
251 return (GAIH_OKIFUNSPEC | -EAI_NONAME);
254 if (req->ai_protocol || req->ai_socktype) {
255 const struct gaih_typeproto *tp = gaih_inet_typeproto + 1;
258 && ((tp->protoflag & GAI_PROTO_NOSERVICE) != 0
259 || (req->ai_socktype != 0 && req->ai_socktype != tp->socktype)
260 || (req->ai_protocol != 0 && !(tp->protoflag & GAI_PROTO_PROTOANY) && req->ai_protocol != tp->protocol))
265 if (req->ai_socktype)
266 return (GAIH_OKIFUNSPEC | -EAI_SOCKTYPE);
267 return (GAIH_OKIFUNSPEC | -EAI_SERVICE);
271 *pai = ai = malloc(sizeof(struct addrinfo) + sizeof(struct sockaddr_un)
272 + ((req->ai_flags & AI_CANONNAME)
273 ? (strlen(utsname.nodename) + 1) : 0));
278 ai->ai_flags = req->ai_flags;
279 ai->ai_family = AF_LOCAL;
280 ai->ai_socktype = req->ai_socktype ? req->ai_socktype : SOCK_STREAM;
281 ai->ai_protocol = req->ai_protocol;
282 ai->ai_addrlen = sizeof(struct sockaddr_un);
283 ai->ai_addr = (void *)ai + sizeof(struct addrinfo);
285 ((struct sockaddr_un *)ai->ai_addr)->sun_len = sizeof(struct sockaddr_un);
288 ((struct sockaddr_un *)ai->ai_addr)->sun_family = AF_LOCAL;
289 memset(((struct sockaddr_un *)ai->ai_addr)->sun_path, 0, UNIX_PATH_MAX);
292 struct sockaddr_un *sunp = (struct sockaddr_un *)ai->ai_addr;
294 if (strchr(service->name, '/') != NULL) {
295 if (strlen(service->name) >= sizeof(sunp->sun_path))
296 return GAIH_OKIFUNSPEC | -EAI_SERVICE;
297 strcpy(sunp->sun_path, service->name);
299 if (strlen(P_tmpdir "/") + 1 + strlen(service->name) >= sizeof(sunp->sun_path))
300 return (GAIH_OKIFUNSPEC | -EAI_SERVICE);
301 stpcpy(stpcpy(sunp->sun_path, P_tmpdir "/"), service->name);
304 /* This is a dangerous use of the interface since there is a time
305 window between the test for the file and the actual creation
306 (done by the caller) in which a file with the same name could
308 char *buf = ((struct sockaddr_un *)ai->ai_addr)->sun_path;
310 if (__path_search(buf, L_tmpnam, NULL, NULL, 0) != 0
311 || __gen_tempname(buf, __GT_NOCREATE, 0) != 0
317 ai->ai_canonname = NULL;
318 if (req->ai_flags & AI_CANONNAME)
319 ai->ai_canonname = strcpy((char *)(ai + 1) + sizeof(struct sockaddr_un),
326 gaih_inet_serv(const char *servicename, const struct gaih_typeproto *tp,
327 const struct addrinfo *req, struct gaih_servtuple *st)
330 size_t tmpbuflen = 1024;
336 tmpbuf = alloca(tmpbuflen);
337 r = getservbyname_r(servicename, tp->name, &ts, tmpbuf, tmpbuflen, &s);
338 if (r == 0 && s != NULL)
341 return (GAIH_OKIFUNSPEC | -EAI_SERVICE);
345 st->socktype = tp->socktype;
346 st->protocol = ((tp->protoflag & GAI_PROTO_PROTOANY) ? req->ai_protocol : tp->protocol);
347 st->port = s->s_port;
351 /* NB: also uses h,pat,rc,no_data variables */
352 #define gethosts(_family, _type) \
363 tmpbuf = alloca(tmpbuflen); \
364 rc = gethostbyname2_r(name, _family, &th, tmpbuf, \
365 tmpbuflen, &h, &herrno); \
366 } while (rc == ERANGE && herrno == NETDB_INTERNAL); \
368 if (herrno == NETDB_INTERNAL) { \
369 __set_h_errno(herrno); \
370 return -EAI_SYSTEM; \
372 if (herrno == TRY_AGAIN) \
373 no_data = EAI_AGAIN; \
375 no_data = (herrno == NO_DATA); \
376 } else if (h != NULL) { \
377 for (i = 0; h->h_addr_list[i]; i++) { \
378 if (*pat == NULL) { \
379 *pat = alloca(sizeof(struct gaih_addrtuple)); \
380 (*pat)->scopeid = 0; \
382 (*pat)->next = NULL; \
383 (*pat)->family = _family; \
384 memcpy((*pat)->addr, h->h_addr_list[i], sizeof(_type)); \
385 pat = &((*pat)->next); \
391 gaih_inet(const char *name, const struct gaih_service *service,
392 const struct addrinfo *req, struct addrinfo **pai)
394 struct gaih_servtuple nullserv;
396 const struct gaih_typeproto *tp = gaih_inet_typeproto;
397 struct gaih_servtuple *st = &nullserv;
398 struct gaih_addrtuple *at = NULL;
400 int v4mapped = (req->ai_family == PF_UNSPEC || req->ai_family == PF_INET6)
401 && (req->ai_flags & AI_V4MAPPED);
402 unsigned seen = __check_pf();
404 memset(&nullserv, 0, sizeof(nullserv));
406 if (req->ai_protocol || req->ai_socktype) {
409 && ((req->ai_socktype != 0 && req->ai_socktype != tp->socktype)
410 || (req->ai_protocol != 0 && !(tp->protoflag & GAI_PROTO_PROTOANY) && req->ai_protocol != tp->protocol)
416 if (req->ai_socktype)
417 return (GAIH_OKIFUNSPEC | -EAI_SOCKTYPE);
418 return (GAIH_OKIFUNSPEC | -EAI_SERVICE);
422 if (service != NULL) {
423 if ((tp->protoflag & GAI_PROTO_NOSERVICE) != 0)
424 return (GAIH_OKIFUNSPEC | -EAI_SERVICE);
426 if (service->num < 0) {
428 st = alloca(sizeof(struct gaih_servtuple));
429 rc = gaih_inet_serv(service->name, tp, req, st);
433 struct gaih_servtuple **pst = &st;
434 for (tp++; tp->name[0]; tp++) {
435 struct gaih_servtuple *newp;
437 if ((tp->protoflag & GAI_PROTO_NOSERVICE) != 0)
440 if (req->ai_socktype != 0 && req->ai_socktype != tp->socktype)
442 if (req->ai_protocol != 0
443 && !(tp->protoflag & GAI_PROTO_PROTOANY)
444 && req->ai_protocol != tp->protocol)
447 newp = alloca(sizeof(struct gaih_servtuple));
448 rc = gaih_inet_serv(service->name, tp, req, newp);
450 if (rc & GAIH_OKIFUNSPEC)
459 return (GAIH_OKIFUNSPEC | -EAI_SERVICE);
462 st = alloca(sizeof(struct gaih_servtuple));
464 st->socktype = tp->socktype;
465 st->protocol = ((tp->protoflag & GAI_PROTO_PROTOANY)
466 ? req->ai_protocol : tp->protocol);
467 st->port = htons(service->num);
469 } else if (req->ai_socktype || req->ai_protocol) {
470 st = alloca(sizeof(struct gaih_servtuple));
472 st->socktype = tp->socktype;
473 st->protocol = ((tp->protoflag & GAI_PROTO_PROTOANY)
474 ? req->ai_protocol : tp->protocol);
478 * Neither socket type nor protocol is set. Return all socket types
481 struct gaih_servtuple **lastp = &st;
482 for (++tp; tp->name[0]; ++tp) {
483 struct gaih_servtuple *newp;
485 newp = alloca(sizeof(struct gaih_servtuple));
487 newp->socktype = tp->socktype;
488 newp->protocol = tp->protocol;
497 at = alloca(sizeof(struct gaih_addrtuple));
498 at->family = AF_UNSPEC;
502 if (inet_pton(AF_INET, name, at->addr) > 0) {
503 if (req->ai_family == AF_UNSPEC || req->ai_family == AF_INET || v4mapped)
504 at->family = AF_INET;
509 #if defined __UCLIBC_HAS_IPV6__
510 if (at->family == AF_UNSPEC) {
511 char *namebuf = strdupa(name);
514 scope_delim = strchr(namebuf, SCOPE_DELIMITER);
515 if (scope_delim != NULL)
518 if (inet_pton(AF_INET6, namebuf, at->addr) > 0) {
519 if (req->ai_family == AF_UNSPEC || req->ai_family == AF_INET6)
520 at->family = AF_INET6;
524 if (scope_delim != NULL) {
525 int try_numericscope = 0;
526 uint32_t *a32 = (uint32_t*)at->addr;
527 if (IN6_IS_ADDR_LINKLOCAL(a32) || IN6_IS_ADDR_MC_LINKLOCAL(at->addr)) {
528 at->scopeid = if_nametoindex(scope_delim + 1);
529 if (at->scopeid == 0)
530 try_numericscope = 1;
532 try_numericscope = 1;
534 if (try_numericscope != 0) {
536 assert(sizeof(uint32_t) <= sizeof(unsigned long));
537 at->scopeid = (uint32_t)strtoul(scope_delim + 1, &end, 10);
539 return (GAIH_OKIFUNSPEC | -EAI_NONAME);
546 if (at->family == AF_UNSPEC && (req->ai_flags & AI_NUMERICHOST) == 0) {
548 struct gaih_addrtuple **pat = &at;
553 * If we are looking for both IPv4 and IPv6 address we don't want
554 * the lookup functions to automatically promote IPv4 addresses to
557 #if defined __UCLIBC_HAS_IPV6__
558 if (req->ai_family == AF_UNSPEC || req->ai_family == AF_INET6)
559 if (!(req->ai_flags & AI_ADDRCONFIG) || (seen & SEEN_IPV6))
560 gethosts(AF_INET6, struct in6_addr);
562 no_inet6_data = no_data;
564 if (req->ai_family == AF_INET
565 || (!v4mapped && req->ai_family == AF_UNSPEC)
566 || (v4mapped && (no_inet6_data != 0 || (req->ai_flags & AI_ALL)))
568 if (!(req->ai_flags & AI_ADDRCONFIG) || (seen & SEEN_IPV4))
569 gethosts(AF_INET, struct in_addr);
572 if (no_data != 0 && no_inet6_data != 0) {
573 /* If both requests timed out report this. */
574 if (no_data == EAI_AGAIN && no_inet6_data == EAI_AGAIN)
577 * We made requests but they turned out no data.
578 * The name is known, though.
580 return (GAIH_OKIFUNSPEC | -EAI_AGAIN);
584 if (at->family == AF_UNSPEC)
585 return (GAIH_OKIFUNSPEC | -EAI_NONAME);
587 struct gaih_addrtuple *atr;
589 atr = at = alloca(sizeof(struct gaih_addrtuple));
590 memset(at, '\0', sizeof(struct gaih_addrtuple));
591 if (req->ai_family == 0) {
592 at->next = alloca(sizeof(struct gaih_addrtuple));
593 memset(at->next, '\0', sizeof(struct gaih_addrtuple));
595 #if defined __UCLIBC_HAS_IPV6__
596 if (req->ai_family == 0 || req->ai_family == AF_INET6) {
597 at->family = AF_INET6;
598 if ((req->ai_flags & AI_PASSIVE) == 0)
599 memcpy(at->addr, &in6addr_loopback, sizeof(struct in6_addr));
603 if (req->ai_family == 0 || req->ai_family == AF_INET) {
604 atr->family = AF_INET;
605 if ((req->ai_flags & AI_PASSIVE) == 0) {
606 uint32_t *a = (uint32_t*)atr->addr;
607 *a = htonl(INADDR_LOOPBACK);
616 const char *c = NULL;
617 struct gaih_servtuple *st2;
618 struct gaih_addrtuple *at2 = at;
619 size_t socklen, namelen;
623 * buffer is the size of an unformatted IPv6 address in
626 char buffer[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255")];
628 while (at2 != NULL) {
629 if (req->ai_flags & AI_CANONNAME) {
630 struct hostent *h = NULL;
633 size_t tmpbuflen = 512;
638 tmpbuf = alloca(tmpbuflen);
639 rc = gethostbyaddr_r(at2->addr,
640 ((at2->family == AF_INET6)
641 ? sizeof(struct in6_addr)
642 : sizeof(struct in_addr)),
644 &th, tmpbuf, tmpbuflen,
646 } while (rc == errno && herrno == NETDB_INTERNAL);
648 if (rc != 0 && herrno == NETDB_INTERNAL) {
649 __set_h_errno(herrno);
654 c = inet_ntop(at2->family, at2->addr, buffer, sizeof(buffer));
659 return (GAIH_OKIFUNSPEC | -EAI_NONAME);
661 namelen = strlen(c) + 1;
665 #if defined __UCLIBC_HAS_IPV6__
666 if (at2->family == AF_INET6 || v4mapped) {
668 socklen = sizeof(struct sockaddr_in6);
671 #if defined __UCLIBC_HAS_IPV4__ && defined __UCLIBC_HAS_IPV6__
674 #if defined __UCLIBC_HAS_IPV4__
677 socklen = sizeof(struct sockaddr_in);
680 for (st2 = st; st2 != NULL; st2 = st2->next) {
681 if (req->ai_flags & AI_ADDRCONFIG) {
682 if (family == AF_INET && !(seen & SEEN_IPV4))
684 #if defined __UCLIBC_HAS_IPV6__
685 else if (family == AF_INET6 && !(seen & SEEN_IPV6))
689 *pai = malloc(sizeof(struct addrinfo) + socklen + namelen);
693 (*pai)->ai_flags = req->ai_flags;
694 (*pai)->ai_family = family;
695 (*pai)->ai_socktype = st2->socktype;
696 (*pai)->ai_protocol = st2->protocol;
697 (*pai)->ai_addrlen = socklen;
698 (*pai)->ai_addr = (void *) (*pai) + sizeof(struct addrinfo);
700 (*pai)->ai_addr->sa_len = socklen;
702 (*pai)->ai_addr->sa_family = family;
704 #if defined __UCLIBC_HAS_IPV6__
705 if (family == AF_INET6) {
706 struct sockaddr_in6 *sin6p = (struct sockaddr_in6 *) (*pai)->ai_addr;
708 sin6p->sin6_flowinfo = 0;
709 if (at2->family == AF_INET6) {
710 memcpy(&sin6p->sin6_addr,
711 at2->addr, sizeof(struct in6_addr));
713 sin6p->sin6_addr.s6_addr32[0] = 0;
714 sin6p->sin6_addr.s6_addr32[1] = 0;
715 sin6p->sin6_addr.s6_addr32[2] = htonl(0x0000ffff);
716 memcpy(&sin6p->sin6_addr.s6_addr32[3],
717 at2->addr, sizeof(sin6p->sin6_addr.s6_addr32[3]));
719 sin6p->sin6_port = st2->port;
720 sin6p->sin6_scope_id = at2->scopeid;
723 #if defined __UCLIBC_HAS_IPV4__ && defined __UCLIBC_HAS_IPV6__
726 #if defined __UCLIBC_HAS_IPV4__
728 struct sockaddr_in *sinp = (struct sockaddr_in *) (*pai)->ai_addr;
730 memcpy(&sinp->sin_addr, at2->addr, sizeof(struct in_addr));
731 sinp->sin_port = st2->port;
732 memset(sinp->sin_zero, '\0', sizeof(sinp->sin_zero));
736 (*pai)->ai_canonname = ((void *) (*pai) +
737 sizeof(struct addrinfo) + socklen);
738 strcpy((*pai)->ai_canonname, c);
740 (*pai)->ai_canonname = NULL;
742 (*pai)->ai_next = NULL;
743 pai = &((*pai)->ai_next);
752 static const struct gaih gaih[] = {
753 #if defined __UCLIBC_HAS_IPV6__
754 { PF_INET6, gaih_inet },
756 { PF_INET, gaih_inet },
758 { PF_LOCAL, gaih_local },
764 freeaddrinfo(struct addrinfo *ai)
774 libc_hidden_def(freeaddrinfo)
777 getaddrinfo(const char *name, const char *service,
778 const struct addrinfo *hints, struct addrinfo **pai)
780 int i = 0, j, last_i = 0;
781 struct addrinfo *p = NULL, **end;
782 const struct gaih *g = gaih, *pg = NULL;
783 struct gaih_service gaih_service, *pservice;
784 struct addrinfo default_hints;
786 if (name != NULL && name[0] == '*' && name[1] == 0)
789 if (service != NULL && service[0] == '*' && service[1] == 0)
792 if (name == NULL && service == NULL)
796 memset(&default_hints, 0, sizeof(default_hints));
798 default_hints.ai_family = AF_UNSPEC;
799 hints = &default_hints;
802 if (hints->ai_flags & ~(AI_PASSIVE|AI_CANONNAME|AI_NUMERICHOST|
803 AI_ADDRCONFIG|AI_V4MAPPED|AI_NUMERICSERV|AI_ALL))
806 if ((hints->ai_flags & AI_CANONNAME) && name == NULL)
809 if (service && service[0]) {
811 gaih_service.name = service;
812 gaih_service.num = strtoul(gaih_service.name, &c, 10);
814 if (hints->ai_flags & AI_NUMERICSERV)
816 gaih_service.num = -1;
819 * Can't specify a numerical socket unless a protocol
822 if (hints->ai_socktype == 0 && hints->ai_protocol == 0)
825 pservice = &gaih_service;
835 if (hints->ai_family == g->family || hints->ai_family == AF_UNSPEC) {
836 if ((hints->ai_flags & AI_ADDRCONFIG) && !addrconfig(g->family)) {
841 if (pg == NULL || pg->gaih != g->gaih) {
843 i = g->gaih(name, pservice, hints, end);
846 if (hints->ai_family == AF_UNSPEC && (i & GAIH_OKIFUNSPEC))
850 return -(i & GAIH_EAI);
854 end = &((*end)->ai_next);
868 if (pai == NULL && last_i == 0)
871 /* if (p) - never happens, see above */
872 /* freeaddrinfo(p); */
874 return last_i ? -(last_i & GAIH_EAI) : EAI_NONAME;
876 libc_hidden_def(getaddrinfo)