Merge remote-tracking branch 'andrea/ticket19858_v2'

Conflict in entrynodes.c: any_bridge_supports_microdescriptors was
removed in master, and modified in 19858_v2
This commit is contained in:
Nick Mathewson 2016-10-19 17:11:47 -04:00
commit 12cf73c451
8 changed files with 556 additions and 197 deletions

4
changes/ticket19858 Normal file
View File

@ -0,0 +1,4 @@
o Features (guards):
- Abolish all global guard context in entrynodes.c; replace with new
guard_selection_t structure as preparation for prop. 271. Closes
ticket 19858.

View File

@ -2235,7 +2235,6 @@ choose_good_entry_server(uint8_t purpose, cpath_build_state_t *state)
* This is an incomplete fix, but is no worse than the previous behaviour, * This is an incomplete fix, but is no worse than the previous behaviour,
* and only applies to minimal, testing tor networks * and only applies to minimal, testing tor networks
* (so it's no less secure) */ * (so it's no less secure) */
/*XXXX++ use the using_as_guard flag to accomplish this.*/
if (options->UseEntryGuards if (options->UseEntryGuards
&& (!options->TestingTorNetwork || && (!options->TestingTorNetwork ||
smartlist_len(nodelist_get_list()) > smartlist_len(get_entry_guards()) smartlist_len(nodelist_get_list()) > smartlist_len(get_entry_guards())

File diff suppressed because it is too large Load Diff

View File

@ -16,6 +16,9 @@
/* XXXX NM I would prefer that all of this stuff be private to /* XXXX NM I would prefer that all of this stuff be private to
* entrynodes.c. */ * entrynodes.c. */
/* Forward declare for guard_selection_t; entrynodes.c has the real struct */
typedef struct guard_selection_s guard_selection_t;
/** An entry_guard_t represents our information about a chosen long-term /** An entry_guard_t represents our information about a chosen long-term
* first hop, known as a "helper" node in the literature. We can't just * first hop, known as a "helper" node in the literature. We can't just
* use a node_t, since we want to remember these even when we * use a node_t, since we want to remember these even when we
@ -70,18 +73,27 @@ typedef struct entry_guard_t {
* this guard as first hop. */ * this guard as first hop. */
} entry_guard_t; } entry_guard_t;
entry_guard_t *entry_guard_get_by_id_digest_for_guard_selection(
guard_selection_t *gs, const char *digest);
entry_guard_t *entry_guard_get_by_id_digest(const char *digest); entry_guard_t *entry_guard_get_by_id_digest(const char *digest);
void entry_guards_changed_for_guard_selection(guard_selection_t *gs);
void entry_guards_changed(void); void entry_guards_changed(void);
guard_selection_t * get_guard_selection_info(void);
const smartlist_t *get_entry_guards_for_guard_selection(
guard_selection_t *gs);
const smartlist_t *get_entry_guards(void); const smartlist_t *get_entry_guards(void);
int num_live_entry_guards_for_guard_selection(
guard_selection_t *gs,
int for_directory);
int num_live_entry_guards(int for_directory); int num_live_entry_guards(int for_directory);
#endif #endif
#ifdef ENTRYNODES_PRIVATE #ifdef ENTRYNODES_PRIVATE
STATIC const node_t *add_an_entry_guard(const node_t *chosen, STATIC const node_t *add_an_entry_guard(guard_selection_t *gs,
const node_t *chosen,
int reset_status, int prepend, int reset_status, int prepend,
int for_discovery, int for_directory); int for_discovery, int for_directory);
STATIC int populate_live_entry_guards(smartlist_t *live_entry_guards, STATIC int populate_live_entry_guards(smartlist_t *live_entry_guards,
const smartlist_t *all_entry_guards, const smartlist_t *all_entry_guards,
const node_t *chosen_exit, const node_t *chosen_exit,
@ -90,7 +102,8 @@ STATIC int populate_live_entry_guards(smartlist_t *live_entry_guards,
int need_uptime, int need_capacity); int need_uptime, int need_capacity);
STATIC int decide_num_guards(const or_options_t *options, int for_directory); STATIC int decide_num_guards(const or_options_t *options, int for_directory);
STATIC void entry_guards_set_from_config(const or_options_t *options); STATIC void entry_guards_set_from_config(guard_selection_t *gs,
const or_options_t *options);
/** Flags to be passed to entry_is_live() to indicate what kind of /** Flags to be passed to entry_is_live() to indicate what kind of
* entry nodes we are looking for. */ * entry nodes we are looking for. */
@ -109,20 +122,32 @@ STATIC int entry_is_time_to_retry(const entry_guard_t *e, time_t now);
#endif #endif
void remove_all_entry_guards_for_guard_selection(guard_selection_t *gs);
void remove_all_entry_guards(void); void remove_all_entry_guards(void);
void entry_guards_compute_status_for_guard_selection(
guard_selection_t *gs, const or_options_t *options, time_t now);
void entry_guards_compute_status(const or_options_t *options, time_t now); void entry_guards_compute_status(const or_options_t *options, time_t now);
int entry_guard_register_connect_status_for_guard_selection(
guard_selection_t *gs, const char *digest, int succeeded,
int mark_relay_status, time_t now);
int entry_guard_register_connect_status(const char *digest, int succeeded, int entry_guard_register_connect_status(const char *digest, int succeeded,
int mark_relay_status, time_t now); int mark_relay_status, time_t now);
void entry_nodes_should_be_added_for_guard_selection(guard_selection_t *gs);
void entry_nodes_should_be_added(void); void entry_nodes_should_be_added(void);
int entry_list_is_constrained(const or_options_t *options); int entry_list_is_constrained(const or_options_t *options);
const node_t *choose_random_entry(cpath_build_state_t *state); const node_t *choose_random_entry(cpath_build_state_t *state);
const node_t *choose_random_dirguard(dirinfo_type_t t); const node_t *choose_random_dirguard(dirinfo_type_t t);
int entry_guards_parse_state_for_guard_selection(
guard_selection_t *gs, or_state_t *state, int set, char **msg);
int entry_guards_parse_state(or_state_t *state, int set, char **msg); int entry_guards_parse_state(or_state_t *state, int set, char **msg);
void entry_guards_update_state(or_state_t *state); void entry_guards_update_state(or_state_t *state);
int getinfo_helper_entry_guards(control_connection_t *conn, int getinfo_helper_entry_guards(control_connection_t *conn,
const char *question, char **answer, const char *question, char **answer,
const char **errmsg); const char **errmsg);
int is_node_used_as_guard_for_guard_selection(guard_selection_t *gs,
const node_t *node);
MOCK_DECL(int, is_node_used_as_guard, (const node_t *node));
void mark_bridge_list(void); void mark_bridge_list(void);
void sweep_bridge_list(void); void sweep_bridge_list(void);

View File

@ -2365,9 +2365,6 @@ typedef struct node_t {
/** Local info: we treat this node as if it rejects everything */ /** Local info: we treat this node as if it rejects everything */
unsigned int rejects_all:1; unsigned int rejects_all:1;
/** Local info: this node is in our list of guards */
unsigned int using_as_guard:1;
/* Local info: derived. */ /* Local info: derived. */
/** True if the IPv6 OR port is preferred over the IPv4 OR port. /** True if the IPv6 OR port is preferred over the IPv4 OR port.

View File

@ -2037,9 +2037,9 @@ router_pick_directory_server_impl(dirinfo_type_t type, int flags,
!router_supports_extrainfo(node->identity, is_trusted_extrainfo)) !router_supports_extrainfo(node->identity, is_trusted_extrainfo))
continue; continue;
/* Don't make the same node a guard twice */ /* Don't make the same node a guard twice */
if (for_guard && node->using_as_guard) { if (for_guard && is_node_used_as_guard(node)) {
continue; continue;
} }
/* Ensure that a directory guard is actually a guard node. */ /* Ensure that a directory guard is actually a guard node. */
if (for_guard && !node->is_possible_guard) { if (for_guard && !node->is_possible_guard) {
continue; continue;

View File

@ -254,7 +254,9 @@ populate_live_entry_guards_test_helper(int num_needed)
{ {
smartlist_t *our_nodelist = NULL; smartlist_t *our_nodelist = NULL;
smartlist_t *live_entry_guards = smartlist_new(); smartlist_t *live_entry_guards = smartlist_new();
const smartlist_t *all_entry_guards = get_entry_guards(); guard_selection_t *gs = get_guard_selection_info();
const smartlist_t *all_entry_guards =
get_entry_guards_for_guard_selection(gs);
or_options_t *options = get_options_mutable(); or_options_t *options = get_options_mutable();
int retval; int retval;
@ -271,7 +273,7 @@ populate_live_entry_guards_test_helper(int num_needed)
SMARTLIST_FOREACH_BEGIN(our_nodelist, const node_t *, node) { SMARTLIST_FOREACH_BEGIN(our_nodelist, const node_t *, node) {
const node_t *node_tmp; const node_t *node_tmp;
node_tmp = add_an_entry_guard(node, 0, 1, 0, 0); node_tmp = add_an_entry_guard(gs, node, 0, 1, 0, 0);
tt_assert(node_tmp); tt_assert(node_tmp);
} SMARTLIST_FOREACH_END(node); } SMARTLIST_FOREACH_END(node);
@ -582,7 +584,9 @@ static void
test_entry_guards_set_from_config(void *arg) test_entry_guards_set_from_config(void *arg)
{ {
or_options_t *options = get_options_mutable(); or_options_t *options = get_options_mutable();
const smartlist_t *all_entry_guards = get_entry_guards(); guard_selection_t *gs = get_guard_selection_info();
const smartlist_t *all_entry_guards =
get_entry_guards_for_guard_selection(gs);
const char *entrynodes_str = "test003r"; const char *entrynodes_str = "test003r";
const node_t *chosen_entry = NULL; const node_t *chosen_entry = NULL;
int retval; int retval;
@ -597,7 +601,7 @@ test_entry_guards_set_from_config(void *arg)
tt_int_op(retval, OP_GE, 0); tt_int_op(retval, OP_GE, 0);
/* Read nodes from EntryNodes */ /* Read nodes from EntryNodes */
entry_guards_set_from_config(options); entry_guards_set_from_config(gs, options);
/* Test that only one guard was added. */ /* Test that only one guard was added. */
tt_int_op(smartlist_len(all_entry_guards), OP_EQ, 1); tt_int_op(smartlist_len(all_entry_guards), OP_EQ, 1);
@ -689,7 +693,9 @@ static void
test_entry_is_live(void *arg) test_entry_is_live(void *arg)
{ {
smartlist_t *our_nodelist = NULL; smartlist_t *our_nodelist = NULL;
const smartlist_t *all_entry_guards = get_entry_guards(); guard_selection_t *gs = get_guard_selection_info();
const smartlist_t *all_entry_guards =
get_entry_guards_for_guard_selection(gs);
const node_t *test_node = NULL; const node_t *test_node = NULL;
const entry_guard_t *test_entry = NULL; const entry_guard_t *test_entry = NULL;
const char *msg; const char *msg;
@ -706,7 +712,7 @@ test_entry_is_live(void *arg)
SMARTLIST_FOREACH_BEGIN(our_nodelist, const node_t *, node) { SMARTLIST_FOREACH_BEGIN(our_nodelist, const node_t *, node) {
const node_t *node_tmp; const node_t *node_tmp;
node_tmp = add_an_entry_guard(node, 0, 1, 0, 0); node_tmp = add_an_entry_guard(gs, node, 0, 1, 0, 0);
tt_assert(node_tmp); tt_assert(node_tmp);
tt_int_op(node->is_stable, OP_EQ, 0); tt_int_op(node->is_stable, OP_EQ, 0);

View File

@ -15,6 +15,7 @@
#include "container.h" #include "container.h"
#include "directory.h" #include "directory.h"
#include "dirvote.h" #include "dirvote.h"
#include "entrynodes.h"
#include "microdesc.h" #include "microdesc.h"
#include "networkstatus.h" #include "networkstatus.h"
#include "nodelist.h" #include "nodelist.h"
@ -203,6 +204,53 @@ mock_usable_consensus_flavor(void)
return mock_usable_consensus_flavor_value; return mock_usable_consensus_flavor_value;
} }
static smartlist_t *mock_is_guard_list = NULL;
static int
mock_is_node_used_as_guard(node_t *n)
{
if (mock_is_guard_list) {
SMARTLIST_FOREACH_BEGIN(mock_is_guard_list, node_t *, e) {
if (e == n) return 1;
} SMARTLIST_FOREACH_END(e);
}
return 0;
}
static void
mark_node_used_as_guard(node_t *n)
{
if (!n) return;
if (!mock_is_guard_list) {
mock_is_guard_list = smartlist_new();
}
if (!mock_is_node_used_as_guard(n)) {
smartlist_add(mock_is_guard_list, n);
}
}
static void
mark_node_unused_as_guard(node_t *n)
{
if (!n) return;
if (!mock_is_guard_list) return;
smartlist_remove(mock_is_guard_list, n);
}
static void
clear_mock_guard_list(void)
{
if (mock_is_guard_list) {
smartlist_free(mock_is_guard_list);
mock_is_guard_list = NULL;
}
}
static void static void
test_router_pick_directory_server_impl(void *arg) test_router_pick_directory_server_impl(void *arg)
{ {
@ -223,6 +271,7 @@ test_router_pick_directory_server_impl(void *arg)
(void)arg; (void)arg;
MOCK(usable_consensus_flavor, mock_usable_consensus_flavor); MOCK(usable_consensus_flavor, mock_usable_consensus_flavor);
MOCK(is_node_used_as_guard, mock_is_node_used_as_guard);
/* With no consensus, we must be bootstrapping, regardless of time or flavor /* With no consensus, we must be bootstrapping, regardless of time or flavor
*/ */
@ -336,28 +385,28 @@ test_router_pick_directory_server_impl(void *arg)
node_router3->is_valid = 1; node_router3->is_valid = 1;
flags |= PDS_FOR_GUARD; flags |= PDS_FOR_GUARD;
node_router1->using_as_guard = 1; mark_node_used_as_guard(node_router1);
node_router2->using_as_guard = 1; mark_node_used_as_guard(node_router2);
node_router3->using_as_guard = 1; mark_node_used_as_guard(node_router3);
rs = router_pick_directory_server_impl(V3_DIRINFO, flags, NULL); rs = router_pick_directory_server_impl(V3_DIRINFO, flags, NULL);
tt_assert(rs == NULL); tt_assert(rs == NULL);
node_router1->using_as_guard = 0; mark_node_unused_as_guard(node_router1);
rs = router_pick_directory_server_impl(V3_DIRINFO, flags, NULL); rs = router_pick_directory_server_impl(V3_DIRINFO, flags, NULL);
tt_assert(rs != NULL); tt_assert(rs != NULL);
tt_assert(tor_memeq(rs->identity_digest, router1_id, DIGEST_LEN)); tt_assert(tor_memeq(rs->identity_digest, router1_id, DIGEST_LEN));
rs = NULL; rs = NULL;
node_router2->using_as_guard = 0; mark_node_unused_as_guard(node_router2);
node_router3->using_as_guard = 0; mark_node_unused_as_guard(node_router3);
/* One not valid, one guard. This should leave one remaining */ /* One not valid, one guard. This should leave one remaining */
node_router1->is_valid = 0; node_router1->is_valid = 0;
node_router2->using_as_guard = 1; mark_node_used_as_guard(node_router2);
rs = router_pick_directory_server_impl(V3_DIRINFO, flags, NULL); rs = router_pick_directory_server_impl(V3_DIRINFO, flags, NULL);
tt_assert(rs != NULL); tt_assert(rs != NULL);
tt_assert(tor_memeq(rs->identity_digest, router3_id, DIGEST_LEN)); tt_assert(tor_memeq(rs->identity_digest, router3_id, DIGEST_LEN));
rs = NULL; rs = NULL;
node_router1->is_valid = 1; node_router1->is_valid = 1;
node_router2->using_as_guard = 0; mark_node_unused_as_guard(node_router2);
/* Manipulate overloaded */ /* Manipulate overloaded */
@ -420,6 +469,9 @@ test_router_pick_directory_server_impl(void *arg)
done: done:
UNMOCK(usable_consensus_flavor); UNMOCK(usable_consensus_flavor);
UNMOCK(is_node_used_as_guard);
clear_mock_guard_list();
if (router1_id) if (router1_id)
tor_free(router1_id); tor_free(router1_id);
if (router2_id) if (router2_id)