📄 getaddrinfo.c
字号:
pai->ai_socktype = SOCK_STREAM; pai->ai_protocol = IPPROTO_TCP; } else ERR(EAI_PROTOCOL); /*xxx*/ } } } /* * hostname == NULL. * passive socket -> anyaddr (0.0.0.0 or ::) * non-passive socket -> localhost (127.0.0.1 or ::1) */ if (hostname == NULL) { struct afd *afd; int s; for (afd = &afdl[0]; afd->a_af; afd++) { if (!(pai->ai_family == PF_UNSPEC || pai->ai_family == afd->a_af)) { continue; } /* * filter out AFs that are not supported by the kernel * XXX errno? */ s = socket(afd->a_af, SOCK_DGRAM, 0); if (s < 0) continue; close(s); if (pai->ai_flags & AI_PASSIVE) { GET_AI(cur->ai_next, afd, afd->a_addrany, port); /* xxx meaningless? * GET_CANONNAME(cur->ai_next, "anyaddr"); */ } else { GET_AI(cur->ai_next, afd, afd->a_loopback, port); /* xxx meaningless? * GET_CANONNAME(cur->ai_next, "localhost"); */ } cur = cur->ai_next; } top = sentinel.ai_next; if (top) goto good; else ERR(EAI_FAMILY); } /* hostname as numeric name */ for (i = 0; afdl[i].a_af; i++) { if (inet_pton(afdl[i].a_af, hostname, pton) == 1) { u_long v4a; u_char pfx; switch (afdl[i].a_af) { case AF_INET: v4a = ntohl(((struct in_addr *)pton)->s_addr); if (IN_MULTICAST(v4a) || IN_EXPERIMENTAL(v4a)) pai->ai_flags &= ~AI_CANONNAME; v4a >>= IN_CLASSA_NSHIFT; if (v4a == 0 || v4a == IN_LOOPBACKNET) pai->ai_flags &= ~AI_CANONNAME; break;#ifdef INET6 case AF_INET6: pfx = ((struct in6_addr *)pton)->s6_addr[0]; if (pfx == 0 || pfx == 0xfe || pfx == 0xff) pai->ai_flags &= ~AI_CANONNAME; break;#endif } if (pai->ai_family == afdl[i].a_af || pai->ai_family == PF_UNSPEC) { if (! (pai->ai_flags & AI_CANONNAME)) { GET_AI(top, &afdl[i], pton, port); goto good; } /* * if AI_CANONNAME and if reverse lookup * fail, return ai anyway to pacify * calling application. * * XXX getaddrinfo() is a name->address * translation function, and it looks strange * that we do addr->name translation here. */ get_name(pton, &afdl[i], &top, pton, pai, port); goto good; } else ERR(EAI_FAMILY); /*xxx*/ } } if (pai->ai_flags & AI_NUMERICHOST) ERR(EAI_NONAME); /* hostname as alphabetical name */ error = get_addr(hostname, pai->ai_family, &top, pai, port); if (error == 0) { if (top) { good: *res = top; return SUCCESS; } else error = EAI_FAIL; } free: if (top) freeaddrinfo(top); bad: *res = NULL; return error;}static intget_name(addr, afd, res, numaddr, pai, port0) const char *addr; struct afd *afd; struct addrinfo **res; char *numaddr; struct addrinfo *pai; int port0;{ u_short port = port0 & 0xffff; struct hostent *hp; struct addrinfo *cur; int error = 0;#ifdef USE_GETIPNODEBY int h_error; hp = getipnodebyaddr(addr, afd->a_addrlen, afd->a_af, &h_error);#else hp = gethostbyaddr(addr, afd->a_addrlen, afd->a_af);#endif if (hp && hp->h_name && hp->h_name[0] && hp->h_addr_list[0]) { GET_AI(cur, afd, hp->h_addr_list[0], port); GET_CANONNAME(cur, hp->h_name); } else GET_AI(cur, afd, numaddr, port); #ifdef USE_GETIPNODEBY if (hp) freehostent(hp);#endif *res = cur; return SUCCESS; free: if (cur) freeaddrinfo(cur);#ifdef USE_GETIPNODEBY if (hp) freehostent(hp);#endif /* bad: */ *res = NULL; return error;}static intget_addr(hostname, af, res0, pai, port0) const char *hostname; int af; struct addrinfo **res0; struct addrinfo *pai; int port0;{#ifdef USE_GETIPNODEBY return get_addr0(hostname, af, res0, pai, port0);#else int i, error, ekeep; struct addrinfo *cur; struct addrinfo **res; int retry; int s; res = res0; ekeep = 0; error = 0; for (i = 0; afdl[i].a_af; i++) { retry = 0; if (af == AF_UNSPEC) { /* * filter out AFs that are not supported by the kernel * XXX errno? */ s = socket(afdl[i].a_af, SOCK_DGRAM, 0); if (s < 0) continue; close(s); } else { if (af != afdl[i].a_af) continue; } /* It is WRONG, we need getipnodebyname(). */again: error = get_addr0(hostname, afdl[i].a_af, res, pai, port0); switch (error) { case EAI_AGAIN: if (++retry < 3) goto again; /* FALL THROUGH*/ default: if (ekeep == 0) ekeep = error; break; } if (*res) { /* make chain of addrs */ for (cur = *res; cur && cur->ai_next; cur = cur->ai_next) ; if (!cur) return EAI_FAIL; res = &cur->ai_next; } } /* if we got something, it's okay */ if (*res0) return 0; return error ? error : ekeep;#endif}static intget_addr0(hostname, af, res, pai, port0) const char *hostname; int af; struct addrinfo **res; struct addrinfo *pai; int port0;{ u_short port = port0 & 0xffff; struct addrinfo sentinel; struct hostent *hp; struct addrinfo *top, *cur; struct afd *afd; int i, error = 0, h_error; char *ap;#ifndef USE_GETIPNODEBY extern int h_errno;#endif top = NULL; sentinel.ai_next = NULL; cur = &sentinel;#ifdef USE_GETIPNODEBY if (af == AF_UNSPEC) { hp = getipnodebyname(hostname, AF_INET6, AI_ADDRCONFIG|AI_ALL|AI_V4MAPPED, &h_error); } else hp = getipnodebyname(hostname, af, AI_ADDRCONFIG, &h_error);#else if (af == AF_UNSPEC) { error = EAI_FAIL; goto bad; } hp = gethostbyname2(hostname, af); h_error = h_errno;#endif if (hp == NULL) { switch (h_error) { case HOST_NOT_FOUND: case NO_DATA: error = EAI_NODATA; break; case TRY_AGAIN: error = EAI_AGAIN; break; case NO_RECOVERY: case NETDB_INTERNAL: default: error = EAI_FAIL; break; } goto bad; } if ((hp->h_name == NULL) || (hp->h_name[0] == 0) || (hp->h_addr_list[0] == NULL)) ERR(EAI_FAIL); for (i = 0; (ap = hp->h_addr_list[i]) != NULL; i++) { switch (af) {#ifdef INET6 case AF_INET6: afd = &afdl[N_INET6]; break;#endif#ifndef INET6 default: /* AF_UNSPEC */#endif case AF_INET: afd = &afdl[N_INET]; break;#ifdef INET6 default: /* AF_UNSPEC */ if (IN6_IS_ADDR_V4MAPPED((struct in6_addr *)ap)) { ap += sizeof(struct in6_addr) - sizeof(struct in_addr); afd = &afdl[N_INET]; } else afd = &afdl[N_INET6]; break;#endif }#ifdef FAITH if (translate && afd->a_af == AF_INET) { struct in6_addr *in6; GET_AI(cur->ai_next, &afdl[N_INET6], ap, port); in6 = &((struct sockaddr_in6 *)cur->ai_next->ai_addr)->sin6_addr; memcpy(&in6->s6_addr[0], &faith_prefix, sizeof(struct in6_addr) - sizeof(struct in_addr)); memcpy(&in6->s6_addr[12], ap, sizeof(struct in_addr)); } else#endif /* FAITH */ GET_AI(cur->ai_next, afd, ap, port); if (cur == &sentinel) { top = cur->ai_next; GET_CANONNAME(top, hp->h_name); } cur = cur->ai_next; }#ifdef USE_GETIPNODEBY freehostent(hp);#endif *res = top; return SUCCESS; free: if (top) freeaddrinfo(top);#ifdef USE_GETIPNODEBY if (hp) freehostent(hp);#endif bad: *res = NULL; return error;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -