addr: New function relay_address_new_suggestion()

This behaves like router_new_address_suggestion() but differs in couple of
ways:

  1. It takes a tor_addr_t instead of an address string and supports both
     AF_INET and AF_INET6.
  2. It does _not_ use the last_guessed_ip local cache and instead only relies
     on the last resolved address cache in resolve_addr.c

It is not used at this commit. This function is made to process a suggested
address found in a NETINFO cell exactly like router_new_address_suggestion()
does with the address a directory suggests us.

Related to #40022

Signed-off-by: David Goulet <dgoulet@torproject.org>
This commit is contained in:
David Goulet 2020-07-06 09:42:10 -04:00
parent f57ce632fe
commit 192d367b41
6 changed files with 122 additions and 0 deletions

View File

@ -44,6 +44,12 @@ typedef enum {
/** Last resolved addresses. */
static tor_addr_t last_resolved_addrs[IDX_SIZE];
/** Last suggested addresses.
*
* These addresses come from a NETINFO cell from a trusted relay (currently
* only authorities). We only use those in last resort. */
static tor_addr_t last_suggested_addrs[IDX_SIZE];
static inline int
af_to_idx(const int family)
{
@ -60,6 +66,29 @@ af_to_idx(const int family)
}
}
/** Copy the last suggested address of family into addr_out.
*
* If no last suggested address exists, the addr_out is a null address (use
* tor_addr_is_null() to confirm). */
void
resolved_addr_get_suggested(int family, tor_addr_t *addr_out)
{
tor_addr_copy(addr_out, &last_suggested_addrs[af_to_idx(family)]);
}
/** Set the last suggested address into our cache. This is called when we get
* a new NETINFO cell from a trusted source. */
void
resolved_addr_set_suggested(const tor_addr_t *addr)
{
if (BUG(tor_addr_family(addr) != AF_INET ||
tor_addr_family(addr) != AF_INET6)) {
return;
}
tor_addr_copy(&last_suggested_addrs[af_to_idx(tor_addr_family(addr))],
addr);
}
/** Copy the last resolved address of family into addr_out.
*
* If not last resolved address existed, the addr_out is a null address (use

View File

@ -20,6 +20,9 @@ void resolved_addr_reset_last(int family);
void resolved_addr_set_last(const tor_addr_t *addr, const char *method_used,
const char *hostname_used);
void resolved_addr_get_suggested(int family, tor_addr_t *addr_out);
void resolved_addr_set_suggested(const tor_addr_t *addr);
MOCK_DECL(bool, is_local_to_resolve_addr, (const tor_addr_t *addr));
#ifdef RESOLVE_ADDR_PRIVATE

View File

@ -250,6 +250,34 @@ router_digest_is_trusted_dir_type(const char *digest, dirinfo_type_t type)
return 0;
}
/** Return true iff the given address matches a trusted directory that matches
* at least one bit of type.
*
* If type is NO_DIRINFO or ALL_DIRINFO, any authority is matched. */
bool
router_addr_is_trusted_dir_type(const tor_addr_t *addr, dirinfo_type_t type)
{
int family = tor_addr_family(addr);
if (!trusted_dir_servers) {
return false;
}
SMARTLIST_FOREACH_BEGIN(trusted_dir_servers, dir_server_t *, ent) {
/* Ignore entries that don't match the given type. */
if (type != NO_DIRINFO && (type & ent->type) == 0) {
continue;
}
/* Match IPv4 or IPv6 address. */
if ((family == AF_INET && tor_addr_eq_ipv4h(addr, ent->addr)) ||
(family == AF_INET6 && tor_addr_eq(addr, &ent->ipv6_addr))) {
return true;
}
} SMARTLIST_FOREACH_END(ent);
return false;
}
/** Create a directory server at <b>address</b>:<b>port</b>, with OR identity
* key <b>digest</b> which has DIGEST_LEN bytes. If <b>address</b> is NULL,
* add ourself. If <b>is_authority</b>, this is a directory authority. Return

View File

@ -25,6 +25,11 @@ int router_digest_is_fallback_dir(const char *digest);
MOCK_DECL(dir_server_t *, trusteddirserver_get_by_v3_auth_digest,
(const char *d));
bool router_addr_is_trusted_dir_type(const tor_addr_t *addr,
dirinfo_type_t type);
#define router_addr_is_trusted_dir(d) \
router_addr_is_trusted_dir_type((d), NO_DIRINFO)
int router_digest_is_trusted_dir_type(const char *digest,
dirinfo_type_t type);
#define router_digest_is_trusted_dir(d) \

View File

@ -15,6 +15,7 @@
#include "feature/control/control_events.h"
#include "feature/dircommon/dir_connection_st.h"
#include "feature/nodelist/dirlist.h"
#include "feature/relay/relay_find_addr.h"
#include "feature/relay/router.h"
#include "feature/relay/routermode.h"
@ -37,6 +38,59 @@ router_guess_address_from_dir_headers(uint32_t *guess)
return -1;
}
/** Consider the address suggestion suggested_addr as a possible one to use as
* our address.
*
* This is called when a valid NETINFO cell is recevied containing a candidate
* for our address.
*
* The suggested address is ignored if it does NOT come from a trusted source.
* At the moment, we only look a trusted directory authorities.
*
* The suggested address is ignored if it is internal or it is the same as the
* given peer_addr which is the address from the endpoint that sent the
* NETINFO cell.
*
* The suggested address is set in our suggested address cache if everything
* passes. */
void
relay_address_new_suggestion(const tor_addr_t *suggested_addr,
const tor_addr_t *peer_addr)
{
const or_options_t *options = get_options();
tor_assert(suggested_addr);
tor_assert(peer_addr);
/* This should never be called on a non Tor relay. */
if (BUG(!server_mode(options))) {
return;
}
/* Is the peer a trusted source? Ignore anything coming from non trusted
* source. In this case, we only look at trusted authorities. */
if (!router_addr_is_trusted_dir(peer_addr)) {
return;
}
/* Ignore a suggestion that is an internal address or the same as the one
* the peer address. */
if (tor_addr_is_internal(suggested_addr, 0)) {
/* Do not believe anyone who says our address is internal. */
return;
}
if (tor_addr_eq(suggested_addr, peer_addr)) {
/* Do not believe anyone who says our address is their address. */
log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
"A relay endpoint %s is telling us that their address is ours.",
fmt_addr(peer_addr));
return;
}
/* Save the suggestion in our cache. */
resolved_addr_set_suggested(suggested_addr);
}
/** A directory server <b>d_conn</b> told us our IP address is
* <b>suggestion</b>.
* If this address is different from the one we think we are now, and

View File

@ -15,6 +15,9 @@ MOCK_DECL(int, router_pick_published_address,
void router_new_address_suggestion(const char *suggestion,
const dir_connection_t *d_conn);
void relay_address_new_suggestion(const tor_addr_t *suggested_addr,
const tor_addr_t *peer_addr);
#ifdef RELAY_FIND_ADDR_PRIVATE
#endif /* RELAY_FIND_ADDR_PRIVATE */