int sandbox_add_addrinfo(const char *name) { struct addrinfo *res; struct addrinfo hints; int i; static const int families[] = { AF_INET, AF_INET6, AF_UNSPEC }; memset(&hints, 0, sizeof(hints)); hints.ai_socktype = SOCK_STREAM; for (i = 0; i < 3; ++i) { hints.ai_family = families[i]; res = NULL; (void) sandbox_getaddrinfo(name, NULL, &hints, &res); if (res) sandbox_freeaddrinfo(res); } return 0; }
/** Similar behavior to Unix gethostbyname: resolve <b>name</b>, and set * *<b>addr</b> to the proper IP address and family. The <b>family</b> * argument (which must be AF_INET, AF_INET6, or AF_UNSPEC) declares a * <i>preferred</i> family, though another one may be returned if only one * family is implemented for this address. * * Return 0 on success, -1 on failure; 1 on transient failure. */ int tor_addr_lookup(const char *name, uint16_t family, tor_addr_t *addr) { /* Perhaps eventually this should be replaced by a tor_getaddrinfo or * something. */ struct in_addr iaddr; struct in6_addr iaddr6; tor_assert(name); tor_assert(addr); tor_assert(family == AF_INET || family == AF_INET6 || family == AF_UNSPEC); if (!*name) { /* Empty address is an error. */ return -1; } else if (tor_inet_pton(AF_INET, name, &iaddr)) { /* It's an IPv4 IP. */ if (family == AF_INET6) return -1; tor_addr_from_in(addr, &iaddr); return 0; } else if (tor_inet_pton(AF_INET6, name, &iaddr6)) { if (family == AF_INET) return -1; tor_addr_from_in6(addr, &iaddr6); return 0; } else { #ifdef HAVE_GETADDRINFO int err; struct addrinfo *res=NULL, *res_p; struct addrinfo *best=NULL; struct addrinfo hints; int result = -1; memset(&hints, 0, sizeof(hints)); hints.ai_family = family; hints.ai_socktype = SOCK_STREAM; err = sandbox_getaddrinfo(name, NULL, &hints, &res); /* The check for 'res' here shouldn't be necessary, but it makes static * analysis tools happy. */ if (!err && res) { best = NULL; for (res_p = res; res_p; res_p = res_p->ai_next) { if (family == AF_UNSPEC) { if (res_p->ai_family == AF_INET) { best = res_p; break; } else if (res_p->ai_family == AF_INET6 && !best) { best = res_p; } } else if (family == res_p->ai_family) { best = res_p; break; } } if (!best) best = res; if (best->ai_family == AF_INET) { tor_addr_from_in(addr, &((struct sockaddr_in*)best->ai_addr)->sin_addr); result = 0; } else if (best->ai_family == AF_INET6) { tor_addr_from_in6(addr, &((struct sockaddr_in6*)best->ai_addr)->sin6_addr); result = 0; } sandbox_freeaddrinfo(res); return result; } return (err == EAI_AGAIN) ? 1 : -1; #else struct hostent *ent; int err; #ifdef HAVE_GETHOSTBYNAME_R_6_ARG char buf[2048]; struct hostent hostent; int r; r = gethostbyname_r(name, &hostent, buf, sizeof(buf), &ent, &err); #elif defined(HAVE_GETHOSTBYNAME_R_5_ARG) char buf[2048]; struct hostent hostent; ent = gethostbyname_r(name, &hostent, buf, sizeof(buf), &err);