Merge remote-tracking branch 'tor-gitlab/mr/51'

This commit is contained in:
Nick Mathewson 2020-07-20 16:50:32 -04:00
commit f5d773c600
11 changed files with 399 additions and 292 deletions

View File

@ -194,7 +194,7 @@ get_address_from_config(const or_options_t *options, int warn_severity,
char **hostname_out, tor_addr_t *addr_out) char **hostname_out, tor_addr_t *addr_out)
{ {
int ret; int ret;
bool explicit_ip = false; bool explicit_ip = false, resolve_failure = false;
int num_valid_addr = 0; int num_valid_addr = 0;
tor_assert(options); tor_assert(options);
@ -246,6 +246,7 @@ get_address_from_config(const or_options_t *options, int warn_severity,
continue; continue;
} else { } else {
/* Hostname that can't be resolved, this is a fatal error. */ /* Hostname that can't be resolved, this is a fatal error. */
resolve_failure = true;
log_fn(warn_severity, LD_CONFIG, log_fn(warn_severity, LD_CONFIG,
"Could not resolve local Address '%s'. Failing.", cfg->value); "Could not resolve local Address '%s'. Failing.", cfg->value);
continue; continue;
@ -253,13 +254,16 @@ get_address_from_config(const or_options_t *options, int warn_severity,
} }
if (!num_valid_addr) { if (!num_valid_addr) {
log_fn(warn_severity, LD_CONFIG, if (resolve_failure) {
"No Address option found for family %s in configuration.", /* We found no address but we got a resolution failure. This means we
fmt_af_family(family)); * can know if the hostname given was v4 or v6 so we can't continue. */
/* No Address statement for family but one exists since Address is not return FN_RET_BAIL;
* NULL thus we have to stop now and not attempt to send back a guessed }
* address. */ log_info(LD_CONFIG,
return FN_RET_BAIL; "No Address option found for family %s in configuration.",
fmt_af_family(family));
/* No Address statement for family so move on to try next method. */
return FN_RET_NEXT;
} }
if (num_valid_addr >= MAX_CONFIG_ADDRESS) { if (num_valid_addr >= MAX_CONFIG_ADDRESS) {
@ -283,8 +287,8 @@ get_address_from_config(const or_options_t *options, int warn_severity,
} }
/* Address can be used. We are done. */ /* Address can be used. We are done. */
log_fn(warn_severity, LD_CONFIG, "Address found in configuration: %s", log_info(LD_CONFIG, "Address found in configuration: %s",
fmt_addr(addr_out)); fmt_addr(addr_out));
return FN_RET_OK; return FN_RET_OK;
} }
@ -346,8 +350,8 @@ get_address_from_hostname(const or_options_t *options, int warn_severity,
*hostname_out = tor_strdup(hostname); *hostname_out = tor_strdup(hostname);
/* Found it! */ /* Found it! */
log_fn(warn_severity, LD_CONFIG, "Address found from local hostname: %s", log_info(LD_CONFIG, "Address found from local hostname: %s",
fmt_addr(addr_out)); fmt_addr(addr_out));
return FN_RET_OK; return FN_RET_OK;
} }
@ -398,8 +402,7 @@ get_address_from_interface(const or_options_t *options, int warn_severity,
*method_out = "INTERFACE"; *method_out = "INTERFACE";
/* Found it! */ /* Found it! */
log_fn(warn_severity, LD_CONFIG, "Address found from interface: %s", log_info(LD_CONFIG, "Address found from interface: %s", fmt_addr(addr_out));
fmt_addr(addr_out));
return FN_RET_OK; return FN_RET_OK;
} }
@ -729,3 +732,13 @@ is_local_to_resolve_addr, (const tor_addr_t *addr))
return false; return false;
} }
} }
#ifdef TOR_UNIT_TESTS
void
resolve_addr_reset_suggested(int family)
{
tor_addr_make_unspec(&last_suggested_addrs[af_to_idx(family)]);
}
#endif /* TOR_UNIT_TESTS */

View File

@ -33,6 +33,12 @@ MOCK_DECL(bool, is_local_to_resolve_addr, (const tor_addr_t *addr));
#ifdef RESOLVE_ADDR_PRIVATE #ifdef RESOLVE_ADDR_PRIVATE
#ifdef TOR_UNIT_TESTS
void resolve_addr_reset_suggested(int family);
#endif /* TOR_UNIT_TESTS */
#endif /* RESOLVE_ADDR_PRIVATE */ #endif /* RESOLVE_ADDR_PRIVATE */
#endif /* TOR_CONFIG_RESOLVE_ADDR_H */ #endif /* TOR_CONFIG_RESOLVE_ADDR_H */

View File

@ -1643,17 +1643,26 @@ pt_get_extra_info_descriptor_string(void)
SMARTLIST_FOREACH_BEGIN(mp->transports, const transport_t *, t) { SMARTLIST_FOREACH_BEGIN(mp->transports, const transport_t *, t) {
char *transport_args = NULL; char *transport_args = NULL;
const char *addrport = NULL;
/* If the transport proxy returned "0.0.0.0" as its address, and /* If the transport proxy returned "0.0.0.0" as its address, and
* we know our external IP address, use it. Otherwise, use the * we know our external IP address, use it. Otherwise, use the
* returned address. */ * returned address. */
const char *addrport = NULL; if (tor_addr_is_null(&t->addr)) {
uint32_t external_ip_address = 0;
if (tor_addr_is_null(&t->addr) &&
router_pick_published_address(get_options(),
&external_ip_address, 0) >= 0) {
tor_addr_t addr; tor_addr_t addr;
tor_addr_from_ipv4h(&addr, external_ip_address); /* Attempt to find the IPv4 and then attempt to find the IPv6 if we
* can't find it. */
bool found = relay_find_addr_to_publish(get_options(), AF_INET,
RELAY_FIND_ADDR_NO_FLAG,
&addr);
if (!found) {
found = relay_find_addr_to_publish(get_options(), AF_INET6,
RELAY_FIND_ADDR_NO_FLAG, &addr);
}
if (!found) {
log_err(LD_PT, "Unable to find address for transport %s", t->name);
continue;
}
addrport = fmt_addrport(&addr, t->port); addrport = fmt_addrport(&addr, t->port);
} else { } else {
addrport = fmt_addrport(&t->addr, t->port); addrport = fmt_addrport(&t->addr, t->port);

View File

@ -132,12 +132,13 @@ getinfo_helper_misc(control_connection_t *conn, const char *question,
} else if (!strcmp(question, "features/names")) { } else if (!strcmp(question, "features/names")) {
*answer = tor_strdup("VERBOSE_NAMES EXTENDED_EVENTS"); *answer = tor_strdup("VERBOSE_NAMES EXTENDED_EVENTS");
} else if (!strcmp(question, "address")) { } else if (!strcmp(question, "address")) {
uint32_t addr; tor_addr_t addr;
if (router_pick_published_address(get_options(), &addr, 0) < 0) { if (!relay_find_addr_to_publish(get_options(), AF_INET,
RELAY_FIND_ADDR_CACHE_ONLY, &addr)) {
*errmsg = "Address unknown"; *errmsg = "Address unknown";
return -1; return -1;
} }
*answer = tor_dup_ip(addr); *answer = tor_addr_to_str_dup(&addr);
tor_assert_nonfatal(*answer); tor_assert_nonfatal(*answer);
} else if (!strcmp(question, "traffic/read")) { } else if (!strcmp(question, "traffic/read")) {
tor_asprintf(answer, "%"PRIu64, (get_bytes_read())); tor_asprintf(answer, "%"PRIu64, (get_bytes_read()));

View File

@ -2106,7 +2106,13 @@ connection_dir_client_reached_eof(dir_connection_t *conn)
if (conn->dirconn_direct) { if (conn->dirconn_direct) {
char *guess = http_get_header(headers, X_ADDRESS_HEADER); char *guess = http_get_header(headers, X_ADDRESS_HEADER);
if (guess) { if (guess) {
router_new_address_suggestion(guess, conn); tor_addr_t addr;
if (tor_addr_parse(&addr, guess) < 0) {
log_debug(LD_DIR, "Malformed X-Your-Address-Is header %s. Ignoring.",
escaped(guess));
} else {
relay_address_new_suggestion(&addr, &TO_CONN(conn)->addr, NULL);
}
tor_free(guess); tor_free(guess);
} }
} }

View File

@ -40,15 +40,19 @@ int
dirclient_fetches_from_authorities(const or_options_t *options) dirclient_fetches_from_authorities(const or_options_t *options)
{ {
const routerinfo_t *me; const routerinfo_t *me;
uint32_t addr;
int refuseunknown; int refuseunknown;
if (options->FetchDirInfoEarly) if (options->FetchDirInfoEarly)
return 1; return 1;
if (options->BridgeRelay == 1) if (options->BridgeRelay == 1)
return 0; return 0;
if (server_mode(options) && /* We don't know our IP address; ask an authority. IPv4 is still mandatory
router_pick_published_address(options, &addr, 1) < 0) * to have thus if we don't have it, we ought to learn it from an authority
return 1; /* we don't know our IP address; ask an authority. */ * through the NETINFO cell or the HTTP header it sends us back.
*
* Note that at the moment, relay do a direct connection so no NETINFO cell
* for now. */
if (server_mode(options) && !relay_has_address_set(AF_INET))
return 1;
refuseunknown = ! router_my_exit_policy_is_reject_star() && refuseunknown = ! router_my_exit_policy_is_reject_star() &&
should_refuse_unknown_exits(options); should_refuse_unknown_exits(options);
if (!dir_server_mode(options) && !refuseunknown) if (!dir_server_mode(options) && !refuseunknown)

View File

@ -20,29 +20,12 @@
#include "feature/relay/router.h" #include "feature/relay/router.h"
#include "feature/relay/routermode.h" #include "feature/relay/routermode.h"
/** The most recently guessed value of our IP address, based on directory
* headers. */
static tor_addr_t last_guessed_ip = TOR_ADDR_NULL;
/** We failed to resolve our address locally, but we'd like to build
* a descriptor and publish / test reachability. If we have a guess
* about our address based on directory headers, answer it and return
* 0; else return -1. */
static int
router_guess_address_from_dir_headers(uint32_t *guess)
{
if (!tor_addr_is_null(&last_guessed_ip)) {
*guess = tor_addr_to_ipv4h(&last_guessed_ip);
return 0;
}
return -1;
}
/** Consider the address suggestion suggested_addr as a possible one to use as /** Consider the address suggestion suggested_addr as a possible one to use as
* our address. * our address.
* *
* This is called when a valid NETINFO cell is recevied containing a candidate * This is called when a valid NETINFO cell is received containing a candidate
* for our address. * for our address or when a directory sends us back the X-Your-Address-Is
* header.
* *
* The suggested address is ignored if it does NOT come from a trusted source. * The suggested address is ignored if it does NOT come from a trusted source.
* At the moment, we only look a trusted directory authorities. * At the moment, we only look a trusted directory authorities.
@ -51,6 +34,9 @@ router_guess_address_from_dir_headers(uint32_t *guess)
* given peer_addr which is the address from the endpoint that sent the * given peer_addr which is the address from the endpoint that sent the
* NETINFO cell. * NETINFO cell.
* *
* The identity_digest is NULL if this is an address suggested by a directory
* since this is a plaintext connection.
*
* The suggested address is set in our suggested address cache if everything * The suggested address is set in our suggested address cache if everything
* passes. */ * passes. */
void void
@ -62,7 +48,6 @@ relay_address_new_suggestion(const tor_addr_t *suggested_addr,
tor_assert(suggested_addr); tor_assert(suggested_addr);
tor_assert(peer_addr); tor_assert(peer_addr);
tor_assert(identity_digest);
/* Non server should just ignore this suggestion. Clients don't need to /* Non server should just ignore this suggestion. Clients don't need to
* learn their address let alone cache it. */ * learn their address let alone cache it. */
@ -73,7 +58,7 @@ relay_address_new_suggestion(const tor_addr_t *suggested_addr,
/* Is the peer a trusted source? Ignore anything coming from non trusted /* Is the peer a trusted source? Ignore anything coming from non trusted
* source. In this case, we only look at trusted directory authorities. */ * source. In this case, we only look at trusted directory authorities. */
if (!router_addr_is_trusted_dir(peer_addr) || if (!router_addr_is_trusted_dir(peer_addr) ||
!router_digest_is_trusted_dir(identity_digest)) { (identity_digest && !router_digest_is_trusted_dir(identity_digest))) {
return; return;
} }
@ -95,110 +80,67 @@ relay_address_new_suggestion(const tor_addr_t *suggested_addr,
resolved_addr_set_suggested(suggested_addr); resolved_addr_set_suggested(suggested_addr);
} }
/** A directory server <b>d_conn</b> told us our IP address is /** Find our address to be published in our descriptor. Three places are
* <b>suggestion</b>. * looked at:
* If this address is different from the one we think we are now, and
* if our computer doesn't actually know its IP address, then switch. */
void
router_new_address_suggestion(const char *suggestion,
const dir_connection_t *d_conn)
{
tor_addr_t addr, my_addr, last_resolved_addr;
const or_options_t *options = get_options();
/* first, learn what the IP address actually is */
if (tor_addr_parse(&addr, suggestion) == -1) {
log_debug(LD_DIR, "Malformed X-Your-Address-Is header %s. Ignoring.",
escaped(suggestion));
return;
}
log_debug(LD_DIR, "Got X-Your-Address-Is: %s.", suggestion);
if (!server_mode(options)) {
tor_addr_copy(&last_guessed_ip, &addr);
return;
}
/* XXXX ipv6 */
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;
}
if (tor_addr_eq(&d_conn->base_.addr, &addr)) {
/* Don't believe anybody who says our IP is their IP. */
log_debug(LD_DIR, "A directory server told us our IP address is %s, "
"but they are just reporting their own IP address. Ignoring.",
suggestion);
return;
}
/* Okay. We can't resolve our own address, and X-Your-Address-Is is giving
* us an answer different from what we had the last time we managed to
* resolve it. */
if (!tor_addr_eq(&last_guessed_ip, &addr)) {
control_event_server_status(LOG_NOTICE,
"EXTERNAL_ADDRESS ADDRESS=%s METHOD=DIRSERV",
suggestion);
log_addr_has_changed(LOG_NOTICE, &last_guessed_ip, &addr,
d_conn->base_.address);
ip_address_changed(0);
tor_addr_copy(&last_guessed_ip, &addr); /* router_rebuild_descriptor()
will fetch it */
}
}
/** Make a current best guess at our address, either because
* it's configured in torrc, or because we've learned it from
* dirserver headers. Place the answer in *<b>addr</b> and return
* 0 on success, else return -1 if we have no guess.
* *
* If <b>cache_only</b> is true, just return any cached answers, and * 1. Resolved cache. Populated by find_my_address() during the relay
* don't try to get any new answers. * periodic event that attempts to learn if our address has changed.
*/ *
MOCK_IMPL(int, * 2. If flags is set with RELAY_FIND_ADDR_CACHE_ONLY, only the resolved
router_pick_published_address, (const or_options_t *options, uint32_t *addr, * and suggested cache are looked at. No address discovery will be done.
int cache_only)) *
* 3. Finally, if all fails, use the suggested address cache which is
* populated by the NETINFO cell content or HTTP header from a
* directory.
*
* Return true on success and addr_out contains the address to use for the
* given family. On failure to find the address, false is returned and
* addr_out is set to an AF_UNSPEC address. */
MOCK_IMPL(bool,
relay_find_addr_to_publish, (const or_options_t *options, int family,
int flags, tor_addr_t *addr_out))
{ {
tor_addr_t last_resolved_addr; tor_assert(options);
tor_assert(addr_out);
/* First, check the cached output from find_my_address(). */ tor_addr_make_unspec(addr_out);
resolved_addr_get_last(AF_INET, &last_resolved_addr);
if (!tor_addr_is_null(&last_resolved_addr)) { /* First, check our resolved address cache. It should contain the address
*addr = tor_addr_to_ipv4h(&last_resolved_addr); * we've discovered from the periodic relay event. */
return 0; resolved_addr_get_last(family, addr_out);
if (!tor_addr_is_null(addr_out)) {
goto found;
} }
/* Second, consider doing a resolve attempt right here. */ /* Second, attempt to find our address. The following can do a DNS resolve
if (!cache_only) { * thus only do it when the no cache only flag is flipped. */
tor_addr_t my_addr; if (!(flags & RELAY_FIND_ADDR_CACHE_ONLY)) {
if (find_my_address(options, AF_INET, LOG_INFO, &my_addr, NULL, NULL)) { if (find_my_address(options, family, LOG_INFO, addr_out, NULL, NULL)) {
log_info(LD_CONFIG,"Success: chose address '%s'.", fmt_addr(&my_addr)); goto found;
*addr = tor_addr_to_ipv4h(&my_addr);
return 0;
} }
} }
/* Third, check the cached output from router_new_address_suggestion(). */ /* Third, consider address from our suggestion cache. */
if (router_guess_address_from_dir_headers(addr) >= 0) resolved_addr_get_suggested(family, addr_out);
return 0; if (!tor_addr_is_null(addr_out)) {
goto found;
}
/* We have no useful cached answers. Return failure. */ /* No publishable address was found. */
return -1; return false;
found:
return true;
}
/** Return true iff this relay has an address set for the given family.
*
* This only checks the caches so it will not trigger a full discovery of the
* address. */
bool
relay_has_address_set(int family)
{
tor_addr_t addr;
return relay_find_addr_to_publish(get_options(), family,
RELAY_FIND_ADDR_CACHE_ONLY, &addr);
} }

View File

@ -9,16 +9,21 @@
#ifndef TOR_RELAY_FIND_ADDR_H #ifndef TOR_RELAY_FIND_ADDR_H
#define TOR_RELAY_FIND_ADDR_H #define TOR_RELAY_FIND_ADDR_H
MOCK_DECL(int, router_pick_published_address, typedef enum {
(const or_options_t *options, uint32_t *addr, int cache_only)); RELAY_FIND_ADDR_NO_FLAG = (1U << 0),
RELAY_FIND_ADDR_CACHE_ONLY = (1U << 1),
void router_new_address_suggestion(const char *suggestion, } relay_find_addr_flags_t;
const dir_connection_t *d_conn);
void relay_address_new_suggestion(const tor_addr_t *suggested_addr, void relay_address_new_suggestion(const tor_addr_t *suggested_addr,
const tor_addr_t *peer_addr, const tor_addr_t *peer_addr,
const char *identity_digest); const char *identity_digest);
MOCK_DECL(bool, relay_find_addr_to_publish,
(const or_options_t *options, int family, int flags,
tor_addr_t *addr_out));
bool relay_has_address_set(int family);
#ifdef RELAY_FIND_ADDR_PRIVATE #ifdef RELAY_FIND_ADDR_PRIVATE
#endif /* RELAY_FIND_ADDR_PRIVATE */ #endif /* RELAY_FIND_ADDR_PRIVATE */

View File

@ -38,6 +38,7 @@
#include "feature/relay/dns.h" #include "feature/relay/dns.h"
#include "feature/relay/relay_config.h" #include "feature/relay/relay_config.h"
#include "feature/relay/relay_find_addr.h" #include "feature/relay/relay_find_addr.h"
#include "feature/relay/relay_periodic.h"
#include "feature/relay/router.h" #include "feature/relay/router.h"
#include "feature/relay/routerkeys.h" #include "feature/relay/routerkeys.h"
#include "feature/relay/routermode.h" #include "feature/relay/routermode.h"
@ -1757,16 +1758,6 @@ router_get_my_routerinfo_with_err,(int *err))
return NULL; return NULL;
} }
if (!desc_clean_since) {
int rebuild_err = router_rebuild_descriptor(0);
if (rebuild_err < 0) {
if (err)
*err = rebuild_err;
return NULL;
}
}
if (!desc_routerinfo) { if (!desc_routerinfo) {
if (err) if (err)
*err = TOR_ROUTERINFO_ERROR_DESC_REBUILDING; *err = TOR_ROUTERINFO_ERROR_DESC_REBUILDING;
@ -1822,54 +1813,55 @@ router_get_descriptor_gen_reason(void)
* ORPort or DirPort. * ORPort or DirPort.
* listener_type is either CONN_TYPE_OR_LISTENER or CONN_TYPE_DIR_LISTENER. */ * listener_type is either CONN_TYPE_OR_LISTENER or CONN_TYPE_DIR_LISTENER. */
static void static void
router_check_descriptor_address_port_consistency(uint32_t ipv4h_desc_addr, router_check_descriptor_address_port_consistency(const tor_addr_t *addr,
int listener_type) int listener_type)
{ {
int family, port_cfg;
tor_assert(addr);
tor_assert(listener_type == CONN_TYPE_OR_LISTENER || tor_assert(listener_type == CONN_TYPE_OR_LISTENER ||
listener_type == CONN_TYPE_DIR_LISTENER); listener_type == CONN_TYPE_DIR_LISTENER);
/* The first advertised Port may be the magic constant CFG_AUTO_PORT. family = tor_addr_family(addr);
*/ /* The first advertised Port may be the magic constant CFG_AUTO_PORT. */
int port_v4_cfg = get_first_advertised_port_by_type_af(listener_type, port_cfg = get_first_advertised_port_by_type_af(listener_type, family);
AF_INET); if (port_cfg != 0 &&
if (port_v4_cfg != 0 && !port_exists_by_type_addr_port(listener_type, addr, port_cfg, 1)) {
!port_exists_by_type_addr32h_port(listener_type, const tor_addr_t *port_addr =
ipv4h_desc_addr, port_v4_cfg, 1)) { get_first_advertised_addr_by_type_af(listener_type, family);
const tor_addr_t *port_addr = get_first_advertised_addr_by_type_af( /* If we're building a descriptor with no advertised address,
listener_type, * something is terribly wrong. */
AF_INET); tor_assert(port_addr);
/* If we're building a descriptor with no advertised address,
* something is terribly wrong. */
tor_assert(port_addr);
tor_addr_t desc_addr; char port_addr_str[TOR_ADDR_BUF_LEN];
char port_addr_str[TOR_ADDR_BUF_LEN]; char desc_addr_str[TOR_ADDR_BUF_LEN];
char desc_addr_str[TOR_ADDR_BUF_LEN];
tor_addr_to_str(port_addr_str, port_addr, TOR_ADDR_BUF_LEN, 0); tor_addr_to_str(port_addr_str, port_addr, TOR_ADDR_BUF_LEN, 0);
tor_addr_to_str(desc_addr_str, addr, TOR_ADDR_BUF_LEN, 0);
tor_addr_from_ipv4h(&desc_addr, ipv4h_desc_addr); const char *listener_str = (listener_type == CONN_TYPE_OR_LISTENER ?
tor_addr_to_str(desc_addr_str, &desc_addr, TOR_ADDR_BUF_LEN, 0); "OR" : "Dir");
const char *af_str = fmt_af_family(family);
const char *listener_str = (listener_type == CONN_TYPE_OR_LISTENER ? log_warn(LD_CONFIG, "The %s %sPort address %s does not match the "
"OR" : "Dir"); "descriptor address %s. If you have a static public IPv4 "
log_warn(LD_CONFIG, "The IPv4 %sPort address %s does not match the " "address, use 'Address <%s>' and 'OutboundBindAddress "
"descriptor address %s. If you have a static public IPv4 " "<%s>'. If you are behind a NAT, use two %sPort lines: "
"address, use 'Address <IPv4>' and 'OutboundBindAddress " "'%sPort <PublicPort> NoListen' and '%sPort <InternalPort> "
"<IPv4>'. If you are behind a NAT, use two %sPort lines: " "NoAdvertise'.",
"'%sPort <PublicPort> NoListen' and '%sPort <InternalPort> " af_str, listener_str, port_addr_str, desc_addr_str, af_str,
"NoAdvertise'.", af_str, listener_str, listener_str, listener_str);
listener_str, port_addr_str, desc_addr_str, listener_str, }
listener_str, listener_str);
}
} }
/* Tor relays only have one IPv4 address in the descriptor, which is derived /** Tor relays only have one IPv4 or/and one IPv6 address in the descriptor,
* from the Address torrc option, or guessed using various methods in * which is derived from the Address torrc option, or guessed using various
* router_pick_published_address(). * methods in relay_find_addr_to_publish().
* Warn the operator if there is no ORPort on the descriptor address *
* ipv4h_desc_addr. * Warn the operator if there is no ORPort associated with the given address
* in addr.
*
* Warn the operator if there is no DirPort on the descriptor address. * Warn the operator if there is no DirPort on the descriptor address.
*
* This catches a few common config errors: * This catches a few common config errors:
* - operators who expect ORPorts and DirPorts to be advertised on the * - operators who expect ORPorts and DirPorts to be advertised on the
* ports' listen addresses, rather than the torrc Address (or guessed * ports' listen addresses, rather than the torrc Address (or guessed
@ -1878,20 +1870,22 @@ router_check_descriptor_address_port_consistency(uint32_t ipv4h_desc_addr,
* addresses; * addresses;
* - discrepancies between guessed addresses and configured listen * - discrepancies between guessed addresses and configured listen
* addresses (when the Address option isn't set). * addresses (when the Address option isn't set).
*
* If a listener is listening on all IPv4 addresses, it is assumed that it * If a listener is listening on all IPv4 addresses, it is assumed that it
* is listening on the configured Address, and no messages are logged. * is listening on the configured Address, and no messages are logged.
*
* If an operators has specified NoAdvertise ORPorts in a NAT setting, * If an operators has specified NoAdvertise ORPorts in a NAT setting,
* no messages are logged, unless they have specified other advertised * no messages are logged, unless they have specified other advertised
* addresses. * addresses.
*
* The message tells operators to configure an ORPort and DirPort that match * The message tells operators to configure an ORPort and DirPort that match
* the Address (using NoListen if needed). * the Address (using NoListen if needed). */
*/
static void static void
router_check_descriptor_address_consistency(uint32_t ipv4h_desc_addr) router_check_descriptor_address_consistency(const tor_addr_t *addr)
{ {
router_check_descriptor_address_port_consistency(ipv4h_desc_addr, router_check_descriptor_address_port_consistency(addr,
CONN_TYPE_OR_LISTENER); CONN_TYPE_OR_LISTENER);
router_check_descriptor_address_port_consistency(ipv4h_desc_addr, router_check_descriptor_address_port_consistency(addr,
CONN_TYPE_DIR_LISTENER); CONN_TYPE_DIR_LISTENER);
} }
@ -2033,7 +2027,7 @@ MOCK_IMPL(STATIC int,
router_build_fresh_unsigned_routerinfo,(routerinfo_t **ri_out)) router_build_fresh_unsigned_routerinfo,(routerinfo_t **ri_out))
{ {
routerinfo_t *ri = NULL; routerinfo_t *ri = NULL;
uint32_t addr; tor_addr_t ipv4_addr, ipv6_addr;
char platform[256]; char platform[256];
int hibernating = we_are_hibernating(); int hibernating = we_are_hibernating();
const or_options_t *options = get_options(); const or_options_t *options = get_options();
@ -2044,22 +2038,41 @@ router_build_fresh_unsigned_routerinfo,(routerinfo_t **ri_out))
goto err; goto err;
} }
if (router_pick_published_address(options, &addr, 0) < 0) { /* Find our resolved address both IPv4 and IPv6. In case the address is not
* found, the object is set to an UNSPEC address. */
bool have_v4 = relay_find_addr_to_publish(options, AF_INET,
RELAY_FIND_ADDR_NO_FLAG,
&ipv4_addr);
bool have_v6 = relay_find_addr_to_publish(options, AF_INET6,
RELAY_FIND_ADDR_NO_FLAG,
&ipv6_addr);
/* Tor requires a relay to have an IPv4 so bail if we can't find it. */
if (!have_v4) {
log_warn(LD_CONFIG, "Don't know my address while generating descriptor"); log_warn(LD_CONFIG, "Don't know my address while generating descriptor");
result = TOR_ROUTERINFO_ERROR_NO_EXT_ADDR; result = TOR_ROUTERINFO_ERROR_NO_EXT_ADDR;
goto err; goto err;
} }
/* Log a message if the address in the descriptor doesn't match the ORPort /* Log a message if the address in the descriptor doesn't match the ORPort
* and DirPort addresses configured by the operator. */ * and DirPort addresses configured by the operator. */
router_check_descriptor_address_consistency(addr); router_check_descriptor_address_consistency(&ipv4_addr);
router_check_descriptor_address_consistency(&ipv6_addr);
ri = tor_malloc_zero(sizeof(routerinfo_t)); ri = tor_malloc_zero(sizeof(routerinfo_t));
ri->cache_info.routerlist_index = -1; ri->cache_info.routerlist_index = -1;
ri->nickname = tor_strdup(options->Nickname); ri->nickname = tor_strdup(options->Nickname);
tor_addr_from_ipv4h(&ri->ipv4_addr, addr);
ri->ipv4_orport = router_get_advertised_or_port(options); /* IPv4. */
tor_addr_copy(&ri->ipv4_addr, &ipv4_addr);
ri->ipv4_orport = router_get_advertised_or_port_by_af(options, AF_INET);
ri->ipv4_dirport = router_get_advertised_dir_port(options, 0); ri->ipv4_dirport = router_get_advertised_dir_port(options, 0);
/* IPv6. */
if (have_v6) {
tor_addr_copy(&ri->ipv6_addr, &ipv6_addr);
ri->ipv6_orport = router_get_advertised_or_port_by_af(options, AF_INET6);
}
ri->supports_tunnelled_dir_requests = ri->supports_tunnelled_dir_requests =
directory_permits_begindir_requests(options); directory_permits_begindir_requests(options);
ri->cache_info.published_on = time(NULL); ri->cache_info.published_on = time(NULL);
@ -2071,13 +2084,6 @@ router_build_fresh_unsigned_routerinfo,(routerinfo_t **ri_out))
tor_memdup(&get_current_curve25519_keypair()->pubkey, tor_memdup(&get_current_curve25519_keypair()->pubkey,
sizeof(curve25519_public_key_t)); sizeof(curve25519_public_key_t));
/* For now, at most one IPv6 or-address is being advertised. */
tor_addr_port_t ipv6_orport;
router_get_advertised_ipv6_or_ap(options, &ipv6_orport);
/* If there is no valid IPv6 ORPort, the address and port are null. */
tor_addr_copy(&ri->ipv6_addr, &ipv6_orport.addr);
ri->ipv6_orport = ipv6_orport.port;
ri->identity_pkey = crypto_pk_dup_key(get_server_identity_key()); ri->identity_pkey = crypto_pk_dup_key(get_server_identity_key());
if (BUG(crypto_pk_get_digest(ri->identity_pkey, if (BUG(crypto_pk_get_digest(ri->identity_pkey,
ri->cache_info.identity_digest) < 0)) { ri->cache_info.identity_digest) < 0)) {
@ -2389,21 +2395,10 @@ router_rebuild_descriptor(int force)
int err = 0; int err = 0;
routerinfo_t *ri; routerinfo_t *ri;
extrainfo_t *ei; extrainfo_t *ei;
uint32_t addr;
const or_options_t *options = get_options();
if (desc_clean_since && !force) if (desc_clean_since && !force)
return 0; return 0;
if (router_pick_published_address(options, &addr, 0) < 0 ||
router_get_advertised_or_port(options) == 0) {
/* Stop trying to rebuild our descriptor every second. We'll
* learn that it's time to try again when ip_address_changed()
* marks it dirty. */
desc_clean_since = time(NULL);
return TOR_ROUTERINFO_ERROR_DESC_REBUILDING;
}
log_info(LD_OR, "Rebuilding relay descriptor%s", force ? " (forced)" : ""); log_info(LD_OR, "Rebuilding relay descriptor%s", force ? " (forced)" : "");
err = router_build_fresh_descriptor(&ri, &ei); err = router_build_fresh_descriptor(&ri, &ei);
@ -2503,11 +2498,13 @@ mark_my_descriptor_dirty(const char *reason)
if (BUG(reason == NULL)) { if (BUG(reason == NULL)) {
reason = "marked descriptor dirty for unspecified reason"; reason = "marked descriptor dirty for unspecified reason";
} }
if (server_mode(options) && options->PublishServerDescriptor_) if (server_mode(options) && options->PublishServerDescriptor_) {
log_info(LD_OR, "Decided to publish new relay descriptor: %s", reason); log_info(LD_OR, "Decided to publish new relay descriptor: %s", reason);
}
desc_clean_since = 0; desc_clean_since = 0;
if (!desc_dirty_reason) if (!desc_dirty_reason)
desc_dirty_reason = reason; desc_dirty_reason = reason;
reschedule_descriptor_update_check();
} }
/** How frequently will we republish our descriptor because of large (factor /** How frequently will we republish our descriptor because of large (factor

View File

@ -1290,10 +1290,6 @@ test_config_find_my_address_mixed(void *arg)
"2a01:4f8:fff0:4f:266:37ff:fe2c:5d19"); "2a01:4f8:fff0:4f:266:37ff:fe2c:5d19");
tor_addr_parse(&test_addr, "2a01:4f8:fff0:4f:266:37ff:fe2c:5d19"); tor_addr_parse(&test_addr, "2a01:4f8:fff0:4f:266:37ff:fe2c:5d19");
/* IPv4 address not guessed since one Address statement exists. */
retval = find_my_address(options, AF_INET, LOG_NOTICE, &resolved_addr,
&method_used, &hostname_out);
VALIDATE_FOUND_ADDRESS(false, NULL, NULL);
/* IPv6 address should be found and considered configured. */ /* IPv6 address should be found and considered configured. */
retval = find_my_address(options, AF_INET6, LOG_NOTICE, &resolved_addr, retval = find_my_address(options, AF_INET6, LOG_NOTICE, &resolved_addr,
&method_used, &hostname_out); &method_used, &hostname_out);
@ -1542,49 +1538,6 @@ test_config_find_my_address(void *arg)
VALIDATE_FOUND_ADDRESS(false, NULL, NULL); VALIDATE_FOUND_ADDRESS(false, NULL, NULL);
CLEANUP_FOUND_ADDRESS; CLEANUP_FOUND_ADDRESS;
/*
* Case 6: Another address family is configured. Expected to fail.
*/
if (p->family == AF_INET) {
config_line_append(&options->Address, "Address", "4242::4242");
} else {
config_line_append(&options->Address, "Address", "1.1.1.1");
}
setup_full_capture_of_logs(LOG_NOTICE);
retval = find_my_address(options, p->family, LOG_NOTICE, &resolved_addr,
&method_used, &hostname_out);
expect_log_msg_containing("No Address option found for family");
teardown_capture_of_logs();
VALIDATE_FOUND_ADDRESS(false, NULL, NULL);
CLEANUP_FOUND_ADDRESS;
/*
* Case 7: Address is a non resolvable hostname. Expected to fail.
*/
MOCK(tor_addr_lookup, tor_addr_lookup_failure);
config_line_append(&options->Address, "Address", "www.torproject.org");
prev_n_hostname_failure = n_hostname_failure;
setup_full_capture_of_logs(LOG_NOTICE);
retval = find_my_address(options, p->family, LOG_NOTICE, &resolved_addr,
&method_used, &hostname_out);
expect_log_msg_containing("Could not resolve local Address "
"'www.torproject.org'. Failing.");
teardown_capture_of_logs();
tt_int_op(n_hostname_failure, OP_EQ, ++prev_n_hostname_failure);
VALIDATE_FOUND_ADDRESS(false, NULL, NULL);
CLEANUP_FOUND_ADDRESS;
UNMOCK(tor_addr_lookup);
/* /*
* Case 8: * Case 8:
* 1. Address is NULL * 1. Address is NULL
@ -3889,16 +3842,17 @@ test_config_default_dir_servers(void *arg)
or_options_free(opts); or_options_free(opts);
} }
static int mock_router_pick_published_address_result = 0; static bool mock_relay_find_addr_to_publish_result = true;
static int static bool
mock_router_pick_published_address(const or_options_t *options, mock_relay_find_addr_to_publish(const or_options_t *options, int family,
uint32_t *addr, int cache_only) int flags, tor_addr_t *addr_out)
{ {
(void)options; (void) options;
(void)addr; (void) family;
(void)cache_only; (void) flags;
return mock_router_pick_published_address_result; (void) addr_out;
return mock_relay_find_addr_to_publish_result;
} }
static int mock_router_my_exit_policy_is_reject_star_result = 0; static int mock_router_my_exit_policy_is_reject_star_result = 0;
@ -3934,11 +3888,11 @@ test_config_directory_fetch(void *arg)
or_options_t *options = options_new(); or_options_t *options = options_new();
routerinfo_t routerinfo; routerinfo_t routerinfo;
memset(&routerinfo, 0, sizeof(routerinfo)); memset(&routerinfo, 0, sizeof(routerinfo));
mock_router_pick_published_address_result = -1; mock_relay_find_addr_to_publish_result = false;
mock_router_my_exit_policy_is_reject_star_result = 1; mock_router_my_exit_policy_is_reject_star_result = 1;
mock_advertised_server_mode_result = 0; mock_advertised_server_mode_result = 0;
mock_router_get_my_routerinfo_result = NULL; mock_router_get_my_routerinfo_result = NULL;
MOCK(router_pick_published_address, mock_router_pick_published_address); MOCK(relay_find_addr_to_publish, mock_relay_find_addr_to_publish);
MOCK(router_my_exit_policy_is_reject_star, MOCK(router_my_exit_policy_is_reject_star,
mock_router_my_exit_policy_is_reject_star); mock_router_my_exit_policy_is_reject_star);
MOCK(advertised_server_mode, mock_advertised_server_mode); MOCK(advertised_server_mode, mock_advertised_server_mode);
@ -3994,14 +3948,14 @@ test_config_directory_fetch(void *arg)
options = options_new(); options = options_new();
options->ORPort_set = 1; options->ORPort_set = 1;
mock_router_pick_published_address_result = -1; mock_relay_find_addr_to_publish_result = false;
tt_assert(server_mode(options) == 1); tt_assert(server_mode(options) == 1);
tt_assert(public_server_mode(options) == 1); tt_assert(public_server_mode(options) == 1);
tt_int_op(dirclient_fetches_from_authorities(options), OP_EQ, 1); tt_int_op(dirclient_fetches_from_authorities(options), OP_EQ, 1);
tt_int_op(networkstatus_consensus_can_use_multiple_directories(options), tt_int_op(networkstatus_consensus_can_use_multiple_directories(options),
OP_EQ, 0); OP_EQ, 0);
mock_router_pick_published_address_result = 0; mock_relay_find_addr_to_publish_result = true;
tt_assert(server_mode(options) == 1); tt_assert(server_mode(options) == 1);
tt_assert(public_server_mode(options) == 1); tt_assert(public_server_mode(options) == 1);
tt_int_op(dirclient_fetches_from_authorities(options), OP_EQ, 0); tt_int_op(dirclient_fetches_from_authorities(options), OP_EQ, 0);
@ -4015,7 +3969,7 @@ test_config_directory_fetch(void *arg)
options = options_new(); options = options_new();
options->ORPort_set = 1; options->ORPort_set = 1;
options->ExitRelay = 1; options->ExitRelay = 1;
mock_router_pick_published_address_result = 0; mock_relay_find_addr_to_publish_result = true;
mock_router_my_exit_policy_is_reject_star_result = 0; mock_router_my_exit_policy_is_reject_star_result = 0;
mock_advertised_server_mode_result = 1; mock_advertised_server_mode_result = 1;
mock_router_get_my_routerinfo_result = &routerinfo; mock_router_get_my_routerinfo_result = &routerinfo;
@ -4030,7 +3984,7 @@ test_config_directory_fetch(void *arg)
OP_EQ, 0); OP_EQ, 0);
options->RefuseUnknownExits = 0; options->RefuseUnknownExits = 0;
mock_router_pick_published_address_result = 0; mock_relay_find_addr_to_publish_result = true;
tt_assert(server_mode(options) == 1); tt_assert(server_mode(options) == 1);
tt_assert(public_server_mode(options) == 1); tt_assert(public_server_mode(options) == 1);
tt_int_op(dirclient_fetches_from_authorities(options), OP_EQ, 0); tt_int_op(dirclient_fetches_from_authorities(options), OP_EQ, 0);
@ -4047,7 +4001,7 @@ test_config_directory_fetch(void *arg)
options->DirPort_set = 1; options->DirPort_set = 1;
options->ORPort_set = 1; options->ORPort_set = 1;
options->DirCache = 1; options->DirCache = 1;
mock_router_pick_published_address_result = 0; mock_relay_find_addr_to_publish_result = true;
mock_router_my_exit_policy_is_reject_star_result = 1; mock_router_my_exit_policy_is_reject_star_result = 1;
mock_advertised_server_mode_result = 1; mock_advertised_server_mode_result = 1;
@ -4098,7 +4052,7 @@ test_config_directory_fetch(void *arg)
done: done:
or_options_free(options); or_options_free(options);
UNMOCK(router_pick_published_address); UNMOCK(relay_find_addr_to_publish);
UNMOCK(router_get_my_routerinfo); UNMOCK(router_get_my_routerinfo);
UNMOCK(advertised_server_mode); UNMOCK(advertised_server_mode);
UNMOCK(router_my_exit_policy_is_reject_star); UNMOCK(router_my_exit_policy_is_reject_star);

View File

@ -17,6 +17,14 @@
#include "core/or/cell_st.h" #include "core/or/cell_st.h"
#include "core/or/or_circuit_st.h" #include "core/or/or_circuit_st.h"
#define RESOLVE_ADDR_PRIVATE
#include "feature/nodelist/dirlist.h"
#include "feature/relay/relay_find_addr.h"
#include "feature/relay/routermode.h"
#include "feature/dirclient/dir_server_st.h"
#include "app/config/resolve_addr.h"
/* Test suite stuff */ /* Test suite stuff */
#include "test/test.h" #include "test/test.h"
#include "test/fakechans.h" #include "test/fakechans.h"
@ -24,6 +32,13 @@
static void test_relay_append_cell_to_circuit_queue(void *arg); static void test_relay_append_cell_to_circuit_queue(void *arg);
static int
mock_server_mode_true(const or_options_t *options)
{
(void) options;
return 1;
}
static void static void
assert_circuit_ok_mock(const circuit_t *c) assert_circuit_ok_mock(const circuit_t *c)
{ {
@ -192,10 +207,165 @@ test_relay_append_cell_to_circuit_queue(void *arg)
return; return;
} }
static void
test_suggested_address(void *arg)
{
int ret;
const char *untrusted_id = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA";
dir_server_t *ds = NULL;
tor_addr_t ipv4_addr, ipv6_addr, cache_addr;
tor_addr_t trusted_addr, untrusted_addr;
tor_addr_port_t trusted_ap_v6 = { .port = 443 };
(void) arg;
MOCK(server_mode, mock_server_mode_true);
/* Unstrusted relay source. */
ret = tor_addr_parse(&untrusted_addr, "8.8.8.8");
tt_int_op(ret, OP_EQ, AF_INET);
/* Add gabelmoo as a trusted directory authority. */
ret = tor_addr_parse(&trusted_addr, "[2001:638:a000:4140::ffff:189]");
tt_int_op(ret, OP_EQ, AF_INET6);
tor_addr_copy(&trusted_ap_v6.addr, &trusted_addr);
ds = trusted_dir_server_new("gabelmoo", "131.188.40.189", 80, 443,
&trusted_ap_v6,
"F2044413DAC2E02E3D6BCF4735A19BCA1DE97281",
"ED03BB616EB2F60BEC80151114BB25CEF515B226",
V3_DIRINFO, 1.0);
tt_assert(ds);
dir_server_add(ds);
/* 1. Valid IPv4 from a trusted authority (gabelmoo). */
ret = tor_addr_parse(&ipv4_addr, "1.2.3.4");
relay_address_new_suggestion(&ipv4_addr, &ds->ipv4_addr, ds->digest);
resolved_addr_get_suggested(AF_INET, &cache_addr);
tt_assert(tor_addr_eq(&cache_addr, &ipv4_addr));
resolve_addr_reset_suggested(AF_INET);
/* 2. Valid IPv6 from a trusted authority (gabelmoo). */
ret = tor_addr_parse(&ipv6_addr, "[4242::4242]");
relay_address_new_suggestion(&ipv6_addr, &ds->ipv6_addr, ds->digest);
resolved_addr_get_suggested(AF_INET6, &cache_addr);
tt_assert(tor_addr_eq(&cache_addr, &ipv6_addr));
resolve_addr_reset_suggested(AF_INET6);
/* 3. Valid IPv4 but untrusted source. */
ret = tor_addr_parse(&ipv4_addr, "1.2.3.4");
relay_address_new_suggestion(&ipv4_addr, &untrusted_addr, untrusted_id);
resolved_addr_get_suggested(AF_INET, &cache_addr);
tt_assert(tor_addr_is_unspec(&cache_addr));
/* 4. Valid IPv6 but untrusted source. */
ret = tor_addr_parse(&ipv6_addr, "[4242::4242]");
relay_address_new_suggestion(&ipv6_addr, &untrusted_addr, untrusted_id);
resolved_addr_get_suggested(AF_INET6, &cache_addr);
tt_assert(tor_addr_is_unspec(&cache_addr));
/* 5. Internal IPv4 from a trusted authority (gabelmoo). */
ret = tor_addr_parse(&ipv4_addr, "127.0.0.1");
relay_address_new_suggestion(&ipv4_addr, &ds->ipv4_addr, ds->digest);
resolved_addr_get_suggested(AF_INET, &cache_addr);
tt_assert(tor_addr_is_unspec(&cache_addr));
/* 6. Internal IPv6 from a trusted authority (gabelmoo). */
ret = tor_addr_parse(&ipv6_addr, "[::1]");
relay_address_new_suggestion(&ipv6_addr, &ds->ipv6_addr, ds->digest);
resolved_addr_get_suggested(AF_INET6, &cache_addr);
tt_assert(tor_addr_is_unspec(&cache_addr));
/* 7. IPv4 from a trusted authority (gabelmoo). */
relay_address_new_suggestion(&ds->ipv4_addr, &ds->ipv4_addr, ds->digest);
resolved_addr_get_suggested(AF_INET, &cache_addr);
tt_assert(tor_addr_is_unspec(&cache_addr));
/* 8. IPv6 from a trusted authority (gabelmoo). */
relay_address_new_suggestion(&ds->ipv6_addr, &ds->ipv6_addr, ds->digest);
resolved_addr_get_suggested(AF_INET6, &cache_addr);
tt_assert(tor_addr_is_unspec(&cache_addr));
done:
dirlist_free_all();
UNMOCK(server_mode);
}
static void
test_find_addr_to_publish(void *arg)
{
int family;
bool ret;
tor_addr_t ipv4_addr, ipv6_addr, cache_addr;
or_options_t options;
(void) arg;
/* Populate our resolved cache with a valid IPv4 and IPv6. */
family = tor_addr_parse(&ipv4_addr, "1.2.3.4");
tt_int_op(family, OP_EQ, AF_INET);
resolved_addr_set_last(&ipv4_addr, "NA", NULL);
resolved_addr_get_last(AF_INET, &cache_addr);
tt_assert(tor_addr_eq(&ipv4_addr, &cache_addr));
family = tor_addr_parse(&ipv6_addr, "[4242::4242]");
tt_int_op(family, OP_EQ, AF_INET6);
resolved_addr_set_last(&ipv6_addr, "NA", NULL);
resolved_addr_get_last(AF_INET6, &cache_addr);
tt_assert(tor_addr_eq(&ipv6_addr, &cache_addr));
/* 1. Address located in the resolved cache. */
ret = relay_find_addr_to_publish(&options, AF_INET,
RELAY_FIND_ADDR_CACHE_ONLY, &cache_addr);
tt_assert(ret);
tt_assert(tor_addr_eq(&ipv4_addr, &cache_addr));
ret = relay_find_addr_to_publish(&options, AF_INET6,
RELAY_FIND_ADDR_CACHE_ONLY, &cache_addr);
tt_assert(ret);
tt_assert(tor_addr_eq(&ipv6_addr, &cache_addr));
resolved_addr_reset_last(AF_INET);
resolved_addr_reset_last(AF_INET6);
/* 2. No IP in the resolve cache, go to the suggested cache. We will ignore
* the find_my_address() code path because that is extensively tested in
* another unit tests. */
resolved_addr_set_suggested(&ipv4_addr);
ret = relay_find_addr_to_publish(&options, AF_INET,
RELAY_FIND_ADDR_CACHE_ONLY, &cache_addr);
tt_assert(ret);
tt_assert(tor_addr_eq(&ipv4_addr, &cache_addr));
resolved_addr_set_suggested(&ipv6_addr);
ret = relay_find_addr_to_publish(&options, AF_INET6,
RELAY_FIND_ADDR_CACHE_ONLY, &cache_addr);
tt_assert(ret);
tt_assert(tor_addr_eq(&ipv6_addr, &cache_addr));
resolve_addr_reset_suggested(AF_INET);
resolve_addr_reset_suggested(AF_INET6);
/* 3. No IP anywhere. */
ret = relay_find_addr_to_publish(&options, AF_INET,
RELAY_FIND_ADDR_CACHE_ONLY, &cache_addr);
tt_assert(!ret);
ret = relay_find_addr_to_publish(&options, AF_INET6,
RELAY_FIND_ADDR_CACHE_ONLY, &cache_addr);
tt_assert(!ret);
done:
;
}
struct testcase_t relay_tests[] = { struct testcase_t relay_tests[] = {
{ "append_cell_to_circuit_queue", test_relay_append_cell_to_circuit_queue, { "append_cell_to_circuit_queue", test_relay_append_cell_to_circuit_queue,
TT_FORK, NULL, NULL }, TT_FORK, NULL, NULL },
{ "close_circ_rephist", test_relay_close_circuit, { "close_circ_rephist", test_relay_close_circuit,
TT_FORK, NULL, NULL }, TT_FORK, NULL, NULL },
{ "suggested_address", test_suggested_address,
TT_FORK, NULL, NULL },
{ "find_addr_to_publish", test_find_addr_to_publish,
TT_FORK, NULL, NULL },
END_OF_TESTCASES END_OF_TESTCASES
}; };