mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2024-11-10 13:13:44 +01:00
Merge branch 'tor-github/pr/1945'
This commit is contained in:
commit
86da0cfd36
4
changes/ticket33233
Normal file
4
changes/ticket33233
Normal file
@ -0,0 +1,4 @@
|
||||
o Major feature (IPv6, relay):
|
||||
- The torrc option Address now supports IPv6. By doing so, we've also
|
||||
unified the interface to find our address to support IPv4, IPv6 and
|
||||
hostname. Closes ticket 33233;
|
@ -46,7 +46,7 @@ problem function-size /src/app/config/config.c:parse_dir_authority_line() 150
|
||||
problem function-size /src/app/config/config.c:parse_dir_fallback_line() 101
|
||||
problem function-size /src/app/config/config.c:port_parse_config() 435
|
||||
problem function-size /src/app/config/config.c:parse_ports() 132
|
||||
problem function-size /src/app/config/resolve_addr.c:resolve_my_address() 191
|
||||
problem function-size /src/app/config/resolve_addr.c:resolve_my_address_v4() 197
|
||||
problem file-size /src/app/config/or_options_st.h 1050
|
||||
problem include-count /src/app/main/main.c 68
|
||||
problem function-size /src/app/main/main.c:dumpstats() 102
|
||||
|
@ -313,7 +313,7 @@ static const config_var_t option_vars_[] = {
|
||||
V(AccountingMax, MEMUNIT, "0 bytes"),
|
||||
VAR("AccountingRule", STRING, AccountingRule_option, "max"),
|
||||
V(AccountingStart, STRING, NULL),
|
||||
V(Address, STRING, NULL),
|
||||
V(Address, LINELIST, NULL),
|
||||
OBSOLETE("AllowDotExit"),
|
||||
OBSOLETE("AllowInvalidNodes"),
|
||||
V(AllowNonRFC953Hostnames, BOOL, "0"),
|
||||
@ -4028,7 +4028,7 @@ options_check_transition_cb(const void *old_,
|
||||
if (! CFG_EQ_INT(old, new_val, opt)) \
|
||||
BAD_CHANGE_TO(opt," with Sandbox active")
|
||||
|
||||
SB_NOCHANGE_STR(Address);
|
||||
SB_NOCHANGE_LINELIST(Address);
|
||||
SB_NOCHANGE_STR(ServerDNSResolvConfFile);
|
||||
SB_NOCHANGE_STR(DirPortFrontPage);
|
||||
SB_NOCHANGE_STR(CookieAuthFile);
|
||||
|
@ -71,7 +71,10 @@ struct or_options_t {
|
||||
int CacheDirectoryGroupReadable; /**< Boolean: Is the CacheDirectory g+r? */
|
||||
|
||||
char *Nickname; /**< OR only: nickname of this onion router. */
|
||||
char *Address; /**< OR only: configured address for this onion router. */
|
||||
/** OR only: configured address for this onion router. Up to two times this
|
||||
* options is accepted as in IPv4 and IPv6. */
|
||||
struct config_line_t *Address;
|
||||
|
||||
char *PidFile; /**< Where to store PID of Tor process. */
|
||||
|
||||
struct routerset_t *ExitNodes; /**< Structure containing nicknames, digests,
|
||||
|
@ -15,300 +15,600 @@
|
||||
|
||||
#include "feature/control/control_events.h"
|
||||
|
||||
#include "lib/encoding/confline.h"
|
||||
#include "lib/net/gethostname.h"
|
||||
#include "lib/net/resolve.h"
|
||||
|
||||
/** Last value actually set by resolve_my_address. */
|
||||
static uint32_t last_resolved_addr = 0;
|
||||
/** Maximum "Address" statement allowed in our configuration. */
|
||||
#define MAX_CONFIG_ADDRESS 2
|
||||
|
||||
/** Accessor for last_resolved_addr from outside this file. */
|
||||
uint32_t
|
||||
get_last_resolved_addr(void)
|
||||
/** Ease our life. Arrays containing state per address family. These are to
|
||||
* add semantic to the code so we know what is accessed. */
|
||||
#define IDX_NULL 0 /* Index to zeroed address object. */
|
||||
#define IDX_IPV4 1 /* Index to AF_INET. */
|
||||
#define IDX_IPV6 2 /* Index to AF_INET6. */
|
||||
#define IDX_SIZE 3 /* How many indexes do we have. */
|
||||
|
||||
/** Function in our address function table return one of these code. */
|
||||
typedef enum {
|
||||
/* The address has been found. */
|
||||
FN_RET_OK = 0,
|
||||
/* The failure requirements were not met and thus it is recommended that the
|
||||
* caller stops the search. */
|
||||
FN_RET_BAIL = 1,
|
||||
/* The address was not found or failure is transient so the caller should go
|
||||
* to the next method. */
|
||||
FN_RET_NEXT = 2,
|
||||
} fn_address_ret_t;
|
||||
|
||||
/** Last resolved addresses. */
|
||||
static tor_addr_t last_resolved_addrs[IDX_SIZE];
|
||||
|
||||
static inline int
|
||||
af_to_idx(const int family)
|
||||
{
|
||||
return last_resolved_addr;
|
||||
switch (family) {
|
||||
case AF_INET:
|
||||
return IDX_IPV4;
|
||||
case AF_INET6:
|
||||
return IDX_IPV6;
|
||||
default:
|
||||
/* It wouldn't be safe to just die here with an assert but we can heavily
|
||||
* scream with a bug. Return the index of the NULL address. */
|
||||
tor_assert_nonfatal_unreached();
|
||||
return IDX_NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/** Reset last_resolved_addr from outside this file. */
|
||||
/** Copy the last resolved address of family into addr_out.
|
||||
*
|
||||
* If not last resolved address existed, the addr_out is a null address (use
|
||||
* tor_addr_is_null()). */
|
||||
void
|
||||
reset_last_resolved_addr(void)
|
||||
resolved_addr_get_last(int family, tor_addr_t *addr_out)
|
||||
{
|
||||
last_resolved_addr = 0;
|
||||
tor_addr_copy(addr_out, &last_resolved_addrs[af_to_idx(family)]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempt getting our non-local (as judged by tor_addr_is_internal()
|
||||
* function) IP address using following techniques, listed in
|
||||
* order from best (most desirable, try first) to worst (least
|
||||
* desirable, try if everything else fails).
|
||||
/** Reset the last resolved address of family.
|
||||
*
|
||||
* First, attempt using <b>options-\>Address</b> to get our
|
||||
* non-local IP address.
|
||||
*
|
||||
* If <b>options-\>Address</b> represents a non-local IP address,
|
||||
* consider it ours.
|
||||
*
|
||||
* If <b>options-\>Address</b> is a DNS name that resolves to
|
||||
* a non-local IP address, consider this IP address ours.
|
||||
*
|
||||
* If <b>options-\>Address</b> is NULL, fall back to getting local
|
||||
* hostname and using it in above-described ways to try and
|
||||
* get our IP address.
|
||||
*
|
||||
* In case local hostname cannot be resolved to a non-local IP
|
||||
* address, try getting an IP address of network interface
|
||||
* in hopes it will be non-local one.
|
||||
*
|
||||
* Fail if one or more of the following is true:
|
||||
* - DNS name in <b>options-\>Address</b> cannot be resolved.
|
||||
* - <b>options-\>Address</b> is a local host address.
|
||||
* - Attempt at getting local hostname fails.
|
||||
* - Attempt at getting network interface address fails.
|
||||
*
|
||||
* Return 0 if all is well, or -1 if we can't find a suitable
|
||||
* public IP address.
|
||||
*
|
||||
* If we are returning 0:
|
||||
* - Put our public IP address (in host order) into *<b>addr_out</b>.
|
||||
* - If <b>method_out</b> is non-NULL, set *<b>method_out</b> to a static
|
||||
* string describing how we arrived at our answer.
|
||||
* - "CONFIGURED" - parsed from IP address string in
|
||||
* <b>options-\>Address</b>
|
||||
* - "RESOLVED" - resolved from DNS name in <b>options-\>Address</b>
|
||||
* - "GETHOSTNAME" - resolved from a local hostname.
|
||||
* - "INTERFACE" - retrieved from a network interface.
|
||||
* - If <b>hostname_out</b> is non-NULL, and we resolved a hostname to
|
||||
* get our address, set *<b>hostname_out</b> to a newly allocated string
|
||||
* holding that hostname. (If we didn't get our address by resolving a
|
||||
* hostname, set *<b>hostname_out</b> to NULL.)
|
||||
*
|
||||
* XXXX ipv6
|
||||
*/
|
||||
int
|
||||
resolve_my_address(int warn_severity, const or_options_t *options,
|
||||
uint32_t *addr_out,
|
||||
const char **method_out, char **hostname_out)
|
||||
* This makes it null address. */
|
||||
void
|
||||
resolved_addr_reset_last(int family)
|
||||
{
|
||||
struct in_addr in;
|
||||
uint32_t addr; /* host order */
|
||||
char hostname[256];
|
||||
const char *method_used;
|
||||
const char *hostname_used;
|
||||
int explicit_ip=1;
|
||||
int explicit_hostname=1;
|
||||
int from_interface=0;
|
||||
char *addr_string = NULL;
|
||||
const char *address = options->Address;
|
||||
int notice_severity = warn_severity <= LOG_NOTICE ?
|
||||
LOG_NOTICE : warn_severity;
|
||||
tor_addr_make_null(&last_resolved_addrs[af_to_idx(family)], family);
|
||||
}
|
||||
|
||||
tor_addr_t myaddr;
|
||||
/** Errors returned by address_can_be_used() in order for the caller to know
|
||||
* why the address is denied or not. */
|
||||
#define ERR_DEFAULT_DIRAUTH -1 /* Using default authorities. */
|
||||
#define ERR_ADDRESS_IS_INTERNAL -2 /* IP is internal. */
|
||||
|
||||
/** @brief Return true iff the given IP address can be used as a valid
|
||||
* external resolved address.
|
||||
*
|
||||
* Two tests are done in this function:
|
||||
* 1) If the address if NOT internal, it can be used.
|
||||
* 2) If the address is internal and we have custom directory authorities
|
||||
* configured then it can they be used. Important for testing networks.
|
||||
*
|
||||
* @param addr The IP address to validate.
|
||||
* @param options Global configuration options.
|
||||
* @param warn_severity Log level that should be used on error.
|
||||
* @param explicit_ip Was the IP address explicitly given.
|
||||
*
|
||||
* @return Return 0 if it can be used. Return error code ERR_* found at the
|
||||
* top of the file.
|
||||
*/
|
||||
static int
|
||||
address_can_be_used(const tor_addr_t *addr, const or_options_t *options,
|
||||
int warn_severity, const bool explicit_ip)
|
||||
{
|
||||
tor_assert(addr);
|
||||
|
||||
/* Public address, this is fine. */
|
||||
if (!tor_addr_is_internal(addr, 0)) {
|
||||
goto allow;
|
||||
}
|
||||
|
||||
/* We have a private IP address. It is allowed only if we set custom
|
||||
* directory authorities. */
|
||||
if (using_default_dir_authorities(options)) {
|
||||
log_fn(warn_severity, LD_CONFIG,
|
||||
"Address '%s' is a private IP address. Tor relays that use "
|
||||
"the default DirAuthorities must have public IP addresses.",
|
||||
fmt_addr(addr));
|
||||
return ERR_DEFAULT_DIRAUTH;
|
||||
}
|
||||
|
||||
if (!explicit_ip) {
|
||||
/* Even with custom directory authorities, only an explicit internal
|
||||
* address is accepted. */
|
||||
log_fn(warn_severity, LD_CONFIG,
|
||||
"Address %s was resolved and thus not explicitly "
|
||||
"set. Even if DirAuthorities are custom, this is "
|
||||
"not allowed.", fmt_addr(addr));
|
||||
return ERR_ADDRESS_IS_INTERNAL;
|
||||
}
|
||||
|
||||
allow:
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** @brief Get IP address from the given config line and for a specific address
|
||||
* family.
|
||||
*
|
||||
* This can fail is more than two Address statement are found for the same
|
||||
* address family. It also fails if no statement is found.
|
||||
*
|
||||
* @param options Global configuration options.
|
||||
* @param warn_severity Log level that should be used on error.
|
||||
* @param family IP address family. Only AF_INET and AF_INET6 are supported.
|
||||
* @param method_out OUT: String denoting by which method the address was
|
||||
* found. This is described in the control-spec.txt as
|
||||
* actions for "STATUS_SERVER".
|
||||
* @param hostname_out OUT: String containing the hostname gotten from the
|
||||
* Address value if any.
|
||||
* @param addr_out OUT: Tor address of the address found in the cline or
|
||||
* resolved from the cline.
|
||||
*
|
||||
* @return Return 0 on success that is an address has been found or resolved
|
||||
* successfully. Return error code ERR_* found at the top of the file.
|
||||
*/
|
||||
static fn_address_ret_t
|
||||
get_address_from_config(const or_options_t *options, int warn_severity,
|
||||
int family, const char **method_out,
|
||||
char **hostname_out, tor_addr_t *addr_out)
|
||||
{
|
||||
int ret;
|
||||
bool explicit_ip = false;
|
||||
int num_valid_addr = 0;
|
||||
|
||||
tor_assert(options);
|
||||
tor_assert(addr_out);
|
||||
tor_assert(method_out);
|
||||
tor_assert(hostname_out);
|
||||
|
||||
/* Set them to NULL for safety reasons. */
|
||||
*hostname_out = NULL;
|
||||
*method_out = NULL;
|
||||
|
||||
log_debug(LD_CONFIG, "Attempting to get address from configuration");
|
||||
|
||||
if (!options->Address) {
|
||||
log_info(LD_CONFIG, "No Address option found in configuration.");
|
||||
/* No Address statement, inform caller to try next method. */
|
||||
return FN_RET_NEXT;
|
||||
}
|
||||
|
||||
for (const config_line_t *cfg = options->Address; cfg != NULL;
|
||||
cfg = cfg->next) {
|
||||
int af;
|
||||
tor_addr_t addr;
|
||||
|
||||
af = tor_addr_parse(&addr, cfg->value);
|
||||
if (af == family) {
|
||||
tor_addr_copy(addr_out, &addr);
|
||||
*method_out = "CONFIGURED";
|
||||
explicit_ip = true;
|
||||
num_valid_addr++;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Not an IP address. Considering this value a hostname and attempting to
|
||||
* do a DNS lookup. */
|
||||
if (!tor_addr_lookup(cfg->value, family, &addr)) {
|
||||
tor_addr_copy(addr_out, &addr);
|
||||
*method_out = "RESOLVED";
|
||||
*hostname_out = tor_strdup(cfg->value);
|
||||
explicit_ip = false;
|
||||
num_valid_addr++;
|
||||
continue;
|
||||
} else {
|
||||
/* Hostname that can't be resolved, this is a fatal error. */
|
||||
log_fn(warn_severity, LD_CONFIG,
|
||||
"Could not resolve local Address '%s'. Failing.", cfg->value);
|
||||
return FN_RET_BAIL;
|
||||
}
|
||||
}
|
||||
|
||||
if (!num_valid_addr) {
|
||||
log_fn(warn_severity, LD_CONFIG,
|
||||
"No Address option found for family %s in configuration.",
|
||||
fmt_af_family(family));
|
||||
/* No Address statement for family, inform caller to try next method. */
|
||||
return FN_RET_NEXT;
|
||||
}
|
||||
|
||||
if (num_valid_addr >= MAX_CONFIG_ADDRESS) {
|
||||
/* Too many Address for same family. This is a fatal error. */
|
||||
log_fn(warn_severity, LD_CONFIG,
|
||||
"Found %d Address statement of address family %s. "
|
||||
"Only one is allowed.", num_valid_addr, fmt_af_family(family));
|
||||
return FN_RET_BAIL;
|
||||
}
|
||||
|
||||
/* Great, we found an address. */
|
||||
ret = address_can_be_used(addr_out, options, warn_severity, explicit_ip);
|
||||
if (ret != 0) {
|
||||
/* One of the requirement of this interface is if an internal Address is
|
||||
* used, custom authorities must be defined else it is a fatal error.
|
||||
* Furthermore, if the Address was resolved to an internal interface, we
|
||||
* stop immediately. */
|
||||
return FN_RET_BAIL;
|
||||
}
|
||||
|
||||
/* Address can be used. We are done. */
|
||||
log_fn(warn_severity, LD_CONFIG, "Address found in configuration: %s",
|
||||
fmt_addr(addr_out));
|
||||
return FN_RET_OK;
|
||||
}
|
||||
|
||||
/** @brief Get IP address from the local hostname by calling gethostbyname()
|
||||
* and doing a DNS resolution on the hostname.
|
||||
*
|
||||
* @param options Global configuration options.
|
||||
* @param warn_severity Log level that should be used on error.
|
||||
* @param family IP address family. Only AF_INET and AF_INET6 are supported.
|
||||
* @param method_out OUT: String denoting by which method the address was
|
||||
* found. This is described in the control-spec.txt as
|
||||
* actions for "STATUS_SERVER".
|
||||
* @param hostname_out OUT: String containing the local hostname.
|
||||
* @param addr_out OUT: Tor address resolved from the local hostname.
|
||||
*
|
||||
* @return Return 0 on success that is an address has been found and resolved
|
||||
* successfully. Return error code ERR_* found at the top of the file.
|
||||
*/
|
||||
static fn_address_ret_t
|
||||
get_address_from_hostname(const or_options_t *options, int warn_severity,
|
||||
int family, const char **method_out,
|
||||
char **hostname_out, tor_addr_t *addr_out)
|
||||
{
|
||||
int ret;
|
||||
char hostname[256];
|
||||
|
||||
tor_assert(addr_out);
|
||||
tor_assert(method_out);
|
||||
|
||||
/* Set them to NULL for safety reasons. */
|
||||
*hostname_out = NULL;
|
||||
*method_out = NULL;
|
||||
|
||||
log_debug(LD_CONFIG, "Attempting to get address from local hostname");
|
||||
|
||||
if (tor_gethostname(hostname, sizeof(hostname)) < 0) {
|
||||
log_fn(warn_severity, LD_NET, "Error obtaining local hostname");
|
||||
/* Unable to obtain the local hostname is a fatal error. */
|
||||
return FN_RET_BAIL;
|
||||
}
|
||||
if (tor_addr_lookup(hostname, family, addr_out)) {
|
||||
log_fn(warn_severity, LD_NET,
|
||||
"Could not resolve local hostname '%s'. Failing.", hostname);
|
||||
/* Unable to resolve, inform caller to try next method. */
|
||||
return FN_RET_NEXT;
|
||||
}
|
||||
|
||||
ret = address_can_be_used(addr_out, options, warn_severity, false);
|
||||
if (ret == ERR_DEFAULT_DIRAUTH) {
|
||||
/* Non custom authorities, inform caller to try next method. */
|
||||
return FN_RET_NEXT;
|
||||
} else if (ret == ERR_ADDRESS_IS_INTERNAL) {
|
||||
/* Internal address is a fatal error. */
|
||||
return FN_RET_BAIL;
|
||||
}
|
||||
|
||||
/* addr_out contains the address of the local hostname. */
|
||||
*method_out = "GETHOSTNAME";
|
||||
*hostname_out = tor_strdup(hostname);
|
||||
|
||||
/* Found it! */
|
||||
log_fn(warn_severity, LD_CONFIG, "Address found from local hostname: %s",
|
||||
fmt_addr(addr_out));
|
||||
return FN_RET_OK;
|
||||
}
|
||||
|
||||
/** @brief Get IP address from a network interface.
|
||||
*
|
||||
* @param options Global configuration options.
|
||||
* @param warn_severity Log level that should be used on error.
|
||||
* @param family IP address family. Only AF_INET and AF_INET6 are supported.
|
||||
* @param method_out OUT: Always "INTERFACE" on success which is detailed in
|
||||
* the control-spec.txt as actions for "STATUS_SERVER".
|
||||
* @param hostname_out OUT: String containing the local hostname. For this
|
||||
* function, it is always set to NULL.
|
||||
* @param addr_out OUT: Tor address found attached to the interface.
|
||||
*
|
||||
* @return Return 0 on success that is an address has been found. Return
|
||||
* error code ERR_* found at the top of the file.
|
||||
*/
|
||||
static fn_address_ret_t
|
||||
get_address_from_interface(const or_options_t *options, int warn_severity,
|
||||
int family, const char **method_out,
|
||||
char **hostname_out, tor_addr_t *addr_out)
|
||||
{
|
||||
int ret;
|
||||
|
||||
tor_assert(method_out);
|
||||
tor_assert(hostname_out);
|
||||
tor_assert(addr_out);
|
||||
|
||||
/*
|
||||
* Step one: Fill in 'hostname' to be our best guess.
|
||||
*/
|
||||
/* Set them to NULL for safety reasons. */
|
||||
*method_out = NULL;
|
||||
*hostname_out = NULL;
|
||||
|
||||
if (address && *address) {
|
||||
strlcpy(hostname, address, sizeof(hostname));
|
||||
log_debug(LD_CONFIG, "Trying configured Address '%s' as local hostname",
|
||||
hostname);
|
||||
} else { /* then we need to guess our address */
|
||||
explicit_ip = 0; /* it's implicit */
|
||||
explicit_hostname = 0; /* it's implicit */
|
||||
log_debug(LD_CONFIG, "Attempting to get address from network interface");
|
||||
|
||||
if (tor_gethostname(hostname, sizeof(hostname)) < 0) {
|
||||
log_fn(warn_severity, LD_NET,"Error obtaining local hostname");
|
||||
return -1;
|
||||
}
|
||||
log_debug(LD_CONFIG, "Guessed local host name as '%s'", hostname);
|
||||
if (get_interface_address6(warn_severity, family, addr_out) < 0) {
|
||||
log_fn(warn_severity, LD_CONFIG,
|
||||
"Could not get local interface IP address.");
|
||||
/* Unable to get IP from interface. Inform caller to try next method. */
|
||||
return FN_RET_NEXT;
|
||||
}
|
||||
|
||||
/*
|
||||
* Step two: Now that we know 'hostname', parse it or resolve it. If
|
||||
* it doesn't parse or resolve, look at the interface address. Set 'addr'
|
||||
* to be our (host-order) 32-bit answer.
|
||||
*/
|
||||
|
||||
if (tor_inet_aton(hostname, &in) == 0) {
|
||||
/* then we have to resolve it */
|
||||
log_debug(LD_CONFIG, "Local hostname '%s' is DNS address. "
|
||||
"Trying to resolve to IP address.", hostname);
|
||||
explicit_ip = 0;
|
||||
if (tor_lookup_hostname(hostname, &addr)) { /* failed to resolve */
|
||||
uint32_t interface_ip; /* host order */
|
||||
|
||||
if (explicit_hostname) {
|
||||
log_fn(warn_severity, LD_CONFIG,
|
||||
"Could not resolve local Address '%s'. Failing.", hostname);
|
||||
return -1;
|
||||
}
|
||||
log_fn(notice_severity, LD_CONFIG,
|
||||
"Could not resolve guessed local hostname '%s'. "
|
||||
"Trying something else.", hostname);
|
||||
if (get_interface_address(warn_severity, &interface_ip)) {
|
||||
log_fn(warn_severity, LD_CONFIG,
|
||||
"Could not get local interface IP address. Failing.");
|
||||
return -1;
|
||||
}
|
||||
from_interface = 1;
|
||||
addr = interface_ip;
|
||||
log_fn(notice_severity, LD_CONFIG, "Learned IP address '%s' for "
|
||||
"local interface. Using that.", fmt_addr32(addr));
|
||||
strlcpy(hostname, "<guessed from interfaces>", sizeof(hostname));
|
||||
} else { /* resolved hostname into addr */
|
||||
tor_addr_from_ipv4h(&myaddr, addr);
|
||||
|
||||
if (!explicit_hostname &&
|
||||
tor_addr_is_internal(&myaddr, 0)) {
|
||||
tor_addr_t interface_ip;
|
||||
|
||||
log_fn(notice_severity, LD_CONFIG, "Guessed local hostname '%s' "
|
||||
"resolves to a private IP address (%s). Trying something "
|
||||
"else.", hostname, fmt_addr32(addr));
|
||||
|
||||
if (get_interface_address6(warn_severity, AF_INET, &interface_ip)<0) {
|
||||
log_fn(warn_severity, LD_CONFIG,
|
||||
"Could not get local interface IP address. Too bad.");
|
||||
} else if (tor_addr_is_internal(&interface_ip, 0)) {
|
||||
log_fn(notice_severity, LD_CONFIG,
|
||||
"Interface IP address '%s' is a private address too. "
|
||||
"Ignoring.", fmt_addr(&interface_ip));
|
||||
} else {
|
||||
from_interface = 1;
|
||||
addr = tor_addr_to_ipv4h(&interface_ip);
|
||||
log_fn(notice_severity, LD_CONFIG,
|
||||
"Learned IP address '%s' for local interface."
|
||||
" Using that.", fmt_addr32(addr));
|
||||
strlcpy(hostname, "<guessed from interfaces>", sizeof(hostname));
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
log_debug(LD_CONFIG, "Local hostname '%s' is already IP address, "
|
||||
"skipping DNS resolution", hostname);
|
||||
addr = ntohl(in.s_addr); /* set addr so that addr_string is not
|
||||
* illformed */
|
||||
ret = address_can_be_used(addr_out, options, warn_severity, false);
|
||||
if (ret < 0) {
|
||||
/* Unable to use address. Inform caller to try next method. */
|
||||
return FN_RET_NEXT;
|
||||
}
|
||||
|
||||
/*
|
||||
* Step three: Check whether 'addr' is an internal IP address, and error
|
||||
* out if it is and we don't want that.
|
||||
*/
|
||||
*method_out = "INTERFACE";
|
||||
|
||||
tor_addr_from_ipv4h(&myaddr,addr);
|
||||
/* Found it! */
|
||||
log_fn(warn_severity, LD_CONFIG, "Address found from interface: %s",
|
||||
fmt_addr(addr_out));
|
||||
return FN_RET_OK;
|
||||
}
|
||||
|
||||
addr_string = tor_dup_ip(addr);
|
||||
if (addr_string && tor_addr_is_internal(&myaddr, 0)) {
|
||||
/* make sure we're ok with publishing an internal IP */
|
||||
if (using_default_dir_authorities(options)) {
|
||||
/* if they are using the default authorities, disallow internal IPs
|
||||
* always. For IPv6 ORPorts, this check is done in
|
||||
* router_get_advertised_ipv6_or_ap(). See #33681. */
|
||||
log_fn(warn_severity, LD_CONFIG,
|
||||
"Address '%s' resolves to private IP address '%s'. "
|
||||
"Tor servers that use the default DirAuthorities must have "
|
||||
"public IP addresses.", hostname, addr_string);
|
||||
tor_free(addr_string);
|
||||
return -1;
|
||||
}
|
||||
if (!explicit_ip) {
|
||||
/* even if they've set their own authorities, require an explicit IP if
|
||||
* they're using an internal address. */
|
||||
log_fn(warn_severity, LD_CONFIG, "Address '%s' resolves to private "
|
||||
"IP address '%s'. Please set the Address config option to be "
|
||||
"the IP address you want to use.", hostname, addr_string);
|
||||
tor_free(addr_string);
|
||||
return -1;
|
||||
}
|
||||
/** @brief Update the last resolved address cache using the given address.
|
||||
*
|
||||
* A log notice is emitted if the given address has changed from before. Not
|
||||
* emitted on first resolve.
|
||||
*
|
||||
* Control port event "STATUS_SERVER" is emitted with the new information if
|
||||
* it has changed.
|
||||
*
|
||||
* Finally, tor is notified that the IP address has changed.
|
||||
*
|
||||
* @param addr IP address to update the cache with.
|
||||
* @param method_used By which method did we resolved it (for logging and
|
||||
* control port).
|
||||
* @param hostname_used Which hostname was used. If none were used, it is
|
||||
* NULL. (for logging and control port).
|
||||
*/
|
||||
static void
|
||||
update_resolved_cache(const tor_addr_t *addr, const char *method_used,
|
||||
const char *hostname_used)
|
||||
{
|
||||
/** Have we done a first resolve. This is used to control logging. */
|
||||
static bool have_resolved_once[IDX_SIZE] = { false, false, false };
|
||||
bool *done_one_resolve;
|
||||
bool have_hostname = false;
|
||||
tor_addr_t *last_resolved;
|
||||
|
||||
tor_assert(addr);
|
||||
tor_assert(method_used);
|
||||
|
||||
/* Do we have an hostname. */
|
||||
have_hostname = (hostname_used != NULL);
|
||||
|
||||
int idx = af_to_idx(tor_addr_family(addr));
|
||||
if (idx == IDX_NULL) {
|
||||
/* Not suppose to happen and if it does, af_to_idx() screams loudly. */
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Step four: We have a winner! 'addr' is our answer for sure, and
|
||||
* 'addr_string' is its string form. Fill out the various fields to
|
||||
* say how we decided it.
|
||||
*/
|
||||
/* Get values from cache. */
|
||||
done_one_resolve = &have_resolved_once[idx];
|
||||
last_resolved = &last_resolved_addrs[idx];
|
||||
|
||||
log_debug(LD_CONFIG, "Resolved Address to '%s'.", addr_string);
|
||||
|
||||
if (explicit_ip) {
|
||||
method_used = "CONFIGURED";
|
||||
hostname_used = NULL;
|
||||
} else if (explicit_hostname) {
|
||||
method_used = "RESOLVED";
|
||||
hostname_used = hostname;
|
||||
} else if (from_interface) {
|
||||
method_used = "INTERFACE";
|
||||
hostname_used = NULL;
|
||||
} else {
|
||||
method_used = "GETHOSTNAME";
|
||||
hostname_used = hostname;
|
||||
/* Same address last resolved. Ignore. */
|
||||
if (tor_addr_eq(last_resolved, addr)) {
|
||||
return;
|
||||
}
|
||||
|
||||
*addr_out = addr;
|
||||
if (method_out)
|
||||
*method_out = method_used;
|
||||
if (hostname_out)
|
||||
*hostname_out = hostname_used ? tor_strdup(hostname_used) : NULL;
|
||||
|
||||
/*
|
||||
* Step five: Check if the answer has changed since last time (or if
|
||||
* there was no last time), and if so call various functions to keep
|
||||
* us up-to-date.
|
||||
*/
|
||||
|
||||
if (last_resolved_addr && last_resolved_addr != *addr_out) {
|
||||
/* Don't log notice if this is the first resolve we do. */
|
||||
if (*done_one_resolve) {
|
||||
/* Leave this as a notice, regardless of the requested severity,
|
||||
* at least until dynamic IP address support becomes bulletproof. */
|
||||
log_notice(LD_NET,
|
||||
"Your IP address seems to have changed to %s "
|
||||
"(METHOD=%s%s%s). Updating.",
|
||||
addr_string, method_used,
|
||||
hostname_used ? " HOSTNAME=" : "",
|
||||
hostname_used ? hostname_used : "");
|
||||
fmt_addr(addr), method_used,
|
||||
have_hostname ? " HOSTNAME=" : "",
|
||||
have_hostname ? hostname_used : "");
|
||||
ip_address_changed(0);
|
||||
}
|
||||
|
||||
if (last_resolved_addr != *addr_out) {
|
||||
control_event_server_status(LOG_NOTICE,
|
||||
"EXTERNAL_ADDRESS ADDRESS=%s METHOD=%s%s%s",
|
||||
addr_string, method_used,
|
||||
hostname_used ? " HOSTNAME=" : "",
|
||||
hostname_used ? hostname_used : "");
|
||||
}
|
||||
last_resolved_addr = *addr_out;
|
||||
/* Notify control port. */
|
||||
control_event_server_status(LOG_NOTICE,
|
||||
"EXTERNAL_ADDRESS ADDRESS=%s METHOD=%s%s%s",
|
||||
fmt_addr(addr), method_used,
|
||||
have_hostname ? " HOSTNAME=" : "",
|
||||
have_hostname ? hostname_used : "");
|
||||
/* Copy address to cache. */
|
||||
tor_addr_copy(last_resolved, addr);
|
||||
*done_one_resolve = true;
|
||||
}
|
||||
|
||||
/** Address discovery function table. The order matters as in the first one is
|
||||
* executed first and so on. */
|
||||
static fn_address_ret_t
|
||||
(*fn_address_table[])(
|
||||
const or_options_t *options, int warn_severity, int family,
|
||||
const char **method_out, char **hostname_out, tor_addr_t *addr_out) =
|
||||
{
|
||||
/* These functions are in order for our find address algorithm. */
|
||||
get_address_from_config,
|
||||
get_address_from_hostname,
|
||||
get_address_from_interface,
|
||||
};
|
||||
/** Length of address table as in how many functions. */
|
||||
static const size_t fn_address_table_len = ARRAY_LENGTH(fn_address_table);
|
||||
|
||||
/** @brief Attempt to find our IP address that can be used as our external
|
||||
* reachable address.
|
||||
*
|
||||
* The following describe the algorithm to find an address. Each have
|
||||
* specific conditions so read carefully.
|
||||
*
|
||||
* On success, true is returned and depending on how the address was found,
|
||||
* the out parameters can have different values.
|
||||
*
|
||||
* On error, false is returned and out parameters are set to NULL.
|
||||
*
|
||||
* 1. Look at the configuration Address option.
|
||||
|
||||
* If Address is a public address, True is returned and addr_out is set
|
||||
* with it, the method_out is set to "CONFIGURED" and hostname_out is set
|
||||
* to NULL.
|
||||
*
|
||||
* If Address is an internal address but NO custom authorities are used,
|
||||
* an error is returned.
|
||||
*
|
||||
* If Address is a hostname, that is it can't be converted to an address,
|
||||
* it is resolved. On success, addr_out is set with the address,
|
||||
* method_out is set to "RESOLVED" and hostname_out is set to the resolved
|
||||
* hostname. On failure to resolve, an error is returned.
|
||||
*
|
||||
* If no given Address, fallback to the local hostname (see section 2).
|
||||
*
|
||||
* 2. Look at the local hostname.
|
||||
*
|
||||
* If the local hostname resolves to a non internal address, addr_out is
|
||||
* set with it, method_out is set to "GETHOSTNAME" and hostname_out is set
|
||||
* to the resolved hostname.
|
||||
*
|
||||
* If a local hostname can NOT be found, an error is returned.
|
||||
*
|
||||
* If the local hostname resolves to an internal address, an error is
|
||||
* returned.
|
||||
*
|
||||
* If the local hostname can NOT be resolved, fallback to the network
|
||||
* interface (see section 3).
|
||||
*
|
||||
* 3. Look at the network interface.
|
||||
*
|
||||
* Attempt to find the first public usable address from the list of
|
||||
* network interface returned by the OS.
|
||||
*
|
||||
* On failure, an error is returned. This error indicates that all
|
||||
* attempts have failed and thus the address for the given family can not
|
||||
* be found.
|
||||
*
|
||||
* On success, addr_out is set with it, method_out is set to "INTERFACE"
|
||||
* and hostname_out is set to NULL.
|
||||
*
|
||||
* @param options Global configuration options.
|
||||
* @param family IP address family. Only AF_INET and AF_INET6 are supported.
|
||||
* @param warn_severity Logging level.
|
||||
* @param addr_out OUT: Set with the IP address found if any.
|
||||
* @param method_out OUT: (optional) String denoting by which method the
|
||||
* address was found. This is described in the
|
||||
* control-spec.txt as actions for "STATUS_SERVER".
|
||||
* @param hostname_out OUT: String containing the hostname if any was used.
|
||||
* Only be set for "RESOLVED" and "GETHOSTNAME" methods.
|
||||
* Else it is set to NULL.
|
||||
*
|
||||
* @return True if the address was found for the given family. False if not or
|
||||
* on errors.
|
||||
*/
|
||||
bool
|
||||
find_my_address(const or_options_t *options, int family, int warn_severity,
|
||||
tor_addr_t *addr_out, const char **method_out,
|
||||
char **hostname_out)
|
||||
{
|
||||
const char *method_used = NULL;
|
||||
char *hostname_used = NULL;
|
||||
tor_addr_t my_addr;
|
||||
|
||||
tor_assert(options);
|
||||
tor_assert(addr_out);
|
||||
|
||||
/* Set them to NULL for safety reasons. */
|
||||
if (method_out) *method_out = NULL;
|
||||
if (hostname_out) *hostname_out = NULL;
|
||||
|
||||
/*
|
||||
* And finally, clean up and return success.
|
||||
* Step 1: Discover address by attempting 3 different methods consecutively.
|
||||
*/
|
||||
|
||||
tor_free(addr_string);
|
||||
return 0;
|
||||
/* Go over the function table. They are in order. */
|
||||
for (size_t idx = 0; idx < fn_address_table_len; idx++) {
|
||||
fn_address_ret_t ret = fn_address_table[idx](options, warn_severity,
|
||||
family, &method_used,
|
||||
&hostname_used, &my_addr);
|
||||
if (ret == FN_RET_BAIL) {
|
||||
return false;
|
||||
} else if (ret == FN_RET_OK) {
|
||||
goto found;
|
||||
}
|
||||
tor_assert(ret == FN_RET_NEXT);
|
||||
}
|
||||
|
||||
/* We've exhausted our attempts. Failure. */
|
||||
log_fn(warn_severity, LD_CONFIG, "Unable to find our IP address.");
|
||||
return false;
|
||||
|
||||
found:
|
||||
/*
|
||||
* Step 2: Update last resolved address cache and inform the control port.
|
||||
*/
|
||||
update_resolved_cache(&my_addr, method_used, hostname_used);
|
||||
|
||||
if (method_out) {
|
||||
*method_out = method_used;
|
||||
}
|
||||
if (hostname_out) {
|
||||
*hostname_out = hostname_used;
|
||||
} else {
|
||||
tor_free(hostname_used);
|
||||
}
|
||||
|
||||
tor_addr_copy(addr_out, &my_addr);
|
||||
return true;
|
||||
}
|
||||
|
||||
/** Return true iff <b>addr</b> is judged to be on the same network as us, or
|
||||
* on a private network.
|
||||
*/
|
||||
MOCK_IMPL(int,
|
||||
is_local_addr, (const tor_addr_t *addr))
|
||||
MOCK_IMPL(bool,
|
||||
is_local_to_resolve_addr, (const tor_addr_t *addr))
|
||||
{
|
||||
if (tor_addr_is_internal(addr, 0))
|
||||
return 1;
|
||||
/* Check whether ip is on the same /24 as we are. */
|
||||
if (get_options()->EnforceDistinctSubnets == 0)
|
||||
return 0;
|
||||
if (tor_addr_family(addr) == AF_INET) {
|
||||
uint32_t ip = tor_addr_to_ipv4h(addr);
|
||||
const int family = tor_addr_family(addr);
|
||||
const tor_addr_t *last_resolved_addr = &last_resolved_addrs[family];
|
||||
|
||||
/* Internal address is always local. */
|
||||
if (tor_addr_is_internal(addr, 0)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Address is not local if we don't enforce subnet distinction. */
|
||||
if (get_options()->EnforceDistinctSubnets == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (family) {
|
||||
case AF_INET:
|
||||
/* XXX: Why is this /24 and not /16 which the rest of tor does? Unknown
|
||||
* reasons at the moment highlighted in ticket #40009. Because of that, we
|
||||
* can't use addrs_in_same_network_family(). */
|
||||
|
||||
/* It's possible that this next check will hit before the first time
|
||||
* resolve_my_address actually succeeds. (For clients, it is likely that
|
||||
* resolve_my_address will never be called at all). In those cases,
|
||||
* last_resolved_addr will be 0, and so checking to see whether ip is on
|
||||
* the same /24 as last_resolved_addr will be the same as checking whether
|
||||
* it was on net 0, which is already done by tor_addr_is_internal.
|
||||
*/
|
||||
if ((last_resolved_addr & (uint32_t)0xffffff00ul)
|
||||
== (ip & (uint32_t)0xffffff00ul))
|
||||
return 1;
|
||||
* find_my_address actually succeeds. For clients, it is likely that
|
||||
* find_my_address will never be called at all. In those cases,
|
||||
* last_resolved_addr_v4 will be 0, and so checking to see whether ip is
|
||||
* on the same /24 as last_resolved_addrs[AF_INET] will be the same as
|
||||
* checking whether it was on net 0, which is already done by
|
||||
* tor_addr_is_internal. */
|
||||
return tor_addr_compare_masked(addr, last_resolved_addr, 24,
|
||||
CMP_SEMANTIC) == 0;
|
||||
case AF_INET6:
|
||||
/* Look at the /32 like addrs_in_same_network_family() does. */
|
||||
return tor_addr_compare_masked(addr, last_resolved_addr, 32,
|
||||
CMP_SEMANTIC) == 0;
|
||||
break;
|
||||
default:
|
||||
/* Unknown address type so not local. */
|
||||
return false;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -11,14 +11,14 @@
|
||||
|
||||
#include "app/config/or_options_st.h"
|
||||
|
||||
int resolve_my_address(int warn_severity, const or_options_t *options,
|
||||
uint32_t *addr_out,
|
||||
const char **method_out, char **hostname_out);
|
||||
bool find_my_address(const or_options_t *options, int family,
|
||||
int warn_severity, tor_addr_t *addr_out,
|
||||
const char **method_out, char **hostname_out);
|
||||
|
||||
uint32_t get_last_resolved_addr(void);
|
||||
void reset_last_resolved_addr(void);
|
||||
void resolved_addr_get_last(int family, tor_addr_t *addr_out);
|
||||
void resolved_addr_reset_last(int family);
|
||||
|
||||
MOCK_DECL(int, is_local_addr, (const tor_addr_t *addr));
|
||||
MOCK_DECL(bool, is_local_to_resolve_addr, (const tor_addr_t *addr));
|
||||
|
||||
#ifdef RESOLVE_ADDR_PRIVATE
|
||||
|
||||
|
@ -795,8 +795,7 @@ do_dump_config(void)
|
||||
static void
|
||||
init_addrinfo(void)
|
||||
{
|
||||
if (! server_mode(get_options()) ||
|
||||
(get_options()->Address && strlen(get_options()->Address) > 0)) {
|
||||
if (! server_mode(get_options()) || get_options()->Address) {
|
||||
/* We don't need to seed our own hostname, because we won't be calling
|
||||
* resolve_my_address on it.
|
||||
*/
|
||||
|
@ -4870,7 +4870,7 @@ client_check_address_changed(tor_socket_t sock)
|
||||
smartlist_clear(outgoing_addrs);
|
||||
smartlist_add(outgoing_addrs, tor_memdup(&out_addr, sizeof(tor_addr_t)));
|
||||
/* We'll need to resolve ourselves again. */
|
||||
reset_last_resolved_addr();
|
||||
resolved_addr_reset_last(AF_INET);
|
||||
/* Okay, now change our keys. */
|
||||
ip_address_changed(1);
|
||||
}
|
||||
|
@ -203,7 +203,7 @@ channel_tls_connect(const tor_addr_t *addr, uint16_t port,
|
||||
tlschan,
|
||||
(chan->global_identifier));
|
||||
|
||||
if (is_local_addr(addr)) {
|
||||
if (is_local_to_resolve_addr(addr)) {
|
||||
log_debug(LD_CHANNEL,
|
||||
"Marking new outgoing channel %"PRIu64 " at %p as local",
|
||||
(chan->global_identifier), chan);
|
||||
@ -340,7 +340,7 @@ channel_tls_handle_incoming(or_connection_t *orconn)
|
||||
tlschan->conn = orconn;
|
||||
orconn->chan = tlschan;
|
||||
|
||||
if (is_local_addr(&(TO_CONN(orconn)->addr))) {
|
||||
if (is_local_to_resolve_addr(&(TO_CONN(orconn)->addr))) {
|
||||
log_debug(LD_CHANNEL,
|
||||
"Marking new incoming channel %"PRIu64 " at %p as local",
|
||||
(chan->global_identifier), chan);
|
||||
@ -1353,7 +1353,7 @@ channel_tls_update_marks(or_connection_t *conn)
|
||||
|
||||
chan = TLS_CHAN_TO_BASE(conn->chan);
|
||||
|
||||
if (is_local_addr(&(TO_CONN(conn)->addr))) {
|
||||
if (is_local_to_resolve_addr(&(TO_CONN(conn)->addr))) {
|
||||
if (!channel_is_local(chan)) {
|
||||
log_debug(LD_CHANNEL,
|
||||
"Marking channel %"PRIu64 " at %p as local",
|
||||
|
@ -77,8 +77,8 @@ options_validate_dirauth_mode(const or_options_t *old_options,
|
||||
return 0;
|
||||
|
||||
/* confirm that our address isn't broken, so we can complain now */
|
||||
uint32_t tmp;
|
||||
if (resolve_my_address(LOG_WARN, options, &tmp, NULL, NULL) < 0)
|
||||
tor_addr_t tmp;
|
||||
if (!find_my_address(options, AF_INET, LOG_WARN, &tmp, NULL, NULL))
|
||||
REJECT("Failed to resolve/guess local address. See logs for details.");
|
||||
|
||||
if (!options->ContactInfo && !options->TestingTorNetwork)
|
||||
|
@ -4463,7 +4463,7 @@ dirserv_generate_networkstatus_vote_obj(crypto_pk_t *private_key,
|
||||
const or_options_t *options = get_options();
|
||||
const dirauth_options_t *d_options = dirauth_get_options();
|
||||
networkstatus_t *v3_out = NULL;
|
||||
uint32_t addr;
|
||||
tor_addr_t addr;
|
||||
char *hostname = NULL, *client_versions = NULL, *server_versions = NULL;
|
||||
const char *contact;
|
||||
smartlist_t *routers, *routerstatuses;
|
||||
@ -4492,13 +4492,13 @@ dirserv_generate_networkstatus_vote_obj(crypto_pk_t *private_key,
|
||||
log_err(LD_BUG, "Error computing identity key digest");
|
||||
return NULL;
|
||||
}
|
||||
if (resolve_my_address(LOG_WARN, options, &addr, NULL, &hostname)<0) {
|
||||
if (!find_my_address(options, AF_INET, LOG_WARN, &addr, NULL, &hostname)) {
|
||||
log_warn(LD_NET, "Couldn't resolve my hostname");
|
||||
return NULL;
|
||||
}
|
||||
if (!hostname || !strchr(hostname, '.')) {
|
||||
tor_free(hostname);
|
||||
hostname = tor_dup_ip(addr);
|
||||
hostname = tor_addr_to_str_dup(&addr);
|
||||
}
|
||||
|
||||
if (!hostname) {
|
||||
@ -4722,7 +4722,7 @@ dirserv_generate_networkstatus_vote_obj(crypto_pk_t *private_key,
|
||||
memcpy(voter->identity_digest, identity_digest, DIGEST_LEN);
|
||||
voter->sigs = smartlist_new();
|
||||
voter->address = hostname;
|
||||
voter->addr = addr;
|
||||
voter->addr = tor_addr_to_ipv4h(&addr);
|
||||
voter->dir_port = router_get_advertised_dir_port(options, 0);
|
||||
voter->or_port = router_get_advertised_or_port(options);
|
||||
voter->contact = tor_strdup(contact);
|
||||
|
@ -142,7 +142,7 @@ write_http_response_header_impl(dir_connection_t *conn, ssize_t length,
|
||||
if (type) {
|
||||
buf_add_printf(buf, "Content-Type: %s\r\n", type);
|
||||
}
|
||||
if (!is_local_addr(&conn->base_.addr)) {
|
||||
if (!is_local_to_resolve_addr(&conn->base_.addr)) {
|
||||
/* Don't report the source address for a nearby/private connection.
|
||||
* Otherwise we tend to mis-report in cases where incoming ports are
|
||||
* being forwarded to a Tor server running behind the firewall. */
|
||||
|
@ -343,25 +343,25 @@ trusted_dir_server_new(const char *nickname, const char *address,
|
||||
const char *digest, const char *v3_auth_digest,
|
||||
dirinfo_type_t type, double weight)
|
||||
{
|
||||
uint32_t a;
|
||||
tor_addr_t addr;
|
||||
char *hostname=NULL;
|
||||
dir_server_t *result;
|
||||
|
||||
if (!address) { /* The address is us; we should guess. */
|
||||
if (resolve_my_address(LOG_WARN, get_options(),
|
||||
&a, NULL, &hostname) < 0) {
|
||||
if (!find_my_address(get_options(), AF_INET, LOG_WARN, &addr,
|
||||
NULL, &hostname)) {
|
||||
log_warn(LD_CONFIG,
|
||||
"Couldn't find a suitable address when adding ourself as a "
|
||||
"trusted directory server.");
|
||||
return NULL;
|
||||
}
|
||||
if (!hostname)
|
||||
hostname = tor_dup_ip(a);
|
||||
hostname = tor_addr_to_str_dup(&addr);
|
||||
|
||||
if (!hostname)
|
||||
return NULL;
|
||||
} else {
|
||||
uint32_t a;
|
||||
if (tor_lookup_hostname(address, &a)) {
|
||||
log_warn(LD_CONFIG,
|
||||
"Unable to lookup address for directory server at '%s'",
|
||||
@ -369,8 +369,8 @@ trusted_dir_server_new(const char *nickname, const char *address,
|
||||
return NULL;
|
||||
}
|
||||
hostname = tor_strdup(address);
|
||||
tor_addr_from_ipv4h(&addr, a);
|
||||
}
|
||||
tor_addr_from_ipv4h(&addr, a);
|
||||
|
||||
result = dir_server_new(1, nickname, &addr, hostname,
|
||||
dir_port, or_port,
|
||||
|
@ -1029,7 +1029,7 @@ options_transition_affects_descriptor(const or_options_t *old_options,
|
||||
|
||||
YES_IF_CHANGED_STRING(DataDirectory);
|
||||
YES_IF_CHANGED_STRING(Nickname);
|
||||
YES_IF_CHANGED_STRING(Address);
|
||||
YES_IF_CHANGED_LINELIST(Address);
|
||||
YES_IF_CHANGED_LINELIST(ExitPolicy);
|
||||
YES_IF_CHANGED_BOOL(ExitRelay);
|
||||
YES_IF_CHANGED_BOOL(ExitPolicyRejectPrivate);
|
||||
|
@ -45,8 +45,7 @@ void
|
||||
router_new_address_suggestion(const char *suggestion,
|
||||
const dir_connection_t *d_conn)
|
||||
{
|
||||
tor_addr_t addr;
|
||||
uint32_t cur = 0; /* Current IPv4 address. */
|
||||
tor_addr_t addr, my_addr, last_resolved_addr;
|
||||
const or_options_t *options = get_options();
|
||||
|
||||
/* first, learn what the IP address actually is */
|
||||
@ -64,14 +63,22 @@ router_new_address_suggestion(const char *suggestion,
|
||||
}
|
||||
|
||||
/* XXXX ipv6 */
|
||||
cur = get_last_resolved_addr();
|
||||
if (cur ||
|
||||
resolve_my_address(LOG_INFO, options, &cur, NULL, NULL) >= 0) {
|
||||
/* We're all set -- we already know our address. Great. */
|
||||
tor_addr_from_ipv4h(&last_guessed_ip, cur); /* store it in case we
|
||||
need it later */
|
||||
resolved_addr_get_last(AF_INET, &last_resolved_addr);
|
||||
if (!tor_addr_is_null(&last_resolved_addr)) {
|
||||
/* Lets use this one. */
|
||||
tor_addr_copy(&last_guessed_ip, &last_resolved_addr);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Attempt to find our address. */
|
||||
if (find_my_address(options, AF_INET, LOG_INFO, &my_addr, NULL, NULL)) {
|
||||
/* We're all set -- we already know our address. Great. */
|
||||
tor_addr_copy(&last_guessed_ip, &my_addr); /* store it in case we
|
||||
need it later */
|
||||
return;
|
||||
}
|
||||
|
||||
/* Consider the suggestion from the directory. */
|
||||
if (tor_addr_is_internal(&addr, 0)) {
|
||||
/* Don't believe anybody who says our IP is, say, 127.0.0.1. */
|
||||
return;
|
||||
@ -111,15 +118,21 @@ MOCK_IMPL(int,
|
||||
router_pick_published_address, (const or_options_t *options, uint32_t *addr,
|
||||
int cache_only))
|
||||
{
|
||||
/* First, check the cached output from resolve_my_address(). */
|
||||
*addr = get_last_resolved_addr();
|
||||
if (*addr)
|
||||
tor_addr_t last_resolved_addr;
|
||||
|
||||
/* First, check the cached output from find_my_address(). */
|
||||
resolved_addr_get_last(AF_INET, &last_resolved_addr);
|
||||
if (!tor_addr_is_null(&last_resolved_addr)) {
|
||||
*addr = tor_addr_to_ipv4h(&last_resolved_addr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Second, consider doing a resolve attempt right here. */
|
||||
if (!cache_only) {
|
||||
if (resolve_my_address(LOG_INFO, options, addr, NULL, NULL) >= 0) {
|
||||
log_info(LD_CONFIG,"Success: chose address '%s'.", fmt_addr32(*addr));
|
||||
tor_addr_t my_addr;
|
||||
if (find_my_address(options, AF_INET, LOG_INFO, &my_addr, NULL, NULL)) {
|
||||
log_info(LD_CONFIG,"Success: chose address '%s'.", fmt_addr(&my_addr));
|
||||
*addr = tor_addr_to_ipv4h(&my_addr);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
@ -2540,6 +2540,7 @@ void
|
||||
check_descriptor_ipaddress_changed(time_t now)
|
||||
{
|
||||
uint32_t prev, cur;
|
||||
tor_addr_t addr;
|
||||
const or_options_t *options = get_options();
|
||||
const char *method = NULL;
|
||||
char *hostname = NULL;
|
||||
@ -2552,10 +2553,12 @@ check_descriptor_ipaddress_changed(time_t now)
|
||||
|
||||
/* XXXX ipv6 */
|
||||
prev = my_ri->addr;
|
||||
if (resolve_my_address(LOG_INFO, options, &cur, &method, &hostname) < 0) {
|
||||
if (!find_my_address(options, AF_INET, LOG_INFO, &addr, &method,
|
||||
&hostname)) {
|
||||
log_info(LD_CONFIG,"options->Address didn't resolve into an IP.");
|
||||
return;
|
||||
}
|
||||
cur = tor_addr_to_ipv4h(&addr);
|
||||
|
||||
if (prev != cur) {
|
||||
char *source;
|
||||
|
@ -38,13 +38,13 @@ static or_connection_t * tlschan_connection_or_connect_mock(
|
||||
const char *digest,
|
||||
const ed25519_public_key_t *ed_id,
|
||||
channel_tls_t *tlschan);
|
||||
static int tlschan_is_local_addr_mock(const tor_addr_t *addr);
|
||||
static bool tlschan_resolved_addr_is_local_mock(const tor_addr_t *addr);
|
||||
|
||||
/* Fake close method */
|
||||
static void tlschan_fake_close_method(channel_t *chan);
|
||||
|
||||
/* Flags controlling behavior of channeltls unit test mocks */
|
||||
static int tlschan_local = 0;
|
||||
static bool tlschan_local = false;
|
||||
static const buf_t * tlschan_buf_datalen_mock_target = NULL;
|
||||
static size_t tlschan_buf_datalen_mock_size = 0;
|
||||
|
||||
@ -67,9 +67,9 @@ test_channeltls_create(void *arg)
|
||||
test_addr.addr.in_addr.s_addr = htonl(0x01020304);
|
||||
|
||||
/* For this test we always want the address to be treated as non-local */
|
||||
tlschan_local = 0;
|
||||
/* Install is_local_addr() mock */
|
||||
MOCK(is_local_addr, tlschan_is_local_addr_mock);
|
||||
tlschan_local = false;
|
||||
/* Install is_local_to_resolve_addr() mock */
|
||||
MOCK(is_local_to_resolve_addr, tlschan_resolved_addr_is_local_mock);
|
||||
|
||||
/* Install mock for connection_or_connect() */
|
||||
MOCK(connection_or_connect, tlschan_connection_or_connect_mock);
|
||||
@ -92,7 +92,7 @@ test_channeltls_create(void *arg)
|
||||
}
|
||||
|
||||
UNMOCK(connection_or_connect);
|
||||
UNMOCK(is_local_addr);
|
||||
UNMOCK(is_local_to_resolve_addr);
|
||||
|
||||
return;
|
||||
}
|
||||
@ -116,9 +116,9 @@ test_channeltls_num_bytes_queued(void *arg)
|
||||
test_addr.addr.in_addr.s_addr = htonl(0x01020304);
|
||||
|
||||
/* For this test we always want the address to be treated as non-local */
|
||||
tlschan_local = 0;
|
||||
/* Install is_local_addr() mock */
|
||||
MOCK(is_local_addr, tlschan_is_local_addr_mock);
|
||||
tlschan_local = false;
|
||||
/* Install is_local_to_resolve_addr() mock */
|
||||
MOCK(is_local_to_resolve_addr, tlschan_resolved_addr_is_local_mock);
|
||||
|
||||
/* Install mock for connection_or_connect() */
|
||||
MOCK(connection_or_connect, tlschan_connection_or_connect_mock);
|
||||
@ -178,7 +178,7 @@ test_channeltls_num_bytes_queued(void *arg)
|
||||
}
|
||||
|
||||
UNMOCK(connection_or_connect);
|
||||
UNMOCK(is_local_addr);
|
||||
UNMOCK(is_local_to_resolve_addr);
|
||||
|
||||
return;
|
||||
}
|
||||
@ -201,9 +201,9 @@ test_channeltls_overhead_estimate(void *arg)
|
||||
test_addr.addr.in_addr.s_addr = htonl(0x01020304);
|
||||
|
||||
/* For this test we always want the address to be treated as non-local */
|
||||
tlschan_local = 0;
|
||||
/* Install is_local_addr() mock */
|
||||
MOCK(is_local_addr, tlschan_is_local_addr_mock);
|
||||
tlschan_local = false;
|
||||
/* Install is_local_to_resolve_addr() mock */
|
||||
MOCK(is_local_to_resolve_addr, tlschan_resolved_addr_is_local_mock);
|
||||
|
||||
/* Install mock for connection_or_connect() */
|
||||
MOCK(connection_or_connect, tlschan_connection_or_connect_mock);
|
||||
@ -252,7 +252,7 @@ test_channeltls_overhead_estimate(void *arg)
|
||||
}
|
||||
|
||||
UNMOCK(connection_or_connect);
|
||||
UNMOCK(is_local_addr);
|
||||
UNMOCK(is_local_to_resolve_addr);
|
||||
|
||||
return;
|
||||
}
|
||||
@ -321,8 +321,8 @@ tlschan_fake_close_method(channel_t *chan)
|
||||
return;
|
||||
}
|
||||
|
||||
static int
|
||||
tlschan_is_local_addr_mock(const tor_addr_t *addr)
|
||||
static bool
|
||||
tlschan_resolved_addr_is_local_mock(const tor_addr_t *addr)
|
||||
{
|
||||
tt_ptr_op(addr, OP_NE, NULL);
|
||||
|
||||
|
@ -990,52 +990,55 @@ test_config_fix_my_family(void *arg)
|
||||
|
||||
static int n_hostname_01010101 = 0;
|
||||
|
||||
/** This mock function is meant to replace tor_lookup_hostname().
|
||||
/** This mock function is meant to replace tor_addr_lookup().
|
||||
* It answers with 1.1.1.1 as IP adddress that resulted from lookup.
|
||||
* This function increments <b>n_hostname_01010101</b> counter by one
|
||||
* every time it is called.
|
||||
*/
|
||||
static int
|
||||
tor_lookup_hostname_01010101(const char *name, uint32_t *addr)
|
||||
tor_addr_lookup_01010101(const char *name, uint16_t family, tor_addr_t *addr)
|
||||
{
|
||||
n_hostname_01010101++;
|
||||
|
||||
if (name && addr) {
|
||||
*addr = ntohl(0x01010101);
|
||||
if (family == AF_INET) {
|
||||
if (name && addr) {
|
||||
tor_addr_from_ipv4h(addr, 0x01010101);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int n_hostname_localhost = 0;
|
||||
|
||||
/** This mock function is meant to replace tor_lookup_hostname().
|
||||
/** This mock function is meant to replace tor_addr_lookup().
|
||||
* It answers with 127.0.0.1 as IP adddress that resulted from lookup.
|
||||
* This function increments <b>n_hostname_localhost</b> counter by one
|
||||
* every time it is called.
|
||||
*/
|
||||
static int
|
||||
tor_lookup_hostname_localhost(const char *name, uint32_t *addr)
|
||||
tor_addr_lookup_localhost(const char *name, uint16_t family, tor_addr_t *addr)
|
||||
{
|
||||
n_hostname_localhost++;
|
||||
|
||||
if (name && addr) {
|
||||
*addr = 0x7f000001;
|
||||
if (family == AF_INET) {
|
||||
if (name && addr) {
|
||||
tor_addr_from_ipv4h(addr, 0x7f000001);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int n_hostname_failure = 0;
|
||||
|
||||
/** This mock function is meant to replace tor_lookup_hostname().
|
||||
/** This mock function is meant to replace tor_addr_lookup().
|
||||
* It pretends to fail by returning -1 to caller. Also, this function
|
||||
* increments <b>n_hostname_failure</b> every time it is called.
|
||||
*/
|
||||
static int
|
||||
tor_lookup_hostname_failure(const char *name, uint32_t *addr)
|
||||
tor_addr_lookup_failure(const char *name, uint16_t family, tor_addr_t *addr)
|
||||
{
|
||||
(void)name;
|
||||
(void)family;
|
||||
(void)addr;
|
||||
|
||||
n_hostname_failure++;
|
||||
@ -1097,29 +1100,29 @@ tor_gethostname_failure(char *name, size_t namelen)
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int n_get_interface_address = 0;
|
||||
static int n_get_interface_address6 = 0;
|
||||
static sa_family_t last_address6_family;
|
||||
|
||||
/** This mock function is meant to replace get_interface_address().
|
||||
* It answers with address 8.8.8.8. This function increments
|
||||
* <b>n_get_interface_address</b> by one every time it is called.
|
||||
*/
|
||||
static int
|
||||
get_interface_address_08080808(int severity, uint32_t *addr)
|
||||
get_interface_address6_08080808(int severity, sa_family_t family,
|
||||
tor_addr_t *addr)
|
||||
{
|
||||
(void)severity;
|
||||
|
||||
n_get_interface_address++;
|
||||
n_get_interface_address6++;
|
||||
|
||||
if (addr) {
|
||||
*addr = ntohl(0x08080808);
|
||||
if (family == AF_INET) {
|
||||
if (addr) {
|
||||
tor_addr_from_ipv4h(addr, 0x08080808);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int n_get_interface_address6 = 0;
|
||||
static sa_family_t last_address6_family;
|
||||
|
||||
/** This mock function is meant to replace get_interface_address6().
|
||||
* It answers with IP address 9.9.9.9 iff both of the following are true:
|
||||
* - <b>family</b> is AF_INET
|
||||
@ -1145,25 +1148,6 @@ get_interface_address6_replacement(int severity, sa_family_t family,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int n_get_interface_address_failure = 0;
|
||||
|
||||
/**
|
||||
* This mock function is meant to replace get_interface_address().
|
||||
* It pretends to fail getting interface address by returning -1.
|
||||
* <b>n_get_interface_address_failure</b> is incremented by one
|
||||
* every time this function is called.
|
||||
*/
|
||||
static int
|
||||
get_interface_address_failure(int severity, uint32_t *addr)
|
||||
{
|
||||
(void)severity;
|
||||
(void)addr;
|
||||
|
||||
n_get_interface_address_failure++;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int n_get_interface_address6_failure = 0;
|
||||
|
||||
/**
|
||||
@ -1186,21 +1170,19 @@ get_interface_address6_failure(int severity, sa_family_t family,
|
||||
}
|
||||
|
||||
static void
|
||||
test_config_resolve_my_address(void *arg)
|
||||
test_config_find_my_address(void *arg)
|
||||
{
|
||||
or_options_t *options;
|
||||
uint32_t resolved_addr;
|
||||
tor_addr_t resolved_addr, test_addr;
|
||||
const char *method_used;
|
||||
char *hostname_out = NULL;
|
||||
int retval;
|
||||
bool retval;
|
||||
int prev_n_hostname_01010101;
|
||||
int prev_n_hostname_localhost;
|
||||
int prev_n_hostname_failure;
|
||||
int prev_n_gethostname_replacement;
|
||||
int prev_n_gethostname_failure;
|
||||
int prev_n_gethostname_localhost;
|
||||
int prev_n_get_interface_address;
|
||||
int prev_n_get_interface_address_failure;
|
||||
int prev_n_get_interface_address6;
|
||||
int prev_n_get_interface_address6_failure;
|
||||
|
||||
@ -1215,166 +1197,170 @@ test_config_resolve_my_address(void *arg)
|
||||
* If options->Address is a valid IPv4 address string, we want
|
||||
* the corresponding address to be parsed and returned.
|
||||
*/
|
||||
config_line_append(&options->Address, "Address", "128.52.128.105");
|
||||
tor_addr_parse(&test_addr, "128.52.128.105");
|
||||
|
||||
options->Address = tor_strdup("128.52.128.105");
|
||||
retval = find_my_address(options, AF_INET, LOG_NOTICE, &resolved_addr,
|
||||
&method_used, &hostname_out);
|
||||
|
||||
retval = resolve_my_address(LOG_NOTICE,options,&resolved_addr,
|
||||
&method_used,&hostname_out);
|
||||
|
||||
tt_want(retval == 0);
|
||||
tt_want(retval == true);
|
||||
tt_want_str_op(method_used,OP_EQ,"CONFIGURED");
|
||||
tt_want(hostname_out == NULL);
|
||||
tt_assert(resolved_addr == 0x80348069);
|
||||
tt_assert(tor_addr_eq(&resolved_addr, &test_addr));
|
||||
|
||||
tor_free(options->Address);
|
||||
config_free_lines(options->Address);
|
||||
|
||||
/*
|
||||
* CASE 2:
|
||||
* If options->Address is a valid DNS address, we want resolve_my_address()
|
||||
* function to ask tor_lookup_hostname() for help with resolving it
|
||||
* If options->Address is a valid DNS address, we want find_my_address()
|
||||
* function to ask tor_addr_lookup() for help with resolving it
|
||||
* and return the address that was resolved (in host order).
|
||||
*/
|
||||
|
||||
MOCK(tor_lookup_hostname,tor_lookup_hostname_01010101);
|
||||
MOCK(tor_addr_lookup, tor_addr_lookup_01010101);
|
||||
|
||||
tor_free(options->Address);
|
||||
options->Address = tor_strdup("www.torproject.org");
|
||||
config_line_append(&options->Address, "Address", "www.torproject.org");
|
||||
tor_addr_parse(&test_addr, "1.1.1.1");
|
||||
|
||||
prev_n_hostname_01010101 = n_hostname_01010101;
|
||||
|
||||
retval = resolve_my_address(LOG_NOTICE,options,&resolved_addr,
|
||||
&method_used,&hostname_out);
|
||||
retval = find_my_address(options, AF_INET, LOG_NOTICE, &resolved_addr,
|
||||
&method_used, &hostname_out);
|
||||
|
||||
tt_want(retval == 0);
|
||||
tt_want(retval == true);
|
||||
tt_want(n_hostname_01010101 == prev_n_hostname_01010101 + 1);
|
||||
tt_want_str_op(method_used,OP_EQ,"RESOLVED");
|
||||
tt_want_str_op(hostname_out,OP_EQ,"www.torproject.org");
|
||||
tt_assert(resolved_addr == 0x01010101);
|
||||
tt_assert(tor_addr_eq(&resolved_addr, &test_addr));
|
||||
|
||||
UNMOCK(tor_lookup_hostname);
|
||||
UNMOCK(tor_addr_lookup);
|
||||
|
||||
tor_free(options->Address);
|
||||
config_free_lines(options->Address);
|
||||
tor_free(hostname_out);
|
||||
|
||||
/*
|
||||
* CASE 3:
|
||||
* Given that options->Address is NULL, we want resolve_my_address()
|
||||
* Given that options->Address is NULL, we want find_my_address()
|
||||
* to try and use tor_gethostname() to get hostname AND use
|
||||
* tor_lookup_hostname() to get IP address.
|
||||
* tor_addr_lookup() to get IP address.
|
||||
*/
|
||||
|
||||
resolved_addr = 0;
|
||||
tor_free(options->Address);
|
||||
tor_addr_make_unspec(&resolved_addr);
|
||||
options->Address = NULL;
|
||||
tor_addr_parse(&test_addr, "1.1.1.1");
|
||||
|
||||
MOCK(tor_gethostname,tor_gethostname_replacement);
|
||||
MOCK(tor_lookup_hostname,tor_lookup_hostname_01010101);
|
||||
MOCK(tor_addr_lookup,tor_addr_lookup_01010101);
|
||||
|
||||
prev_n_gethostname_replacement = n_gethostname_replacement;
|
||||
prev_n_hostname_01010101 = n_hostname_01010101;
|
||||
|
||||
retval = resolve_my_address(LOG_NOTICE,options,&resolved_addr,
|
||||
&method_used,&hostname_out);
|
||||
retval = find_my_address(options, AF_INET, LOG_NOTICE, &resolved_addr,
|
||||
&method_used, &hostname_out);
|
||||
|
||||
tt_want(retval == 0);
|
||||
tt_want(retval == true);
|
||||
tt_want(n_gethostname_replacement == prev_n_gethostname_replacement + 1);
|
||||
tt_want(n_hostname_01010101 == prev_n_hostname_01010101 + 1);
|
||||
tt_want_str_op(method_used,OP_EQ,"GETHOSTNAME");
|
||||
tt_want_str_op(hostname_out,OP_EQ,"onionrouter!");
|
||||
tt_assert(resolved_addr == 0x01010101);
|
||||
tt_assert(tor_addr_eq(&resolved_addr, &test_addr));
|
||||
|
||||
UNMOCK(tor_gethostname);
|
||||
UNMOCK(tor_lookup_hostname);
|
||||
UNMOCK(tor_addr_lookup);
|
||||
|
||||
tor_free(hostname_out);
|
||||
|
||||
/*
|
||||
* CASE 4:
|
||||
* Given that options->Address is a local host address, we want
|
||||
* resolve_my_address() function to fail.
|
||||
* find_my_address() function to fail.
|
||||
*/
|
||||
|
||||
resolved_addr = 0;
|
||||
tor_free(options->Address);
|
||||
options->Address = tor_strdup("127.0.0.1");
|
||||
tor_addr_make_unspec(&resolved_addr);
|
||||
config_line_append(&options->Address, "Address", "127.0.0.1");
|
||||
tor_addr_parse(&test_addr, "127.0.0.1");
|
||||
|
||||
retval = resolve_my_address(LOG_NOTICE,options,&resolved_addr,
|
||||
&method_used,&hostname_out);
|
||||
retval = find_my_address(options, AF_INET, LOG_NOTICE, &resolved_addr,
|
||||
&method_used, &hostname_out);
|
||||
|
||||
tt_want(resolved_addr == 0);
|
||||
tt_int_op(retval, OP_EQ, -1);
|
||||
tt_want(tor_addr_is_null(&resolved_addr) == 1);
|
||||
tt_want(retval == false);
|
||||
|
||||
tor_free(options->Address);
|
||||
config_free_lines(options->Address);
|
||||
tor_free(hostname_out);
|
||||
|
||||
/*
|
||||
* CASE 5:
|
||||
* We want resolve_my_address() to fail if DNS address in options->Address
|
||||
* We want find_my_address() to fail if DNS address in options->Address
|
||||
* cannot be resolved.
|
||||
*/
|
||||
|
||||
MOCK(tor_lookup_hostname,tor_lookup_hostname_failure);
|
||||
MOCK(tor_addr_lookup,tor_addr_lookup_failure);
|
||||
|
||||
prev_n_hostname_failure = n_hostname_failure;
|
||||
|
||||
tor_free(options->Address);
|
||||
options->Address = tor_strdup("www.tor-project.org");
|
||||
config_line_append(&options->Address, "Address", "www.tor-project.org");
|
||||
|
||||
retval = resolve_my_address(LOG_NOTICE,options,&resolved_addr,
|
||||
&method_used,&hostname_out);
|
||||
retval = find_my_address(options, AF_INET, LOG_NOTICE, &resolved_addr,
|
||||
&method_used, &hostname_out);
|
||||
|
||||
tt_want(n_hostname_failure == prev_n_hostname_failure + 1);
|
||||
tt_int_op(retval, OP_EQ, -1);
|
||||
tt_want(tor_addr_is_null(&resolved_addr) == 1);
|
||||
tt_want(retval == false);
|
||||
|
||||
UNMOCK(tor_lookup_hostname);
|
||||
UNMOCK(tor_addr_lookup);
|
||||
|
||||
tor_free(options->Address);
|
||||
config_free_lines(options->Address);
|
||||
options->Address = NULL;
|
||||
tor_free(hostname_out);
|
||||
|
||||
/*
|
||||
* CASE 6:
|
||||
* If options->Address is NULL AND gettting local hostname fails, we want
|
||||
* resolve_my_address() to fail as well.
|
||||
* find_my_address() to fail as well.
|
||||
*/
|
||||
|
||||
MOCK(tor_gethostname,tor_gethostname_failure);
|
||||
|
||||
prev_n_gethostname_failure = n_gethostname_failure;
|
||||
|
||||
retval = resolve_my_address(LOG_NOTICE,options,&resolved_addr,
|
||||
&method_used,&hostname_out);
|
||||
retval = find_my_address(options, AF_INET, LOG_NOTICE, &resolved_addr,
|
||||
&method_used, &hostname_out);
|
||||
|
||||
tt_want(n_gethostname_failure == prev_n_gethostname_failure + 1);
|
||||
tt_int_op(retval, OP_EQ, -1);
|
||||
tt_want(tor_addr_is_null(&resolved_addr) == 1);
|
||||
tt_want(retval == false);
|
||||
|
||||
UNMOCK(tor_gethostname);
|
||||
tor_free(hostname_out);
|
||||
|
||||
/*
|
||||
* CASE 7:
|
||||
* We want resolve_my_address() to try and get network interface address via
|
||||
* We want find_my_address() to try and get network interface address via
|
||||
* get_interface_address() if hostname returned by tor_gethostname() cannot be
|
||||
* resolved into IP address.
|
||||
*/
|
||||
|
||||
MOCK(tor_gethostname,tor_gethostname_replacement);
|
||||
MOCK(tor_lookup_hostname,tor_lookup_hostname_failure);
|
||||
MOCK(get_interface_address,get_interface_address_08080808);
|
||||
MOCK(tor_addr_lookup,tor_addr_lookup_failure);
|
||||
MOCK(get_interface_address6, get_interface_address6_08080808);
|
||||
|
||||
tor_addr_parse(&test_addr, "8.8.8.8");
|
||||
|
||||
prev_n_gethostname_replacement = n_gethostname_replacement;
|
||||
prev_n_get_interface_address = n_get_interface_address;
|
||||
prev_n_get_interface_address6 = n_get_interface_address6;
|
||||
|
||||
retval = resolve_my_address(LOG_NOTICE,options,&resolved_addr,
|
||||
&method_used,&hostname_out);
|
||||
retval = find_my_address(options, AF_INET, LOG_NOTICE, &resolved_addr,
|
||||
&method_used, &hostname_out);
|
||||
|
||||
tt_want(retval == 0);
|
||||
tt_want(retval == true);
|
||||
tt_want_int_op(n_gethostname_replacement, OP_EQ,
|
||||
prev_n_gethostname_replacement + 1);
|
||||
tt_want_int_op(n_get_interface_address, OP_EQ,
|
||||
prev_n_get_interface_address + 1);
|
||||
tt_want_int_op(n_get_interface_address6, OP_EQ,
|
||||
prev_n_get_interface_address6 + 1);
|
||||
tt_want_str_op(method_used,OP_EQ,"INTERFACE");
|
||||
tt_want(hostname_out == NULL);
|
||||
tt_assert(resolved_addr == 0x08080808);
|
||||
tt_assert(tor_addr_eq(&resolved_addr, &test_addr));
|
||||
|
||||
UNMOCK(get_interface_address);
|
||||
tor_free(hostname_out);
|
||||
@ -1382,86 +1368,87 @@ test_config_resolve_my_address(void *arg)
|
||||
/*
|
||||
* CASE 8:
|
||||
* Suppose options->Address is NULL AND hostname returned by tor_gethostname()
|
||||
* is unresolvable. We want resolve_my_address to fail if
|
||||
* is unresolvable. We want find_my_address to fail if
|
||||
* get_interface_address() fails.
|
||||
*/
|
||||
|
||||
MOCK(get_interface_address,get_interface_address_failure);
|
||||
MOCK(get_interface_address6, get_interface_address6_failure);
|
||||
|
||||
prev_n_get_interface_address_failure = n_get_interface_address_failure;
|
||||
prev_n_get_interface_address6_failure = n_get_interface_address6_failure;
|
||||
prev_n_gethostname_replacement = n_gethostname_replacement;
|
||||
|
||||
retval = resolve_my_address(LOG_NOTICE,options,&resolved_addr,
|
||||
&method_used,&hostname_out);
|
||||
retval = find_my_address(options, AF_INET, LOG_NOTICE, &resolved_addr,
|
||||
&method_used, &hostname_out);
|
||||
|
||||
tt_want(n_get_interface_address_failure ==
|
||||
prev_n_get_interface_address_failure + 1);
|
||||
tt_want(n_get_interface_address6_failure ==
|
||||
prev_n_get_interface_address6_failure + 1);
|
||||
tt_want(n_gethostname_replacement ==
|
||||
prev_n_gethostname_replacement + 1);
|
||||
tt_int_op(retval, OP_EQ, -1);
|
||||
tt_want(retval == false);
|
||||
|
||||
UNMOCK(get_interface_address);
|
||||
tor_free(hostname_out);
|
||||
|
||||
/*
|
||||
* CASE 9:
|
||||
* Given that options->Address is NULL AND tor_lookup_hostname()
|
||||
* Given that options->Address is NULL AND tor_addr_lookup()
|
||||
* fails AND hostname returned by gethostname() resolves
|
||||
* to local IP address, we want resolve_my_address() function to
|
||||
* to local IP address, we want find_my_address() function to
|
||||
* call get_interface_address6(.,AF_INET,.) and return IP address
|
||||
* the latter function has found.
|
||||
*/
|
||||
|
||||
MOCK(tor_lookup_hostname,tor_lookup_hostname_failure);
|
||||
MOCK(tor_addr_lookup,tor_addr_lookup_failure);
|
||||
MOCK(tor_gethostname,tor_gethostname_replacement);
|
||||
MOCK(get_interface_address6,get_interface_address6_replacement);
|
||||
|
||||
tor_addr_parse(&test_addr, "9.9.9.9");
|
||||
|
||||
prev_n_gethostname_replacement = n_gethostname_replacement;
|
||||
prev_n_hostname_failure = n_hostname_failure;
|
||||
prev_n_get_interface_address6 = n_get_interface_address6;
|
||||
|
||||
retval = resolve_my_address(LOG_NOTICE,options,&resolved_addr,
|
||||
&method_used,&hostname_out);
|
||||
retval = find_my_address(options, AF_INET, LOG_NOTICE, &resolved_addr,
|
||||
&method_used, &hostname_out);
|
||||
|
||||
tt_want(last_address6_family == AF_INET);
|
||||
tt_want(n_get_interface_address6 == prev_n_get_interface_address6 + 1);
|
||||
tt_want(n_hostname_failure == prev_n_hostname_failure + 1);
|
||||
tt_want(n_gethostname_replacement == prev_n_gethostname_replacement + 1);
|
||||
tt_want(retval == 0);
|
||||
tt_want(retval == true);
|
||||
tt_want_str_op(method_used,OP_EQ,"INTERFACE");
|
||||
tt_assert(resolved_addr == 0x09090909);
|
||||
tt_assert(tor_addr_eq(&resolved_addr, &test_addr));
|
||||
|
||||
UNMOCK(tor_lookup_hostname);
|
||||
UNMOCK(tor_addr_lookup);
|
||||
UNMOCK(tor_gethostname);
|
||||
UNMOCK(get_interface_address6);
|
||||
|
||||
tor_free(hostname_out);
|
||||
|
||||
/*
|
||||
* CASE 10: We want resolve_my_address() to fail if all of the following
|
||||
* CASE 10: We want find_my_address() to fail if all of the following
|
||||
* are true:
|
||||
* 1. options->Address is not NULL
|
||||
* 2. ... but it cannot be converted to struct in_addr by
|
||||
* tor_inet_aton()
|
||||
* 3. ... and tor_lookup_hostname() fails to resolve the
|
||||
* 3. ... and tor_addr_lookup() fails to resolve the
|
||||
* options->Address
|
||||
*/
|
||||
|
||||
MOCK(tor_lookup_hostname,tor_lookup_hostname_failure);
|
||||
MOCK(tor_addr_lookup, tor_addr_lookup_failure);
|
||||
|
||||
prev_n_hostname_failure = n_hostname_failure;
|
||||
|
||||
tor_free(options->Address);
|
||||
options->Address = tor_strdup("some_hostname");
|
||||
config_line_append(&options->Address, "Address", "some_hostname");
|
||||
|
||||
retval = resolve_my_address(LOG_NOTICE, options, &resolved_addr,
|
||||
&method_used,&hostname_out);
|
||||
retval = find_my_address(options, AF_INET, LOG_NOTICE, &resolved_addr,
|
||||
&method_used, &hostname_out);
|
||||
|
||||
tt_want(n_hostname_failure == prev_n_hostname_failure + 1);
|
||||
tt_int_op(retval, OP_EQ, -1);
|
||||
tt_want(retval == false);
|
||||
|
||||
UNMOCK(tor_gethostname);
|
||||
UNMOCK(tor_lookup_hostname);
|
||||
UNMOCK(tor_addr_lookup);
|
||||
|
||||
tor_free(hostname_out);
|
||||
|
||||
@ -1473,7 +1460,7 @@ test_config_resolve_my_address(void *arg)
|
||||
* if running on.
|
||||
* 3. Hostname from previous step cannot be converted to
|
||||
* address by using tor_inet_aton() function.
|
||||
* 4. However, tor_lookup_hostname() succeeds in resolving the
|
||||
* 4. However, tor_addr_lookup() succeeds in resolving the
|
||||
* hostname from step 2.
|
||||
* 5. Unfortunately, tor_addr_is_internal() deems this address
|
||||
* to be internal.
|
||||
@ -1484,19 +1471,20 @@ test_config_resolve_my_address(void *arg)
|
||||
* and address from step 6.
|
||||
*/
|
||||
|
||||
tor_free(options->Address);
|
||||
config_free_lines(options->Address);
|
||||
options->Address = NULL;
|
||||
tor_addr_parse(&test_addr, "9.9.9.9");
|
||||
|
||||
MOCK(tor_gethostname,tor_gethostname_replacement);
|
||||
MOCK(tor_lookup_hostname,tor_lookup_hostname_localhost);
|
||||
MOCK(tor_addr_lookup,tor_addr_lookup_localhost);
|
||||
MOCK(get_interface_address6,get_interface_address6_replacement);
|
||||
|
||||
prev_n_gethostname_replacement = n_gethostname_replacement;
|
||||
prev_n_hostname_localhost = n_hostname_localhost;
|
||||
prev_n_get_interface_address6 = n_get_interface_address6;
|
||||
|
||||
retval = resolve_my_address(LOG_DEBUG, options, &resolved_addr,
|
||||
&method_used,&hostname_out);
|
||||
retval = find_my_address(options, AF_INET, LOG_NOTICE, &resolved_addr,
|
||||
&method_used, &hostname_out);
|
||||
|
||||
tt_want(n_gethostname_replacement == prev_n_gethostname_replacement + 1);
|
||||
tt_want(n_hostname_localhost == prev_n_hostname_localhost + 1);
|
||||
@ -1504,14 +1492,15 @@ test_config_resolve_my_address(void *arg)
|
||||
|
||||
tt_str_op(method_used,OP_EQ,"INTERFACE");
|
||||
tt_ptr_op(hostname_out, OP_EQ, NULL);
|
||||
tt_int_op(retval, OP_EQ, 0);
|
||||
tt_want(retval == true);
|
||||
tt_assert(tor_addr_eq(&resolved_addr, &test_addr));
|
||||
|
||||
/*
|
||||
* CASE 11b:
|
||||
* 1-5 as above.
|
||||
* 6. get_interface_address6() fails.
|
||||
*
|
||||
* In this subcase, we want resolve_my_address() to fail.
|
||||
* In this subcase, we want find_my_address() to fail.
|
||||
*/
|
||||
|
||||
UNMOCK(get_interface_address6);
|
||||
@ -1521,18 +1510,18 @@ test_config_resolve_my_address(void *arg)
|
||||
prev_n_hostname_localhost = n_hostname_localhost;
|
||||
prev_n_get_interface_address6_failure = n_get_interface_address6_failure;
|
||||
|
||||
retval = resolve_my_address(LOG_DEBUG, options, &resolved_addr,
|
||||
&method_used,&hostname_out);
|
||||
retval = find_my_address(options, AF_INET, LOG_DEBUG, &resolved_addr,
|
||||
&method_used, &hostname_out);
|
||||
|
||||
tt_want(n_gethostname_replacement == prev_n_gethostname_replacement + 1);
|
||||
tt_want(n_hostname_localhost == prev_n_hostname_localhost + 1);
|
||||
tt_want(n_get_interface_address6_failure ==
|
||||
prev_n_get_interface_address6_failure + 1);
|
||||
|
||||
tt_int_op(retval, OP_EQ, -1);
|
||||
tt_want(retval == false);
|
||||
|
||||
UNMOCK(tor_gethostname);
|
||||
UNMOCK(tor_lookup_hostname);
|
||||
UNMOCK(tor_addr_lookup);
|
||||
UNMOCK(get_interface_address6);
|
||||
|
||||
/* CASE 12:
|
||||
@ -1543,7 +1532,7 @@ test_config_resolve_my_address(void *arg)
|
||||
* 4. into IPv4 address that tor_addr_is_inernal() considers to be
|
||||
* internal.
|
||||
*
|
||||
* In this case, we want resolve_my_address() to fail.
|
||||
* In this case, we want find_my_address() to fail.
|
||||
*/
|
||||
|
||||
tor_free(options->Address);
|
||||
@ -1554,22 +1543,22 @@ test_config_resolve_my_address(void *arg)
|
||||
|
||||
prev_n_gethostname_localhost = n_gethostname_localhost;
|
||||
|
||||
retval = resolve_my_address(LOG_DEBUG, options, &resolved_addr,
|
||||
&method_used,&hostname_out);
|
||||
retval = find_my_address(options, AF_INET, LOG_DEBUG, &resolved_addr,
|
||||
&method_used, &hostname_out);
|
||||
|
||||
tt_want(n_gethostname_localhost == prev_n_gethostname_localhost + 1);
|
||||
tt_int_op(retval, OP_EQ, -1);
|
||||
tt_want(retval == false);
|
||||
|
||||
UNMOCK(tor_gethostname);
|
||||
|
||||
done:
|
||||
tor_free(options->Address);
|
||||
config_free_lines(options->Address);
|
||||
tor_free(options->DirAuthorities);
|
||||
or_options_free(options);
|
||||
tor_free(hostname_out);
|
||||
|
||||
UNMOCK(tor_gethostname);
|
||||
UNMOCK(tor_lookup_hostname);
|
||||
UNMOCK(tor_addr_lookup);
|
||||
UNMOCK(get_interface_address);
|
||||
UNMOCK(get_interface_address6);
|
||||
UNMOCK(tor_gethostname);
|
||||
@ -6256,7 +6245,7 @@ struct testcase_t config_tests[] = {
|
||||
CONFIG_TEST(adding_dir_servers, TT_FORK),
|
||||
CONFIG_TEST(default_dir_servers, TT_FORK),
|
||||
CONFIG_TEST(default_fallback_dirs, 0),
|
||||
CONFIG_TEST(resolve_my_address, TT_FORK),
|
||||
CONFIG_TEST(find_my_address, TT_FORK),
|
||||
CONFIG_TEST(addressmap, 0),
|
||||
CONFIG_TEST(parse_bridge_line, 0),
|
||||
CONFIG_TEST(parse_transport_options_line, 0),
|
||||
|
Loading…
Reference in New Issue
Block a user