mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2024-11-30 23:53:32 +01:00
Merge branch 'prop293_squashed'
This commit is contained in:
commit
1f95e80351
8
changes/ticket26770
Normal file
8
changes/ticket26770
Normal file
@ -0,0 +1,8 @@
|
||||
o Minor features (directory authority, relay):
|
||||
- Authorities now vote on a "StaleDesc" flag to indicate that a relay's
|
||||
descriptor is so old that the relay should upload again soon. Relays
|
||||
understand this flag, and treat it as a signal to upload a new
|
||||
descriptor. This flag will eventually let us remove the 'published'
|
||||
date from routerstatus entries, and save a great deal of space in our
|
||||
consensus diffs. Closes ticket 26770; implements proposal 293.
|
||||
|
@ -4372,6 +4372,23 @@ clear_status_flags_on_sybil(routerstatus_t *rs)
|
||||
* forget to add it to this clause. */
|
||||
}
|
||||
|
||||
/** Space-separated list of all the flags that we will always vote on. */
|
||||
const char DIRVOTE_UNIVERSAL_FLAGS[] =
|
||||
"Authority "
|
||||
"Exit "
|
||||
"Fast "
|
||||
"Guard "
|
||||
"HSDir "
|
||||
"Stable "
|
||||
"StaleDesc "
|
||||
"V2Dir "
|
||||
"Valid";
|
||||
/** Space-separated list of all flags that we may or may not vote on,
|
||||
* depending on our configuration. */
|
||||
const char DIRVOTE_OPTIONAL_FLAGS[] =
|
||||
"BadExit "
|
||||
"Running";
|
||||
|
||||
/** Return a new networkstatus_t* containing our current opinion. (For v3
|
||||
* authorities) */
|
||||
networkstatus_t *
|
||||
@ -4620,7 +4637,7 @@ dirserv_generate_networkstatus_vote_obj(crypto_pk_t *private_key,
|
||||
|
||||
v3_out->known_flags = smartlist_new();
|
||||
smartlist_split_string(v3_out->known_flags,
|
||||
"Authority Exit Fast Guard Stable V2Dir Valid HSDir",
|
||||
DIRVOTE_UNIVERSAL_FLAGS,
|
||||
0, SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0);
|
||||
if (vote_on_reachability)
|
||||
smartlist_add_strdup(v3_out->known_flags, "Running");
|
||||
|
@ -92,6 +92,9 @@
|
||||
/** Maximum size of a line in a vote. */
|
||||
#define MAX_BW_FILE_HEADERS_LINE_LEN 1024
|
||||
|
||||
extern const char DIRVOTE_UNIVERSAL_FLAGS[];
|
||||
extern const char DIRVOTE_OPTIONAL_FLAGS[];
|
||||
|
||||
/*
|
||||
* Public API. Used outside of the dirauth subsystem.
|
||||
*
|
||||
|
@ -95,7 +95,7 @@ real_uptime(const routerinfo_t *router, time_t now)
|
||||
*/
|
||||
static int
|
||||
dirserv_thinks_router_is_unreliable(time_t now,
|
||||
routerinfo_t *router,
|
||||
const routerinfo_t *router,
|
||||
int need_uptime, int need_capacity)
|
||||
{
|
||||
if (need_uptime) {
|
||||
@ -541,7 +541,7 @@ dirserv_set_router_is_running(routerinfo_t *router, time_t now)
|
||||
void
|
||||
set_routerstatus_from_routerinfo(routerstatus_t *rs,
|
||||
node_t *node,
|
||||
routerinfo_t *ri,
|
||||
const routerinfo_t *ri,
|
||||
time_t now,
|
||||
int listbadexits)
|
||||
{
|
||||
@ -593,6 +593,10 @@ set_routerstatus_from_routerinfo(routerstatus_t *rs,
|
||||
rs->or_port = ri->or_port;
|
||||
rs->dir_port = ri->dir_port;
|
||||
rs->is_v2_dir = ri->supports_tunnelled_dir_requests;
|
||||
|
||||
rs->is_staledesc =
|
||||
(ri->cache_info.published_on + DESC_IS_STALE_INTERVAL) < now;
|
||||
|
||||
if (options->AuthDirHasIPv6Connectivity == 1 &&
|
||||
!tor_addr_is_null(&ri->ipv6_addr) &&
|
||||
node->last_reachable6 >= now - REACHABLE_TIMEOUT) {
|
||||
|
@ -19,12 +19,16 @@ int running_long_enough_to_decide_unreachable(void);
|
||||
|
||||
void set_routerstatus_from_routerinfo(routerstatus_t *rs,
|
||||
node_t *node,
|
||||
routerinfo_t *ri, time_t now,
|
||||
const routerinfo_t *ri,
|
||||
time_t now,
|
||||
int listbadexits);
|
||||
|
||||
void dirserv_compute_performance_thresholds(digestmap_t *omit_as_sybil);
|
||||
|
||||
#ifdef VOTEFLAGS_PRIVATE
|
||||
/** Any descriptor older than this age causes the authorities to set the
|
||||
* StaleDesc flag. */
|
||||
#define DESC_IS_STALE_INTERVAL (18*60*60)
|
||||
STATIC void dirserv_set_routerstatus_testing(routerstatus_t *rs);
|
||||
#endif
|
||||
|
||||
|
@ -434,6 +434,8 @@ routerstatus_parse_entry_from_string(memarea_t *area,
|
||||
rs->is_hs_dir = 1;
|
||||
} else if (!strcmp(tok->args[i], "V2Dir")) {
|
||||
rs->is_v2_dir = 1;
|
||||
} else if (!strcmp(tok->args[i], "StaleDesc")) {
|
||||
rs->is_staledesc = 1;
|
||||
}
|
||||
}
|
||||
/* These are implied true by having been included in a consensus made
|
||||
|
@ -135,7 +135,7 @@ routerstatus_format_entry(const routerstatus_t *rs, const char *version,
|
||||
goto done;
|
||||
|
||||
smartlist_add_asprintf(chunks,
|
||||
"s%s%s%s%s%s%s%s%s%s%s\n",
|
||||
"s%s%s%s%s%s%s%s%s%s%s%s\n",
|
||||
/* These must stay in alphabetical order. */
|
||||
rs->is_authority?" Authority":"",
|
||||
rs->is_bad_exit?" BadExit":"",
|
||||
@ -145,6 +145,7 @@ routerstatus_format_entry(const routerstatus_t *rs, const char *version,
|
||||
rs->is_hs_dir?" HSDir":"",
|
||||
rs->is_flagged_running?" Running":"",
|
||||
rs->is_stable?" Stable":"",
|
||||
rs->is_staledesc?" StaleDesc":"",
|
||||
rs->is_v2_dir?" V2Dir":"",
|
||||
rs->is_valid?" Valid":"");
|
||||
|
||||
|
@ -724,8 +724,8 @@ networkstatus_vote_find_mutable_entry(networkstatus_t *ns, const char *digest)
|
||||
|
||||
/** Return the entry in <b>ns</b> for the identity digest <b>digest</b>, or
|
||||
* NULL if none was found. */
|
||||
const routerstatus_t *
|
||||
networkstatus_vote_find_entry(networkstatus_t *ns, const char *digest)
|
||||
MOCK_IMPL(const routerstatus_t *,
|
||||
networkstatus_vote_find_entry,(networkstatus_t *ns, const char *digest))
|
||||
{
|
||||
return networkstatus_vote_find_mutable_entry(ns, digest);
|
||||
}
|
||||
|
@ -40,8 +40,9 @@ int compare_digest_to_routerstatus_entry(const void *_key,
|
||||
const void **_member);
|
||||
int compare_digest_to_vote_routerstatus_entry(const void *_key,
|
||||
const void **_member);
|
||||
const routerstatus_t *networkstatus_vote_find_entry(networkstatus_t *ns,
|
||||
const char *digest);
|
||||
MOCK_DECL(const routerstatus_t *,networkstatus_vote_find_entry,(
|
||||
networkstatus_t *ns,
|
||||
const char *digest));
|
||||
routerstatus_t *networkstatus_vote_find_mutable_entry(networkstatus_t *ns,
|
||||
const char *digest);
|
||||
int networkstatus_vote_find_entry_idx(networkstatus_t *ns,
|
||||
|
@ -47,6 +47,8 @@ struct routerstatus_t {
|
||||
unsigned int is_v2_dir:1; /** True iff this router publishes an open DirPort
|
||||
* or it claims to accept tunnelled dir requests.
|
||||
*/
|
||||
unsigned int is_staledesc:1; /** True iff the authorities think this router
|
||||
* should upload a new descriptor soon. */
|
||||
|
||||
unsigned int has_bandwidth:1; /**< The vote/consensus had bw info */
|
||||
unsigned int has_exitsummary:1; /**< The vote/consensus had exit summaries */
|
||||
|
@ -59,6 +59,7 @@
|
||||
#include "feature/dircommon/dir_connection_st.h"
|
||||
#include "feature/nodelist/authority_cert_st.h"
|
||||
#include "feature/nodelist/extrainfo_st.h"
|
||||
#include "feature/nodelist/networkstatus_st.h"
|
||||
#include "feature/nodelist/node_st.h"
|
||||
#include "feature/nodelist/routerinfo_st.h"
|
||||
#include "feature/nodelist/routerstatus_st.h"
|
||||
@ -1470,9 +1471,9 @@ static extrainfo_t *desc_extrainfo = NULL;
|
||||
static const char *desc_gen_reason = "uninitialized reason";
|
||||
/** Since when has our descriptor been "clean"? 0 if we need to regenerate it
|
||||
* now. */
|
||||
static time_t desc_clean_since = 0;
|
||||
STATIC time_t desc_clean_since = 0;
|
||||
/** Why did we mark the descriptor dirty? */
|
||||
static const char *desc_dirty_reason = "Tor just started";
|
||||
STATIC const char *desc_dirty_reason = "Tor just started";
|
||||
/** Boolean: do we need to regenerate the above? */
|
||||
static int desc_needs_upload = 0;
|
||||
|
||||
@ -2134,7 +2135,9 @@ mark_my_descriptor_dirty_if_too_old(time_t now)
|
||||
/* Now we see whether we want to be retrying frequently or no. The
|
||||
* rule here is that we'll retry frequently if we aren't listed in the
|
||||
* live consensus we have, or if the publication time of the
|
||||
* descriptor listed for us in the consensus is very old. */
|
||||
* descriptor listed for us in the consensus is very old, or if the
|
||||
* consensus lists us as "stale" and we haven't regenerated since the
|
||||
* consensus was published. */
|
||||
ns = networkstatus_get_live_consensus(now);
|
||||
if (ns) {
|
||||
rs = networkstatus_vote_find_entry(ns, server_identitykey_digest);
|
||||
@ -2142,6 +2145,8 @@ mark_my_descriptor_dirty_if_too_old(time_t now)
|
||||
retry_fast_reason = "not listed in consensus";
|
||||
else if (rs->published_on < slow_cutoff)
|
||||
retry_fast_reason = "version listed in consensus is quite old";
|
||||
else if (rs->is_staledesc && ns->valid_after > desc_clean_since)
|
||||
retry_fast_reason = "listed as stale in consensus";
|
||||
}
|
||||
|
||||
if (retry_fast_reason && desc_clean_since < fast_cutoff)
|
||||
|
@ -117,6 +117,10 @@ void router_free_all(void);
|
||||
/* Used only by router.c and test.c */
|
||||
STATIC void get_platform_str(char *platform, size_t len);
|
||||
STATIC int router_write_fingerprint(int hashed);
|
||||
#ifdef TOR_UNIT_TESTS
|
||||
extern time_t desc_clean_since;
|
||||
extern const char *desc_dirty_reason;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#endif /* !defined(TOR_ROUTER_H) */
|
||||
|
@ -3,6 +3,7 @@
|
||||
#define NS_PARSE_PRIVATE
|
||||
#define NETWORKSTATUS_PRIVATE
|
||||
#include "core/or/or.h"
|
||||
#include "feature/dirauth/dirvote.h"
|
||||
#include "feature/dirparse/ns_parse.h"
|
||||
#include "feature/dirparse/unparseable.h"
|
||||
#include "lib/memarea/memarea.h"
|
||||
@ -35,9 +36,12 @@ fuzz_init(void)
|
||||
dummy_vote = tor_malloc_zero(sizeof(*dummy_vote));
|
||||
dummy_vote->known_flags = smartlist_new();
|
||||
smartlist_split_string(dummy_vote->known_flags,
|
||||
"Authority BadExit Exit Fast Guard HSDir "
|
||||
"NoEdConsensus Running Stable V2Dir Valid",
|
||||
DIRVOTE_UNIVERSAL_FLAGS,
|
||||
" ", 0, 0);
|
||||
smartlist_split_string(dummy_vote->known_flags,
|
||||
DIRVOTE_OPTIONAL_FLAGS,
|
||||
" ", 0, 0);
|
||||
smartlist_sort_strings(dummy_vote->known_flags);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -177,6 +177,7 @@ src_test_test_SOURCES += \
|
||||
src/test/test_util.c \
|
||||
src/test/test_util_format.c \
|
||||
src/test/test_util_process.c \
|
||||
src/test/test_voting_flags.c \
|
||||
src/test/test_voting_schedule.c \
|
||||
src/test/test_x509.c \
|
||||
src/test/test_helpers.c \
|
||||
|
@ -866,7 +866,8 @@ struct testgroup_t testgroups[] = {
|
||||
{ "crypto/pem/", pem_tests },
|
||||
{ "dir/", dir_tests },
|
||||
{ "dir/md/", microdesc_tests },
|
||||
{ "dir/voting-schedule/", voting_schedule_tests },
|
||||
{ "dir/voting/flags/", voting_flags_tests },
|
||||
{ "dir/voting/schedule/", voting_schedule_tests },
|
||||
{ "dir_handle_get/", dir_handle_get_tests },
|
||||
{ "dns/", dns_tests },
|
||||
{ "dos/", dos_tests },
|
||||
|
@ -265,6 +265,7 @@ extern struct testcase_t tortls_tests[];
|
||||
extern struct testcase_t util_format_tests[];
|
||||
extern struct testcase_t util_process_tests[];
|
||||
extern struct testcase_t util_tests[];
|
||||
extern struct testcase_t voting_flags_tests[];
|
||||
extern struct testcase_t voting_schedule_tests[];
|
||||
extern struct testcase_t x509_tests[];
|
||||
|
||||
|
@ -6052,6 +6052,80 @@ test_dir_find_dl_min_delay(void* data)
|
||||
mock_options = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
test_dir_matching_flags(void *arg)
|
||||
{
|
||||
(void) arg;
|
||||
routerstatus_t *rs_noflags = NULL;
|
||||
routerstatus_t *rs = NULL;
|
||||
char *s = NULL;
|
||||
|
||||
smartlist_t *tokens = smartlist_new();
|
||||
memarea_t *area = memarea_new();
|
||||
|
||||
int expected_val_when_unused = 0;
|
||||
|
||||
const char *ex_noflags =
|
||||
"r example hereiswhereyouridentitygoes 2015-08-30 12:00:00 "
|
||||
"192.168.0.1 9001 0\n"
|
||||
"m thisoneislongerbecauseitisa256bitmddigest33\n"
|
||||
"s\n";
|
||||
const char *cp = ex_noflags;
|
||||
rs_noflags = routerstatus_parse_entry_from_string(
|
||||
area, &cp,
|
||||
cp + strlen(cp),
|
||||
tokens, NULL, NULL,
|
||||
MAX_SUPPORTED_CONSENSUS_METHOD, FLAV_MICRODESC);
|
||||
tt_assert(rs_noflags);
|
||||
|
||||
#define FLAG(string, field) STMT_BEGIN { \
|
||||
tor_asprintf(&s,\
|
||||
"r example hereiswhereyouridentitygoes 2015-08-30 12:00:00 " \
|
||||
"192.168.0.1 9001 0\n" \
|
||||
"m thisoneislongerbecauseitisa256bitmddigest33\n" \
|
||||
"s %s\n", string); \
|
||||
cp = s; \
|
||||
rs = routerstatus_parse_entry_from_string( \
|
||||
area, &cp, \
|
||||
cp + strlen(cp), \
|
||||
tokens, NULL, NULL, \
|
||||
MAX_SUPPORTED_CONSENSUS_METHOD, FLAV_MICRODESC); \
|
||||
/* the field should usually be 0 when no flags are listed */ \
|
||||
tt_int_op(rs_noflags->field, OP_EQ, expected_val_when_unused); \
|
||||
/* the field should be 1 when this flags islisted */ \
|
||||
tt_int_op(rs->field, OP_EQ, 1); \
|
||||
tor_free(s); \
|
||||
routerstatus_free(rs); \
|
||||
} STMT_END
|
||||
|
||||
FLAG("Authority", is_authority);
|
||||
FLAG("BadExit", is_bad_exit);
|
||||
FLAG("Exit", is_exit);
|
||||
FLAG("Fast", is_fast);
|
||||
FLAG("Guard", is_possible_guard);
|
||||
FLAG("HSDir", is_hs_dir);
|
||||
FLAG("Stable", is_stable);
|
||||
FLAG("StaleDesc", is_staledesc);
|
||||
FLAG("V2Dir", is_v2_dir);
|
||||
|
||||
// These flags are assumed to be set whether they're declared or not.
|
||||
expected_val_when_unused = 1;
|
||||
FLAG("Running", is_flagged_running);
|
||||
FLAG("Valid", is_valid);
|
||||
expected_val_when_unused = 0;
|
||||
|
||||
// These flags are no longer used, but still parsed.
|
||||
FLAG("Named", is_named);
|
||||
FLAG("Unnamed", is_unnamed);
|
||||
|
||||
done:
|
||||
tor_free(s);
|
||||
routerstatus_free(rs);
|
||||
routerstatus_free(rs_noflags);
|
||||
memarea_drop_all(area);
|
||||
smartlist_free(tokens);
|
||||
}
|
||||
|
||||
static void
|
||||
test_dir_assumed_flags(void *arg)
|
||||
{
|
||||
@ -6377,6 +6451,7 @@ struct testcase_t dir_tests[] = {
|
||||
DIR_ARG(find_dl_min_delay, TT_FORK, "cfr"),
|
||||
DIR_ARG(find_dl_min_delay, TT_FORK, "car"),
|
||||
DIR(assumed_flags, 0),
|
||||
DIR(matching_flags, 0),
|
||||
DIR(networkstatus_compute_bw_weights_v10, 0),
|
||||
DIR(platform_str, 0),
|
||||
DIR(networkstatus_consensus_has_ipv6, TT_FORK),
|
||||
|
@ -7,12 +7,17 @@
|
||||
* \brief Unittests for code in router.c
|
||||
**/
|
||||
|
||||
#define ROUTER_PRIVATE
|
||||
|
||||
#include "core/or/or.h"
|
||||
#include "app/config/config.h"
|
||||
#include "core/mainloop/mainloop.h"
|
||||
#include "feature/hibernate/hibernate.h"
|
||||
#include "feature/nodelist/networkstatus.h"
|
||||
#include "feature/nodelist/networkstatus_st.h"
|
||||
#include "feature/nodelist/routerinfo_st.h"
|
||||
#include "feature/nodelist/routerlist.h"
|
||||
#include "feature/nodelist/routerstatus_st.h"
|
||||
#include "feature/relay/router.h"
|
||||
#include "feature/stats/rephist.h"
|
||||
#include "lib/crypt_ops/crypto_curve25519.h"
|
||||
@ -231,11 +236,104 @@ test_router_check_descriptor_bandwidth_changed(void *arg)
|
||||
UNMOCK(we_are_hibernating);
|
||||
}
|
||||
|
||||
static networkstatus_t *mock_ns = NULL;
|
||||
static networkstatus_t *
|
||||
mock_networkstatus_get_live_consensus(time_t now)
|
||||
{
|
||||
(void)now;
|
||||
return mock_ns;
|
||||
}
|
||||
|
||||
static routerstatus_t *mock_rs = NULL;
|
||||
static const routerstatus_t *
|
||||
mock_networkstatus_vote_find_entry(networkstatus_t *ns, const char *digest)
|
||||
{
|
||||
(void)ns;
|
||||
(void)digest;
|
||||
return mock_rs;
|
||||
}
|
||||
|
||||
static void
|
||||
test_router_mark_if_too_old(void *arg)
|
||||
{
|
||||
(void)arg;
|
||||
time_t now = approx_time();
|
||||
MOCK(networkstatus_get_live_consensus,
|
||||
mock_networkstatus_get_live_consensus);
|
||||
MOCK(networkstatus_vote_find_entry, mock_networkstatus_vote_find_entry);
|
||||
|
||||
routerstatus_t rs;
|
||||
networkstatus_t ns;
|
||||
memset(&rs, 0, sizeof(rs));
|
||||
memset(&ns, 0, sizeof(ns));
|
||||
mock_ns = &ns;
|
||||
mock_ns->valid_after = now-3600;
|
||||
mock_rs = &rs;
|
||||
mock_rs->published_on = now - 10;
|
||||
|
||||
// no reason to mark this time.
|
||||
desc_clean_since = now-10;
|
||||
desc_dirty_reason = NULL;
|
||||
mark_my_descriptor_dirty_if_too_old(now);
|
||||
tt_i64_op(desc_clean_since, OP_EQ, now-10);
|
||||
|
||||
// Doesn't appear in consensus? Still don't mark it.
|
||||
mock_ns = NULL;
|
||||
mark_my_descriptor_dirty_if_too_old(now);
|
||||
tt_i64_op(desc_clean_since, OP_EQ, now-10);
|
||||
mock_ns = &ns;
|
||||
|
||||
// No new descriptor in a long time? Mark it.
|
||||
desc_clean_since = now - 3600 * 96;
|
||||
mark_my_descriptor_dirty_if_too_old(now);
|
||||
tt_i64_op(desc_clean_since, OP_EQ, 0);
|
||||
tt_str_op(desc_dirty_reason, OP_EQ, "time for new descriptor");
|
||||
|
||||
// Version in consensus published a long time ago? We won't mark it
|
||||
// if it's been clean for only a short time.
|
||||
desc_clean_since = now - 10;
|
||||
desc_dirty_reason = NULL;
|
||||
mock_rs->published_on = now - 3600 * 96;
|
||||
mark_my_descriptor_dirty_if_too_old(now);
|
||||
tt_i64_op(desc_clean_since, OP_EQ, now - 10);
|
||||
|
||||
// ... but if it's been clean a while, we mark.
|
||||
desc_clean_since = now - 2 * 3600;
|
||||
mark_my_descriptor_dirty_if_too_old(now);
|
||||
tt_i64_op(desc_clean_since, OP_EQ, 0);
|
||||
tt_str_op(desc_dirty_reason, OP_EQ,
|
||||
"version listed in consensus is quite old");
|
||||
|
||||
// same deal if we're marked stale.
|
||||
desc_clean_since = now - 2 * 3600;
|
||||
desc_dirty_reason = NULL;
|
||||
mock_rs->published_on = now - 10;
|
||||
mock_rs->is_staledesc = 1;
|
||||
mark_my_descriptor_dirty_if_too_old(now);
|
||||
tt_i64_op(desc_clean_since, OP_EQ, 0);
|
||||
tt_str_op(desc_dirty_reason, OP_EQ,
|
||||
"listed as stale in consensus");
|
||||
|
||||
// same deal if we're absent from the consensus.
|
||||
desc_clean_since = now - 2 * 3600;
|
||||
desc_dirty_reason = NULL;
|
||||
mock_rs = NULL;
|
||||
mark_my_descriptor_dirty_if_too_old(now);
|
||||
tt_i64_op(desc_clean_since, OP_EQ, 0);
|
||||
tt_str_op(desc_dirty_reason, OP_EQ,
|
||||
"not listed in consensus");
|
||||
|
||||
done:
|
||||
UNMOCK(networkstatus_get_live_consensus);
|
||||
UNMOCK(networkstatus_vote_find_entry);
|
||||
}
|
||||
|
||||
#define ROUTER_TEST(name, flags) \
|
||||
{ #name, test_router_ ## name, flags, NULL, NULL }
|
||||
|
||||
struct testcase_t router_tests[] = {
|
||||
ROUTER_TEST(check_descriptor_bandwidth_changed, TT_FORK),
|
||||
ROUTER_TEST(dump_router_to_string_no_bridge_distribution_method, TT_FORK),
|
||||
ROUTER_TEST(mark_if_too_old, TT_FORK),
|
||||
END_OF_TESTCASES
|
||||
};
|
||||
|
192
src/test/test_voting_flags.c
Normal file
192
src/test/test_voting_flags.c
Normal file
@ -0,0 +1,192 @@
|
||||
/* Copyright (c) 2018, The Tor Project, Inc. */
|
||||
/* See LICENSE for licensing information */
|
||||
|
||||
#include "orconfig.h"
|
||||
|
||||
#define VOTEFLAGS_PRIVATE
|
||||
|
||||
#include "core/or/or.h"
|
||||
|
||||
#include "feature/dirauth/voteflags.h"
|
||||
#include "feature/nodelist/node_st.h"
|
||||
#include "feature/nodelist/routerstatus_st.h"
|
||||
#include "feature/nodelist/routerinfo_st.h"
|
||||
|
||||
#include "app/config/config.h"
|
||||
|
||||
#include "test/test.h"
|
||||
|
||||
typedef struct {
|
||||
time_t now;
|
||||
routerinfo_t ri;
|
||||
node_t node;
|
||||
|
||||
routerstatus_t expected;
|
||||
} flag_vote_test_cfg_t;
|
||||
|
||||
static void
|
||||
setup_cfg(flag_vote_test_cfg_t *c)
|
||||
{
|
||||
memset(c, 0, sizeof(*c));
|
||||
|
||||
c->now = approx_time();
|
||||
|
||||
c->ri.nickname = (char *) "testing100";
|
||||
strlcpy(c->expected.nickname, "testing100", sizeof(c->expected.nickname));
|
||||
|
||||
memset(c->ri.cache_info.identity_digest, 0xff, DIGEST_LEN);
|
||||
memset(c->ri.cache_info.signed_descriptor_digest, 0xee, DIGEST256_LEN);
|
||||
|
||||
c->ri.cache_info.published_on = c->now - 100;
|
||||
c->expected.published_on = c->now - 100;
|
||||
|
||||
c->ri.addr = 0x7f010105;
|
||||
c->expected.addr = 0x7f010105;
|
||||
c->ri.or_port = 9090;
|
||||
c->expected.or_port = 9090;
|
||||
|
||||
tor_addr_make_null(&c->ri.ipv6_addr, AF_INET6);
|
||||
tor_addr_make_null(&c->expected.ipv6_addr, AF_INET6);
|
||||
|
||||
// By default we have no loaded information about stability or speed,
|
||||
// so we'll default to voting "yeah sure." on these two.
|
||||
c->expected.is_fast = 1;
|
||||
c->expected.is_stable = 1;
|
||||
}
|
||||
|
||||
static bool
|
||||
check_result(flag_vote_test_cfg_t *c)
|
||||
{
|
||||
bool result = false;
|
||||
routerstatus_t rs;
|
||||
memset(&rs, 0, sizeof(rs));
|
||||
set_routerstatus_from_routerinfo(&rs, &c->node, &c->ri, c->now, 0);
|
||||
|
||||
tt_i64_op(rs.published_on, OP_EQ, c->expected.published_on);
|
||||
tt_str_op(rs.nickname, OP_EQ, c->expected.nickname);
|
||||
|
||||
// identity_digest and descriptor_digest are not set here.
|
||||
|
||||
tt_uint_op(rs.addr, OP_EQ, c->expected.addr);
|
||||
tt_uint_op(rs.or_port, OP_EQ, c->expected.or_port);
|
||||
tt_uint_op(rs.dir_port, OP_EQ, c->expected.dir_port);
|
||||
|
||||
tt_assert(tor_addr_eq(&rs.ipv6_addr, &c->expected.ipv6_addr));
|
||||
tt_uint_op(rs.ipv6_orport, OP_EQ, c->expected.ipv6_orport);
|
||||
|
||||
#define FLAG(flagname) \
|
||||
tt_uint_op(rs.flagname, OP_EQ, c->expected.flagname)
|
||||
|
||||
FLAG(is_authority);
|
||||
FLAG(is_exit);
|
||||
FLAG(is_stable);
|
||||
FLAG(is_fast);
|
||||
FLAG(is_flagged_running);
|
||||
FLAG(is_named);
|
||||
FLAG(is_unnamed);
|
||||
FLAG(is_valid);
|
||||
FLAG(is_possible_guard);
|
||||
FLAG(is_bad_exit);
|
||||
FLAG(is_hs_dir);
|
||||
FLAG(is_v2_dir);
|
||||
FLAG(is_staledesc);
|
||||
FLAG(has_bandwidth);
|
||||
FLAG(has_exitsummary);
|
||||
FLAG(bw_is_unmeasured);
|
||||
|
||||
result = true;
|
||||
|
||||
done:
|
||||
return result;
|
||||
}
|
||||
|
||||
static void
|
||||
test_voting_flags_minimal(void *arg)
|
||||
{
|
||||
flag_vote_test_cfg_t *cfg = arg;
|
||||
check_result(cfg);
|
||||
}
|
||||
|
||||
static void
|
||||
test_voting_flags_ipv6(void *arg)
|
||||
{
|
||||
flag_vote_test_cfg_t *cfg = arg;
|
||||
|
||||
tt_assert(tor_addr_parse(&cfg->ri.ipv6_addr, "f00::b42") == AF_INET6);
|
||||
cfg->ri.ipv6_orport = 9091;
|
||||
// no change in expected results, since we aren't set up with ipv6
|
||||
// connectivity.
|
||||
if (!check_result(cfg))
|
||||
goto done;
|
||||
|
||||
get_options_mutable()->AuthDirHasIPv6Connectivity = 1;
|
||||
// no change in expected results, since last_reachable6 won't be set.
|
||||
if (!check_result(cfg))
|
||||
goto done;
|
||||
|
||||
cfg->node.last_reachable6 = cfg->now - 10;
|
||||
// now that lastreachable6 is set, we expect to see the result.
|
||||
tt_assert(tor_addr_parse(&cfg->expected.ipv6_addr, "f00::b42") == AF_INET6);
|
||||
cfg->expected.ipv6_orport = 9091;
|
||||
if (!check_result(cfg))
|
||||
goto done;
|
||||
done:
|
||||
;
|
||||
}
|
||||
|
||||
static void
|
||||
test_voting_flags_staledesc(void *arg)
|
||||
{
|
||||
flag_vote_test_cfg_t *cfg = arg;
|
||||
time_t now = cfg->now;
|
||||
|
||||
cfg->ri.cache_info.published_on = now - DESC_IS_STALE_INTERVAL + 10;
|
||||
cfg->expected.published_on = now - DESC_IS_STALE_INTERVAL + 10;
|
||||
// no change in expectations for is_staledesc
|
||||
if (!check_result(cfg))
|
||||
goto done;
|
||||
|
||||
cfg->ri.cache_info.published_on = now - DESC_IS_STALE_INTERVAL - 10;
|
||||
cfg->expected.published_on = now - DESC_IS_STALE_INTERVAL - 10;
|
||||
cfg->expected.is_staledesc = 1;
|
||||
if (!check_result(cfg))
|
||||
goto done;
|
||||
|
||||
done:
|
||||
;
|
||||
}
|
||||
|
||||
static void *
|
||||
setup_voting_flags_test(const struct testcase_t *testcase)
|
||||
{
|
||||
(void)testcase;
|
||||
flag_vote_test_cfg_t *cfg = tor_malloc_zero(sizeof(*cfg));
|
||||
setup_cfg(cfg);
|
||||
return cfg;
|
||||
}
|
||||
|
||||
static int
|
||||
teardown_voting_flags_test(const struct testcase_t *testcase, void *arg)
|
||||
{
|
||||
(void)testcase;
|
||||
flag_vote_test_cfg_t *cfg = arg;
|
||||
tor_free(cfg);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static const struct testcase_setup_t voting_flags_setup = {
|
||||
.setup_fn = setup_voting_flags_test,
|
||||
.cleanup_fn = teardown_voting_flags_test,
|
||||
};
|
||||
|
||||
#define T(name,flags) \
|
||||
{ #name, test_voting_flags_##name, (flags), &voting_flags_setup, NULL }
|
||||
|
||||
struct testcase_t voting_flags_tests[] = {
|
||||
T(minimal, 0),
|
||||
T(ipv6, TT_FORK),
|
||||
// TODO: Add more of these tests.
|
||||
T(staledesc, TT_FORK),
|
||||
END_OF_TESTCASES
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user