📄 getaddrinfo.c
字号:
if (!strchr(hostname, '.') && (cp = res_hostalias(net_data->res, hostname, tmp, sizeof(tmp)))) hostname = cp; result = (*ho->addrinfo)(ho, hostname, pai); if (!net_data->ho_stayopen) { (*ho->minimize)(ho); } if (result == NULL) { int e = h_errno; switch(e) { case NETDB_INTERNAL: error = EAI_SYSTEM; break; case TRY_AGAIN: error = EAI_AGAIN; break; case NO_RECOVERY: error = EAI_FAIL; break; case HOST_NOT_FOUND: case NO_DATA: error = EAI_NONAME; break; default: case NETDB_SUCCESS: /* should be impossible... */ error = EAI_NONAME; break; } goto free; } for (cur = result; cur; cur = cur->ai_next) { GET_PORT(cur, servname); /* XXX: redundant lookups... */ /* canonname should already be filled. */ } *res = result; return(0);free: if (result) freeaddrinfo(result); return error;}static intexplore_copy(pai, src0, res) const struct addrinfo *pai; /* seed */ const struct addrinfo *src0; /* source */ struct addrinfo **res;{ int error; struct addrinfo sentinel, *cur; const struct addrinfo *src; error = 0; sentinel.ai_next = NULL; cur = &sentinel; for (src = src0; src != NULL; src = src->ai_next) { if (src->ai_family != pai->ai_family) continue; cur->ai_next = copy_ai(src); if (!cur->ai_next) { error = EAI_MEMORY; goto fail; } cur->ai_next->ai_socktype = pai->ai_socktype; cur->ai_next->ai_protocol = pai->ai_protocol; cur = cur->ai_next; } *res = sentinel.ai_next; return 0;fail: freeaddrinfo(sentinel.ai_next); return error;}/* * hostname == NULL. * passive socket -> anyaddr (0.0.0.0 or ::) * non-passive socket -> localhost (127.0.0.1 or ::1) */static intexplore_null(pai, servname, res) const struct addrinfo *pai; const char *servname; struct addrinfo **res;{ const struct afd *afd; struct addrinfo *cur; struct addrinfo sentinel; int error; *res = NULL; sentinel.ai_next = NULL; cur = &sentinel; afd = find_afd(pai->ai_family); if (afd == NULL) return 0; if (pai->ai_flags & AI_PASSIVE) { GET_AI(cur->ai_next, afd, afd->a_addrany); /* xxx meaningless? * GET_CANONNAME(cur->ai_next, "anyaddr"); */ GET_PORT(cur->ai_next, servname); } else { GET_AI(cur->ai_next, afd, afd->a_loopback); /* xxx meaningless? * GET_CANONNAME(cur->ai_next, "localhost"); */ GET_PORT(cur->ai_next, servname); } cur = cur->ai_next; *res = sentinel.ai_next; return 0;free: if (sentinel.ai_next) freeaddrinfo(sentinel.ai_next); return error;}/* * numeric hostname */static intexplore_numeric(pai, hostname, servname, res) const struct addrinfo *pai; const char *hostname; const char *servname; struct addrinfo **res;{ const struct afd *afd; struct addrinfo *cur; struct addrinfo sentinel; int error; char pton[PTON_MAX]; *res = NULL; sentinel.ai_next = NULL; cur = &sentinel; afd = find_afd(pai->ai_family); if (afd == NULL) return 0; switch (afd->a_af) {#if 0 /*X/Open spec*/ case AF_INET: if (inet_aton(hostname, (struct in_addr *)pton) == 1) { if (pai->ai_family == afd->a_af || pai->ai_family == PF_UNSPEC /*?*/) { GET_AI(cur->ai_next, afd, pton); GET_PORT(cur->ai_next, servname); while (cur && cur->ai_next) cur = cur->ai_next; } else ERR(EAI_FAMILY); /*xxx*/ } break;#endif default: if (inet_pton(afd->a_af, hostname, pton) == 1) { if (pai->ai_family == afd->a_af || pai->ai_family == PF_UNSPEC /*?*/) { GET_AI(cur->ai_next, afd, pton); GET_PORT(cur->ai_next, servname); while (cur && cur->ai_next) cur = cur->ai_next; } else ERR(EAI_FAMILY); /*xxx*/ } break; } *res = sentinel.ai_next; return 0;free:bad: if (sentinel.ai_next) freeaddrinfo(sentinel.ai_next); return error;}/* * numeric hostname with scope */static intexplore_numeric_scope(pai, hostname, servname, res) const struct addrinfo *pai; const char *hostname; const char *servname; struct addrinfo **res;{#ifndef SCOPE_DELIMITER return explore_numeric(pai, hostname, servname, res);#else const struct afd *afd; struct addrinfo *cur; int error; char *cp, *hostname2 = NULL, *scope, *addr; struct sockaddr_in6 *sin6; afd = find_afd(pai->ai_family); if (afd == NULL) return 0; if (!afd->a_scoped) return explore_numeric(pai, hostname, servname, res); cp = strchr(hostname, SCOPE_DELIMITER); if (cp == NULL) return explore_numeric(pai, hostname, servname, res); /* * Handle special case of <scoped_address><delimiter><scope id> */ hostname2 = strdup(hostname); if (hostname2 == NULL) return EAI_MEMORY; /* terminate at the delimiter */ hostname2[cp - hostname] = '\0'; addr = hostname2; scope = cp + 1; error = explore_numeric(pai, addr, servname, res); if (error == 0) { u_int32_t scopeid = 0; for (cur = *res; cur; cur = cur->ai_next) { if (cur->ai_family != AF_INET6) continue; sin6 = (struct sockaddr_in6 *)(void *)cur->ai_addr; if (!ip6_str2scopeid(scope, sin6, &scopeid)) { free(hostname2); return(EAI_NONAME); /* XXX: is return OK? */ }#ifdef HAVE_SIN6_SCOPE_ID sin6->sin6_scope_id = scopeid;#endif } } free(hostname2); return error;#endif}static intget_canonname(pai, ai, str) const struct addrinfo *pai; struct addrinfo *ai; const char *str;{ if ((pai->ai_flags & AI_CANONNAME) != 0) { ai->ai_canonname = (char *)malloc(strlen(str) + 1); if (ai->ai_canonname == NULL) return EAI_MEMORY; strcpy(ai->ai_canonname, str); } return 0;}static struct addrinfo *get_ai(pai, afd, addr) const struct addrinfo *pai; const struct afd *afd; const char *addr;{ char *p; struct addrinfo *ai; ai = (struct addrinfo *)malloc(sizeof(struct addrinfo) + (afd->a_socklen)); if (ai == NULL) return NULL; memcpy(ai, pai, sizeof(struct addrinfo)); ai->ai_addr = (struct sockaddr *)(void *)(ai + 1); memset(ai->ai_addr, 0, (size_t)afd->a_socklen);#ifdef HAVE_SA_LEN ai->ai_addr->sa_len = afd->a_socklen;#endif ai->ai_addrlen = afd->a_socklen; ai->ai_addr->sa_family = ai->ai_family = afd->a_af; p = (char *)(void *)(ai->ai_addr); memcpy(p + afd->a_off, addr, (size_t)afd->a_addrlen); return ai;}/* XXX need to malloc() the same way we do from other functions! */static struct addrinfo *copy_ai(pai) const struct addrinfo *pai;{ struct addrinfo *ai; size_t l; l = sizeof(*ai) + pai->ai_addrlen; if ((ai = (struct addrinfo *)malloc(l)) == NULL) return NULL; memset(ai, 0, l); memcpy(ai, pai, sizeof(*ai)); ai->ai_addr = (struct sockaddr *)(void *)(ai + 1); memcpy(ai->ai_addr, pai->ai_addr, pai->ai_addrlen); if (pai->ai_canonname) { l = strlen(pai->ai_canonname) + 1; if ((ai->ai_canonname = malloc(l)) == NULL) { free(ai); return NULL; } strcpy(ai->ai_canonname, pai->ai_canonname); /* (checked) */ } else { /* just to make sure */ ai->ai_canonname = NULL; } ai->ai_next = NULL; return ai;}static intget_portmatch(const struct addrinfo *ai, const char *servname) { /* get_port does not touch first argument. when matchonly == 1. */ /* LINTED const cast */ return get_port((const struct addrinfo *)ai, servname, 1);}static intget_port(const struct addrinfo *ai, const char *servname, int matchonly) { const char *proto; struct servent *sp; int port; int allownumeric; if (servname == NULL) return 0; switch (ai->ai_family) { case AF_INET:#ifdef AF_INET6 case AF_INET6:#endif break; default: return 0; } switch (ai->ai_socktype) { case SOCK_RAW: return EAI_SERVICE; case SOCK_DGRAM: case SOCK_STREAM: allownumeric = 1; break; case ANY: switch (ai->ai_family) { case AF_INET:#ifdef AF_INET6 case AF_INET6:#endif allownumeric = 1; break; default: allownumeric = 0; break; } break; default: return EAI_SOCKTYPE; } if (str_isnumber(servname)) { if (!allownumeric) return EAI_SERVICE; port = atoi(servname); if (port < 0 || port > 65535) return EAI_SERVICE; port = htons(port); } else { switch (ai->ai_socktype) { case SOCK_DGRAM: proto = "udp"; break; case SOCK_STREAM: proto = "tcp"; break; default: proto = NULL; break; } if ((sp = getservbyname(servname, proto)) == NULL) return EAI_SERVICE; port = sp->s_port; } if (!matchonly) { switch (ai->ai_family) { case AF_INET: ((struct sockaddr_in *)(void *) ai->ai_addr)->sin_port = port; break; case AF_INET6: ((struct sockaddr_in6 *)(void *) ai->ai_addr)->sin6_port = port; break; } } return 0;}static const struct afd *find_afd(af) int af;{ const struct afd *afd; if (af == PF_UNSPEC) return NULL; for (afd = afdl; afd->a_af; afd++) { if (afd->a_af == af) return afd; } return NULL;}/* * post-2553: AI_ADDRCONFIG check. if we use getipnodeby* as backend, backend * will take care of it. * the semantics of AI_ADDRCONFIG is not defined well. we are not sure * if the code is right or not. */static intaddrconfig(af) int af;{ int s; /* XXX errno */ s = socket(af, SOCK_DGRAM, 0); if (s < 0) { if (errno != EMFILE) return 0; } else close(s); return 1;}/* convert a string to a scope identifier. XXX: IPv6 specific */static intip6_str2scopeid(char *scope, struct sockaddr_in6 *sin6, u_int32_t *scopeidp){ u_int32_t scopeid; u_long lscopeid; struct in6_addr *a6 = &sin6->sin6_addr; char *ep; /* empty scopeid portion is invalid */ if (*scope == '\0') return (0);#ifdef USE_IFNAMELINKID if (IN6_IS_ADDR_LINKLOCAL(a6) || IN6_IS_ADDR_MC_LINKLOCAL(a6) || IN6_IS_ADDR_MC_NODELOCAL(a6)) { /* * Using interface names as link indices can be allowed * only when we can assume a one-to-one mappings between * links and interfaces. See comments in getnameinfo.c. */ scopeid = if_nametoindex(scope); if (scopeid == 0) goto trynumeric; *scopeidp = scopeid; return (1); }#endif /* still unclear about literal, allow numeric only - placeholder */ if (IN6_IS_ADDR_SITELOCAL(a6) || IN6_IS_ADDR_MC_SITELOCAL(a6)) goto trynumeric; if (IN6_IS_ADDR_MC_ORGLOCAL(a6)) goto trynumeric; else goto trynumeric; /* global */ /* try to convert to a numeric id as a last resort */trynumeric: errno = 0; lscopeid = strtoul(scope, &ep, 10); scopeid = lscopeid & 0xffffffff; if (errno == 0 && ep && *ep == '\0' && scopeid == lscopeid) { *scopeidp = scopeid; return (1); } else return (0);}struct addrinfo *hostent2addrinfo(hp, pai) struct hostent *hp; const struct addrinfo *pai;{ int i, af, error = 0; char **aplist = NULL, *ap; struct addrinfo sentinel, *cur; const struct afd *afd; af = hp->h_addrtype; if (pai->ai_family != AF_UNSPEC && af != pai->ai_family) return(NULL); afd = find_afd(af); if (afd == NULL) return(NULL); aplist = hp->h_addr_list; memset(&sentinel, 0, sizeof(sentinel)); cur = &sentinel; for (i = 0; (ap = aplist[i]) != NULL; i++) {#if 0 /* the trick seems too much */ af = hp->h_addr_list; if (af == AF_INET6 && IN6_IS_ADDR_V4MAPPED((struct in6_addr *)ap)) { af = AF_INET; ap = ap + sizeof(struct in6_addr) - sizeof(struct in_addr); } afd = find_afd(af); if (afd == NULL) continue;#endif /* 0 */ GET_AI(cur->ai_next, afd, ap); /* GET_PORT(cur->ai_next, servname); */ if ((pai->ai_flags & AI_CANONNAME) != 0) { /* * RFC2553 says that ai_canonname will be set only for * the first element. we do it for all the elements, * just for convenience. */ GET_CANONNAME(cur->ai_next, hp->h_name); } while (cur && cur->ai_next) /* no need to loop, actually. */ cur = cur->ai_next; continue; free: if (cur->ai_next) freeaddrinfo(cur->ai_next); cur->ai_next = NULL; /* continue, without tht pointer CUR advanced. */ } return(sentinel.ai_next);}struct addrinfo *addr2addrinfo(pai, cp) const struct addrinfo *pai; const char *cp;{ const struct afd *afd; afd = find_afd(pai->ai_family); if (afd == NULL) return(NULL); return(get_ai(pai, afd, cp));}static struct net_data *init(){ struct net_data *net_data; if (!(net_data = net_data_init(NULL))) goto error; if (!net_data->ho) { net_data->ho = (*net_data->irs->ho_map)(net_data->irs); if (!net_data->ho || !net_data->res) {error: errno = EIO; if (net_data && net_data->res) RES_SET_H_ERRNO(net_data->res, NETDB_INTERNAL); return (NULL); } (*net_data->ho->res_set)(net_data->ho, net_data->res, NULL); } return (net_data);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -