mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2024-11-11 13:43:47 +01:00
Merge remote-tracking branch 'tor-gitlab/mr/51'
This commit is contained in:
commit
f5d773c600
@ -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) {
|
||||||
|
/* We found no address but we got a resolution failure. This means we
|
||||||
|
* can know if the hostname given was v4 or v6 so we can't continue. */
|
||||||
|
return FN_RET_BAIL;
|
||||||
|
}
|
||||||
|
log_info(LD_CONFIG,
|
||||||
"No Address option found for family %s in configuration.",
|
"No Address option found for family %s in configuration.",
|
||||||
fmt_af_family(family));
|
fmt_af_family(family));
|
||||||
/* No Address statement for family but one exists since Address is not
|
/* No Address statement for family so move on to try next method. */
|
||||||
* NULL thus we have to stop now and not attempt to send back a guessed
|
return FN_RET_NEXT;
|
||||||
* address. */
|
|
||||||
return FN_RET_BAIL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (num_valid_addr >= MAX_CONFIG_ADDRESS) {
|
if (num_valid_addr >= MAX_CONFIG_ADDRESS) {
|
||||||
@ -283,7 +287,7 @@ 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,7 +350,7 @@ 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 */
|
||||||
|
@ -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 */
|
||||||
|
@ -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);
|
||||||
|
@ -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()));
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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)
|
||||||
|
@ -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. */
|
}
|
||||||
return -1;
|
|
||||||
|
/* No publishable address was found. */
|
||||||
|
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);
|
||||||
}
|
}
|
||||||
|
@ -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 */
|
||||||
|
@ -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(
|
|
||||||
listener_type,
|
|
||||||
AF_INET);
|
|
||||||
/* If we're building a descriptor with no advertised address,
|
/* If we're building a descriptor with no advertised address,
|
||||||
* something is terribly wrong. */
|
* something is terribly wrong. */
|
||||||
tor_assert(port_addr);
|
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);
|
|
||||||
tor_addr_to_str(desc_addr_str, &desc_addr, TOR_ADDR_BUF_LEN, 0);
|
|
||||||
|
|
||||||
const char *listener_str = (listener_type == CONN_TYPE_OR_LISTENER ?
|
const char *listener_str = (listener_type == CONN_TYPE_OR_LISTENER ?
|
||||||
"OR" : "Dir");
|
"OR" : "Dir");
|
||||||
log_warn(LD_CONFIG, "The IPv4 %sPort address %s does not match the "
|
const char *af_str = fmt_af_family(family);
|
||||||
|
log_warn(LD_CONFIG, "The %s %sPort address %s does not match the "
|
||||||
"descriptor address %s. If you have a static public IPv4 "
|
"descriptor address %s. If you have a static public IPv4 "
|
||||||
"address, use 'Address <IPv4>' and 'OutboundBindAddress "
|
"address, use 'Address <%s>' and 'OutboundBindAddress "
|
||||||
"<IPv4>'. If you are behind a NAT, use two %sPort lines: "
|
"<%s>'. If you are behind a NAT, use two %sPort lines: "
|
||||||
"'%sPort <PublicPort> NoListen' and '%sPort <InternalPort> "
|
"'%sPort <PublicPort> NoListen' and '%sPort <InternalPort> "
|
||||||
"NoAdvertise'.",
|
"NoAdvertise'.",
|
||||||
listener_str, port_addr_str, desc_addr_str, listener_str,
|
af_str, listener_str, port_addr_str, desc_addr_str, af_str,
|
||||||
listener_str, listener_str);
|
af_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
|
||||||
|
@ -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);
|
||||||
|
@ -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
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user