diff options
Diffstat (limited to 'src/or/entrynodes.c')
-rw-r--r-- | src/or/entrynodes.c | 132 |
1 files changed, 115 insertions, 17 deletions
diff --git a/src/or/entrynodes.c b/src/or/entrynodes.c index 76a8f591b9..cbdb36aa43 100644 --- a/src/or/entrynodes.c +++ b/src/or/entrynodes.c @@ -740,7 +740,8 @@ node_is_possible_guard(const node_t *node) node->is_stable && node->is_fast && node->is_valid && - node_is_dir(node)); + node_is_dir(node) && + !router_digest_is_me(node->identity)); } /** @@ -966,7 +967,7 @@ entry_guard_learned_bridge_identity(const tor_addr_port_t *addrport, * violate it. */ STATIC int -num_reachable_filtered_guards(guard_selection_t *gs, +num_reachable_filtered_guards(const guard_selection_t *gs, const entry_guard_restriction_t *rst) { int n_reachable_filtered_guards = 0; @@ -1460,6 +1461,94 @@ guard_in_node_family(const entry_guard_t *guard, const node_t *node) } } +/* Allocate and return a new exit guard restriction (where <b>exit_id</b> is of + * size DIGEST_LEN) */ +STATIC entry_guard_restriction_t * +guard_create_exit_restriction(const uint8_t *exit_id) +{ + entry_guard_restriction_t *rst = NULL; + rst = tor_malloc_zero(sizeof(entry_guard_restriction_t)); + rst->type = RST_EXIT_NODE; + memcpy(rst->exclude_id, exit_id, DIGEST_LEN); + return rst; +} + +/** If we have fewer than this many possible usable guards, don't set + * MD-availability-based restrictions: we might blacklist all of them. */ +#define MIN_GUARDS_FOR_MD_RESTRICTION 10 + +/** Return true if we should set md dirserver restrictions. We might not want + * to set those if our guard options are too restricted, since we don't want + * to blacklist all of them. */ +static int +should_set_md_dirserver_restriction(void) +{ + const guard_selection_t *gs = get_guard_selection_info(); + int num_usable_guards = num_reachable_filtered_guards(gs, NULL); + + /* Don't set restriction if too few reachable filtered guards. */ + if (num_usable_guards < MIN_GUARDS_FOR_MD_RESTRICTION) { + log_info(LD_GUARD, "Not setting md restriction: only %d" + " usable guards.", num_usable_guards); + return 0; + } + + /* We have enough usable guards: set MD restriction */ + return 1; +} + +/** Allocate and return an outdated md guard restriction. Return NULL if no + * such restriction is needed. */ +STATIC entry_guard_restriction_t * +guard_create_dirserver_md_restriction(void) +{ + entry_guard_restriction_t *rst = NULL; + + if (!should_set_md_dirserver_restriction()) { + log_debug(LD_GUARD, "Not setting md restriction: too few " + "filtered guards."); + return NULL; + } + + rst = tor_malloc_zero(sizeof(entry_guard_restriction_t)); + rst->type = RST_OUTDATED_MD_DIRSERVER; + + return rst; +} + +/* Return True if <b>guard</b> obeys the exit restriction <b>rst</b>. */ +static int +guard_obeys_exit_restriction(const entry_guard_t *guard, + const entry_guard_restriction_t *rst) +{ + tor_assert(rst->type == RST_EXIT_NODE); + + // Exclude the exit ID and all of its family. + const node_t *node = node_get_by_id((const char*)rst->exclude_id); + if (node && guard_in_node_family(guard, node)) + return 0; + + return tor_memneq(guard->identity, rst->exclude_id, DIGEST_LEN); +} + +/** Return True if <b>guard</b> should be used as a dirserver for fetching + * microdescriptors. */ +static int +guard_obeys_md_dirserver_restriction(const entry_guard_t *guard) +{ + /* If this guard is an outdated dirserver, don't use it. */ + if (microdesc_relay_is_outdated_dirserver(guard->identity)) { + log_info(LD_GENERAL, "Skipping %s dirserver: outdated", + hex_str(guard->identity, DIGEST_LEN)); + return 0; + } + + log_debug(LD_GENERAL, "%s dirserver obeys md restrictions", + hex_str(guard->identity, DIGEST_LEN)); + + return 1; +} + /** * Return true iff <b>guard</b> obeys the restrictions defined in <b>rst</b>. * (If <b>rst</b> is NULL, there are no restrictions.) @@ -1472,13 +1561,14 @@ entry_guard_obeys_restriction(const entry_guard_t *guard, if (! rst) return 1; // No restriction? No problem. - // Only one kind of restriction exists right now: excluding an exit - // ID and all of its family. - const node_t *node = node_get_by_id((const char*)rst->exclude_id); - if (node && guard_in_node_family(guard, node)) - return 0; + if (rst->type == RST_EXIT_NODE) { + return guard_obeys_exit_restriction(guard, rst); + } else if (rst->type == RST_OUTDATED_MD_DIRSERVER) { + return guard_obeys_md_dirserver_restriction(guard); + } - return tor_memneq(guard->identity, rst->exclude_id, DIGEST_LEN); + tor_assert_nonfatal_unreached(); + return 0; } /** @@ -2105,8 +2195,8 @@ entry_guard_has_higher_priority(entry_guard_t *a, entry_guard_t *b) } /** Release all storage held in <b>restriction</b> */ -static void -entry_guard_restriction_free(entry_guard_restriction_t *rst) +STATIC void +entry_guard_restriction_free_(entry_guard_restriction_t *rst) { tor_free(rst); } @@ -2115,7 +2205,7 @@ entry_guard_restriction_free(entry_guard_restriction_t *rst) * Release all storage held in <b>state</b>. */ void -circuit_guard_state_free(circuit_guard_state_t *state) +circuit_guard_state_free_(circuit_guard_state_t *state) { if (!state) return; @@ -3018,7 +3108,7 @@ get_guard_state_for_bridge_desc_fetch(const char *digest) /** Release all storage held by <b>e</b>. */ STATIC void -entry_guard_free(entry_guard_t *e) +entry_guard_free_(entry_guard_t *e) { if (!e) return; @@ -3358,8 +3448,8 @@ guards_choose_guard(cpath_build_state_t *state, /* We're building to a targeted exit node, so that node can't be * chosen as our guard for this circuit. Remember that fact in a * restriction. */ - rst = tor_malloc_zero(sizeof(entry_guard_restriction_t)); - memcpy(rst->exclude_id, exit_id, DIGEST_LEN); + rst = guard_create_exit_restriction(exit_id); + tor_assert(rst); } if (entry_guard_pick_for_circuit(get_guard_selection_info(), GUARD_USAGE_TRAFFIC, @@ -3411,12 +3501,20 @@ remove_all_entry_guards(void) /** Helper: pick a directory guard, with whatever algorithm is used. */ const node_t * -guards_choose_dirguard(circuit_guard_state_t **guard_state_out) +guards_choose_dirguard(uint8_t dir_purpose, + circuit_guard_state_t **guard_state_out) { const node_t *r = NULL; + entry_guard_restriction_t *rst = NULL; + + /* If we are fetching microdescs, don't query outdated dirservers. */ + if (dir_purpose == DIR_PURPOSE_FETCH_MICRODESC) { + rst = guard_create_dirserver_md_restriction(); + } + if (entry_guard_pick_for_circuit(get_guard_selection_info(), GUARD_USAGE_DIRGUARD, - NULL, + rst, &r, guard_state_out) < 0) { tor_assert(r == NULL); @@ -3503,7 +3601,7 @@ entry_guards_get_err_str_if_dir_info_missing(int using_mds, /** Free one guard selection context */ STATIC void -guard_selection_free(guard_selection_t *gs) +guard_selection_free_(guard_selection_t *gs) { if (!gs) return; |