mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2024-11-28 06:13:31 +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. */
|
* 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
|
/** Return a new networkstatus_t* containing our current opinion. (For v3
|
||||||
* authorities) */
|
* authorities) */
|
||||||
networkstatus_t *
|
networkstatus_t *
|
||||||
@ -4620,7 +4637,7 @@ dirserv_generate_networkstatus_vote_obj(crypto_pk_t *private_key,
|
|||||||
|
|
||||||
v3_out->known_flags = smartlist_new();
|
v3_out->known_flags = smartlist_new();
|
||||||
smartlist_split_string(v3_out->known_flags,
|
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);
|
0, SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0);
|
||||||
if (vote_on_reachability)
|
if (vote_on_reachability)
|
||||||
smartlist_add_strdup(v3_out->known_flags, "Running");
|
smartlist_add_strdup(v3_out->known_flags, "Running");
|
||||||
|
@ -92,6 +92,9 @@
|
|||||||
/** Maximum size of a line in a vote. */
|
/** Maximum size of a line in a vote. */
|
||||||
#define MAX_BW_FILE_HEADERS_LINE_LEN 1024
|
#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.
|
* Public API. Used outside of the dirauth subsystem.
|
||||||
*
|
*
|
||||||
|
@ -95,7 +95,7 @@ real_uptime(const routerinfo_t *router, time_t now)
|
|||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
dirserv_thinks_router_is_unreliable(time_t now,
|
dirserv_thinks_router_is_unreliable(time_t now,
|
||||||
routerinfo_t *router,
|
const routerinfo_t *router,
|
||||||
int need_uptime, int need_capacity)
|
int need_uptime, int need_capacity)
|
||||||
{
|
{
|
||||||
if (need_uptime) {
|
if (need_uptime) {
|
||||||
@ -541,7 +541,7 @@ dirserv_set_router_is_running(routerinfo_t *router, time_t now)
|
|||||||
void
|
void
|
||||||
set_routerstatus_from_routerinfo(routerstatus_t *rs,
|
set_routerstatus_from_routerinfo(routerstatus_t *rs,
|
||||||
node_t *node,
|
node_t *node,
|
||||||
routerinfo_t *ri,
|
const routerinfo_t *ri,
|
||||||
time_t now,
|
time_t now,
|
||||||
int listbadexits)
|
int listbadexits)
|
||||||
{
|
{
|
||||||
@ -593,6 +593,10 @@ set_routerstatus_from_routerinfo(routerstatus_t *rs,
|
|||||||
rs->or_port = ri->or_port;
|
rs->or_port = ri->or_port;
|
||||||
rs->dir_port = ri->dir_port;
|
rs->dir_port = ri->dir_port;
|
||||||
rs->is_v2_dir = ri->supports_tunnelled_dir_requests;
|
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 &&
|
if (options->AuthDirHasIPv6Connectivity == 1 &&
|
||||||
!tor_addr_is_null(&ri->ipv6_addr) &&
|
!tor_addr_is_null(&ri->ipv6_addr) &&
|
||||||
node->last_reachable6 >= now - REACHABLE_TIMEOUT) {
|
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,
|
void set_routerstatus_from_routerinfo(routerstatus_t *rs,
|
||||||
node_t *node,
|
node_t *node,
|
||||||
routerinfo_t *ri, time_t now,
|
const routerinfo_t *ri,
|
||||||
|
time_t now,
|
||||||
int listbadexits);
|
int listbadexits);
|
||||||
|
|
||||||
void dirserv_compute_performance_thresholds(digestmap_t *omit_as_sybil);
|
void dirserv_compute_performance_thresholds(digestmap_t *omit_as_sybil);
|
||||||
|
|
||||||
#ifdef VOTEFLAGS_PRIVATE
|
#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);
|
STATIC void dirserv_set_routerstatus_testing(routerstatus_t *rs);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -434,6 +434,8 @@ routerstatus_parse_entry_from_string(memarea_t *area,
|
|||||||
rs->is_hs_dir = 1;
|
rs->is_hs_dir = 1;
|
||||||
} else if (!strcmp(tok->args[i], "V2Dir")) {
|
} else if (!strcmp(tok->args[i], "V2Dir")) {
|
||||||
rs->is_v2_dir = 1;
|
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
|
/* 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;
|
goto done;
|
||||||
|
|
||||||
smartlist_add_asprintf(chunks,
|
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. */
|
/* These must stay in alphabetical order. */
|
||||||
rs->is_authority?" Authority":"",
|
rs->is_authority?" Authority":"",
|
||||||
rs->is_bad_exit?" BadExit":"",
|
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_hs_dir?" HSDir":"",
|
||||||
rs->is_flagged_running?" Running":"",
|
rs->is_flagged_running?" Running":"",
|
||||||
rs->is_stable?" Stable":"",
|
rs->is_stable?" Stable":"",
|
||||||
|
rs->is_staledesc?" StaleDesc":"",
|
||||||
rs->is_v2_dir?" V2Dir":"",
|
rs->is_v2_dir?" V2Dir":"",
|
||||||
rs->is_valid?" Valid":"");
|
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
|
/** Return the entry in <b>ns</b> for the identity digest <b>digest</b>, or
|
||||||
* NULL if none was found. */
|
* NULL if none was found. */
|
||||||
const routerstatus_t *
|
MOCK_IMPL(const routerstatus_t *,
|
||||||
networkstatus_vote_find_entry(networkstatus_t *ns, const char *digest)
|
networkstatus_vote_find_entry,(networkstatus_t *ns, const char *digest))
|
||||||
{
|
{
|
||||||
return networkstatus_vote_find_mutable_entry(ns, 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);
|
const void **_member);
|
||||||
int compare_digest_to_vote_routerstatus_entry(const void *_key,
|
int compare_digest_to_vote_routerstatus_entry(const void *_key,
|
||||||
const void **_member);
|
const void **_member);
|
||||||
const routerstatus_t *networkstatus_vote_find_entry(networkstatus_t *ns,
|
MOCK_DECL(const routerstatus_t *,networkstatus_vote_find_entry,(
|
||||||
const char *digest);
|
networkstatus_t *ns,
|
||||||
|
const char *digest));
|
||||||
routerstatus_t *networkstatus_vote_find_mutable_entry(networkstatus_t *ns,
|
routerstatus_t *networkstatus_vote_find_mutable_entry(networkstatus_t *ns,
|
||||||
const char *digest);
|
const char *digest);
|
||||||
int networkstatus_vote_find_entry_idx(networkstatus_t *ns,
|
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
|
unsigned int is_v2_dir:1; /** True iff this router publishes an open DirPort
|
||||||
* or it claims to accept tunnelled dir requests.
|
* 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_bandwidth:1; /**< The vote/consensus had bw info */
|
||||||
unsigned int has_exitsummary:1; /**< The vote/consensus had exit summaries */
|
unsigned int has_exitsummary:1; /**< The vote/consensus had exit summaries */
|
||||||
|
@ -59,6 +59,7 @@
|
|||||||
#include "feature/dircommon/dir_connection_st.h"
|
#include "feature/dircommon/dir_connection_st.h"
|
||||||
#include "feature/nodelist/authority_cert_st.h"
|
#include "feature/nodelist/authority_cert_st.h"
|
||||||
#include "feature/nodelist/extrainfo_st.h"
|
#include "feature/nodelist/extrainfo_st.h"
|
||||||
|
#include "feature/nodelist/networkstatus_st.h"
|
||||||
#include "feature/nodelist/node_st.h"
|
#include "feature/nodelist/node_st.h"
|
||||||
#include "feature/nodelist/routerinfo_st.h"
|
#include "feature/nodelist/routerinfo_st.h"
|
||||||
#include "feature/nodelist/routerstatus_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";
|
static const char *desc_gen_reason = "uninitialized reason";
|
||||||
/** Since when has our descriptor been "clean"? 0 if we need to regenerate it
|
/** Since when has our descriptor been "clean"? 0 if we need to regenerate it
|
||||||
* now. */
|
* now. */
|
||||||
static time_t desc_clean_since = 0;
|
STATIC time_t desc_clean_since = 0;
|
||||||
/** Why did we mark the descriptor dirty? */
|
/** 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? */
|
/** Boolean: do we need to regenerate the above? */
|
||||||
static int desc_needs_upload = 0;
|
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
|
/* 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
|
* 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
|
* 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);
|
ns = networkstatus_get_live_consensus(now);
|
||||||
if (ns) {
|
if (ns) {
|
||||||
rs = networkstatus_vote_find_entry(ns, server_identitykey_digest);
|
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";
|
retry_fast_reason = "not listed in consensus";
|
||||||
else if (rs->published_on < slow_cutoff)
|
else if (rs->published_on < slow_cutoff)
|
||||||
retry_fast_reason = "version listed in consensus is quite old";
|
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)
|
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 */
|
/* Used only by router.c and test.c */
|
||||||
STATIC void get_platform_str(char *platform, size_t len);
|
STATIC void get_platform_str(char *platform, size_t len);
|
||||||
STATIC int router_write_fingerprint(int hashed);
|
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
|
||||||
|
|
||||||
#endif /* !defined(TOR_ROUTER_H) */
|
#endif /* !defined(TOR_ROUTER_H) */
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
#define NS_PARSE_PRIVATE
|
#define NS_PARSE_PRIVATE
|
||||||
#define NETWORKSTATUS_PRIVATE
|
#define NETWORKSTATUS_PRIVATE
|
||||||
#include "core/or/or.h"
|
#include "core/or/or.h"
|
||||||
|
#include "feature/dirauth/dirvote.h"
|
||||||
#include "feature/dirparse/ns_parse.h"
|
#include "feature/dirparse/ns_parse.h"
|
||||||
#include "feature/dirparse/unparseable.h"
|
#include "feature/dirparse/unparseable.h"
|
||||||
#include "lib/memarea/memarea.h"
|
#include "lib/memarea/memarea.h"
|
||||||
@ -35,9 +36,12 @@ fuzz_init(void)
|
|||||||
dummy_vote = tor_malloc_zero(sizeof(*dummy_vote));
|
dummy_vote = tor_malloc_zero(sizeof(*dummy_vote));
|
||||||
dummy_vote->known_flags = smartlist_new();
|
dummy_vote->known_flags = smartlist_new();
|
||||||
smartlist_split_string(dummy_vote->known_flags,
|
smartlist_split_string(dummy_vote->known_flags,
|
||||||
"Authority BadExit Exit Fast Guard HSDir "
|
DIRVOTE_UNIVERSAL_FLAGS,
|
||||||
"NoEdConsensus Running Stable V2Dir Valid",
|
|
||||||
" ", 0, 0);
|
" ", 0, 0);
|
||||||
|
smartlist_split_string(dummy_vote->known_flags,
|
||||||
|
DIRVOTE_OPTIONAL_FLAGS,
|
||||||
|
" ", 0, 0);
|
||||||
|
smartlist_sort_strings(dummy_vote->known_flags);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -177,6 +177,7 @@ src_test_test_SOURCES += \
|
|||||||
src/test/test_util.c \
|
src/test/test_util.c \
|
||||||
src/test/test_util_format.c \
|
src/test/test_util_format.c \
|
||||||
src/test/test_util_process.c \
|
src/test/test_util_process.c \
|
||||||
|
src/test/test_voting_flags.c \
|
||||||
src/test/test_voting_schedule.c \
|
src/test/test_voting_schedule.c \
|
||||||
src/test/test_x509.c \
|
src/test/test_x509.c \
|
||||||
src/test/test_helpers.c \
|
src/test/test_helpers.c \
|
||||||
|
@ -866,7 +866,8 @@ struct testgroup_t testgroups[] = {
|
|||||||
{ "crypto/pem/", pem_tests },
|
{ "crypto/pem/", pem_tests },
|
||||||
{ "dir/", dir_tests },
|
{ "dir/", dir_tests },
|
||||||
{ "dir/md/", microdesc_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 },
|
{ "dir_handle_get/", dir_handle_get_tests },
|
||||||
{ "dns/", dns_tests },
|
{ "dns/", dns_tests },
|
||||||
{ "dos/", dos_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_format_tests[];
|
||||||
extern struct testcase_t util_process_tests[];
|
extern struct testcase_t util_process_tests[];
|
||||||
extern struct testcase_t util_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 voting_schedule_tests[];
|
||||||
extern struct testcase_t x509_tests[];
|
extern struct testcase_t x509_tests[];
|
||||||
|
|
||||||
|
@ -6052,6 +6052,80 @@ test_dir_find_dl_min_delay(void* data)
|
|||||||
mock_options = NULL;
|
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
|
static void
|
||||||
test_dir_assumed_flags(void *arg)
|
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, "cfr"),
|
||||||
DIR_ARG(find_dl_min_delay, TT_FORK, "car"),
|
DIR_ARG(find_dl_min_delay, TT_FORK, "car"),
|
||||||
DIR(assumed_flags, 0),
|
DIR(assumed_flags, 0),
|
||||||
|
DIR(matching_flags, 0),
|
||||||
DIR(networkstatus_compute_bw_weights_v10, 0),
|
DIR(networkstatus_compute_bw_weights_v10, 0),
|
||||||
DIR(platform_str, 0),
|
DIR(platform_str, 0),
|
||||||
DIR(networkstatus_consensus_has_ipv6, TT_FORK),
|
DIR(networkstatus_consensus_has_ipv6, TT_FORK),
|
||||||
|
@ -7,12 +7,17 @@
|
|||||||
* \brief Unittests for code in router.c
|
* \brief Unittests for code in router.c
|
||||||
**/
|
**/
|
||||||
|
|
||||||
|
#define ROUTER_PRIVATE
|
||||||
|
|
||||||
#include "core/or/or.h"
|
#include "core/or/or.h"
|
||||||
#include "app/config/config.h"
|
#include "app/config/config.h"
|
||||||
#include "core/mainloop/mainloop.h"
|
#include "core/mainloop/mainloop.h"
|
||||||
#include "feature/hibernate/hibernate.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/routerinfo_st.h"
|
||||||
#include "feature/nodelist/routerlist.h"
|
#include "feature/nodelist/routerlist.h"
|
||||||
|
#include "feature/nodelist/routerstatus_st.h"
|
||||||
#include "feature/relay/router.h"
|
#include "feature/relay/router.h"
|
||||||
#include "feature/stats/rephist.h"
|
#include "feature/stats/rephist.h"
|
||||||
#include "lib/crypt_ops/crypto_curve25519.h"
|
#include "lib/crypt_ops/crypto_curve25519.h"
|
||||||
@ -231,11 +236,104 @@ test_router_check_descriptor_bandwidth_changed(void *arg)
|
|||||||
UNMOCK(we_are_hibernating);
|
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) \
|
#define ROUTER_TEST(name, flags) \
|
||||||
{ #name, test_router_ ## name, flags, NULL, NULL }
|
{ #name, test_router_ ## name, flags, NULL, NULL }
|
||||||
|
|
||||||
struct testcase_t router_tests[] = {
|
struct testcase_t router_tests[] = {
|
||||||
ROUTER_TEST(check_descriptor_bandwidth_changed, TT_FORK),
|
ROUTER_TEST(check_descriptor_bandwidth_changed, TT_FORK),
|
||||||
ROUTER_TEST(dump_router_to_string_no_bridge_distribution_method, 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
|
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