commit 28d4355a6ebe69c84d0ae31d7a0763f0a17f0151 Author: teor teor2345@gmail.com Date: Sat Dec 2 23:01:07 2017 +1100
Add networkstatus_consensus_has_ipv6() and unit tests
networkstatus_consensus_has_ipv6() tells us whether the consensus method of our current consensus supports IPv6 ORPorts in the consensus.
Part of #23827. --- src/or/networkstatus.c | 26 ++++++++++++++ src/or/networkstatus.h | 1 + src/test/test_dir.c | 96 ++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 123 insertions(+)
diff --git a/src/or/networkstatus.c b/src/or/networkstatus.c index 2843d0626..61cca1b9b 100644 --- a/src/or/networkstatus.c +++ b/src/or/networkstatus.c @@ -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 diff --git a/src/or/networkstatus.h b/src/or/networkstatus.h index 791e32adc..1851a55e8 100644 --- a/src/or/networkstatus.h +++ b/src/or/networkstatus.h @@ -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 diff --git a/src/test/test_dir.c b/src/test/test_dir.c index ee7aea5b8..0da4e7e15 100644 --- a/src/test/test_dir.c +++ b/src/test/test_dir.c @@ -6174,6 +6174,101 @@ 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 +6336,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 };