mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2024-11-10 21:23:58 +01:00
Move tor_addr_{,port_}lookup to resolve.c
This commit is contained in:
parent
5d8336c182
commit
c2ddb7b231
@ -234,127 +234,6 @@ tor_addr_make_null(tor_addr_t *a, sa_family_t family)
|
||||
a->family = family;
|
||||
}
|
||||
|
||||
/** 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.
|
||||
*/
|
||||
MOCK_IMPL(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 = tor_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;
|
||||
}
|
||||
tor_freeaddrinfo(res);
|
||||
return result;
|
||||
}
|
||||
return (err == EAI_AGAIN) ? 1 : -1;
|
||||
#else /* !(defined(HAVE_GETADDRINFO)) */
|
||||
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);
|
||||
#elif defined(HAVE_GETHOSTBYNAME_R_3_ARG)
|
||||
struct hostent_data data;
|
||||
struct hostent hent;
|
||||
memset(&data, 0, sizeof(data));
|
||||
err = gethostbyname_r(name, &hent, &data);
|
||||
ent = err ? NULL : &hent;
|
||||
#else
|
||||
ent = gethostbyname(name);
|
||||
#ifdef _WIN32
|
||||
err = WSAGetLastError();
|
||||
#else
|
||||
err = h_errno;
|
||||
#endif
|
||||
#endif /* defined(HAVE_GETHOSTBYNAME_R_6_ARG) || ... */
|
||||
if (ent) {
|
||||
if (ent->h_addrtype == AF_INET) {
|
||||
tor_addr_from_in(addr, (struct in_addr*) ent->h_addr);
|
||||
} else if (ent->h_addrtype == AF_INET6) {
|
||||
tor_addr_from_in6(addr, (struct in6_addr*) ent->h_addr);
|
||||
} else {
|
||||
tor_assert(0); // LCOV_EXCL_LINE: gethostbyname() returned bizarre type
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#ifdef _WIN32
|
||||
return (err == WSATRY_AGAIN) ? 1 : -1;
|
||||
#else
|
||||
return (err == TRY_AGAIN) ? 1 : -1;
|
||||
#endif
|
||||
#endif /* defined(HAVE_GETADDRINFO) */
|
||||
}
|
||||
}
|
||||
|
||||
/** Return true iff <b>ip</b> is an IP reserved to localhost or local networks
|
||||
* in RFC1918 or RFC4193 or RFC4291. (fec0::/10, deprecated by RFC3879, is
|
||||
* also treated as internal for now.)
|
||||
@ -1324,64 +1203,6 @@ tor_addr_parse(tor_addr_t *addr, const char *src)
|
||||
return result;
|
||||
}
|
||||
|
||||
/** Parse an address or address-port combination from <b>s</b>, resolve the
|
||||
* address as needed, and put the result in <b>addr_out</b> and (optionally)
|
||||
* <b>port_out</b>. Return 0 on success, negative on failure. */
|
||||
int
|
||||
tor_addr_port_lookup(const char *s, tor_addr_t *addr_out, uint16_t *port_out)
|
||||
{
|
||||
const char *port;
|
||||
tor_addr_t addr;
|
||||
uint16_t portval;
|
||||
char *tmp = NULL;
|
||||
|
||||
tor_assert(s);
|
||||
tor_assert(addr_out);
|
||||
|
||||
s = eat_whitespace(s);
|
||||
|
||||
if (*s == '[') {
|
||||
port = strstr(s, "]");
|
||||
if (!port)
|
||||
goto err;
|
||||
tmp = tor_strndup(s+1, port-(s+1));
|
||||
port = port+1;
|
||||
if (*port == ':')
|
||||
port++;
|
||||
else
|
||||
port = NULL;
|
||||
} else {
|
||||
port = strchr(s, ':');
|
||||
if (port)
|
||||
tmp = tor_strndup(s, port-s);
|
||||
else
|
||||
tmp = tor_strdup(s);
|
||||
if (port)
|
||||
++port;
|
||||
}
|
||||
|
||||
if (tor_addr_lookup(tmp, AF_UNSPEC, &addr) != 0)
|
||||
goto err;
|
||||
tor_free(tmp);
|
||||
|
||||
if (port) {
|
||||
portval = (int) tor_parse_long(port, 10, 1, 65535, NULL, NULL);
|
||||
if (!portval)
|
||||
goto err;
|
||||
} else {
|
||||
portval = 0;
|
||||
}
|
||||
|
||||
if (port_out)
|
||||
*port_out = portval;
|
||||
tor_addr_copy(addr_out, &addr);
|
||||
|
||||
return 0;
|
||||
err:
|
||||
tor_free(tmp);
|
||||
return -1;
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
typedef ULONG (WINAPI *GetAdaptersAddresses_fn_t)(
|
||||
ULONG, ULONG, PVOID, PIP_ADAPTER_ADDRESSES, PULONG);
|
||||
|
@ -204,8 +204,6 @@ tor_addr_eq_ipv4h(const tor_addr_t *a, uint32_t u)
|
||||
*/
|
||||
#define TOR_ADDR_BUF_LEN 48
|
||||
|
||||
MOCK_DECL(int, tor_addr_lookup,(const char *name, uint16_t family,
|
||||
tor_addr_t *addr_out));
|
||||
char *tor_addr_to_str_dup(const tor_addr_t *addr) ATTR_MALLOC;
|
||||
|
||||
/** Wrapper function of fmt_addr_impl(). It does not decorate IPv6
|
||||
@ -263,9 +261,6 @@ int tor_addr_to_PTR_name(char *out, size_t outlen,
|
||||
int tor_addr_parse_PTR_name(tor_addr_t *result, const char *address,
|
||||
int family, int accept_regular);
|
||||
|
||||
int tor_addr_port_lookup(const char *s, tor_addr_t *addr_out,
|
||||
uint16_t *port_out);
|
||||
|
||||
/* Does the address * yield an AF_UNSPEC wildcard address (1),
|
||||
* which expands to corresponding wildcard IPv4 and IPv6 rules, and do we
|
||||
* allow *4 and *6 for IPv4 and IPv6 wildcards, respectively;
|
||||
|
@ -9,8 +9,12 @@
|
||||
**/
|
||||
|
||||
#include "lib/net/resolve.h"
|
||||
|
||||
#include "lib/net/address.h"
|
||||
#include "lib/net/inaddr.h"
|
||||
#include "lib/malloc/util_malloc.h"
|
||||
#include "lib/string/parse_int.h"
|
||||
#include "lib/string/util_string.h"
|
||||
|
||||
#include "siphash.h"
|
||||
#include "ht.h"
|
||||
@ -52,6 +56,185 @@ tor_lookup_hostname,(const char *name, uint32_t *addr))
|
||||
return -1;
|
||||
}
|
||||
|
||||
/** 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.
|
||||
*/
|
||||
MOCK_IMPL(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 = tor_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;
|
||||
}
|
||||
tor_freeaddrinfo(res);
|
||||
return result;
|
||||
}
|
||||
return (err == EAI_AGAIN) ? 1 : -1;
|
||||
#else /* !(defined(HAVE_GETADDRINFO)) */
|
||||
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);
|
||||
#elif defined(HAVE_GETHOSTBYNAME_R_3_ARG)
|
||||
struct hostent_data data;
|
||||
struct hostent hent;
|
||||
memset(&data, 0, sizeof(data));
|
||||
err = gethostbyname_r(name, &hent, &data);
|
||||
ent = err ? NULL : &hent;
|
||||
#else
|
||||
ent = gethostbyname(name);
|
||||
#ifdef _WIN32
|
||||
err = WSAGetLastError();
|
||||
#else
|
||||
err = h_errno;
|
||||
#endif
|
||||
#endif /* defined(HAVE_GETHOSTBYNAME_R_6_ARG) || ... */
|
||||
if (ent) {
|
||||
if (ent->h_addrtype == AF_INET) {
|
||||
tor_addr_from_in(addr, (struct in_addr*) ent->h_addr);
|
||||
} else if (ent->h_addrtype == AF_INET6) {
|
||||
tor_addr_from_in6(addr, (struct in6_addr*) ent->h_addr);
|
||||
} else {
|
||||
tor_assert(0); // LCOV_EXCL_LINE: gethostbyname() returned bizarre type
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#ifdef _WIN32
|
||||
return (err == WSATRY_AGAIN) ? 1 : -1;
|
||||
#else
|
||||
return (err == TRY_AGAIN) ? 1 : -1;
|
||||
#endif
|
||||
#endif /* defined(HAVE_GETADDRINFO) */
|
||||
}
|
||||
}
|
||||
|
||||
/** Parse an address or address-port combination from <b>s</b>, resolve the
|
||||
* address as needed, and put the result in <b>addr_out</b> and (optionally)
|
||||
* <b>port_out</b>. Return 0 on success, negative on failure. */
|
||||
int
|
||||
tor_addr_port_lookup(const char *s, tor_addr_t *addr_out, uint16_t *port_out)
|
||||
{
|
||||
const char *port;
|
||||
tor_addr_t addr;
|
||||
uint16_t portval;
|
||||
char *tmp = NULL;
|
||||
|
||||
tor_assert(s);
|
||||
tor_assert(addr_out);
|
||||
|
||||
s = eat_whitespace(s);
|
||||
|
||||
if (*s == '[') {
|
||||
port = strstr(s, "]");
|
||||
if (!port)
|
||||
goto err;
|
||||
tmp = tor_strndup(s+1, port-(s+1));
|
||||
port = port+1;
|
||||
if (*port == ':')
|
||||
port++;
|
||||
else
|
||||
port = NULL;
|
||||
} else {
|
||||
port = strchr(s, ':');
|
||||
if (port)
|
||||
tmp = tor_strndup(s, port-s);
|
||||
else
|
||||
tmp = tor_strdup(s);
|
||||
if (port)
|
||||
++port;
|
||||
}
|
||||
|
||||
if (tor_addr_lookup(tmp, AF_UNSPEC, &addr) != 0)
|
||||
goto err;
|
||||
tor_free(tmp);
|
||||
|
||||
if (port) {
|
||||
portval = (int) tor_parse_long(port, 10, 1, 65535, NULL, NULL);
|
||||
if (!portval)
|
||||
goto err;
|
||||
} else {
|
||||
portval = 0;
|
||||
}
|
||||
|
||||
if (port_out)
|
||||
*port_out = portval;
|
||||
tor_addr_copy(addr_out, &addr);
|
||||
|
||||
return 0;
|
||||
err:
|
||||
tor_free(tmp);
|
||||
return -1;
|
||||
}
|
||||
|
||||
#ifdef USE_SANDBOX_GETADDRINFO
|
||||
/** True if we should only return cached values */
|
||||
static int sandbox_getaddrinfo_is_active = 0;
|
||||
|
@ -22,7 +22,13 @@
|
||||
#define USE_SANDBOX_GETADDRINFO
|
||||
#endif
|
||||
|
||||
MOCK_DECL(int,tor_lookup_hostname,(const char *name, uint32_t *addr));
|
||||
struct tor_addr_t;
|
||||
|
||||
MOCK_DECL(int, tor_lookup_hostname,(const char *name, uint32_t *addr));
|
||||
MOCK_DECL(int, tor_addr_lookup,(const char *name, uint16_t family,
|
||||
struct tor_addr_t *addr_out));
|
||||
int tor_addr_port_lookup(const char *s, struct tor_addr_t *addr_out,
|
||||
uint16_t *port_out);
|
||||
|
||||
struct addrinfo;
|
||||
#ifdef USE_SANDBOX_GETADDRINFO
|
||||
|
Loading…
Reference in New Issue
Block a user