getaddrinfo.c
来自「Axis 221 camera embedded programing inte」· C语言 代码 · 共 874 行 · 第 1/2 页
C
874 行
} else if (req->ai_socktype || req->ai_protocol) { st = alloca (sizeof (struct gaih_servtuple)); st->next = NULL; st->socktype = tp->socktype; st->protocol = ((tp->protoflag & GAI_PROTO_PROTOANY) ? req->ai_protocol : tp->protocol); st->port = 0; } else { /* * Neither socket type nor protocol is set. Return all socket types * we know about. */ struct gaih_servtuple **lastp = &st; for (++tp; tp->name[0]; ++tp) { struct gaih_servtuple *newp; newp = alloca (sizeof (struct gaih_servtuple)); newp->next = NULL; newp->socktype = tp->socktype; newp->protocol = tp->protocol; newp->port = 0; *lastp = newp; lastp = &newp->next; } } if (name != NULL) { at = alloca (sizeof (struct gaih_addrtuple)); at->family = AF_UNSPEC; at->scopeid = 0; at->next = NULL; if (inet_pton (AF_INET, name, at->addr) > 0) { if (req->ai_family == AF_UNSPEC || req->ai_family == AF_INET || v4mapped) at->family = AF_INET; else return -EAI_FAMILY; }#if __UCLIBC_HAS_IPV6__ if (at->family == AF_UNSPEC) { char *namebuf = strdupa (name); char *scope_delim; scope_delim = strchr (namebuf, SCOPE_DELIMITER); if (scope_delim != NULL) *scope_delim = '\0'; if (inet_pton (AF_INET6, namebuf, at->addr) > 0) { if (req->ai_family == AF_UNSPEC || req->ai_family == AF_INET6) at->family = AF_INET6; else return -EAI_FAMILY; if (scope_delim != NULL) { int try_numericscope = 0; if (IN6_IS_ADDR_LINKLOCAL (at->addr) || IN6_IS_ADDR_MC_LINKLOCAL (at->addr)) { at->scopeid = if_nametoindex (scope_delim + 1); if (at->scopeid == 0) try_numericscope = 1; } else try_numericscope = 1; if (try_numericscope != 0) { char *end; assert (sizeof (uint32_t) <= sizeof (unsigned long)); at->scopeid = (uint32_t) strtoul (scope_delim + 1, &end, 10); if (*end != '\0') return GAIH_OKIFUNSPEC | -EAI_NONAME; } } } }#endif if (at->family == AF_UNSPEC && (req->ai_flags & AI_NUMERICHOST) == 0) { struct hostent *h; struct gaih_addrtuple **pat = &at; int no_data = 0; int no_inet6_data; /* * If we are looking for both IPv4 and IPv6 address we don't want * the lookup functions to automatically promote IPv4 addresses to * IPv6 addresses. */#if __UCLIBC_HAS_IPV6__ if (req->ai_family == AF_UNSPEC || req->ai_family == AF_INET6) gethosts (AF_INET6, struct in6_addr);#endif no_inet6_data = no_data; if (req->ai_family == AF_INET || (!v4mapped && req->ai_family == AF_UNSPEC) || (v4mapped && (no_inet6_data != 0 || (req->ai_flags & AI_ALL)))) gethosts (AF_INET, struct in_addr); if (no_data != 0 && no_inet6_data != 0) { /* If both requests timed out report this. */ if (no_data == EAI_AGAIN && no_inet6_data == EAI_AGAIN) return -EAI_AGAIN; /* * We made requests but they turned out no data. * The name is known, though. */ return (GAIH_OKIFUNSPEC | -EAI_AGAIN); } } if (at->family == AF_UNSPEC) return (GAIH_OKIFUNSPEC | -EAI_NONAME); } else { struct gaih_addrtuple *atr; atr = at = alloca (sizeof (struct gaih_addrtuple)); memset (at, '\0', sizeof (struct gaih_addrtuple)); if (req->ai_family == 0) { at->next = alloca (sizeof (struct gaih_addrtuple)); memset (at->next, '\0', sizeof (struct gaih_addrtuple)); }#if __UCLIBC_HAS_IPV6__ if (req->ai_family == 0 || req->ai_family == AF_INET6) { extern const struct in6_addr __in6addr_loopback; at->family = AF_INET6; if ((req->ai_flags & AI_PASSIVE) == 0) memcpy (at->addr, &__in6addr_loopback, sizeof (struct in6_addr)); atr = at->next; }#endif if (req->ai_family == 0 || req->ai_family == AF_INET) { atr->family = AF_INET; if ((req->ai_flags & AI_PASSIVE) == 0) *(uint32_t *) atr->addr = htonl (INADDR_LOOPBACK); } } if (pai == NULL) return 0; { const char *c = NULL; struct gaih_servtuple *st2; struct gaih_addrtuple *at2 = at; size_t socklen, namelen; sa_family_t family; /* * buffer is the size of an unformatted IPv6 address in * printable format. */ char buffer[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255"]; while (at2 != NULL) { if (req->ai_flags & AI_CANONNAME) { struct hostent *h = NULL; int herrno; struct hostent th; size_t tmpbuflen = 512; char *tmpbuf; do { tmpbuflen *= 2; tmpbuf = alloca (tmpbuflen); if (tmpbuf == NULL) return -EAI_MEMORY; rc = gethostbyaddr_r (at2->addr, ((at2->family == AF_INET6) ? sizeof(struct in6_addr) : sizeof(struct in_addr)), at2->family, &th, tmpbuf, tmpbuflen, &h, &herrno); } while (rc == errno && herrno == NETDB_INTERNAL); if (rc != 0 && herrno == NETDB_INTERNAL) { __set_h_errno (herrno); return -EAI_SYSTEM; } if (h == NULL) c = inet_ntop (at2->family, at2->addr, buffer, sizeof(buffer)); else c = h->h_name; if (c == NULL) return GAIH_OKIFUNSPEC | -EAI_NONAME; namelen = strlen (c) + 1; } else namelen = 0;#if __UCLIBC_HAS_IPV6__ if (at2->family == AF_INET6 || v4mapped) { family = AF_INET6; socklen = sizeof (struct sockaddr_in6); } else#endif { family = AF_INET; socklen = sizeof (struct sockaddr_in); } for (st2 = st; st2 != NULL; st2 = st2->next) { *pai = malloc (sizeof (struct addrinfo) + socklen + namelen); if (*pai == NULL) return -EAI_MEMORY; (*pai)->ai_flags = req->ai_flags; (*pai)->ai_family = family; (*pai)->ai_socktype = st2->socktype; (*pai)->ai_protocol = st2->protocol; (*pai)->ai_addrlen = socklen; (*pai)->ai_addr = (void *) (*pai) + sizeof(struct addrinfo);#if SALEN (*pai)->ai_addr->sa_len = socklen;#endif /* SALEN */ (*pai)->ai_addr->sa_family = family;#if __UCLIBC_HAS_IPV6__ if (family == AF_INET6) { struct sockaddr_in6 *sin6p = (struct sockaddr_in6 *) (*pai)->ai_addr; sin6p->sin6_flowinfo = 0; if (at2->family == AF_INET6) { memcpy (&sin6p->sin6_addr, at2->addr, sizeof (struct in6_addr)); } else { sin6p->sin6_addr.s6_addr32[0] = 0; sin6p->sin6_addr.s6_addr32[1] = 0; sin6p->sin6_addr.s6_addr32[2] = htonl(0x0000ffff); memcpy(&sin6p->sin6_addr.s6_addr32[3], at2->addr, sizeof (sin6p->sin6_addr.s6_addr32[3])); } sin6p->sin6_port = st2->port; sin6p->sin6_scope_id = at2->scopeid; } else#endif { struct sockaddr_in *sinp = (struct sockaddr_in *) (*pai)->ai_addr; memcpy (&sinp->sin_addr, at2->addr, sizeof (struct in_addr)); sinp->sin_port = st2->port; memset (sinp->sin_zero, '\0', sizeof (sinp->sin_zero)); } if (c) { (*pai)->ai_canonname = ((void *) (*pai) + sizeof (struct addrinfo) + socklen); strcpy ((*pai)->ai_canonname, c); } else (*pai)->ai_canonname = NULL; (*pai)->ai_next = NULL; pai = &((*pai)->ai_next); } at2 = at2->next; } } return 0;}static struct gaih gaih[] ={#if __UCLIBC_HAS_IPV6__ { PF_INET6, gaih_inet },#endif { PF_INET, gaih_inet },#if 0 { PF_LOCAL, gaih_local },#endif { PF_UNSPEC, NULL }};intgetaddrinfo (const char *name, const char *service, const struct addrinfo *hints, struct addrinfo **pai){ int i = 0, j = 0, last_i = 0; struct addrinfo *p = NULL, **end; struct gaih *g = gaih, *pg = NULL; struct gaih_service gaih_service, *pservice; if (name != NULL && name[0] == '*' && name[1] == 0) name = NULL; if (service != NULL && service[0] == '*' && service[1] == 0) service = NULL; if (name == NULL && service == NULL) return EAI_NONAME; if (hints == NULL) hints = &default_hints; if (hints->ai_flags & ~(AI_PASSIVE|AI_CANONNAME|AI_NUMERICHOST| AI_ADDRCONFIG|AI_V4MAPPED|AI_ALL)) return EAI_BADFLAGS; if ((hints->ai_flags & AI_CANONNAME) && name == NULL) return EAI_BADFLAGS; if (service && service[0]) { char *c; gaih_service.name = service; gaih_service.num = strtoul (gaih_service.name, &c, 10); if (*c) gaih_service.num = -1; else /* * Can't specify a numerical socket unless a protocol * family was given. */ if (hints->ai_socktype == 0 && hints->ai_protocol == 0) return EAI_SERVICE; pservice = &gaih_service; } else pservice = NULL; if (pai) end = &p; else end = NULL; while (g->gaih) { if (hints->ai_family == g->family || hints->ai_family == AF_UNSPEC) { if ((hints->ai_flags & AI_ADDRCONFIG) && !addrconfig(g->family)) continue; j++; if (pg == NULL || pg->gaih != g->gaih) { pg = g; i = g->gaih (name, pservice, hints, end); if (i != 0) { last_i = i; if (hints->ai_family == AF_UNSPEC && (i & GAIH_OKIFUNSPEC)) continue; if (p) freeaddrinfo (p); return -(i & GAIH_EAI); } if (end) while(*end) end = &((*end)->ai_next); } } ++g; } if (j == 0) return EAI_FAMILY; if (p) { *pai = p; return 0; } if (pai == NULL && last_i == 0) return 0; if (p) freeaddrinfo (p); return last_i ? -(last_i & GAIH_EAI) : EAI_NONAME;}voidfreeaddrinfo (struct addrinfo *ai){ struct addrinfo *p; while (ai != NULL) { p = ai; ai = ai->ai_next; free (p); }}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?