Merge branch 'ticket26526_26532'

This commit is contained in:
Nick Mathewson 2018-07-10 14:48:12 -04:00
commit 422abd4fa3
26 changed files with 320 additions and 400 deletions

4
changes/ticket26526 Normal file
View File

@ -0,0 +1,4 @@
o Code simplification and refactoring:
- Utility functions that can perform a DNS lookup are now wholly
separated from those that can't, in separate headers and C
modules. Closes ticket 26526.

View File

@ -0,0 +1,3 @@
o Minor features (tor-resolve):
- The tor-resolve utility can now be used with IPv6 SOCKS proxies.
Side-effect of the refactoring for ticket 26526.

View File

@ -106,6 +106,7 @@
#include "feature/client/transports.h" #include "feature/client/transports.h"
#include "feature/relay/ext_orport.h" #include "feature/relay/ext_orport.h"
#include "feature/dircommon/voting_schedule.h" #include "feature/dircommon/voting_schedule.h"
#include "lib/net/resolve.h"
#ifdef _WIN32 #ifdef _WIN32
#include <shlobj.h> #include <shlobj.h>
#endif #endif
@ -6459,26 +6460,17 @@ parse_dir_authority_line(const char *line, dirinfo_type_t required_type,
addrport = smartlist_get(items, 0); addrport = smartlist_get(items, 0);
smartlist_del_keeporder(items, 0); smartlist_del_keeporder(items, 0);
const char *addrport_sep = strchr(addrport, ':'); if (tor_addr_port_split(LOG_WARN, addrport, &address, &dir_port) < 0) {
if (!addrport_sep) { log_warn(LD_CONFIG, "Error parsing DirAuthority address '%s'.", addrport);
log_warn(LD_CONFIG, "Error parsing DirAuthority address '%s' "
"(':' not found)", addrport);
goto err; goto err;
} }
address = tor_strndup(addrport, addrport_sep - addrport);
if (!string_is_valid_ipv4_address(address)) { if (!string_is_valid_ipv4_address(address)) {
log_warn(LD_CONFIG, "Error parsing DirAuthority address '%s' " log_warn(LD_CONFIG, "Error parsing DirAuthority address '%s' "
"(invalid IPv4 address)", address); "(invalid IPv4 address)", address);
goto err; goto err;
} }
tor_free(address);
if (addr_port_lookup(LOG_WARN, addrport, &address, NULL, &dir_port)<0) {
log_warn(LD_CONFIG, "Error parsing DirAuthority address '%s'", addrport);
goto err;
}
if (!dir_port) { if (!dir_port) {
log_warn(LD_CONFIG, "Missing port in DirAuthority address '%s'",addrport); log_warn(LD_CONFIG, "Missing port in DirAuthority address '%s'",addrport);
goto err; goto err;

View File

@ -43,6 +43,7 @@
#include "lib/sandbox/sandbox.h" #include "lib/sandbox/sandbox.h"
#include "app/config/statefile.h" #include "app/config/statefile.h"
#include "lib/encoding/confline.h" #include "lib/encoding/confline.h"
#include "lib/net/resolve.h"
#include "app/config/or_state_st.h" #include "app/config/or_state_st.h"

View File

@ -116,6 +116,7 @@
#include "lib/sandbox/sandbox.h" #include "lib/sandbox/sandbox.h"
#include "lib/fs/lockfile.h" #include "lib/fs/lockfile.h"
#include "lib/net/buffers_net.h" #include "lib/net/buffers_net.h"
#include "lib/net/resolve.h"
#include "lib/tls/tortls.h" #include "lib/tls/tortls.h"
#include "lib/evloop/compat_libevent.h" #include "lib/evloop/compat_libevent.h"
#include "lib/encoding/confline.h" #include "lib/encoding/confline.h"

View File

@ -49,9 +49,7 @@
#include "lib/log/util_bug.h" #include "lib/log/util_bug.h"
#include "lib/malloc/util_malloc.h" #include "lib/malloc/util_malloc.h"
#include "lib/net/address.h" #include "lib/net/address.h"
#include "lib/net/ipv4.h" #include "lib/net/inaddr.h"
#include "lib/net/ipv6.h"
#include "lib/net/resolve.h"
#include "lib/net/socket.h" #include "lib/net/socket.h"
#include "lib/string/compat_ctype.h" #include "lib/string/compat_ctype.h"
#include "lib/string/compat_string.h" #include "lib/string/compat_string.h"

View File

@ -123,6 +123,7 @@
#include "lib/sandbox/sandbox.h" #include "lib/sandbox/sandbox.h"
#include "feature/nodelist/torcert.h" #include "feature/nodelist/torcert.h"
#include "lib/math/fp.h" #include "lib/math/fp.h"
#include "lib/net/resolve.h"
#include "feature/dirauth/dirvote.h" #include "feature/dirauth/dirvote.h"
#include "feature/dirauth/mode.h" #include "feature/dirauth/mode.h"

View File

@ -37,6 +37,7 @@
#include "feature/nodelist/routerparse.h" #include "feature/nodelist/routerparse.h"
#include "feature/nodelist/routerset.h" #include "feature/nodelist/routerset.h"
#include "lib/encoding/confline.h" #include "lib/encoding/confline.h"
#include "lib/net/resolve.h"
#include "core/or/cpath_build_state_st.h" #include "core/or/cpath_build_state_st.h"
#include "core/or/crypt_path_st.h" #include "core/or/crypt_path_st.h"

View File

@ -6,6 +6,9 @@
/** /**
* \file address.c * \file address.c
* \brief Functions to use and manipulate the tor_addr_t structure. * \brief Functions to use and manipulate the tor_addr_t structure.
*
* This module doesn't have any support for the libc resolver: that is all in
* resolve.c.
**/ **/
#define ADDRESS_PRIVATE #define ADDRESS_PRIVATE
@ -37,13 +40,12 @@
#include "lib/net/address.h" #include "lib/net/address.h"
#include "lib/net/socket.h" #include "lib/net/socket.h"
#include "lib/net/resolve.h"
#include "lib/container/smartlist.h" #include "lib/container/smartlist.h"
#include "lib/ctime/di_ops.h" #include "lib/ctime/di_ops.h"
#include "lib/log/torlog.h" #include "lib/log/torlog.h"
#include "lib/log/escape.h" #include "lib/log/escape.h"
#include "lib/malloc/util_malloc.h" #include "lib/malloc/util_malloc.h"
#include "lib/net/ipv4.h" #include "lib/net/inaddr.h"
#include "lib/string/compat_ctype.h" #include "lib/string/compat_ctype.h"
#include "lib/string/compat_string.h" #include "lib/string/compat_string.h"
#include "lib/string/parse_int.h" #include "lib/string/parse_int.h"
@ -234,127 +236,6 @@ tor_addr_make_null(tor_addr_t *a, sa_family_t family)
a->family = 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 /** 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 * in RFC1918 or RFC4193 or RFC4291. (fec0::/10, deprecated by RFC3879, is
* also treated as internal for now.) * also treated as internal for now.)
@ -1324,64 +1205,6 @@ tor_addr_parse(tor_addr_t *addr, const char *src)
return result; 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 #ifdef _WIN32
typedef ULONG (WINAPI *GetAdaptersAddresses_fn_t)( typedef ULONG (WINAPI *GetAdaptersAddresses_fn_t)(
ULONG, ULONG, PVOID, PIP_ADAPTER_ADDRESSES, PULONG); ULONG, ULONG, PVOID, PIP_ADAPTER_ADDRESSES, PULONG);
@ -1927,7 +1750,7 @@ tor_addr_port_split(int severity, const char *addrport,
tor_assert(addrport); tor_assert(addrport);
tor_assert(address_out); tor_assert(address_out);
tor_assert(port_out); tor_assert(port_out);
/* We need to check for IPv6 manually because addr_port_lookup() doesn't /* We need to check for IPv6 manually because the logic below doesn't
* do a good job on IPv6 addresses that lack a port. */ * do a good job on IPv6 addresses that lack a port. */
if (tor_addr_parse(&a_tmp, addrport) == AF_INET6) { if (tor_addr_parse(&a_tmp, addrport) == AF_INET6) {
*port_out = 0; *port_out = 0;
@ -1935,30 +1758,11 @@ tor_addr_port_split(int severity, const char *addrport,
return 0; return 0;
} }
return addr_port_lookup(severity, addrport, address_out, NULL, port_out);
}
/** Parse a string of the form "host[:port]" from <b>addrport</b>. If
* <b>address</b> is provided, set *<b>address</b> to a copy of the
* host portion of the string. If <b>addr</b> is provided, try to
* resolve the host portion of the string and store it into
* *<b>addr</b> (in host byte order). If <b>port_out</b> is provided,
* store the port number into *<b>port_out</b>, or 0 if no port is given.
* If <b>port_out</b> is NULL, then there must be no port number in
* <b>addrport</b>.
* Return 0 on success, -1 on failure.
*/
int
addr_port_lookup(int severity, const char *addrport, char **address,
uint32_t *addr, uint16_t *port_out)
{
const char *colon; const char *colon;
char *address_ = NULL; char *address_ = NULL;
int port_; int port_;
int ok = 1; int ok = 1;
tor_assert(addrport);
colon = strrchr(addrport, ':'); colon = strrchr(addrport, ':');
if (colon) { if (colon) {
address_ = tor_strndup(addrport, colon-addrport); address_ = tor_strndup(addrport, colon-addrport);
@ -1980,22 +1784,13 @@ addr_port_lookup(int severity, const char *addrport, char **address,
port_ = 0; port_ = 0;
} }
if (addr) { if (ok) {
/* There's an addr pointer, so we need to resolve the hostname. */ *address_out = address_;
if (tor_lookup_hostname(address_,addr)) {
log_fn(severity, LD_NET, "Couldn't look up %s", escaped(address_));
ok = 0;
*addr = 0;
}
}
if (address && ok) {
*address = address_;
} else { } else {
if (address) *address_out = NULL;
*address = NULL;
tor_free(address_); tor_free(address_);
} }
if (port_out) if (port_out)
*port_out = ok ? ((uint16_t) port_) : 0; *port_out = ok ? ((uint16_t) port_) : 0;

View File

@ -14,7 +14,7 @@
#include "orconfig.h" #include "orconfig.h"
#include "lib/cc/torint.h" #include "lib/cc/torint.h"
#include "lib/log/util_bug.h" #include "lib/log/util_bug.h"
#include "lib/net/ipv6.h" #include "lib/net/inaddr_st.h"
#include "lib/net/nettypes.h" #include "lib/net/nettypes.h"
#ifdef HAVE_NETINET_IN_H #ifdef HAVE_NETINET_IN_H
@ -204,8 +204,6 @@ tor_addr_eq_ipv4h(const tor_addr_t *a, uint32_t u)
*/ */
#define TOR_ADDR_BUF_LEN 48 #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; char *tor_addr_to_str_dup(const tor_addr_t *addr) ATTR_MALLOC;
/** Wrapper function of fmt_addr_impl(). It does not decorate IPv6 /** 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 tor_addr_parse_PTR_name(tor_addr_t *result, const char *address,
int family, int accept_regular); 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), /* Does the address * yield an AF_UNSPEC wildcard address (1),
* which expands to corresponding wildcard IPv4 and IPv6 rules, and do we * which expands to corresponding wildcard IPv4 and IPv6 rules, and do we
* allow *4 and *6 for IPv4 and IPv6 wildcards, respectively; * allow *4 and *6 for IPv4 and IPv6 wildcards, respectively;
@ -330,8 +325,6 @@ int tor_addr_port_parse(int severity, const char *addrport,
int tor_addr_hostname_is_local(const char *name); int tor_addr_hostname_is_local(const char *name);
/* IPv4 helpers */ /* IPv4 helpers */
int addr_port_lookup(int severity, const char *addrport, char **address,
uint32_t *addr, uint16_t *port_out);
int parse_port_range(const char *port, uint16_t *port_min_out, int parse_port_range(const char *port, uint16_t *port_min_out,
uint16_t *port_max_out); uint16_t *port_max_out);
int addr_mask_get_bits(uint32_t mask); int addr_mask_get_bits(uint32_t mask);

View File

@ -4,20 +4,20 @@
/* See LICENSE for licensing information */ /* See LICENSE for licensing information */
/** /**
* \file ipv6.c * \file inaddr.c
* \brief Functions for encoding and decoding IPv6 addresses * \brief Convert in_addr and in6_addr to and from strings.
*
* (Because these functions are generic, they can also handle IPv4 addresses).
**/ **/
#include "lib/net/ipv6.h" #include "lib/net/inaddr.h"
#include "lib/net/ipv4.h"
#include "lib/string/util_string.h" #include "lib/cc/torint.h"
#include "lib/string/compat_string.h" #include "lib/log/util_bug.h"
#include "lib/net/inaddr_st.h"
#include "lib/string/compat_ctype.h" #include "lib/string/compat_ctype.h"
#include "lib/string/compat_string.h"
#include "lib/string/printf.h" #include "lib/string/printf.h"
#include "lib/string/scanf.h" #include "lib/string/scanf.h"
#include "lib/log/util_bug.h" #include "lib/string/util_string.h"
#ifdef HAVE_ARPA_INET_H #ifdef HAVE_ARPA_INET_H
#include <arpa/inet.h> #include <arpa/inet.h>
@ -26,6 +26,45 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#ifdef _WIN32
#include <winsock2.h>
#endif
/** Set *addr to the IP address (in dotted-quad notation) stored in *str.
* Return 1 on success, 0 if *str is badly formatted.
* (Like inet_aton(str,addr), but works on Windows and Solaris.)
*/
int
tor_inet_aton(const char *str, struct in_addr* addr)
{
unsigned a,b,c,d;
char more;
if (tor_sscanf(str, "%3u.%3u.%3u.%3u%c", &a,&b,&c,&d,&more) != 4)
return 0;
if (a > 255) return 0;
if (b > 255) return 0;
if (c > 255) return 0;
if (d > 255) return 0;
addr->s_addr = htonl((a<<24) | (b<<16) | (c<<8) | d);
return 1;
}
/** Given an IPv4 in_addr struct *<b>in</b> (in network order, as usual),
* write it as a string into the <b>buf_len</b>-byte buffer in
* <b>buf</b>. Returns a non-negative integer on success.
* Returns -1 on failure.
*/
int
tor_inet_ntoa(const struct in_addr *in, char *buf, size_t buf_len)
{
uint32_t a = ntohl(in->s_addr);
return tor_snprintf(buf, buf_len, "%d.%d.%d.%d",
(int)(uint8_t)((a>>24)&0xff),
(int)(uint8_t)((a>>16)&0xff),
(int)(uint8_t)((a>>8 )&0xff),
(int)(uint8_t)((a )&0xff));
}
/** Given <b>af</b>==AF_INET and <b>src</b> a struct in_addr, or /** Given <b>af</b>==AF_INET and <b>src</b> a struct in_addr, or
* <b>af</b>==AF_INET6 and <b>src</b> a struct in6_addr, try to format the * <b>af</b>==AF_INET6 and <b>src</b> a struct in6_addr, try to format the
* address and store it in the <b>len</b>-byte buffer <b>dst</b>. Returns * address and store it in the <b>len</b>-byte buffer <b>dst</b>. Returns

View File

@ -4,18 +4,24 @@
/* See LICENSE for licensing information */ /* See LICENSE for licensing information */
/** /**
* \file ipv4.h * \file inaddr.h
* \brief Header for ipv4.c * \brief Header for inaddr.c.
**/ **/
#ifndef TOR_IPV4_H
#define TOR_IPV4_H
#ifndef TOR_INADDR_H
#define TOR_INADDR_H
#include "orconfig.h"
#include <stddef.h> #include <stddef.h>
struct in_addr; struct in_addr;
int tor_inet_aton(const char *str, struct in_addr *addr); int tor_inet_aton(const char *str, struct in_addr *addr);
/** Length of a buffer to allocate to hold the results of tor_inet_ntoa.*/ /** Length of a buffer to allocate to hold the results of tor_inet_ntoa.*/
#define INET_NTOA_BUF_LEN 16 #define INET_NTOA_BUF_LEN 16
int tor_inet_ntoa(const struct in_addr *in, char *buf, size_t buf_len); int tor_inet_ntoa(const struct in_addr *in, char *buf, size_t buf_len);
const char *tor_inet_ntop(int af, const void *src, char *dst, size_t len);
int tor_inet_pton(int af, const char *src, void *dst);
#endif #endif

View File

@ -4,25 +4,29 @@
/* See LICENSE for licensing information */ /* See LICENSE for licensing information */
/** /**
* \file ipv6.h * \file inaddr_st.h
* \brief Header for ipv6.c *
* \brief Define in6_addr, its members, and related types on platforms that
* lack it.
**/ **/
#ifndef TOR_IPV6_H #ifndef TOR_INADDR_ST_H
#define TOR_IPV6_H #define TOR_INADDR_ST_H
#include "orconfig.h"
#include <stddef.h>
#ifdef HAVE_NETINET_IN6_H #ifdef HAVE_NETINET_IN6_H
#include <netinet/in6.h> #include <netinet/in6.h>
#endif #endif
#ifdef _WIN32 #ifdef _WIN32
#include <winsock2.h> #include <winsock2.h>
#include <ws2tcpip.h> #include <ws2tcpip.h>
#include <windows.h> #include <windows.h>
#endif #endif
#include "lib/cc/torint.h" #include "lib/cc/torint.h"
struct in_addr;
/** Implementation of struct in6_addr for platforms that do not have it. /** Implementation of struct in6_addr for platforms that do not have it.
* Generally, these platforms are ones without IPv6 support, but we want to * Generally, these platforms are ones without IPv6 support, but we want to
* have a working in6_addr there anyway, so we can use it to parse IPv6 * have a working in6_addr there anyway, so we can use it to parse IPv6
@ -85,7 +89,4 @@ struct sockaddr_in6 {
}; };
#endif /* !defined(HAVE_STRUCT_SOCKADDR_IN6) */ #endif /* !defined(HAVE_STRUCT_SOCKADDR_IN6) */
const char *tor_inet_ntop(int af, const void *src, char *dst, size_t len); #endif /* TOR_INADDR_ST_H */
int tor_inet_pton(int af, const char *src, void *dst);
#endif

View File

@ -10,8 +10,7 @@ src_lib_libtor_net_a_SOURCES = \
src/lib/net/alertsock.c \ src/lib/net/alertsock.c \
src/lib/net/buffers_net.c \ src/lib/net/buffers_net.c \
src/lib/net/gethostname.c \ src/lib/net/gethostname.c \
src/lib/net/ipv4.c \ src/lib/net/inaddr.c \
src/lib/net/ipv6.c \
src/lib/net/resolve.c \ src/lib/net/resolve.c \
src/lib/net/socket.c src/lib/net/socket.c
@ -25,8 +24,8 @@ noinst_HEADERS += \
src/lib/net/alertsock.h \ src/lib/net/alertsock.h \
src/lib/net/buffers_net.h \ src/lib/net/buffers_net.h \
src/lib/net/gethostname.h \ src/lib/net/gethostname.h \
src/lib/net/ipv4.h \ src/lib/net/inaddr.h \
src/lib/net/ipv6.h \ src/lib/net/inaddr_st.h \
src/lib/net/nettypes.h \ src/lib/net/nettypes.h \
src/lib/net/resolve.h \ src/lib/net/resolve.h \
src/lib/net/socket.h \ src/lib/net/socket.h \

View File

@ -1,57 +0,0 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
* Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
* \file ipv4.c
* \brief Functions for encoding and decoding IPv4 addresses into strings
**/
#include "orconfig.h"
#include "lib/cc/torint.h"
#include "lib/net/ipv4.h"
#include "lib/string/printf.h"
#include "lib/string/scanf.h"
#ifdef HAVE_ARPA_INET_H
#include <arpa/inet.h>
#endif
#ifdef _WIN32
#include <winsock2.h>
#endif
/** Set *addr to the IP address (in dotted-quad notation) stored in *str.
* Return 1 on success, 0 if *str is badly formatted.
* (Like inet_aton(str,addr), but works on Windows and Solaris.)
*/
int
tor_inet_aton(const char *str, struct in_addr* addr)
{
unsigned a,b,c,d;
char more;
if (tor_sscanf(str, "%3u.%3u.%3u.%3u%c", &a,&b,&c,&d,&more) != 4)
return 0;
if (a > 255) return 0;
if (b > 255) return 0;
if (c > 255) return 0;
if (d > 255) return 0;
addr->s_addr = htonl((a<<24) | (b<<16) | (c<<8) | d);
return 1;
}
/** Given an IPv4 in_addr struct *<b>in</b> (in network order, as usual),
* write it as a string into the <b>buf_len</b>-byte buffer in
* <b>buf</b>. Returns a non-negative integer on success.
* Returns -1 on failure.
*/
int
tor_inet_ntoa(const struct in_addr *in, char *buf, size_t buf_len)
{
uint32_t a = ntohl(in->s_addr);
return tor_snprintf(buf, buf_len, "%d.%d.%d.%d",
(int)(uint8_t)((a>>24)&0xff),
(int)(uint8_t)((a>>16)&0xff),
(int)(uint8_t)((a>>8 )&0xff),
(int)(uint8_t)((a )&0xff));
}

View File

@ -9,8 +9,12 @@
**/ **/
#include "lib/net/resolve.h" #include "lib/net/resolve.h"
#include "lib/net/address.h" #include "lib/net/address.h"
#include "lib/net/inaddr.h"
#include "lib/malloc/util_malloc.h" #include "lib/malloc/util_malloc.h"
#include "lib/string/parse_int.h"
#include "lib/string/util_string.h"
#include "siphash.h" #include "siphash.h"
#include "ht.h" #include "ht.h"
@ -52,6 +56,185 @@ tor_lookup_hostname,(const char *name, uint32_t *addr))
return -1; 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 #ifdef USE_SANDBOX_GETADDRINFO
/** True if we should only return cached values */ /** True if we should only return cached values */
static int sandbox_getaddrinfo_is_active = 0; static int sandbox_getaddrinfo_is_active = 0;

View File

@ -22,7 +22,13 @@
#define USE_SANDBOX_GETADDRINFO #define USE_SANDBOX_GETADDRINFO
#endif #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; struct addrinfo;
#ifdef USE_SANDBOX_GETADDRINFO #ifdef USE_SANDBOX_GETADDRINFO

View File

@ -10,71 +10,16 @@
#include "test/test.h" #include "test/test.h"
#include "feature/client/addressmap.h" #include "feature/client/addressmap.h"
#include "test/log_test_helpers.h" #include "test/log_test_helpers.h"
#include "lib/net/resolve.h"
#ifdef HAVE_SYS_UN_H #ifdef HAVE_SYS_UN_H
#include <sys/un.h> #include <sys/un.h>
#endif #endif
/** Mocking replacement: only handles localhost. */
static int
mock_tor_addr_lookup(const char *name, uint16_t family, tor_addr_t *addr_out)
{
if (!strcmp(name, "localhost")) {
if (family == AF_INET || family == AF_UNSPEC) {
tor_addr_from_ipv4h(addr_out, 0x7f000001);
return 0;
} else if (family == AF_INET6) {
char bytes[16] = { 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 1 };
tor_addr_from_ipv6_bytes(addr_out, bytes);
return 0;
}
}
return -1;
}
static void static void
test_addr_basic(void *arg) test_addr_basic(void *arg)
{ {
uint32_t u32; (void) arg;
uint16_t u16;
char *cp;
/* Test addr_port_lookup */
(void)arg;
cp = NULL; u32 = 3; u16 = 3;
tt_assert(!addr_port_lookup(LOG_WARN, "1.2.3.4", &cp, &u32, &u16));
tt_str_op(cp,OP_EQ, "1.2.3.4");
tt_int_op(u32,OP_EQ, 0x01020304u);
tt_int_op(u16,OP_EQ, 0);
tor_free(cp);
tt_assert(!addr_port_lookup(LOG_WARN, "4.3.2.1:99", &cp, &u32, &u16));
tt_str_op(cp,OP_EQ, "4.3.2.1");
tt_int_op(u32,OP_EQ, 0x04030201u);
tt_int_op(u16,OP_EQ, 99);
tor_free(cp);
MOCK(tor_addr_lookup, mock_tor_addr_lookup);
tt_assert(!addr_port_lookup(LOG_WARN, "nonexistent.address:4040",
&cp, NULL, &u16));
tt_str_op(cp,OP_EQ, "nonexistent.address");
tt_int_op(u16,OP_EQ, 4040);
tor_free(cp);
tt_assert(!addr_port_lookup(LOG_WARN, "localhost:9999", &cp, &u32, &u16));
tt_str_op(cp,OP_EQ, "localhost");
tt_int_op(u16,OP_EQ, 9999);
tt_int_op(u32,OP_EQ, 0x7f000001u);
tor_free(cp);
u32 = 3;
tt_assert(!addr_port_lookup(LOG_WARN, "localhost", NULL, &u32, &u16));
tt_ptr_op(cp,OP_EQ, NULL);
tt_int_op(u32,OP_EQ, 0x7f000001u);
tt_int_op(u16,OP_EQ, 0);
tor_free(cp);
tt_assert(addr_port_lookup(LOG_WARN, "localhost:3", &cp, &u32, NULL));
tor_free(cp);
tt_int_op(0,OP_EQ, addr_mask_get_bits(0x0u)); tt_int_op(0,OP_EQ, addr_mask_get_bits(0x0u));
tt_int_op(32,OP_EQ, addr_mask_get_bits(0xFFFFFFFFu)); tt_int_op(32,OP_EQ, addr_mask_get_bits(0xFFFFFFFFu));
@ -102,8 +47,7 @@ test_addr_basic(void *arg)
} }
done: done:
UNMOCK(tor_addr_lookup); ;
tor_free(cp);
} }
#define test_op_ip6_(a,op,b,e1,e2) \ #define test_op_ip6_(a,op,b,e1,e2) \

View File

@ -10,6 +10,7 @@
#define ROUTERSET_PRIVATE #define ROUTERSET_PRIVATE
#include "core/or/or.h" #include "core/or/or.h"
#include "lib/net/address.h" #include "lib/net/address.h"
#include "lib/net/resolve.h"
#include "feature/client/addressmap.h" #include "feature/client/addressmap.h"
#include "feature/client/bridges.h" #include "feature/client/bridges.h"
#include "core/or/circuitmux_ewma.h" #include "core/or/circuitmux_ewma.h"

View File

@ -20,6 +20,7 @@
#include "feature/rend/rendcache.h" #include "feature/rend/rendcache.h"
#include "feature/dircache/directory.h" #include "feature/dircache/directory.h"
#include "core/or/connection_or.h" #include "core/or/connection_or.h"
#include "lib/net/resolve.h"
#include "test/test_connection.h" #include "test/test_connection.h"
#include "test/test_helpers.h" #include "test/test_helpers.h"
@ -899,4 +900,3 @@ struct testcase_t connection_tests[] = {
{ "failed_orconn_tracker", test_failed_orconn_tracker, TT_FORK, NULL, NULL }, { "failed_orconn_tracker", test_failed_orconn_tracker, TT_FORK, NULL, NULL },
END_OF_TESTCASES END_OF_TESTCASES
}; };

View File

@ -14,6 +14,7 @@
#include "feature/nodelist/nodelist.h" #include "feature/nodelist/nodelist.h"
#include "test/test.h" #include "test/test.h"
#include "test/test_helpers.h" #include "test/test_helpers.h"
#include "lib/net/resolve.h"
#include "feature/control/control_connection_st.h" #include "feature/control/control_connection_st.h"
#include "feature/dirclient/download_status_st.h" #include "feature/dirclient/download_status_st.h"

View File

@ -24,6 +24,7 @@
#include "core/or/relay.h" #include "core/or/relay.h"
#include "feature/nodelist/routerlist.h" #include "feature/nodelist/routerlist.h"
#include "lib/encoding/confline.h" #include "lib/encoding/confline.h"
#include "lib/net/resolve.h"
#include "core/or/cell_st.h" #include "core/or/cell_st.h"
#include "core/or/connection_st.h" #include "core/or/connection_st.h"

View File

@ -21,6 +21,7 @@
#include "lib/encoding/confline.h" #include "lib/encoding/confline.h"
#include "core/or/policies.h" #include "core/or/policies.h"
#include "test/test_helpers.h" #include "test/test_helpers.h"
#include "lib/net/resolve.h"
#define NS_MODULE test_options #define NS_MODULE test_options

View File

@ -19,6 +19,7 @@
#include "test/test.h" #include "test/test.h"
#include "lib/process/subprocess.h" #include "lib/process/subprocess.h"
#include "lib/encoding/confline.h" #include "lib/encoding/confline.h"
#include "lib/net/resolve.h"
#include "app/config/or_state_st.h" #include "app/config/or_state_st.h"

View File

@ -41,7 +41,8 @@ ENABLE_GCC_WARNING(redundant-decls)
#include "lib/log/torlog.h" #include "lib/log/torlog.h"
#include "lib/malloc/util_malloc.h" #include "lib/malloc/util_malloc.h"
#include "lib/net/address.h" #include "lib/net/address.h"
#include "lib/net/ipv4.h" #include "lib/net/inaddr.h"
#include "lib/net/resolve.h"
#include "lib/string/compat_string.h" #include "lib/string/compat_string.h"
#include "lib/string/printf.h" #include "lib/string/printf.h"
@ -170,19 +171,22 @@ parse_commandline(int argc, char **argv)
} else if (!strcmp(argv[i], "-v")) { } else if (!strcmp(argv[i], "-v")) {
verbose = 1; verbose = 1;
} else if (!strcmp(argv[i], "-a")) { } else if (!strcmp(argv[i], "-a")) {
uint32_t addr; tor_addr_t addr;
uint16_t port; uint16_t port;
char b[INET_NTOA_BUF_LEN];
struct in_addr in;
if (i+1>=argc) { if (i+1>=argc) {
fprintf(stderr, "No argument to -a\n"); fprintf(stderr, "No argument to -a\n");
return 1; return 1;
} }
if (addr_port_lookup(LOG_ERR, argv[++i], NULL, &addr, &port)<0) const char *addr_arg = argv[++i];
if (tor_addr_port_lookup(addr_arg, &addr, &port)<0) {
fprintf(stderr, "Can't resolve address/port for %s", addr_arg);
return 1; return 1;
in.s_addr = htonl(addr); }
tor_inet_ntoa(&in, b, sizeof(b)); if (tor_addr_family(&addr) != AF_INET) {
tor_asprintf(&address, "%s:%d", b, (int)port); fprintf(stderr, "%s must resolve to an IPv4 address", addr_arg);
return 1;
}
address = tor_strdup(fmt_addrport(&addr, port));
} else if (!strcmp(argv[i], "--create-identity-key")) { } else if (!strcmp(argv[i], "--create-identity-key")) {
make_new_id = 1; make_new_id = 1;
} else if (!strcmp(argv[i], "--passphrase-fd")) { } else if (!strcmp(argv[i], "--passphrase-fd")) {

View File

@ -197,12 +197,14 @@ socks5_reason_to_string(char reason)
* address (in host order) into *<b>result_addr</b>. * address (in host order) into *<b>result_addr</b>.
*/ */
static int static int
do_resolve(const char *hostname, uint32_t sockshost, uint16_t socksport, do_resolve(const char *hostname,
const tor_addr_t *sockshost, uint16_t socksport,
int reverse, int version, int reverse, int version,
tor_addr_t *result_addr, char **result_hostname) tor_addr_t *result_addr, char **result_hostname)
{ {
int s = -1; int s = -1;
struct sockaddr_in socksaddr; struct sockaddr_storage ss;
socklen_t socklen;
char *req = NULL; char *req = NULL;
ssize_t len = 0; ssize_t len = 0;
@ -219,11 +221,10 @@ do_resolve(const char *hostname, uint32_t sockshost, uint16_t socksport,
return -1; return -1;
} }
memset(&socksaddr, 0, sizeof(socksaddr)); socklen = tor_addr_to_sockaddr(sockshost, socksport,
socksaddr.sin_family = AF_INET; (struct sockaddr *)&ss, sizeof(ss));
socksaddr.sin_port = htons(socksport);
socksaddr.sin_addr.s_addr = htonl(sockshost); if (connect(s, (struct sockaddr*)&ss, sizeof(socklen))) {
if (connect(s, (struct sockaddr*)&socksaddr, sizeof(socksaddr))) {
log_sock_error("connecting to SOCKS host", s); log_sock_error("connecting to SOCKS host", s);
goto err; goto err;
} }
@ -346,7 +347,7 @@ usage(void)
int int
main(int argc, char **argv) main(int argc, char **argv)
{ {
uint32_t sockshost; tor_addr_t sockshost;
uint16_t socksport = 0, port_option = 0; uint16_t socksport = 0, port_option = 0;
int isSocks4 = 0, isVerbose = 0, isReverse = 0; int isSocks4 = 0, isVerbose = 0, isReverse = 0;
char **arg; char **arg;
@ -414,7 +415,7 @@ main(int argc, char **argv)
if (n_args == 1) { if (n_args == 1) {
log_debug(LD_CONFIG, "defaulting to localhost"); log_debug(LD_CONFIG, "defaulting to localhost");
sockshost = 0x7f000001u; /* localhost */ tor_addr_from_ipv4h(&sockshost, 0x7f000001u); /* localhost */
if (port_option) { if (port_option) {
log_debug(LD_CONFIG, "Using port %d", (int)port_option); log_debug(LD_CONFIG, "Using port %d", (int)port_option);
socksport = port_option; socksport = port_option;
@ -423,7 +424,7 @@ main(int argc, char **argv)
socksport = 9050; /* 9050 */ socksport = 9050; /* 9050 */
} }
} else if (n_args == 2) { } else if (n_args == 2) {
if (addr_port_lookup(LOG_WARN, arg[1], NULL, &sockshost, &socksport)<0) { if (tor_addr_port_lookup(arg[1], &sockshost, &socksport)<0) {
fprintf(stderr, "Couldn't parse/resolve address %s", arg[1]); fprintf(stderr, "Couldn't parse/resolve address %s", arg[1]);
return 1; return 1;
} }
@ -445,7 +446,7 @@ main(int argc, char **argv)
return 1; return 1;
} }
if (do_resolve(arg[0], sockshost, socksport, isReverse, if (do_resolve(arg[0], &sockshost, socksport, isReverse,
isSocks4 ? 4 : 5, &result, isSocks4 ? 4 : 5, &result,
&result_hostname)) &result_hostname))
return 1; return 1;