mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2024-12-06 19:41:15 +01:00
Merge remote-tracking branch 'teor/bug23827-v2'
This commit is contained in:
@@ -0,0 +1,8 @@
|
||||
o Minor feature (IPv6):
|
||||
- When a consensus has IPv6 ORPorts, make IPv6-only clients use them,
|
||||
rather than waiting to download microdescriptors.
|
||||
Implements 23827.
|
||||
- Make IPv6-only clients wait for microdescs for relays, even if we were
|
||||
previously using descriptors (or were using them as a bridge) and have
|
||||
a cached descriptor for them.
|
||||
Implements 23827.
|
||||
@@ -1507,6 +1507,32 @@ networkstatus_consensus_is_already_downloading(const char *resource)
|
||||
return answer;
|
||||
}
|
||||
|
||||
/* Does the current, reasonably live consensus have IPv6 addresses?
|
||||
* Returns 1 if there is a reasonably live consensus and its consensus method
|
||||
* includes IPv6 addresses in the consensus.
|
||||
* Otherwise, if there is no consensus, or the method does not include IPv6
|
||||
* addresses, returns 0. */
|
||||
int
|
||||
networkstatus_consensus_has_ipv6(const or_options_t* options)
|
||||
{
|
||||
const networkstatus_t *cons = networkstatus_get_reasonably_live_consensus(
|
||||
approx_time(),
|
||||
usable_consensus_flavor());
|
||||
|
||||
/* If we have no consensus, we have no IPv6 in it */
|
||||
if (!cons) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Different flavours of consensus gained IPv6 at different times */
|
||||
if (we_use_microdescriptors_for_circuits(options)) {
|
||||
return
|
||||
cons->consensus_method >= MIN_METHOD_FOR_A_LINES_IN_MICRODESC_CONSENSUS;
|
||||
} else {
|
||||
return cons->consensus_method >= MIN_METHOD_FOR_A_LINES;
|
||||
}
|
||||
}
|
||||
|
||||
/** Given two router status entries for the same router identity, return 1 if
|
||||
* if the contents have changed between them. Otherwise, return 0. */
|
||||
static int
|
||||
|
||||
@@ -93,6 +93,7 @@ int networkstatus_consensus_can_use_multiple_directories(
|
||||
MOCK_DECL(int, networkstatus_consensus_can_use_extra_fallbacks,(
|
||||
const or_options_t *options));
|
||||
int networkstatus_consensus_is_already_downloading(const char *resource);
|
||||
int networkstatus_consensus_has_ipv6(const or_options_t* options);
|
||||
|
||||
#define NSSET_FROM_CACHE 1
|
||||
#define NSSET_WAS_WAITING_FOR_CERTS 2
|
||||
|
||||
+24
-7
@@ -18,6 +18,7 @@
|
||||
#define POLICIES_PRIVATE
|
||||
|
||||
#include "or.h"
|
||||
#include "bridges.h"
|
||||
#include "config.h"
|
||||
#include "dirserv.h"
|
||||
#include "microdesc.h"
|
||||
@@ -893,9 +894,10 @@ fascist_firewall_choose_address_ipv4h(uint32_t ipv4h_addr,
|
||||
pref_ipv6, ap);
|
||||
}
|
||||
|
||||
/* The microdescriptor consensus has no IPv6 addresses in rs: they are in
|
||||
* the microdescriptors. This means we can't rely on the node's IPv6 address
|
||||
* until its microdescriptor is available (when using microdescs).
|
||||
/* Some microdescriptor consensus methods have no IPv6 addresses in rs: they
|
||||
* are in the microdescriptors. For these consensus methods, we can't rely on
|
||||
* the node's IPv6 address until its microdescriptor is available (when using
|
||||
* microdescs).
|
||||
* But for bridges, rewrite_node_address_for_bridge() updates node->ri with
|
||||
* the configured address, so we can trust bridge addresses.
|
||||
* (Bridges could gain an IPv6 address if their microdescriptor arrives, but
|
||||
@@ -913,11 +915,26 @@ node_awaiting_ipv6(const or_options_t* options, const node_t *node)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* If the node has an IPv6 address, we're not waiting */
|
||||
if (node_has_ipv6_addr(node)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* If the current consensus method and flavour has IPv6 addresses, we're not
|
||||
* waiting */
|
||||
if (networkstatus_consensus_has_ipv6(options)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Bridge clients never use the address from a bridge's md, so there's no
|
||||
* need to wait for it. */
|
||||
if (node_is_a_configured_bridge(node)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* We are waiting if we_use_microdescriptors_for_circuits() and we have no
|
||||
* md. Bridges have a ri based on their config. They would never use the
|
||||
* address from their md, so there's no need to wait for it. */
|
||||
return (!node->md && we_use_microdescriptors_for_circuits(options) &&
|
||||
!node->ri);
|
||||
* md. */
|
||||
return (!node->md && we_use_microdescriptors_for_circuits(options));
|
||||
}
|
||||
|
||||
/** Like fascist_firewall_choose_address_base(), but takes <b>rs</b>.
|
||||
|
||||
@@ -6174,6 +6174,106 @@ test_dir_platform_str(void *arg)
|
||||
;
|
||||
}
|
||||
|
||||
static networkstatus_t *mock_networkstatus;
|
||||
|
||||
static networkstatus_t *
|
||||
mock_networkstatus_get_latest_consensus_by_flavor(consensus_flavor_t f)
|
||||
{
|
||||
(void)f;
|
||||
return mock_networkstatus;
|
||||
}
|
||||
|
||||
static void
|
||||
test_dir_networkstatus_consensus_has_ipv6(void *arg)
|
||||
{
|
||||
(void)arg;
|
||||
|
||||
int has_ipv6 = 0;
|
||||
|
||||
/* Init options and networkstatus */
|
||||
or_options_t our_options;
|
||||
mock_options = &our_options;
|
||||
reset_options(mock_options, &mock_get_options_calls);
|
||||
MOCK(get_options, mock_get_options);
|
||||
|
||||
networkstatus_t our_networkstatus;
|
||||
mock_networkstatus = &our_networkstatus;
|
||||
memset(mock_networkstatus, 0, sizeof(*mock_networkstatus));
|
||||
MOCK(networkstatus_get_latest_consensus_by_flavor,
|
||||
mock_networkstatus_get_latest_consensus_by_flavor);
|
||||
|
||||
/* A live consensus */
|
||||
mock_networkstatus->valid_after = time(NULL) - 3600;
|
||||
mock_networkstatus->valid_until = time(NULL) + 3600;
|
||||
|
||||
/* Test the bounds for A lines in the NS consensus */
|
||||
mock_options->UseMicrodescriptors = 0;
|
||||
|
||||
mock_networkstatus->consensus_method = MIN_METHOD_FOR_A_LINES;
|
||||
has_ipv6 = networkstatus_consensus_has_ipv6(get_options());
|
||||
tt_assert(has_ipv6);
|
||||
|
||||
mock_networkstatus->consensus_method = MIN_METHOD_FOR_A_LINES + 1;
|
||||
has_ipv6 = networkstatus_consensus_has_ipv6(get_options());
|
||||
tt_assert(has_ipv6);
|
||||
|
||||
mock_networkstatus->consensus_method = MIN_METHOD_FOR_A_LINES + 20;
|
||||
has_ipv6 = networkstatus_consensus_has_ipv6(get_options());
|
||||
tt_assert(has_ipv6);
|
||||
|
||||
mock_networkstatus->consensus_method = MIN_METHOD_FOR_A_LINES - 1;
|
||||
has_ipv6 = networkstatus_consensus_has_ipv6(get_options());
|
||||
tt_assert(!has_ipv6);
|
||||
|
||||
/* Test the bounds for A lines in the microdesc consensus */
|
||||
mock_options->UseMicrodescriptors = 1;
|
||||
|
||||
mock_networkstatus->consensus_method =
|
||||
MIN_METHOD_FOR_A_LINES_IN_MICRODESC_CONSENSUS;
|
||||
has_ipv6 = networkstatus_consensus_has_ipv6(get_options());
|
||||
tt_assert(has_ipv6);
|
||||
|
||||
mock_networkstatus->consensus_method =
|
||||
MIN_METHOD_FOR_A_LINES_IN_MICRODESC_CONSENSUS + 1;
|
||||
has_ipv6 = networkstatus_consensus_has_ipv6(get_options());
|
||||
tt_assert(has_ipv6);
|
||||
|
||||
mock_networkstatus->consensus_method =
|
||||
MIN_METHOD_FOR_A_LINES_IN_MICRODESC_CONSENSUS + 20;
|
||||
has_ipv6 = networkstatus_consensus_has_ipv6(get_options());
|
||||
tt_assert(has_ipv6);
|
||||
|
||||
mock_networkstatus->consensus_method =
|
||||
MIN_METHOD_FOR_A_LINES_IN_MICRODESC_CONSENSUS - 1;
|
||||
has_ipv6 = networkstatus_consensus_has_ipv6(get_options());
|
||||
tt_assert(!has_ipv6);
|
||||
|
||||
/* Test the edge cases */
|
||||
mock_options->UseMicrodescriptors = 1;
|
||||
mock_networkstatus->consensus_method =
|
||||
MIN_METHOD_FOR_A_LINES_IN_MICRODESC_CONSENSUS;
|
||||
|
||||
/* Reasonably live */
|
||||
mock_networkstatus->valid_until = time(NULL) - 60;
|
||||
has_ipv6 = networkstatus_consensus_has_ipv6(get_options());
|
||||
tt_assert(has_ipv6);
|
||||
|
||||
/* Not reasonably live */
|
||||
mock_networkstatus->valid_after = time(NULL) - 24*60*60 - 3600;
|
||||
mock_networkstatus->valid_until = time(NULL) - 24*60*60 - 60;
|
||||
has_ipv6 = networkstatus_consensus_has_ipv6(get_options());
|
||||
tt_assert(!has_ipv6);
|
||||
|
||||
/* NULL consensus */
|
||||
mock_networkstatus = NULL;
|
||||
has_ipv6 = networkstatus_consensus_has_ipv6(get_options());
|
||||
tt_assert(!has_ipv6);
|
||||
|
||||
done:
|
||||
UNMOCK(get_options);
|
||||
UNMOCK(networkstatus_get_latest_consensus_by_flavor);
|
||||
}
|
||||
|
||||
#define DIR_LEGACY(name) \
|
||||
{ #name, test_dir_ ## name , TT_FORK, NULL, NULL }
|
||||
|
||||
@@ -6241,6 +6341,7 @@ struct testcase_t dir_tests[] = {
|
||||
DIR(assumed_flags, 0),
|
||||
DIR(networkstatus_compute_bw_weights_v10, 0),
|
||||
DIR(platform_str, 0),
|
||||
DIR(networkstatus_consensus_has_ipv6, 0),
|
||||
END_OF_TESTCASES
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user