diff --git a/src/or/bridges.c b/src/or/bridges.c index 7d1acdfeaa..d9a8873c96 100644 --- a/src/or/bridges.c +++ b/src/or/bridges.c @@ -762,11 +762,7 @@ learned_bridge_descriptor(routerinfo_t *ri, int from_cache) (int) bridge->port); } if (get_options()->UseDeprecatedGuardAlgorithm) { -#ifdef ENABLE_LEGACY_GUARD_ALGORITHM - add_bridge_as_entry_guard(get_guard_selection_info(), node); -#else tor_assert_nonfatal_unreached(); -#endif } else { entry_guard_learned_bridge_identity(&bridge->addrport_configured, (const uint8_t*)ri->cache_info.identity_digest); @@ -777,12 +773,7 @@ learned_bridge_descriptor(routerinfo_t *ri, int from_cache) /* set entry->made_contact so if it goes down we don't drop it from * our entry node list */ if (get_options()->UseDeprecatedGuardAlgorithm) { -#ifdef ENABLE_LEGACY_GUARD_ALGORITHM - entry_guard_register_connect_status(ri->cache_info.identity_digest, - 1, 0, now); -#else tor_assert_nonfatal_unreached(); -#endif } if (first) { routerlist_retry_directory_downloads(now); diff --git a/src/or/channel.c b/src/or/channel.c index dbf442eca0..45f1602ab2 100644 --- a/src/or/channel.c +++ b/src/or/channel.c @@ -2577,19 +2577,6 @@ channel_do_open_actions(channel_t *chan) if (started_here) { circuit_build_times_network_is_live(get_circuit_build_times_mutable()); rep_hist_note_connect_succeeded(chan->identity_digest, now); -#ifdef ENABLE_LEGACY_GUARD_ALGORITHM - // XXXX prop271 this call is no longer useful with the new algorithm. - if (entry_guard_register_connect_status( - chan->identity_digest, 1, 0, now) < 0) { - /* Close any circuits pending on this channel. We leave it in state - * 'open' though, because it didn't actually *fail* -- we just - * chose not to use it. */ - log_debug(LD_OR, - "New entry guard was reachable, but closing this " - "connection so we can retry the earlier entry guards."); - close_origin_circuits = 1; - } -#endif router_set_status(chan->identity_digest, 1); } else { /* only report it to the geoip module if it's not a known router */ diff --git a/src/or/circpathbias.c b/src/or/circpathbias.c index d86d70f1ff..cdcb6deae4 100644 --- a/src/or/circpathbias.c +++ b/src/or/circpathbias.c @@ -1279,10 +1279,6 @@ pathbias_measure_use_rate(entry_guard_t *guard) tor_lround(pb->timeouts), tor_lround(get_circuit_build_close_time_ms()/1000)); pb->path_bias_disabled = 1; -#ifdef ENABLE_LEGACY_GUARD_ALGORITHM - // XXXX - entry_guard_mark_bad(guard); -#endif return; } } else if (!pb->path_bias_use_extreme) { @@ -1388,10 +1384,6 @@ pathbias_measure_close_rate(entry_guard_t *guard) tor_lround(pb->timeouts), tor_lround(get_circuit_build_close_time_ms()/1000)); pb->path_bias_disabled = 1; -#ifdef ENABLE_LEGACY_GUARD_ALGORITHM - // XXXX - entry_guard_mark_bad(guard); -#endif return; } } else if (!pb->path_bias_extreme) { diff --git a/src/or/circuitbuild.c b/src/or/circuitbuild.c index d4e30196cc..91bd823451 100644 --- a/src/or/circuitbuild.c +++ b/src/or/circuitbuild.c @@ -2308,26 +2308,6 @@ choose_good_entry_server(uint8_t purpose, cpath_build_state_t *state, * family. */ nodelist_add_node_and_family(excluded, node); } -#ifdef ENABLE_LEGACY_GUARD_ALGORITHM - /* and exclude current entry guards and their families, - * unless we're in a test network, and excluding guards - * would exclude all nodes (i.e. we're in an incredibly small tor network, - * or we're using TestingAuthVoteGuard *). - * This is an incomplete fix, but is no worse than the previous behaviour, - * and only applies to minimal, testing tor networks - * (so it's no less secure) */ - if (options->UseEntryGuards - && (!options->TestingTorNetwork || - smartlist_len(nodelist_get_list()) > smartlist_len(get_entry_guards()) - )) { - SMARTLIST_FOREACH(get_entry_guards(), const entry_guard_t *, entry, - { - if ((node = entry_guard_find_node(entry))) { - nodelist_add_node_and_family(excluded, node); - } - }); - } -#endif if (state) { if (state->need_uptime) diff --git a/src/or/circuituse.c b/src/or/circuituse.c index 72293f577e..c2b450606b 100644 --- a/src/or/circuituse.c +++ b/src/or/circuituse.c @@ -1732,10 +1732,6 @@ circuit_build_failed(origin_circuit_t *circ) /* New guard API: we failed. */ if (circ->guard_state) entry_guard_failed(&circ->guard_state); -#ifdef ENABLE_LEGACY_GUARD_ALGORITHM - /* Old guard API: we failed. */ - entry_guard_register_connect_status(n_chan_id, 0, 1, time(NULL)); -#endif /* if there are any one-hop streams waiting on this circuit, fail * them now so they can retry elsewhere. */ connection_ap_fail_onehop(n_chan_id, circ->build_state); diff --git a/src/or/config.c b/src/or/config.c index f885cbca3b..7240308c2f 100644 --- a/src/or/config.c +++ b/src/or/config.c @@ -2097,15 +2097,6 @@ options_act(const or_options_t *old_options) !options->BridgeAuthoritativeDir) rep_hist_desc_stats_term(); - /* Check if we need to parse and add the EntryNodes config option. */ -#ifdef ENABLE_LEGACY_GUARD_ALGORITHM - if (options->EntryNodes && - (!old_options || - !routerset_equal(old_options->EntryNodes,options->EntryNodes) || - !routerset_equal(old_options->ExcludeNodes,options->ExcludeNodes))) - entry_nodes_should_be_added(); -#endif - /* Since our options changed, we might need to regenerate and upload our * server descriptor. */ @@ -3009,13 +3000,6 @@ options_validate(or_options_t *old_options, or_options_t *options, warn_about_relative_paths(options); -#ifndef ENABLE_LEGACY_GUARD_ALGORITHM - if (options->UseDeprecatedGuardAlgorithm) { - log_warn(LD_CONFIG, "DeprecatedGuardAlgorithm not supported."); - return -1; - } -#endif - if (server_mode(options) && (!strcmpstart(uname, "Windows 95") || !strcmpstart(uname, "Windows 98") || diff --git a/src/or/connection_or.c b/src/or/connection_or.c index b3ae291831..cefe42c4db 100644 --- a/src/or/connection_or.c +++ b/src/or/connection_or.c @@ -718,11 +718,6 @@ connection_or_about_to_close(or_connection_t *or_conn) rep_hist_note_connect_failed(or_conn->identity_digest, now); /* Tell the new guard API about the channel failure */ entry_guard_chan_failed(TLS_CHAN_TO_BASE(or_conn->chan)); -#ifdef ENABLE_LEGACY_GUARD_ALGORITHM - /* Tell the old guard API about the channel failure */ - entry_guard_register_connect_status(or_conn->identity_digest,0, - !options->HTTPSProxy, now); -#endif if (conn->state >= OR_CONN_STATE_TLS_HANDSHAKING) { int reason = tls_error_to_orconn_end_reason(or_conn->tls_error); control_event_or_conn_status(or_conn, OR_CONN_EVENT_FAILED, @@ -1728,11 +1723,6 @@ connection_or_client_learned_peer_id(or_connection_t *conn, /* Tell the new guard API about the channel failure */ entry_guard_chan_failed(TLS_CHAN_TO_BASE(conn->chan)); -#ifdef ENABLE_LEGACY_GUARD_ALGORITHM - /* Tell the old guard API about the channel failure */ - entry_guard_register_connect_status(conn->identity_digest, 0, 1, - time(NULL)); -#endif control_event_or_conn_status(conn, OR_CONN_EVENT_FAILED, END_OR_CONN_REASON_OR_IDENTITY); if (!authdir_mode_tests_reachability(options)) diff --git a/src/or/entrynodes.c b/src/or/entrynodes.c index ca3e57b064..195c6b98ad 100644 --- a/src/or/entrynodes.c +++ b/src/or/entrynodes.c @@ -151,13 +151,6 @@ static guard_selection_t *curr_guard_context = NULL; * and those changes need to be flushed to disk. */ static int entry_guards_dirty = 0; -#ifdef ENABLE_LEGACY_GUARD_ALGORITHM -static const node_t *choose_random_entry_impl(guard_selection_t *gs, - cpath_build_state_t *state, - int for_directory, - dirinfo_type_t dirtype, - int *n_options_out); -#endif static void entry_guard_set_filtered_flags(const or_options_t *options, guard_selection_t *gs, entry_guard_t *guard); @@ -232,9 +225,6 @@ guard_selection_new(const char *name, gs = tor_malloc_zero(sizeof(*gs)); gs->name = tor_strdup(name); gs->type = type; -#ifdef ENABLE_LEGACY_GUARD_ALGORITHM - gs->chosen_entry_guards = smartlist_new(); -#endif gs->sampled_entry_guards = smartlist_new(); gs->confirmed_entry_guards = smartlist_new(); gs->primary_entry_guards = smartlist_new(); @@ -304,35 +294,6 @@ get_guard_selection_info(void) return curr_guard_context; } -#ifdef ENABLE_LEGACY_GUARD_ALGORITHM -/** Return the list of entry guards for a guard_selection_t, creating it - * if necessary. */ -const smartlist_t * -get_entry_guards_for_guard_selection(guard_selection_t *gs) -{ - tor_assert(gs != NULL); - tor_assert(gs->chosen_entry_guards != NULL); - - return gs->chosen_entry_guards; -} - -/** Return the list of entry guards for the default guard_selection_t, - * creating it if necessary. */ -const smartlist_t * -get_entry_guards(void) -{ - return get_entry_guards_for_guard_selection(get_guard_selection_info()); -} - -/** Helper: mark an entry guard as not usable. */ -void -entry_guard_mark_bad(entry_guard_t *guard) -{ - guard->bad_since = approx_time(); - entry_guards_changed(); -} -#endif - /** Return a statically allocated human-readable description of guard */ const char * @@ -2927,291 +2888,6 @@ entry_guards_load_guards_from_state(or_state_t *state, int set) return n_errors ? -1 : 0; } -/* XXXXX ----------------------------------------------- */ -/* XXXXX prop271 ----- end of new-for-prop271 code ----- */ -/* XXXXX ----------------------------------------------- */ - -#ifdef ENABLE_LEGACY_GUARD_ALGORITHM -/** - * @name Constants for old (pre-prop271) guard selection algorithm. - */ - -/**@{*/ - -/* Default number of entry guards in the case where the NumEntryGuards - * consensus parameter is not set */ -#define DEFAULT_N_GUARDS 1 -/* Minimum and maximum number of entry guards (in case the NumEntryGuards - * consensus parameter is set). */ -#define MIN_N_GUARDS 1 -#define MAX_N_GUARDS 10 -/** Largest amount that we'll backdate chosen_on_date */ -#define CHOSEN_ON_DATE_SLOP (30*86400) -/** How long (in seconds) do we allow an entry guard to be nonfunctional, - * unlisted, excluded, or otherwise nonusable before we give up on it? */ -#define ENTRY_GUARD_REMOVE_AFTER (30*24*60*60) -/**}@*/ - -/** - * @name Networkstatus parameters for old (pre-prop271) guard selection - */ -/**@}*/ -/** Choose how many entry guards or directory guards we'll use. If - * for_directory is true, we return how many directory guards to - * use; else we return how many entry guards to use. */ -STATIC int -decide_num_guards(const or_options_t *options, int for_directory) -{ - if (for_directory) { - int answer; - if (options->NumDirectoryGuards != 0) - return options->NumDirectoryGuards; - answer = networkstatus_get_param(NULL, "NumDirectoryGuards", 0, 0, 10); - if (answer) /* non-zero means use the consensus value */ - return answer; - } - - if (options->NumEntryGuards) - return options->NumEntryGuards; - - /* Use the value from the consensus, or 3 if no guidance. */ - return networkstatus_get_param(NULL, "NumEntryGuards", DEFAULT_N_GUARDS, - MIN_N_GUARDS, MAX_N_GUARDS); -} - -/** Check whether the entry guard e is usable, given the directory - * authorities' opinion about the router (stored in ri) and the user's - * configuration (in options). Set e->bad_since - * accordingly. Return true iff the entry guard's status changes. - * - * If it's not usable, set *reason to a static string explaining why. - */ -static int -entry_guard_set_status(entry_guard_t *e, const node_t *node, - time_t now, const or_options_t *options, - const char **reason) -{ - char buf[HEX_DIGEST_LEN+1]; - int changed = 0; - - *reason = NULL; - - /* Do we want to mark this guard as bad? */ - if (!node) - *reason = "unlisted"; - else if (!node->is_running) - *reason = "down"; - else if (options->UseBridges && (!node->ri || - node->ri->purpose != ROUTER_PURPOSE_BRIDGE)) - *reason = "not a bridge"; - else if (options->UseBridges && !node_is_a_configured_bridge(node)) - *reason = "not a configured bridge"; - else if (!options->UseBridges && !node->is_possible_guard && - !routerset_contains_node(options->EntryNodes,node)) - *reason = "not recommended as a guard"; - else if (routerset_contains_node(options->ExcludeNodes, node)) - *reason = "excluded"; - /* We only care about OR connection connectivity for entry guards. */ - else if (!fascist_firewall_allows_node(node, FIREWALL_OR_CONNECTION, 0)) - *reason = "unreachable by config"; - else if (e->pb.path_bias_disabled) - *reason = "path-biased"; - - if (*reason && ! e->bad_since) { - /* Router is newly bad. */ - base16_encode(buf, sizeof(buf), e->identity, DIGEST_LEN); - log_info(LD_CIRC, "Entry guard %s (%s) is %s: marking as unusable.", - e->nickname, buf, *reason); - - e->bad_since = now; - control_event_guard(e->nickname, e->identity, "BAD"); - changed = 1; - } else if (!*reason && e->bad_since) { - /* There's nothing wrong with the router any more. */ - base16_encode(buf, sizeof(buf), e->identity, DIGEST_LEN); - log_info(LD_CIRC, "Entry guard %s (%s) is no longer unusable: " - "marking as ok.", e->nickname, buf); - - e->bad_since = 0; - control_event_guard(e->nickname, e->identity, "GOOD"); - changed = 1; - } - - if (node) { - int is_dir = node_is_dir(node); - if (options->UseBridges && node_is_a_configured_bridge(node)) - is_dir = 1; - if (e->is_dir_cache != is_dir) { - e->is_dir_cache = is_dir; - changed = 1; - } - } - - return changed; -} - -/** Return true iff enough time has passed since we last tried to connect - * to the unreachable guard e that we're willing to try again. */ -STATIC int -entry_is_time_to_retry(const entry_guard_t *e, time_t now) -{ - struct guard_retry_period_s { - time_t period_duration; - time_t interval_during_period; - }; - - struct guard_retry_period_s periods[] = { - { 6*60*60, 60*60 }, /* For first 6 hrs., retry hourly; */ - { 3*24*60*60, 4*60*60 }, /* Then retry every 4 hrs. until the - 3-day mark; */ - { 7*24*60*60, 18*60*60 }, /* After 3 days, retry every 18 hours until - 1 week mark. */ - { TIME_MAX, 36*60*60 } /* After 1 week, retry every 36 hours. */ - }; - - time_t ith_deadline_for_retry; - time_t unreachable_for; - unsigned i; - - if (e->last_attempted < e->unreachable_since) - return 1; - - unreachable_for = now - e->unreachable_since; - - for (i = 0; i < ARRAY_LENGTH(periods); i++) { - if (unreachable_for <= periods[i].period_duration) { - ith_deadline_for_retry = e->last_attempted + - periods[i].interval_during_period; - - return (now > ith_deadline_for_retry); - } - } - return 0; -} - -/** Return the node corresponding to e, if e is - * working well enough that we are willing to use it as an entry - * right now. (Else return NULL.) In particular, it must be - * - Listed as either up or never yet contacted; - * - Present in the routerlist; - * - Listed as 'stable' or 'fast' by the current dirserver consensus, - * if demanded by need_uptime or need_capacity - * (unless it's a configured EntryNode); - * - Allowed by our current ReachableORAddresses config option; and - * - Currently thought to be reachable by us (unless assume_reachable - * is true). - * - * If the answer is no, set *msg to an explanation of why. - * - * If need_descriptor is true, only return the node if we currently have - * a descriptor (routerinfo or microdesc) for it. - */ -STATIC const node_t * -entry_is_live(const entry_guard_t *e, entry_is_live_flags_t flags, - const char **msg) -{ - const node_t *node; - const or_options_t *options = get_options(); - int need_uptime = (flags & ENTRY_NEED_UPTIME) != 0; - int need_capacity = (flags & ENTRY_NEED_CAPACITY) != 0; - const int assume_reachable = (flags & ENTRY_ASSUME_REACHABLE) != 0; - const int need_descriptor = (flags & ENTRY_NEED_DESCRIPTOR) != 0; - - tor_assert(msg); - - if (e->pb.path_bias_disabled) { - *msg = "path-biased"; - return NULL; - } - if (e->bad_since) { - *msg = "bad"; - return NULL; - } - /* no good if it's unreachable, unless assume_unreachable or can_retry. */ - if (!assume_reachable && !e->can_retry && - e->unreachable_since && !entry_is_time_to_retry(e, time(NULL))) { - *msg = "unreachable"; - return NULL; - } - node = node_get_by_id(e->identity); - if (!node) { - *msg = "no node info"; - return NULL; - } - if (need_descriptor && !node_has_descriptor(node)) { - *msg = "no descriptor"; - return NULL; - } - if (get_options()->UseBridges) { - if (node_get_purpose(node) != ROUTER_PURPOSE_BRIDGE) { - *msg = "not a bridge"; - return NULL; - } - if (!node_is_a_configured_bridge(node)) { - *msg = "not a configured bridge"; - return NULL; - } - } else { /* !get_options()->UseBridges */ - if (node_get_purpose(node) != ROUTER_PURPOSE_GENERAL) { - *msg = "not general-purpose"; - return NULL; - } - } - if (routerset_contains_node(options->EntryNodes, node)) { - /* they asked for it, they get it */ - need_uptime = need_capacity = 0; - } - if (node_is_unreliable(node, need_uptime, need_capacity, 0)) { - *msg = "not fast/stable"; - return NULL; - } - if (!fascist_firewall_allows_node(node, FIREWALL_OR_CONNECTION, 0)) { - *msg = "unreachable by config"; - return NULL; - } - return node; -} - -/** Return the number of entry guards that we think are usable, in the - * context of the given guard_selection_t */ -int -num_live_entry_guards_for_guard_selection(guard_selection_t *gs, - int for_directory) -{ - int n = 0; - const char *msg; - - tor_assert(gs != NULL); - - /* Set the entry node attributes we are interested in. */ - entry_is_live_flags_t entry_flags = ENTRY_NEED_CAPACITY; - if (!for_directory) { - entry_flags |= ENTRY_NEED_DESCRIPTOR; - } - - if (!(gs->chosen_entry_guards)) { - return 0; - } - - SMARTLIST_FOREACH_BEGIN(gs->chosen_entry_guards, entry_guard_t *, entry) { - if (for_directory && !entry->is_dir_cache) - continue; - if (entry_is_live(entry, entry_flags, &msg)) - ++n; - } SMARTLIST_FOREACH_END(entry); - return n; -} - -/** Return the number of entry guards that we think are usable, for the - * default guard selection */ -int -num_live_entry_guards(int for_directory) -{ - return num_live_entry_guards_for_guard_selection( - get_guard_selection_info(), for_directory); -} -#endif - /** If digest matches the identity of any node in the * entry_guards list for the provided guard selection state, return that node. Else return NULL. */ @@ -3225,12 +2901,6 @@ entry_guard_get_by_id_digest_for_guard_selection(guard_selection_t *gs, if (tor_memeq(digest, entry->identity, DIGEST_LEN)) return entry; ); -#ifdef ENABLE_LEGACY_GUARD_ALGORITHM - SMARTLIST_FOREACH(gs->chosen_entry_guards, entry_guard_t *, entry, - if (tor_memeq(digest, entry->identity, DIGEST_LEN)) - return entry; - ); -#endif return NULL; } @@ -3253,234 +2923,6 @@ entry_guard_get_by_id_digest(const char *digest) get_guard_selection_info(), digest); } -#ifdef ENABLE_LEGACY_GUARD_ALGORITHM -/** Dump a description of our list of entry guards in the given guard - * selection context to the log at level severity. */ -static void -log_entry_guards_for_guard_selection(guard_selection_t *gs, int severity) -{ - smartlist_t *elements = smartlist_new(); - char *s; - - /* - * TODO this should probably log more info about prop-271 state too - * when it's implemented. - */ - - tor_assert(gs != NULL); - - SMARTLIST_FOREACH_BEGIN(gs->chosen_entry_guards, entry_guard_t *, e) - { - const char *msg = NULL; - if (entry_is_live(e, ENTRY_NEED_CAPACITY, &msg)) - smartlist_add_asprintf(elements, "%s [%s] (up %s)", - e->nickname, - hex_str(e->identity, DIGEST_LEN), - e->made_contact ? "made-contact" : "never-contacted"); - else - smartlist_add_asprintf(elements, "%s [%s] (%s, %s)", - e->nickname, - hex_str(e->identity, DIGEST_LEN), - msg, - e->made_contact ? "made-contact" : "never-contacted"); - } - SMARTLIST_FOREACH_END(e); - - s = smartlist_join_strings(elements, ",", 0, NULL); - SMARTLIST_FOREACH(elements, char*, cp, tor_free(cp)); - smartlist_free(elements); - log_fn(severity,LD_CIRC,"%s",s); - tor_free(s); -} - -/** Called when one or more guards that we would previously have used for some - * purpose are no longer in use because a higher-priority guard has become - * usable again. */ -static void -control_event_guard_deferred(void) -{ - /* XXXX We don't actually have a good way to figure out _how many_ entries - * are live for some purpose. We need an entry_is_even_slightly_live() - * function for this to work right. NumEntryGuards isn't reliable: if we - * need guards with weird properties, we can have more than that number - * live. - **/ -#if 0 - int n = 0; - const char *msg; - const or_options_t *options = get_options(); - if (!entry_guards) - return; - SMARTLIST_FOREACH(entry_guards, entry_guard_t *, entry, - { - if (entry_is_live(entry, 0, 1, 0, &msg)) { - if (n++ == options->NumEntryGuards) { - control_event_guard(entry->nickname, entry->identity, "DEFERRED"); - return; - } - } - }); -#endif -} - -/** Add a new (preferably stable and fast) router to our chosen_entry_guards - * list for the supplied guard selection. Return a pointer to the router if - * we succeed, or NULL if we can't find any more suitable entries. - * - * If chosen is defined, use that one, and if it's not - * already in our entry_guards list, put it at the *beginning*. - * Else, put the one we pick at the end of the list. */ -STATIC const node_t * -add_an_entry_guard(guard_selection_t *gs, - const node_t *chosen, int reset_status, int prepend, - int for_discovery, int for_directory) -{ - const node_t *node; - entry_guard_t *entry; - - tor_assert(gs != NULL); - tor_assert(gs->chosen_entry_guards != NULL); - - if (chosen) { - node = chosen; - entry = entry_guard_get_by_id_digest_for_guard_selection(gs, - node->identity); - if (entry) { - if (reset_status) { - entry->bad_since = 0; - entry->can_retry = 1; - } - entry->is_dir_cache = node_is_dir(node); - if (get_options()->UseBridges && node_is_a_configured_bridge(node)) - entry->is_dir_cache = 1; - - return NULL; - } - } else if (!for_directory) { - node = choose_good_entry_server(CIRCUIT_PURPOSE_C_GENERAL, NULL, NULL); - if (!node) - return NULL; - } else { - const routerstatus_t *rs; - rs = router_pick_directory_server(MICRODESC_DIRINFO|V3_DIRINFO, - PDS_FOR_GUARD); - if (!rs) - return NULL; - node = node_get_by_id(rs->identity_digest); - if (!node) - return NULL; - } - if (entry_guard_get_by_id_digest_for_guard_selection(gs, node->identity) - != NULL) { - log_info(LD_CIRC, "I was about to add a duplicate entry guard."); - /* This can happen if we choose a guard, then the node goes away, then - * comes back. */ - return NULL; - } - entry = tor_malloc_zero(sizeof(entry_guard_t)); - entry->is_persistent = 1; - log_info(LD_CIRC, "Chose %s as new entry guard.", - node_describe(node)); - strlcpy(entry->nickname, node_get_nickname(node), sizeof(entry->nickname)); - memcpy(entry->identity, node->identity, DIGEST_LEN); - entry->is_dir_cache = node_is_dir(node); - if (get_options()->UseBridges && node_is_a_configured_bridge(node)) - entry->is_dir_cache = 1; - - /* Choose expiry time smudged over the past month. The goal here - * is to a) spread out when Tor clients rotate their guards, so they - * don't all select them on the same day, and b) avoid leaving a - * precise timestamp in the state file about when we first picked - * this guard. For details, see the Jan 2010 or-dev thread. */ - time_t now = time(NULL); - entry->chosen_on_date = crypto_rand_time_range(now - 3600*24*30, now); - entry->chosen_by_version = tor_strdup(VERSION); - - /* Are we picking this guard because all of our current guards are - * down so we need another one (for_discovery is 1), or because we - * decided we need more variety in our guard list (for_discovery is 0)? - * - * Currently we hack this behavior into place by setting "made_contact" - * for guards of the latter variety, so we'll be willing to use any of - * them right off the bat. - */ - if (!for_discovery) - entry->made_contact = 1; - - if (prepend) - smartlist_insert(gs->chosen_entry_guards, 0, entry); - else - smartlist_add(gs->chosen_entry_guards, entry); - entry->in_selection = gs; - - control_event_guard(entry->nickname, entry->identity, "NEW"); - control_event_guard_deferred(); - log_entry_guards_for_guard_selection(gs, LOG_INFO); - - return node; -} - -/** Entry point for bridges.c to add a bridge as guard. - * - * XXXX prop271 refactor, bridge.*/ -void -add_bridge_as_entry_guard(guard_selection_t *gs, - const node_t *chosen) -{ - add_an_entry_guard(gs, chosen, 1, 1, 0, 0); -} - -/** - * Return the minimum lifetime of working entry guard, in seconds, - * as given in the consensus networkstatus. (Plus CHOSEN_ON_DATE_SLOP, - * so that we can do the chosen_on_date randomization while achieving the - * desired minimum lifetime.) - */ -static int32_t -guards_get_lifetime(void) -{ - const or_options_t *options = get_options(); -#define DFLT_GUARD_LIFETIME (86400 * 60) /* Two months. */ -#define MIN_GUARD_LIFETIME (86400 * 30) /* One months. */ -#define MAX_GUARD_LIFETIME (86400 * 1826) /* Five years. */ - - if (options->GuardLifetime >= 1) { - return CLAMP(MIN_GUARD_LIFETIME, - options->GuardLifetime, - MAX_GUARD_LIFETIME) + CHOSEN_ON_DATE_SLOP; - } - - return networkstatus_get_param(NULL, "GuardLifetime", - DFLT_GUARD_LIFETIME, - MIN_GUARD_LIFETIME, - MAX_GUARD_LIFETIME) + CHOSEN_ON_DATE_SLOP; -} - -/** If the use of entry guards is configured, choose more entry guards - * until we have enough in the list. */ -static void -pick_entry_guards(guard_selection_t *gs, - const or_options_t *options, - int for_directory) -{ - int changed = 0; - const int num_needed = decide_num_guards(options, for_directory); - - tor_assert(gs != NULL); - tor_assert(gs->chosen_entry_guards != NULL); - - while (num_live_entry_guards_for_guard_selection(gs, for_directory) - < num_needed) { - if (!add_an_entry_guard(gs, NULL, 0, 0, 0, for_directory)) - break; - changed = 1; - } - - if (changed) - entry_guards_changed_for_guard_selection(gs); -} -#endif - /** Release all storage held by e. */ STATIC void entry_guard_free(entry_guard_t *e) @@ -3488,9 +2930,6 @@ entry_guard_free(entry_guard_t *e) if (!e) return; entry_guard_handles_clear(e); -#ifdef ENABLE_LEGACY_GUARD_ALGORITHM - tor_free(e->chosen_by_version); -#endif tor_free(e->sampled_by_version); tor_free(e->extra_state_fields); tor_free(e->selection_name); @@ -3498,487 +2937,6 @@ entry_guard_free(entry_guard_t *e) tor_free(e); } -#ifdef ENABLE_LEGACY_GUARD_ALGORITHM -/** Remove from a guard selection context any entry guard which was selected - * by an unknown version of Tor, or which was selected by a version of Tor - * that's known to select entry guards badly, or which was selected more 2 - * months ago. */ -/* XXXX The "obsolete guards" and "chosen long ago guards" things should - * probably be different functions. */ -static int -remove_obsolete_entry_guards(guard_selection_t *gs, time_t now) -{ - int changed = 0, i; - int32_t guard_lifetime = guards_get_lifetime(); - - tor_assert(gs != NULL); - if (!(gs->chosen_entry_guards)) goto done; - - for (i = 0; i < smartlist_len(gs->chosen_entry_guards); ++i) { - entry_guard_t *entry = smartlist_get(gs->chosen_entry_guards, i); - const char *ver = entry->chosen_by_version; - const char *msg = NULL; - tor_version_t v; - int version_is_bad = 0, date_is_bad = 0; - if (!ver) { - msg = "does not say what version of Tor it was selected by"; - version_is_bad = 1; - } else if (tor_version_parse(ver, &v)) { - msg = "does not seem to be from any recognized version of Tor"; - version_is_bad = 1; - } - if (!version_is_bad && entry->chosen_on_date + guard_lifetime < now) { - /* It's been too long since the date listed in our state file. */ - msg = "was selected several months ago"; - date_is_bad = 1; - } - - if (version_is_bad || date_is_bad) { /* we need to drop it */ - char dbuf[HEX_DIGEST_LEN+1]; - tor_assert(msg); - base16_encode(dbuf, sizeof(dbuf), entry->identity, DIGEST_LEN); - log_fn(version_is_bad ? LOG_NOTICE : LOG_INFO, LD_CIRC, - "Entry guard '%s' (%s) %s. (Version=%s.) Replacing it.", - entry->nickname, dbuf, msg, ver?escaped(ver):"none"); - control_event_guard(entry->nickname, entry->identity, "DROPPED"); - entry_guard_free(entry); - smartlist_del_keeporder(gs->chosen_entry_guards, i--); - log_entry_guards_for_guard_selection(gs, LOG_INFO); - changed = 1; - } - } - - done: - return changed ? 1 : 0; -} - -/** Remove all entry guards from this guard selection context that have - * been down or unlisted for so long that we don't think they'll come up - * again. Return 1 if we removed any, or 0 if we did nothing. */ -static int -remove_dead_entry_guards(guard_selection_t *gs, time_t now) -{ - char dbuf[HEX_DIGEST_LEN+1]; - char tbuf[ISO_TIME_LEN+1]; - int i; - int changed = 0; - - tor_assert(gs != NULL); - if (!(gs->chosen_entry_guards)) goto done; - - for (i = 0; i < smartlist_len(gs->chosen_entry_guards); ) { - entry_guard_t *entry = smartlist_get(gs->chosen_entry_guards, i); - if (entry->bad_since && - ! entry->pb.path_bias_disabled && - entry->bad_since + ENTRY_GUARD_REMOVE_AFTER < now) { - - base16_encode(dbuf, sizeof(dbuf), entry->identity, DIGEST_LEN); - format_local_iso_time(tbuf, entry->bad_since); - log_info(LD_CIRC, "Entry guard '%s' (%s) has been down or unlisted " - "since %s local time; removing.", - entry->nickname, dbuf, tbuf); - control_event_guard(entry->nickname, entry->identity, "DROPPED"); - entry_guard_free(entry); - smartlist_del_keeporder(gs->chosen_entry_guards, i); - log_entry_guards_for_guard_selection(gs, LOG_INFO); - changed = 1; - } else - ++i; - } - - done: - return changed ? 1 : 0; -} - -/** Remove all currently listed entry guards for a given guard selection - * context */ -void -remove_all_entry_guards_for_guard_selection(guard_selection_t *gs) -{ - char dbuf[HEX_DIGEST_LEN+1]; - - tor_assert(gs != NULL); - - if (gs->chosen_entry_guards) { - while (smartlist_len(gs->chosen_entry_guards)) { - entry_guard_t *entry = smartlist_get(gs->chosen_entry_guards, 0); - base16_encode(dbuf, sizeof(dbuf), entry->identity, DIGEST_LEN); - log_info(LD_CIRC, "Entry guard '%s' (%s) has been dropped.", - entry->nickname, dbuf); - control_event_guard(entry->nickname, entry->identity, "DROPPED"); - entry_guard_free(entry); - smartlist_del(gs->chosen_entry_guards, 0); - } - } - - log_entry_guards_for_guard_selection(gs, LOG_INFO); - entry_guards_changed_for_guard_selection(gs); -} - -/** Remove all currently listed entry guards. So new ones will be chosen. */ -void -remove_all_entry_guards(void) -{ - // XXXX prop271 this function shouldn't exist, in the new order. - remove_all_entry_guards_for_guard_selection(get_guard_selection_info()); -} - -/** A new directory or router-status has arrived; update the down/listed - * status of the entry guards. - * - * An entry is 'down' if the directory lists it as nonrunning. - * An entry is 'unlisted' if the directory doesn't include it. - * - * Don't call this on startup; only on a fresh download. Otherwise we'll - * think that things are unlisted. - */ -void -entry_guards_compute_status_for_guard_selection(guard_selection_t *gs, - const or_options_t *options, - time_t now) -{ - int changed = 0; - digestmap_t *reasons; - - if ((!gs) || !(gs->chosen_entry_guards)) - return; - - if (!get_options()->UseDeprecatedGuardAlgorithm) - return; - - if (options->EntryNodes) /* reshuffle the entry guard list if needed */ - entry_nodes_should_be_added(); - - reasons = digestmap_new(); - SMARTLIST_FOREACH_BEGIN(gs->chosen_entry_guards, entry_guard_t *, entry) - { - const node_t *r = node_get_by_id(entry->identity); - const char *reason = NULL; - if (entry_guard_set_status(entry, r, now, options, &reason)) - changed = 1; - - if (entry->bad_since) - tor_assert(reason); - if (reason) - digestmap_set(reasons, entry->identity, (char*)reason); - } - SMARTLIST_FOREACH_END(entry); - - if (remove_dead_entry_guards(gs, now)) - changed = 1; - if (remove_obsolete_entry_guards(gs, now)) - changed = 1; - - if (changed) { - SMARTLIST_FOREACH_BEGIN(gs->chosen_entry_guards, entry_guard_t *, - entry) { - const char *reason = digestmap_get(reasons, entry->identity); - const char *live_msg = ""; - const node_t *r = entry_is_live(entry, ENTRY_NEED_CAPACITY, &live_msg); - log_info(LD_CIRC, "Summary: Entry %s [%s] is %s, %s%s%s, and %s%s.", - entry->nickname, - hex_str(entry->identity, DIGEST_LEN), - entry->unreachable_since ? "unreachable" : "reachable", - entry->bad_since ? "unusable" : "usable", - reason ? ", ": "", - reason ? reason : "", - r ? "live" : "not live / ", - r ? "" : live_msg); - } SMARTLIST_FOREACH_END(entry); - log_info(LD_CIRC, " (%d/%d entry guards are usable/new)", - num_live_entry_guards_for_guard_selection(gs, 0), - smartlist_len(gs->chosen_entry_guards)); - log_entry_guards_for_guard_selection(gs, LOG_INFO); - entry_guards_changed_for_guard_selection(gs); - } - - digestmap_free(reasons, NULL); -} - -/** A new directory or router-status has arrived; update the down/listed - * status of the entry guards. - * - * An entry is 'down' if the directory lists it as nonrunning. - * An entry is 'unlisted' if the directory doesn't include it. - * - * Don't call this on startup; only on a fresh download. Otherwise we'll - * think that things are unlisted. - */ -void -entry_guards_compute_status(const or_options_t *options, time_t now) -{ - entry_guards_compute_status_for_guard_selection(get_guard_selection_info(), - options, now); -} - -/** Called when a connection to an OR with the identity digest digest - * is established (succeeded==1) or has failed (succeeded==0). - * If the OR is an entry, change that entry's up/down status. - * Return 0 normally, or -1 if we want to tear down the new connection. - * - * If mark_relay_status, also call router_set_status() on this - * relay. - */ -/* XXX We could change succeeded and mark_relay_status into 'int flags'. - * Too many boolean arguments is a recipe for confusion. - */ -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 changed = 0; - int refuse_conn = 0; - int first_contact = 0; - entry_guard_t *entry = NULL; - int idx = -1; - char buf[HEX_DIGEST_LEN+1]; - - if (!(gs) || !(gs->chosen_entry_guards)) { - return 0; - } - - if (! get_options()->UseDeprecatedGuardAlgorithm) { - return 0; - } - - SMARTLIST_FOREACH_BEGIN(gs->chosen_entry_guards, entry_guard_t *, e) { - tor_assert(e); - if (tor_memeq(e->identity, digest, DIGEST_LEN)) { - entry = e; - idx = e_sl_idx; - break; - } - } SMARTLIST_FOREACH_END(e); - - if (!entry) - return 0; - - base16_encode(buf, sizeof(buf), entry->identity, DIGEST_LEN); - - if (succeeded) { - if (entry->unreachable_since) { - log_info(LD_CIRC, "Entry guard '%s' (%s) is now reachable again. Good.", - entry->nickname, buf); - entry->can_retry = 0; - entry->unreachable_since = 0; - entry->last_attempted = now; - control_event_guard(entry->nickname, entry->identity, "UP"); - changed = 1; - } - if (!entry->made_contact) { - entry->made_contact = 1; - first_contact = changed = 1; - } - } else { /* ! succeeded */ - if (!entry->made_contact) { - /* We've never connected to this one. */ - log_info(LD_CIRC, - "Connection to never-contacted entry guard '%s' (%s) failed. " - "Removing from the list. %d/%d entry guards usable/new.", - entry->nickname, buf, - num_live_entry_guards_for_guard_selection(gs, 0) - 1, - smartlist_len(gs->chosen_entry_guards)-1); - control_event_guard(entry->nickname, entry->identity, "DROPPED"); - entry_guard_free(entry); - smartlist_del_keeporder(gs->chosen_entry_guards, idx); - log_entry_guards_for_guard_selection(gs, LOG_INFO); - changed = 1; - } else if (!entry->unreachable_since) { - log_info(LD_CIRC, "Unable to connect to entry guard '%s' (%s). " - "Marking as unreachable.", entry->nickname, buf); - entry->unreachable_since = entry->last_attempted = now; - control_event_guard(entry->nickname, entry->identity, "DOWN"); - changed = 1; - entry->can_retry = 0; /* We gave it an early chance; no good. */ - } else { - char tbuf[ISO_TIME_LEN+1]; - format_iso_time(tbuf, entry->unreachable_since); - log_debug(LD_CIRC, "Failed to connect to unreachable entry guard " - "'%s' (%s). It has been unreachable since %s.", - entry->nickname, buf, tbuf); - entry->last_attempted = now; - entry->can_retry = 0; /* We gave it an early chance; no good. */ - } - } - - /* if the caller asked us to, also update the is_running flags for this - * relay */ - if (mark_relay_status) - router_set_status(digest, succeeded); - - if (first_contact) { - /* We've just added a new long-term entry guard. Perhaps the network just - * came back? We should give our earlier entries another try too, - * and close this connection so we don't use it before we've given - * the others a shot. */ - SMARTLIST_FOREACH_BEGIN(gs->chosen_entry_guards, entry_guard_t *, e) { - if (e == entry) - break; - if (e->made_contact) { - const char *msg; - const node_t *r = entry_is_live(e, - ENTRY_NEED_CAPACITY | ENTRY_ASSUME_REACHABLE, - &msg); - if (r && e->unreachable_since) { - refuse_conn = 1; - e->can_retry = 1; - } - } - } SMARTLIST_FOREACH_END(e); - if (refuse_conn) { - log_info(LD_CIRC, - "Connected to new entry guard '%s' (%s). Marking earlier " - "entry guards up. %d/%d entry guards usable/new.", - entry->nickname, buf, - num_live_entry_guards_for_guard_selection(gs, 0), - smartlist_len(gs->chosen_entry_guards)); - log_entry_guards_for_guard_selection(gs, LOG_INFO); - changed = 1; - } - } - - if (changed) - entry_guards_changed_for_guard_selection(gs); - return refuse_conn ? -1 : 0; -} - -/** Called when a connection to an OR with the identity digest digest - * is established (succeeded==1) or has failed (succeeded==0). - * If the OR is an entry, change that entry's up/down status in the default - * guard selection context. - * Return 0 normally, or -1 if we want to tear down the new connection. - * - * If mark_relay_status, also call router_set_status() on this - * relay. - */ -int -entry_guard_register_connect_status(const char *digest, int succeeded, - int mark_relay_status, time_t now) -{ - return entry_guard_register_connect_status_for_guard_selection( - get_guard_selection_info(), digest, succeeded, mark_relay_status, now); -} - -/** Called when the value of EntryNodes changes in our configuration. */ -void -entry_nodes_should_be_added_for_guard_selection(guard_selection_t *gs) -{ - tor_assert(gs != NULL); - - log_info(LD_CIRC, "EntryNodes config option set. Putting configured " - "relays at the front of the entry guard list."); - gs->should_add_entry_nodes = 1; -} - -/** Called when the value of EntryNodes changes in our configuration. */ -void -entry_nodes_should_be_added(void) -{ - entry_nodes_should_be_added_for_guard_selection( - get_guard_selection_info()); -} - -/** Adjust the entry guards list so that it only contains entries from - * EntryNodes, adding new entries from EntryNodes to the list as needed. */ -STATIC void -entry_guards_set_from_config(guard_selection_t *gs, - const or_options_t *options) -{ - smartlist_t *entry_nodes, *worse_entry_nodes, *entry_fps; - smartlist_t *old_entry_guards_on_list, *old_entry_guards_not_on_list; - const int numentryguards = decide_num_guards(options, 0); - - tor_assert(gs != NULL); - tor_assert(gs->chosen_entry_guards != NULL); - - gs->should_add_entry_nodes = 0; - - if (!options->EntryNodes) { - /* It's possible that a controller set EntryNodes, thus making - * should_add_entry_nodes set, then cleared it again, all before the - * call to choose_random_entry() that triggered us. If so, just return. - */ - return; - } - - { - char *string = routerset_to_string(options->EntryNodes); - log_info(LD_CIRC,"Adding configured EntryNodes '%s'.", string); - tor_free(string); - } - - entry_nodes = smartlist_new(); - worse_entry_nodes = smartlist_new(); - entry_fps = smartlist_new(); - old_entry_guards_on_list = smartlist_new(); - old_entry_guards_not_on_list = smartlist_new(); - - /* Split entry guards into those on the list and those not. */ - - routerset_get_all_nodes(entry_nodes, options->EntryNodes, - options->ExcludeNodes, 0); - SMARTLIST_FOREACH(entry_nodes, const node_t *,node, - smartlist_add(entry_fps, (void*)node->identity)); - - SMARTLIST_FOREACH(gs->chosen_entry_guards, entry_guard_t *, e, { - if (smartlist_contains_digest(entry_fps, e->identity)) - smartlist_add(old_entry_guards_on_list, e); - else - smartlist_add(old_entry_guards_not_on_list, e); - }); - - /* Remove all currently configured guard nodes, excluded nodes, unreachable - * nodes, or non-Guard nodes from entry_nodes. */ - SMARTLIST_FOREACH_BEGIN(entry_nodes, const node_t *, node) { - if (entry_guard_get_by_id_digest_for_guard_selection(gs, - node->identity)) { - SMARTLIST_DEL_CURRENT(entry_nodes, node); - continue; - } else if (routerset_contains_node(options->ExcludeNodes, node)) { - SMARTLIST_DEL_CURRENT(entry_nodes, node); - continue; - } else if (!fascist_firewall_allows_node(node, FIREWALL_OR_CONNECTION, - 0)) { - SMARTLIST_DEL_CURRENT(entry_nodes, node); - continue; - } else if (! node->is_possible_guard) { - smartlist_add(worse_entry_nodes, (node_t*)node); - SMARTLIST_DEL_CURRENT(entry_nodes, node); - } - } SMARTLIST_FOREACH_END(node); - - /* Now build the new entry_guards list. */ - smartlist_clear(gs->chosen_entry_guards); - /* First, the previously configured guards that are in EntryNodes. */ - smartlist_add_all(gs->chosen_entry_guards, old_entry_guards_on_list); - /* Next, scramble the rest of EntryNodes, putting the guards first. */ - smartlist_shuffle(entry_nodes); - smartlist_shuffle(worse_entry_nodes); - smartlist_add_all(entry_nodes, worse_entry_nodes); - - /* Next, the rest of EntryNodes */ - SMARTLIST_FOREACH_BEGIN(entry_nodes, const node_t *, node) { - add_an_entry_guard(gs, node, 0, 0, 1, 0); - if (smartlist_len(gs->chosen_entry_guards) > numentryguards * 10) - break; - } SMARTLIST_FOREACH_END(node); - log_notice(LD_GENERAL, "%d entries in guards", - smartlist_len(gs->chosen_entry_guards)); - /* Finally, free the remaining previously configured guards that are not in - * EntryNodes. */ - SMARTLIST_FOREACH(old_entry_guards_not_on_list, entry_guard_t *, e, - entry_guard_free(e)); - - smartlist_free(entry_nodes); - smartlist_free(worse_entry_nodes); - smartlist_free(entry_fps); - smartlist_free(old_entry_guards_on_list); - smartlist_free(old_entry_guards_not_on_list); - entry_guards_changed_for_guard_selection(gs); -} -#endif - /** Return 0 if we're fine adding arbitrary routers out of the * directory to our entry guard list, or return 1 if we have a * list already and we must stick to it. @@ -3994,35 +2952,6 @@ entry_list_is_constrained(const or_options_t *options) return 0; } -#ifdef ENABLE_LEGACY_GUARD_ALGORITHM -/** Pick a live (up and listed) entry guard from entry_guards. If - * state is non-NULL, this is for a specific circuit -- - * make sure not to pick this circuit's exit or any node in the - * exit's family. If state is NULL, we're looking for a random - * guard (likely a bridge). If dirinfo is not NO_DIRINFO (zero), - * then only select from nodes that know how to answer directory questions - * of that type. */ -const node_t * -choose_random_entry(cpath_build_state_t *state) -{ - tor_assert(get_options()->UseDeprecatedGuardAlgorithm); - - return choose_random_entry_impl(get_guard_selection_info(), - state, 0, NO_DIRINFO, NULL); -} - -/** Pick a live (up and listed) directory guard from entry_guards for - * downloading information of type type. */ -const node_t * -choose_random_dirguard(dirinfo_type_t type) -{ - tor_assert(get_options()->UseDeprecatedGuardAlgorithm); - - return choose_random_entry_impl(get_guard_selection_info(), - NULL, 1, type, NULL); -} -#endif - /** Return the number of bridges that have descriptors that are marked with * purpose 'bridge' and are running. */ @@ -4031,15 +2960,7 @@ num_bridges_usable(void) { int n_options = 0; - if (get_options()->UseDeprecatedGuardAlgorithm) { -#ifdef ENABLE_LEGACY_GUARD_ALGORITHM - tor_assert(get_options()->UseBridges); - (void) choose_random_entry_impl(get_guard_selection_info(), - NULL, 0, 0, &n_options); -#else - tor_assert_nonfatal_unreached(); -#endif - } else { + if (1) { /* XXXX prop271 Is this quite right? */ tor_assert(get_options()->UseBridges); guard_selection_t *gs = get_guard_selection_info(); @@ -4059,221 +2980,6 @@ num_bridges_usable(void) return n_options; } -#ifdef ENABLE_LEGACY_GUARD_ALGORITHM -/** Filter all_entry_guards for usable entry guards and put them - * in live_entry_guards. We filter based on whether the node is - * currently alive, and on whether it satisfies the restrictions - * imposed by the other arguments of this function. - * - * We don't place more guards than NumEntryGuards in live_entry_guards. - * - * If chosen_exit is set, it contains the exit node of this - * circuit. Make sure to not use it or its family as an entry guard. - * - * If need_uptime is set, we are looking for a stable entry guard. - * if need_capacity is set, we are looking for a fast entry guard. - * - * The rest of the arguments are the same as in choose_random_entry_impl(). - * - * Return 1 if we should choose a guard right away. Return 0 if we - * should try to add more nodes to our list before deciding on a - * guard. - */ -STATIC int -populate_live_entry_guards(smartlist_t *live_entry_guards, - const smartlist_t *all_entry_guards, - const node_t *chosen_exit, - dirinfo_type_t dirinfo_type, - int for_directory, - int need_uptime, int need_capacity) -{ - const or_options_t *options = get_options(); - const node_t *node = NULL; - const int num_needed = decide_num_guards(options, for_directory); - smartlist_t *exit_family = smartlist_new(); - int retval = 0; - entry_is_live_flags_t entry_flags = 0; - - (void) dirinfo_type; - - { /* Set the flags we want our entry node to have */ - if (need_uptime) { - entry_flags |= ENTRY_NEED_UPTIME; - } - if (need_capacity) { - entry_flags |= ENTRY_NEED_CAPACITY; - } - if (!for_directory) { - entry_flags |= ENTRY_NEED_DESCRIPTOR; - } - } - - tor_assert(all_entry_guards); - - if (chosen_exit) { - nodelist_add_node_and_family(exit_family, chosen_exit); - } - - SMARTLIST_FOREACH_BEGIN(all_entry_guards, const entry_guard_t *, entry) { - const char *msg; - node = entry_is_live(entry, entry_flags, &msg); - if (!node) - continue; /* down, no point */ - if (for_directory) { - if (!entry->is_dir_cache) - continue; /* We need a directory and didn't get one. */ - } - if (node == chosen_exit) - continue; /* don't pick the same node for entry and exit */ - if (smartlist_contains(exit_family, node)) - continue; /* avoid relays that are family members of our exit */ - smartlist_add(live_entry_guards, (void*)node); - if (!entry->made_contact) { - /* Always start with the first not-yet-contacted entry - * guard. Otherwise we might add several new ones, pick - * the second new one, and now we've expanded our entry - * guard list without needing to. */ - retval = 1; - goto done; - } - if (smartlist_len(live_entry_guards) >= num_needed) { - retval = 1; - goto done; /* We picked enough entry guards. Done! */ - } - } SMARTLIST_FOREACH_END(entry); - - done: - smartlist_free(exit_family); - - return retval; -} - -/** Pick a node to be used as the entry guard of a circuit, relative to - * a supplied guard selection context. - * - * If state is set, it contains the information we know about - * the upcoming circuit. - * - * If for_directory is set, we are looking for a directory guard. - * - * dirinfo_type contains the kind of directory information we - * are looking for in our node, or NO_DIRINFO (zero) if we are not - * looking for any particular directory information (when set to - * NO_DIRINFO, the dirinfo_type filter is ignored). - * - * If n_options_out is set, we set it to the number of - * candidate guard nodes we had before picking a specific guard node. - * - * On success, return the node that should be used as the entry guard - * of the circuit. Return NULL if no such node could be found. - * - * Helper for choose_random{entry,dirguard}. -*/ -static const node_t * -choose_random_entry_impl(guard_selection_t *gs, - cpath_build_state_t *state, int for_directory, - dirinfo_type_t dirinfo_type, int *n_options_out) -{ - const or_options_t *options = get_options(); - smartlist_t *live_entry_guards = smartlist_new(); - const node_t *chosen_exit = - state?build_state_get_exit_node(state) : NULL; - const node_t *node = NULL; - int need_uptime = state ? state->need_uptime : 0; - int need_capacity = state ? state->need_capacity : 0; - int preferred_min = 0; - const int num_needed = decide_num_guards(options, for_directory); - int retval = 0; - - tor_assert(gs != NULL); - tor_assert(gs->chosen_entry_guards != NULL); - - if (n_options_out) - *n_options_out = 0; - - if (gs->should_add_entry_nodes) - entry_guards_set_from_config(gs, options); - - if (!entry_list_is_constrained(options) && - smartlist_len(gs->chosen_entry_guards) < num_needed) - pick_entry_guards(gs, options, for_directory); - - retry: - smartlist_clear(live_entry_guards); - - /* Populate the list of live entry guards so that we pick one of - them. */ - retval = populate_live_entry_guards(live_entry_guards, - gs->chosen_entry_guards, - chosen_exit, - dirinfo_type, - for_directory, - need_uptime, need_capacity); - - if (retval == 1) { /* We should choose a guard right now. */ - goto choose_and_finish; - } - - if (entry_list_is_constrained(options)) { - /* If we prefer the entry nodes we've got, and we have at least - * one choice, that's great. Use it. */ - preferred_min = 1; - } else { - /* Try to have at least 2 choices available. This way we don't - * get stuck with a single live-but-crummy entry and just keep - * using it. - * (We might get 2 live-but-crummy entry guards, but so be it.) */ - preferred_min = 2; - } - - if (smartlist_len(live_entry_guards) < preferred_min) { - if (!entry_list_is_constrained(options)) { - /* still no? try adding a new entry then */ - /* XXX if guard doesn't imply fast and stable, then we need - * to tell add_an_entry_guard below what we want, or it might - * be a long time til we get it. -RD */ - node = add_an_entry_guard(gs, NULL, 0, 0, 1, for_directory); - if (node) { - entry_guards_changed_for_guard_selection(gs); - /* XXX we start over here in case the new node we added shares - * a family with our exit node. There's a chance that we'll just - * load up on entry guards here, if the network we're using is - * one big family. Perhaps we should teach add_an_entry_guard() - * to understand nodes-to-avoid-if-possible? -RD */ - goto retry; - } - } - if (!node && need_uptime) { - need_uptime = 0; /* try without that requirement */ - goto retry; - } - if (!node && need_capacity) { - /* still no? last attempt, try without requiring capacity */ - need_capacity = 0; - goto retry; - } - - /* live_entry_guards may be empty below. Oh well, we tried. */ - } - - choose_and_finish: - if (entry_list_is_constrained(options)) { - /* We need to weight by bandwidth, because our bridges or entryguards - * were not already selected proportional to their bandwidth. */ - node = node_sl_choose_by_bandwidth(live_entry_guards, WEIGHT_FOR_GUARD); - } else { - /* We choose uniformly at random here, because choose_good_entry_server() - * already weights its choices by bandwidth, so we don't want to - * *double*-weight our guard selection. */ - node = smartlist_choose(live_entry_guards); - } - if (n_options_out) - *n_options_out = smartlist_len(live_entry_guards); - smartlist_free(live_entry_guards); - return node; -} -#endif - /** Check the pathbias use success count of node and disable it if it * goes over our thresholds. */ static void @@ -4320,262 +3026,6 @@ pathbias_check_close_success_count(entry_guard_t *node) } } -#ifdef ENABLE_LEGACY_GUARD_ALGORITHM -/** Parse state and learn about the entry guards it describes. - * If set is true, and there are no errors, replace the guard - * list in the provided guard selection context with what we find. - * On success, return 0. On failure, alloc into *msg a string - * describing the error, and return -1. - */ -int -entry_guards_parse_state_for_guard_selection( - guard_selection_t *gs, - or_state_t *state, int set, char **msg) -{ - entry_guard_t *node = NULL; - smartlist_t *new_entry_guards = smartlist_new(); - config_line_t *line; - time_t now = time(NULL); - const char *state_version = state->TorVersion; - digestmap_t *added_by = digestmap_new(); - - tor_assert(gs != NULL); - - *msg = NULL; - for (line = state->EntryGuards; line; line = line->next) { - if (!strcasecmp(line->key, "EntryGuard")) { - smartlist_t *args = smartlist_new(); - node = tor_malloc_zero(sizeof(entry_guard_t)); - /* all entry guards on disk have been contacted */ - node->made_contact = 1; - node->is_persistent = 1; - smartlist_add(new_entry_guards, node); - smartlist_split_string(args, line->value, " ", - SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0); - if (smartlist_len(args)<2) { - *msg = tor_strdup("Unable to parse entry nodes: " - "Too few arguments to EntryGuard"); - } else if (!is_legal_nickname(smartlist_get(args,0))) { - *msg = tor_strdup("Unable to parse entry nodes: " - "Bad nickname for EntryGuard"); - } else { - strlcpy(node->nickname, smartlist_get(args,0), MAX_NICKNAME_LEN+1); - if (base16_decode(node->identity, DIGEST_LEN, smartlist_get(args,1), - strlen(smartlist_get(args,1))) != DIGEST_LEN) { - *msg = tor_strdup("Unable to parse entry nodes: " - "Bad hex digest for EntryGuard"); - } - } - if (smartlist_len(args) >= 3) { - const char *is_cache = smartlist_get(args, 2); - if (!strcasecmp(is_cache, "DirCache")) { - node->is_dir_cache = 1; - } else if (!strcasecmp(is_cache, "NoDirCache")) { - node->is_dir_cache = 0; - } else { - log_warn(LD_CONFIG, "Bogus third argument to EntryGuard line: %s", - escaped(is_cache)); - } - } - SMARTLIST_FOREACH(args, char*, cp, tor_free(cp)); - smartlist_free(args); - if (*msg) - break; - } else if (!strcasecmp(line->key, "EntryGuardDownSince") || - !strcasecmp(line->key, "EntryGuardUnlistedSince")) { - time_t when; - time_t last_try = 0; - if (!node) { - *msg = tor_strdup("Unable to parse entry nodes: " - "EntryGuardDownSince/UnlistedSince without EntryGuard"); - break; - } - if (parse_iso_time_(line->value, &when, 0, 0)<0) { - *msg = tor_strdup("Unable to parse entry nodes: " - "Bad time in EntryGuardDownSince/UnlistedSince"); - break; - } - if (when > now) { - /* It's a bad idea to believe info in the future: you can wind - * up with timeouts that aren't allowed to happen for years. */ - continue; - } - if (strlen(line->value) >= ISO_TIME_LEN+ISO_TIME_LEN+1) { - /* ignore failure */ - (void) parse_iso_time(line->value+ISO_TIME_LEN+1, &last_try); - } - if (!strcasecmp(line->key, "EntryGuardDownSince")) { - node->unreachable_since = when; - node->last_attempted = last_try; - } else { - node->bad_since = when; - } - } else if (!strcasecmp(line->key, "EntryGuardAddedBy")) { - char d[DIGEST_LEN]; - /* format is digest version date */ - if (strlen(line->value) < HEX_DIGEST_LEN+1+1+1+ISO_TIME_LEN) { - log_warn(LD_BUG, "EntryGuardAddedBy line is not long enough."); - continue; - } - if (base16_decode(d, sizeof(d), - line->value, HEX_DIGEST_LEN) != sizeof(d) || - line->value[HEX_DIGEST_LEN] != ' ') { - log_warn(LD_BUG, "EntryGuardAddedBy line %s does not begin with " - "hex digest", escaped(line->value)); - continue; - } - digestmap_set(added_by, d, tor_strdup(line->value+HEX_DIGEST_LEN+1)); - } else if (!strcasecmp(line->key, "EntryGuardPathUseBias")) { - double use_cnt, success_cnt; - - if (!node) { - *msg = tor_strdup("Unable to parse entry nodes: " - "EntryGuardPathUseBias without EntryGuard"); - break; - } - - if (tor_sscanf(line->value, "%lf %lf", - &use_cnt, &success_cnt) != 2) { - log_info(LD_GENERAL, "Malformed path use bias line for node %s", - node->nickname); - continue; - } - - if (use_cnt < success_cnt) { - int severity = LOG_INFO; - /* If this state file was written by a Tor that would have - * already fixed it, then the overcounting bug is still there.. */ - if (tor_version_as_new_as(state_version, "0.2.4.13-alpha")) { - severity = LOG_NOTICE; - } - log_fn(severity, LD_BUG, - "State file contains unexpectedly high usage success " - "counts %lf/%lf for Guard %s ($%s)", - success_cnt, use_cnt, - node->nickname, hex_str(node->identity, DIGEST_LEN)); - success_cnt = use_cnt; - } - - node->pb.use_attempts = use_cnt; - node->pb.use_successes = success_cnt; - - log_info(LD_GENERAL, "Read %f/%f path use bias for node %s", - node->pb.use_successes, node->pb.use_attempts, node->nickname); - - pathbias_check_use_success_count(node); - - } else if (!strcasecmp(line->key, "EntryGuardPathBias")) { - double hop_cnt, success_cnt, timeouts, collapsed, successful_closed, - unusable; - - if (!node) { - *msg = tor_strdup("Unable to parse entry nodes: " - "EntryGuardPathBias without EntryGuard"); - break; - } - - /* First try 3 params, then 2. */ - /* In the long run: circuit_success ~= successful_circuit_close + - * collapsed_circuits + - * unusable_circuits */ - if (tor_sscanf(line->value, "%lf %lf %lf %lf %lf %lf", - &hop_cnt, &success_cnt, &successful_closed, - &collapsed, &unusable, &timeouts) != 6) { - int old_success, old_hops; - if (tor_sscanf(line->value, "%u %u", &old_success, &old_hops) != 2) { - continue; - } - log_info(LD_GENERAL, "Reading old-style EntryGuardPathBias %s", - escaped(line->value)); - - success_cnt = old_success; - successful_closed = old_success; - hop_cnt = old_hops; - timeouts = 0; - collapsed = 0; - unusable = 0; - } - - if (hop_cnt < success_cnt) { - int severity = LOG_INFO; - /* If this state file was written by a Tor that would have - * already fixed it, then the overcounting bug is still there.. */ - if (tor_version_as_new_as(state_version, "0.2.4.13-alpha")) { - severity = LOG_NOTICE; - } - log_fn(severity, LD_BUG, - "State file contains unexpectedly high success counts " - "%lf/%lf for Guard %s ($%s)", - success_cnt, hop_cnt, - node->nickname, hex_str(node->identity, DIGEST_LEN)); - success_cnt = hop_cnt; - } - - node->pb.circ_attempts = hop_cnt; - node->pb.circ_successes = success_cnt; - - node->pb.successful_circuits_closed = successful_closed; - node->pb.timeouts = timeouts; - node->pb.collapsed_circuits = collapsed; - node->pb.unusable_circuits = unusable; - - log_info(LD_GENERAL, "Read %f/%f path bias for node %s", - node->pb.circ_successes, node->pb.circ_attempts, - node->nickname); - - pathbias_check_close_success_count(node); - } else { - log_warn(LD_BUG, "Unexpected key %s", line->key); - } - } - - SMARTLIST_FOREACH_BEGIN(new_entry_guards, entry_guard_t *, e) { - char *sp; - char *val = digestmap_get(added_by, e->identity); - if (val && (sp = strchr(val, ' '))) { - time_t when; - *sp++ = '\0'; - if (parse_iso_time(sp, &when)<0) { - log_warn(LD_BUG, "Can't read time %s in EntryGuardAddedBy", sp); - } else { - e->chosen_by_version = tor_strdup(val); - e->chosen_on_date = when; - } - } else { - if (state_version) { - e->chosen_on_date = crypto_rand_time_range(now - 3600*24*30, now); - e->chosen_by_version = tor_strdup(state_version); - } - } - if (e->pb.path_bias_disabled && !e->bad_since) - e->bad_since = time(NULL); - } - SMARTLIST_FOREACH_END(e); - - if (*msg || !set) { - SMARTLIST_FOREACH(new_entry_guards, entry_guard_t *, e, - entry_guard_free(e)); - smartlist_free(new_entry_guards); - } else { /* !err && set */ - if (gs->chosen_entry_guards) { - SMARTLIST_FOREACH(gs->chosen_entry_guards, entry_guard_t *, e, - entry_guard_free(e)); - smartlist_free(gs->chosen_entry_guards); - } - gs->chosen_entry_guards = new_entry_guards; - SMARTLIST_FOREACH(new_entry_guards, entry_guard_t *, e, - e->in_selection = gs); - - /* XXX hand new_entry_guards to this func, and move it up a - * few lines, so we don't have to re-dirty it */ - if (remove_obsolete_entry_guards(gs, now)) - entry_guards_dirty = 1; - } - digestmap_free(added_by, tor_free_); - return *msg ? -1 : 0; -} -#endif - /** Parse state and learn about the entry guards it describes. * If set is true, and there are no errors, replace the guard * list in the default guard selection context with what we find. @@ -4586,20 +3036,10 @@ int entry_guards_parse_state(or_state_t *state, int set, char **msg) { entry_guards_dirty = 0; - int r1 = entry_guards_load_guards_from_state(state, set); - -#ifdef ENABLE_LEGACY_GUARD_ALGORITHM - int r2 = entry_guards_parse_state_for_guard_selection( - get_guard_selection_by_name("legacy", GS_TYPE_LEGACY, 1), - state, set, msg); -#else - int r2 = 0; -#endif - entry_guards_dirty = 0; - if (r1 < 0 || r2 < 0) { + if (r1 < 0) { if (msg && *msg == NULL) { *msg = tor_strdup("parsing error"); //xxxx prop271 should we try harder? } @@ -4664,83 +3104,6 @@ entry_guards_update_state(or_state_t *state) entry_guards_dirty = 0; -#ifdef ENABLE_LEGACY_GUARD_ALGORITHM - config_line_t **next, *line; - - guard_selection_t *gs; - gs = get_guard_selection_by_name("legacy", GS_TYPE_LEGACY, 0); - if (!gs) - return; // nothign to save. - tor_assert(gs->chosen_entry_guards != NULL); - - config_free_lines(state->EntryGuards); - next = &state->EntryGuards; - *next = NULL; - SMARTLIST_FOREACH_BEGIN(gs->chosen_entry_guards, entry_guard_t *, e) { - char dbuf[HEX_DIGEST_LEN+1]; - if (!e->made_contact) - continue; /* don't write this one to disk */ - *next = line = tor_malloc_zero(sizeof(config_line_t)); - line->key = tor_strdup("EntryGuard"); - base16_encode(dbuf, sizeof(dbuf), e->identity, DIGEST_LEN); - tor_asprintf(&line->value, "%s %s %sDirCache", e->nickname, dbuf, - e->is_dir_cache ? "" : "No"); - next = &(line->next); - if (e->unreachable_since) { - *next = line = tor_malloc_zero(sizeof(config_line_t)); - line->key = tor_strdup("EntryGuardDownSince"); - line->value = tor_malloc(ISO_TIME_LEN+1+ISO_TIME_LEN+1); - format_iso_time(line->value, e->unreachable_since); - if (e->last_attempted) { - line->value[ISO_TIME_LEN] = ' '; - format_iso_time(line->value+ISO_TIME_LEN+1, e->last_attempted); - } - next = &(line->next); - } - if (e->bad_since) { - *next = line = tor_malloc_zero(sizeof(config_line_t)); - line->key = tor_strdup("EntryGuardUnlistedSince"); - line->value = tor_malloc(ISO_TIME_LEN+1); - format_iso_time(line->value, e->bad_since); - next = &(line->next); - } - if (e->chosen_on_date && e->chosen_by_version && - !strchr(e->chosen_by_version, ' ')) { - char d[HEX_DIGEST_LEN+1]; - char t[ISO_TIME_LEN+1]; - *next = line = tor_malloc_zero(sizeof(config_line_t)); - line->key = tor_strdup("EntryGuardAddedBy"); - base16_encode(d, sizeof(d), e->identity, DIGEST_LEN); - format_iso_time(t, e->chosen_on_date); - tor_asprintf(&line->value, "%s %s %s", - d, e->chosen_by_version, t); - next = &(line->next); - } - if (e->pb.circ_attempts > 0) { - *next = line = tor_malloc_zero(sizeof(config_line_t)); - line->key = tor_strdup("EntryGuardPathBias"); - /* In the long run: circuit_success ~= successful_circuit_close + - * collapsed_circuits + - * unusable_circuits */ - tor_asprintf(&line->value, "%f %f %f %f %f %f", - e->pb.circ_attempts, e->pb.circ_successes, - pathbias_get_close_success_count(e), - e->pb.collapsed_circuits, - e->pb.unusable_circuits, e->pb.timeouts); - next = &(line->next); - } - if (e->pb.use_attempts > 0) { - *next = line = tor_malloc_zero(sizeof(config_line_t)); - line->key = tor_strdup("EntryGuardPathUseBias"); - - tor_asprintf(&line->value, "%f %f", - e->pb.use_attempts, - pathbias_get_use_success_count(e)); - next = &(line->next); - } - - } SMARTLIST_FOREACH_END(e); -#endif if (!get_options()->AvoidDiskWrites) or_state_mark_dirty(get_or_state(), 0); entry_guards_dirty = 0; @@ -4761,22 +3124,8 @@ getinfo_helper_format_single_entry_guard(const entry_guard_t *e, char nbuf[MAX_VERBOSE_NICKNAME_LEN+1]; if (legacy_guard) { -#ifdef ENABLE_LEGACY_GUARD_ALGORITHM - if (!e->made_contact) { - status = "never-connected"; - } else if (e->bad_since) { - when = e->bad_since; - status = "unusable"; - } else if (e->unreachable_since) { - when = e->unreachable_since; - status = "down"; - } else { - status = "up"; - } -#else tor_assert_nonfatal_unreached(); status = "BUG"; -#endif } else { /* modern case. This is going to be a bit tricky, since the status * codes above weren't really intended for prop271 guards. @@ -4835,9 +3184,6 @@ getinfo_helper_entry_guards(control_connection_t *conn, guard_selection_t *gs = get_guard_selection_info(); tor_assert(gs != NULL); -#ifdef ENABLE_LEGACY_GUARD_ALGORITHM - tor_assert(gs->chosen_entry_guards != NULL); -#endif (void) conn; (void) errmsg; @@ -4847,13 +3193,8 @@ getinfo_helper_entry_guards(control_connection_t *conn, const smartlist_t *guards; int legacy_mode; if (gs->type == GS_TYPE_LEGACY) { -#ifdef ENABLE_LEGACY_GUARD_ALGORITHM - guards = gs->chosen_entry_guards; - legacy_mode = 1; -#else tor_assert_nonfatal_unreached(); return 0; -#endif } else { guards = gs->sampled_entry_guards; legacy_mode = 0; @@ -4907,107 +3248,6 @@ guard_get_guardfraction_bandwidth(guardfraction_bandwidth_t *guardfraction_bw, guardfraction_bw->non_guard_bw = orig_bandwidth - (int) guard_bw; } -#ifdef ENABLE_LEGACY_GUARD_ALGORITHM -/** Returns true iff the node is used as a guard in the specified guard - * context */ -int -is_node_used_as_guard_for_guard_selection(guard_selection_t *gs, - const node_t *node) -{ - int res = 0; - - /* - * We used to have a using_as_guard flag in node_t, but it had to go away - * to allow for multiple guard selection contexts. Instead, search the - * guard list for a matching digest. - */ - - tor_assert(gs != NULL); - tor_assert(node != NULL); - - SMARTLIST_FOREACH_BEGIN(gs->chosen_entry_guards, entry_guard_t *, e) { - if (tor_memeq(e->identity, node->identity, DIGEST_LEN)) { - res = 1; - break; - } - } SMARTLIST_FOREACH_END(e); - - return res; -} - -/** Returns true iff the node is used as a guard in the default guard - * context */ -MOCK_IMPL(int, -is_node_used_as_guard, (const node_t *node)) -{ - return is_node_used_as_guard_for_guard_selection( - get_guard_selection_info(), node); -} - -/** Return 1 if we have at least one descriptor for an entry guard - * (bridge or member of EntryNodes) and all descriptors we know are - * down. Else return 0. If act is 1, then mark the down guards - * up; else just observe and report. */ -static int -entries_retry_helper(const or_options_t *options, int act) -{ - const node_t *node; - int any_known = 0; - int any_running = 0; - int need_bridges = options->UseBridges != 0; - guard_selection_t *gs = get_guard_selection_info(); - - tor_assert(gs != NULL); - tor_assert(gs->chosen_entry_guards != NULL); - - SMARTLIST_FOREACH_BEGIN(gs->chosen_entry_guards, entry_guard_t *, e) { - node = node_get_by_id(e->identity); - if (node && node_has_descriptor(node) && - node_is_bridge(node) == need_bridges && - (!need_bridges || (!e->bad_since && - node_is_a_configured_bridge(node)))) { - any_known = 1; - if (node->is_running) - any_running = 1; /* some entry is both known and running */ - else if (act) { - /* Mark all current connections to this OR as unhealthy, since - * otherwise there could be one that started 30 seconds - * ago, and in 30 seconds it will time out, causing us to mark - * the node down and undermine the retry attempt. We mark even - * the established conns, since if the network just came back - * we'll want to attach circuits to fresh conns. */ - channel_update_bad_for_new_circs(node->identity, 1); - - /* mark this entry node for retry */ - router_set_status(node->identity, 1); - e->can_retry = 1; - e->bad_since = 0; - } - } - } SMARTLIST_FOREACH_END(e); - log_debug(LD_DIR, "%d: any_known %d, any_running %d", - act, any_known, any_running); - return any_known && !any_running; -} - -/** Do we know any descriptors for our bridges / entrynodes, and are - * all the ones we have descriptors for down? */ -int -entries_known_but_down(const or_options_t *options) -{ - tor_assert(entry_list_is_constrained(options)); - return entries_retry_helper(options, 0); -} - -/** Mark all down known bridges / entrynodes up. */ -void -entries_retry_all(const or_options_t *options) -{ - tor_assert(entry_list_is_constrained(options)); - entries_retry_helper(options, 1); -} -#endif - /** Helper: Update the status of all entry guards, in whatever algorithm * is used. Return true if we should stop using all previously generated * circuits, by calling circuit_mark_all_unused_circs() and @@ -5023,11 +3263,7 @@ guards_update_all(void) tor_assert(curr_guard_context); if (curr_guard_context->type == GS_TYPE_LEGACY) { -#ifdef ENABLE_LEGACY_GUARD_ALGORITHM - entry_guards_compute_status(get_options(), approx_time()); -#else tor_assert_nonfatal_unreached(); -#endif } else { if (entry_guards_update_all(curr_guard_context)) mark_circuits = 1; @@ -5043,12 +3279,8 @@ guards_choose_guard(cpath_build_state_t *state, circuit_guard_state_t **guard_state_out) { if (get_options()->UseDeprecatedGuardAlgorithm) { -#ifdef ENABLE_LEGACY_GUARD_ALGORITHM - return choose_random_entry(state); -#else tor_assert_nonfatal_unreached(); return NULL; -#endif } else { const node_t *r = NULL; const uint8_t *exit_id = NULL; @@ -5077,13 +3309,9 @@ guards_choose_dirguard(dirinfo_type_t info, circuit_guard_state_t **guard_state_out) { if (get_options()->UseDeprecatedGuardAlgorithm) { -#ifdef ENABLE_LEGACY_GUARD_ALGORITHM - return choose_random_dirguard(info); -#else (void)info; tor_assert_nonfatal_unreached(); return NULL; -#endif } else { /* XXXX prop271 We don't need to look at the dirinfo_type_t here, * apparently. If you look at the old implementation, and you follow info @@ -5114,15 +3342,6 @@ guards_retry_optimistic(const or_options_t *options) if (! entry_list_is_constrained(options)) return 0; -#ifdef ENABLE_LEGACY_GUARD_ALGORITHM - if (options->UseDeprecatedGuardAlgorithm) { - if (entries_known_but_down(options)) { - entries_retry_all(options); - return 1; - } - } -#endif - // XXXX prop271 -- is this correct? mark_primary_guards_maybe_reachable(get_guard_selection_info()); @@ -5137,15 +3356,6 @@ guard_selection_free(guard_selection_t *gs) tor_free(gs->name); -#ifdef ENABLE_LEGACY_GUARD_ALGORITHM - if (gs->chosen_entry_guards) { - SMARTLIST_FOREACH(gs->chosen_entry_guards, entry_guard_t *, e, - entry_guard_free(e)); - smartlist_free(gs->chosen_entry_guards); - gs->chosen_entry_guards = NULL; - } -#endif - if (gs->sampled_entry_guards) { SMARTLIST_FOREACH(gs->sampled_entry_guards, entry_guard_t *, e, entry_guard_free(e)); diff --git a/src/or/entrynodes.h b/src/or/entrynodes.h index 5fa0fec37f..a1ede71971 100644 --- a/src/or/entrynodes.h +++ b/src/or/entrynodes.h @@ -28,11 +28,6 @@ typedef struct circuit_guard_state_t circuit_guard_state_t; private. */ typedef struct entry_guard_restriction_t entry_guard_restriction_t; -/* - XXXX Prop271 undefine this in order to disable all legacy guard functions. -*/ -// #define ENABLE_LEGACY_GUARD_ALGORITHM - /* Information about a guard's pathbias status. * These fields are used in circpathbias.c to try to detect entry * nodes that are failing circuits at a suspicious frequency. @@ -179,37 +174,6 @@ struct entry_guard_t { guard_selection_t *in_selection; /**@}*/ -#ifdef ENABLE_LEGACY_GUARD_ALGORITHM - /** - * @name legacy guard selection algorithm fields - * - * These are used and maintained by the legacy (pre-prop271) entry guard - * algorithm. Most of them we will remove as prop271 gets implemented. - * The rest we'll migrate over, if they are 100% semantically identical to - * their prop271 equivalents. XXXXprop271 - */ - /**@{*/ - time_t chosen_on_date; /**< Approximately when was this guard added? - * "0" if we don't know. */ - char *chosen_by_version; /**< What tor version added this guard? NULL - * if we don't know. */ - unsigned int made_contact : 1; /**< 0 if we have never connected to this - * router, 1 if we have. */ - unsigned int can_retry : 1; /**< Should we retry connecting to this entry, - * in spite of having it marked as unreachable?*/ - unsigned int is_dir_cache : 1; /**< Is this node a directory cache? */ - time_t bad_since; /**< 0 if this guard is currently usable, or the time at - * which it was observed to become (according to the - * directory or the user configuration) unusable. */ - time_t unreachable_since; /**< 0 if we can connect to this guard, or the - * time at which we first noticed we couldn't - * connect to it. */ - time_t last_attempted; /**< 0 if we can connect to this guard, or the time - * at which we last failed to connect to it. */ - - /**}@*/ -#endif - /** Path bias information for this guard. */ guard_pathbias_t pb; }; @@ -305,20 +269,6 @@ struct guard_selection_s { * confirmed_entry_guards receive? */ int next_confirmed_idx; -#ifdef ENABLE_LEGACY_GUARD_ALGORITHM - /** - * A list of our chosen entry guards, as entry_guard_t structures; this - * preserves the pre-Prop271 behavior. - */ - smartlist_t *chosen_entry_guards; - - /** - * When we try to choose an entry guard, should we parse and add - * config's EntryNodes first? This was formerly a global. This - * preserves the pre-Prop271 behavior. - */ - int should_add_entry_nodes; -#endif }; struct entry_guard_handle_t; @@ -378,11 +328,6 @@ 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); guard_selection_t * get_guard_selection_info(void); -#ifdef ENABLE_LEGACY_GUARD_ALGORITHM -const smartlist_t *get_entry_guards_for_guard_selection( - guard_selection_t *gs); -const smartlist_t *get_entry_guards(void); -#endif int num_live_entry_guards_for_guard_selection( guard_selection_t *gs, int for_directory); @@ -390,9 +335,6 @@ int num_live_entry_guards(int for_directory); #endif const node_t *entry_guard_find_node(const entry_guard_t *guard); -#ifdef ENABLE_LEGACY_GUARD_ALGORITHM -void entry_guard_mark_bad(entry_guard_t *guard); -#endif const char *entry_guard_get_rsa_id_digest(const entry_guard_t *guard); const char *entry_guard_describe(const entry_guard_t *guard); guard_pathbias_t *entry_guard_get_pathbias_state(entry_guard_t *guard); @@ -432,10 +374,6 @@ void entry_guards_note_internet_connectivity(guard_selection_t *gs); int update_guard_selection_choice(const or_options_t *options); /* Used by bridges.c only. */ -#ifdef ENABLE_LEGACY_GUARD_ALGORITHM -void add_bridge_as_entry_guard(guard_selection_t *gs, - const node_t *chosen); -#endif int num_bridges_usable(void); #ifdef ENTRYNODES_PRIVATE @@ -612,68 +550,13 @@ STATIC unsigned entry_guards_note_guard_success(guard_selection_t *gs, STATIC int entry_guard_has_higher_priority(entry_guard_t *a, entry_guard_t *b); STATIC char *getinfo_helper_format_single_entry_guard(const entry_guard_t *e, int is_legacy); -#ifdef ENABLE_LEGACY_GUARD_ALGORITHM -// ---------- XXXX this stuff is pre-prop271. - -STATIC const node_t *add_an_entry_guard(guard_selection_t *gs, - const node_t *chosen, - int reset_status, int prepend, - int for_discovery, int for_directory); -STATIC int populate_live_entry_guards(smartlist_t *live_entry_guards, - const smartlist_t *all_entry_guards, - const node_t *chosen_exit, - dirinfo_type_t dirinfo_type, - int for_directory, - int need_uptime, int need_capacity); -STATIC int decide_num_guards(const or_options_t *options, int for_directory); - -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 - * entry nodes we are looking for. */ -typedef enum { - ENTRY_NEED_UPTIME = 1<<0, - ENTRY_NEED_CAPACITY = 1<<1, - ENTRY_ASSUME_REACHABLE = 1<<2, - ENTRY_NEED_DESCRIPTOR = 1<<3, -} entry_is_live_flags_t; - -STATIC const node_t *entry_is_live(const entry_guard_t *e, - entry_is_live_flags_t flags, - const char **msg); - -STATIC int entry_is_time_to_retry(const entry_guard_t *e, time_t now); -#endif - -#endif - -#ifdef ENABLE_LEGACY_GUARD_ALGORITHM -void remove_all_entry_guards_for_guard_selection(guard_selection_t *gs); -void remove_all_entry_guards(void); #endif struct bridge_info_t; void entry_guard_learned_bridge_identity(const tor_addr_port_t *addrport, const uint8_t *rsa_id_digest); -#ifdef ENABLE_LEGACY_GUARD_ALGORITHM -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); -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 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); -#endif int entry_list_is_constrained(const or_options_t *options); -#ifdef ENABLE_LEGACY_GUARD_ALGORITHM -const node_t *choose_random_entry(cpath_build_state_t *state); -const node_t *choose_random_dirguard(dirinfo_type_t t); -#endif int guards_retry_optimistic(const or_options_t *options); int entry_guards_parse_state_for_guard_selection( guard_selection_t *gs, or_state_t *state, int set, char **msg); @@ -682,11 +565,6 @@ void entry_guards_update_state(or_state_t *state); int getinfo_helper_entry_guards(control_connection_t *conn, const char *question, char **answer, const char **errmsg); -#ifdef ENABLE_LEGACY_GUARD_ALGORITHM -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)); -#endif int entries_known_but_down(const or_options_t *options); void entries_retry_all(const or_options_t *options); diff --git a/src/or/routerlist.c b/src/or/routerlist.c index 72474b1152..03f8bc7744 100644 --- a/src/or/routerlist.c +++ b/src/or/routerlist.c @@ -1999,10 +1999,7 @@ router_pick_directory_server_impl(dirinfo_type_t type, int flags, const int for_guard = (flags & PDS_FOR_GUARD); int try_excluding = 1, n_excluded = 0, n_busy = 0; int try_ip_pref = 1; - -#ifndef ENABLE_LEGACY_GUARD_ALGORITHM - tor_assert_nonfatal(! for_guard); -#endif + tor_assert_nonfatal(! for_guard); // XXXX prop271 if (!consensus) return NULL; @@ -2036,12 +2033,6 @@ router_pick_directory_server_impl(dirinfo_type_t type, int flags, SKIP_MISSING_TRUSTED_EXTRAINFO(type, node->identity); -#ifdef ENABLE_LEGACY_GUARD_ALGORITHM - /* Don't make the same node a guard twice */ - if (for_guard && is_node_used_as_guard(node)) { - continue; - } -#endif /* Ensure that a directory guard is actually a guard node. */ if (for_guard && !node->is_possible_guard) { continue; diff --git a/src/test/test_entrynodes.c b/src/test/test_entrynodes.c index 32f8b6e0dd..2e7abd1e00 100644 --- a/src/test/test_entrynodes.c +++ b/src/test/test_entrynodes.c @@ -45,41 +45,6 @@ get_or_state_replacement(void) return dummy_state; } -#ifdef ENABLE_LEGACY_GUARD_ALGORITHM -/* Unittest cleanup function: Cleanup the fake network. */ -static int -fake_network_cleanup(const struct testcase_t *testcase, void *ptr) -{ - (void) testcase; - (void) ptr; - - routerlist_free_all(); - nodelist_free_all(); - entry_guards_free_all(); - or_state_free(dummy_state); - - return 1; /* NOP */ -} - -/* Unittest setup function: Setup a fake network. */ -static void * -fake_network_setup(const struct testcase_t *testcase) -{ - (void) testcase; - - /* Setup fake state */ - dummy_state = tor_malloc_zero(sizeof(or_state_t)); - MOCK(get_or_state, - get_or_state_replacement); - - /* Setup fake routerlist. */ - helper_setup_fake_routerlist(); - - /* Return anything but NULL (it's interpreted as test fail) */ - return dummy_state; -} -#endif - static networkstatus_t *dummy_consensus = NULL; static smartlist_t *big_fake_net_nodes = NULL; @@ -202,697 +167,6 @@ mock_get_options(void) return &mocked_options; } -#ifdef ENABLE_LEGACY_GUARD_ALGORITHM -/** Test choose_random_entry() with none of our routers being guard nodes. */ -static void -test_choose_random_entry_no_guards(void *arg) -{ - const node_t *chosen_entry = NULL; - - (void) arg; - - MOCK(get_options, mock_get_options); - - /* Check that we get a guard if it passes preferred - * address settings */ - memset(&mocked_options, 0, sizeof(mocked_options)); - mocked_options.ClientUseIPv4 = 1; - mocked_options.ClientPreferIPv6ORPort = 0; - mocked_options.UseDeprecatedGuardAlgorithm = 1; - - /* Try to pick an entry even though none of our routers are guards. */ - chosen_entry = choose_random_entry(NULL); - - /* Unintuitively, we actually pick a random node as our entry, - because router_choose_random_node() relaxes its constraints if it - can't find a proper entry guard. */ - tt_assert(chosen_entry); - - /* And with the other IP version active */ - mocked_options.ClientUseIPv6 = 1; - chosen_entry = choose_random_entry(NULL); - tt_assert(chosen_entry); - - /* And with the preference on auto */ - mocked_options.ClientPreferIPv6ORPort = -1; - chosen_entry = choose_random_entry(NULL); - tt_assert(chosen_entry); - - /* Check that we don't get a guard if it doesn't pass mandatory address - * settings */ - memset(&mocked_options, 0, sizeof(mocked_options)); - mocked_options.ClientUseIPv4 = 0; - mocked_options.ClientPreferIPv6ORPort = 0; - mocked_options.UseDeprecatedGuardAlgorithm = 1; - - chosen_entry = choose_random_entry(NULL); - - /* If we don't allow IPv4 at all, we don't get a guard*/ - tt_assert(!chosen_entry); - - /* Check that we get a guard if it passes allowed but not preferred address - * settings */ - memset(&mocked_options, 0, sizeof(mocked_options)); - mocked_options.ClientUseIPv4 = 1; - mocked_options.ClientUseIPv6 = 1; - mocked_options.ClientPreferIPv6ORPort = 1; - mocked_options.UseDeprecatedGuardAlgorithm = 1; - - chosen_entry = choose_random_entry(NULL); - tt_assert(chosen_entry); - - /* Check that we get a guard if it passes preferred address settings when - * they're auto */ - memset(&mocked_options, 0, sizeof(mocked_options)); - mocked_options.ClientUseIPv4 = 1; - mocked_options.ClientPreferIPv6ORPort = -1; - mocked_options.UseDeprecatedGuardAlgorithm = 1; - - chosen_entry = choose_random_entry(NULL); - tt_assert(chosen_entry); - - /* And with IPv6 active */ - mocked_options.ClientUseIPv6 = 1; - - chosen_entry = choose_random_entry(NULL); - tt_assert(chosen_entry); - - done: - memset(&mocked_options, 0, sizeof(mocked_options)); - UNMOCK(get_options); -} - -/** Test choose_random_entry() with only one of our routers being a - guard node. */ -static void -test_choose_random_entry_one_possible_guard(void *arg) -{ - const node_t *chosen_entry = NULL; - node_t *the_guard = NULL; - smartlist_t *our_nodelist = NULL; - - (void) arg; - - MOCK(get_options, mock_get_options); - - /* Set one of the nodes to be a guard. */ - our_nodelist = nodelist_get_list(); - the_guard = smartlist_get(our_nodelist, 4); /* chosen by fair dice roll */ - the_guard->is_possible_guard = 1; - - /* Check that we get the guard if it passes preferred - * address settings */ - memset(&mocked_options, 0, sizeof(mocked_options)); - mocked_options.ClientUseIPv4 = 1; - mocked_options.ClientPreferIPv6ORPort = 0; - mocked_options.UseDeprecatedGuardAlgorithm = 1; - - /* Pick an entry. Make sure we pick the node we marked as guard. */ - chosen_entry = choose_random_entry(NULL); - tt_ptr_op(chosen_entry, OP_EQ, the_guard); - - /* And with the other IP version active */ - mocked_options.ClientUseIPv6 = 1; - chosen_entry = choose_random_entry(NULL); - tt_ptr_op(chosen_entry, OP_EQ, the_guard); - - /* And with the preference on auto */ - mocked_options.ClientPreferIPv6ORPort = -1; - chosen_entry = choose_random_entry(NULL); - tt_ptr_op(chosen_entry, OP_EQ, the_guard); - - /* Check that we don't get a guard if it doesn't pass mandatory address - * settings */ - memset(&mocked_options, 0, sizeof(mocked_options)); - mocked_options.ClientUseIPv4 = 0; - mocked_options.ClientPreferIPv6ORPort = 0; - mocked_options.UseDeprecatedGuardAlgorithm = 1; - - chosen_entry = choose_random_entry(NULL); - - /* If we don't allow IPv4 at all, we don't get a guard*/ - tt_assert(!chosen_entry); - - /* Check that we get a node if it passes allowed but not preferred - * address settings */ - memset(&mocked_options, 0, sizeof(mocked_options)); - mocked_options.ClientUseIPv4 = 1; - mocked_options.ClientUseIPv6 = 1; - mocked_options.ClientPreferIPv6ORPort = 1; - mocked_options.UseDeprecatedGuardAlgorithm = 1; - - chosen_entry = choose_random_entry(NULL); - - /* We disable the guard check and the preferred address check at the same - * time, so we can't be sure we get the guard */ - tt_assert(chosen_entry); - - /* Check that we get a node if it is allowed but not preferred when settings - * are auto */ - memset(&mocked_options, 0, sizeof(mocked_options)); - mocked_options.ClientUseIPv4 = 1; - mocked_options.ClientPreferIPv6ORPort = -1; - mocked_options.UseDeprecatedGuardAlgorithm = 1; - - chosen_entry = choose_random_entry(NULL); - - /* We disable the guard check and the preferred address check at the same - * time, so we can't be sure we get the guard */ - tt_assert(chosen_entry); - - /* and with IPv6 active */ - mocked_options.ClientUseIPv6 = 1; - - chosen_entry = choose_random_entry(NULL); - tt_assert(chosen_entry); - - done: - memset(&mocked_options, 0, sizeof(mocked_options)); - UNMOCK(get_options); -} - -/** Helper to conduct tests for populate_live_entry_guards(). - - This test adds some entry guards to our list, and then tests - populate_live_entry_guards() to mke sure it filters them correctly. - - num_needed is the number of guard nodes we support. It's - configurable to make sure we function properly with 1 or 3 guard - nodes configured. -*/ -static void -populate_live_entry_guards_test_helper(int num_needed) -{ - smartlist_t *our_nodelist = NULL; - smartlist_t *live_entry_guards = smartlist_new(); - 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(); - int retval; - - /* Set NumEntryGuards to the provided number. */ - options->NumEntryGuards = num_needed; - tt_int_op(num_needed, OP_EQ, decide_num_guards(options, 0)); - - /* The global entry guards smartlist should be empty now. */ - tt_int_op(smartlist_len(all_entry_guards), OP_EQ, 0); - - /* Walk the nodelist and add all nodes as entry guards. */ - our_nodelist = nodelist_get_list(); - tt_int_op(smartlist_len(our_nodelist), OP_EQ, HELPER_NUMBER_OF_DESCRIPTORS); - - SMARTLIST_FOREACH_BEGIN(our_nodelist, const node_t *, node) { - const node_t *node_tmp; - node_tmp = add_an_entry_guard(gs, node, 0, 1, 0, 0); - tt_assert(node_tmp); - } SMARTLIST_FOREACH_END(node); - - /* Make sure the nodes were added as entry guards. */ - tt_int_op(smartlist_len(all_entry_guards), OP_EQ, - HELPER_NUMBER_OF_DESCRIPTORS); - - /* Ensure that all the possible entry guards are enough to satisfy us. */ - tt_int_op(smartlist_len(all_entry_guards), OP_GE, num_needed); - - /* Walk the entry guard list for some sanity checking */ - SMARTLIST_FOREACH_BEGIN(all_entry_guards, const entry_guard_t *, entry) { - /* Since we called add_an_entry_guard() with 'for_discovery' being - False, all guards should have made_contact enabled. */ - tt_int_op(entry->made_contact, OP_EQ, 1); - - } SMARTLIST_FOREACH_END(entry); - - /* First, try to get some fast guards. This should fail. */ - retval = populate_live_entry_guards(live_entry_guards, - all_entry_guards, - NULL, - NO_DIRINFO, /* Don't care about DIRINFO*/ - 0, 0, - 1); /* We want fast guard! */ - tt_int_op(retval, OP_EQ, 0); - tt_int_op(smartlist_len(live_entry_guards), OP_EQ, 0); - - /* Now try to get some stable guards. This should fail too. */ - retval = populate_live_entry_guards(live_entry_guards, - all_entry_guards, - NULL, - NO_DIRINFO, - 0, - 1, /* We want stable guard! */ - 0); - tt_int_op(retval, OP_EQ, 0); - tt_int_op(smartlist_len(live_entry_guards), OP_EQ, 0); - - /* Now try to get any guard we can find. This should succeed. */ - retval = populate_live_entry_guards(live_entry_guards, - all_entry_guards, - NULL, - NO_DIRINFO, - 0, 0, 0); /* No restrictions! */ - - /* Since we had more than enough guards in 'all_entry_guards', we - should have added 'num_needed' of them to live_entry_guards. - 'retval' should be 1 since we now have enough live entry guards - to pick one. */ - tt_int_op(retval, OP_EQ, 1); - tt_int_op(smartlist_len(live_entry_guards), OP_EQ, num_needed); - - done: - smartlist_free(live_entry_guards); -} - -/* Test populate_live_entry_guards() for 1 guard node. */ -static void -test_populate_live_entry_guards_1guard(void *arg) -{ - (void) arg; - - populate_live_entry_guards_test_helper(1); -} - -/* Test populate_live_entry_guards() for 3 guard nodes. */ -static void -test_populate_live_entry_guards_3guards(void *arg) -{ - (void) arg; - - populate_live_entry_guards_test_helper(3); -} - -/** Append some EntryGuard lines to the Tor state at state. - - entry_guard_lines is a smartlist containing 2-tuple - smartlists that carry the key and values of the statefile. - As an example: - entry_guard_lines = - (("EntryGuard", "name 67E72FF33D7D41BF11C569646A0A7B4B188340DF DirCache"), - ("EntryGuardDownSince", "2014-06-07 16:02:46 2014-06-07 16:02:46")) -*/ -static void -state_insert_entry_guard_helper(or_state_t *state, - smartlist_t *entry_guard_lines) -{ - config_line_t **next, *line; - - next = &state->EntryGuards; - *next = NULL; - - /* Loop over all the state lines in the smartlist */ - SMARTLIST_FOREACH_BEGIN(entry_guard_lines, const smartlist_t *,state_lines) { - /* Get key and value for each line */ - const char *state_key = smartlist_get(state_lines, 0); - const char *state_value = smartlist_get(state_lines, 1); - - *next = line = tor_malloc_zero(sizeof(config_line_t)); - line->key = tor_strdup(state_key); - tor_asprintf(&line->value, "%s", state_value); - next = &(line->next); - } SMARTLIST_FOREACH_END(state_lines); -} - -/** Free memory occupied by entry_guard_lines. */ -static void -state_lines_free(smartlist_t *entry_guard_lines) -{ - SMARTLIST_FOREACH_BEGIN(entry_guard_lines, smartlist_t *, state_lines) { - char *state_key = smartlist_get(state_lines, 0); - char *state_value = smartlist_get(state_lines, 1); - - tor_free(state_key); - tor_free(state_value); - smartlist_free(state_lines); - } SMARTLIST_FOREACH_END(state_lines); - - smartlist_free(entry_guard_lines); -} - -/* Tests entry_guards_parse_state(). It creates a fake Tor state with - a saved entry guard and makes sure that Tor can parse it and - creates the right entry node out of it. -*/ -static void -test_entry_guards_parse_state_simple(void *arg) -{ - or_options_t *options = get_options_mutable(); - options->UseDeprecatedGuardAlgorithm = 1; - or_state_t *state = or_state_new(); - const smartlist_t *all_entry_guards = get_entry_guards(); - smartlist_t *entry_state_lines = smartlist_new(); - char *msg = NULL; - int retval; - - /* Details of our fake guard node */ - const char *nickname = "hagbard"; - const char *fpr = "B29D536DD1752D542E1FBB3C9CE4449D51298212"; - const char *tor_version = "0.2.5.3-alpha-dev"; - const char *added_at = get_yesterday_date_str(); - const char *unlisted_since = "2014-06-08 16:16:50"; - - (void) arg; - - /* The global entry guards smartlist should be empty now. */ - tt_int_op(smartlist_len(all_entry_guards), OP_EQ, 0); - - { /* Prepare the state entry */ - - /* Prepare the smartlist to hold the key/value of each line */ - smartlist_t *state_line = smartlist_new(); - smartlist_add_asprintf(state_line, "EntryGuard"); - smartlist_add_asprintf(state_line, "%s %s %s", nickname, fpr, "DirCache"); - smartlist_add(entry_state_lines, state_line); - - state_line = smartlist_new(); - smartlist_add_asprintf(state_line, "EntryGuardAddedBy"); - smartlist_add_asprintf(state_line, "%s %s %s", fpr, tor_version, added_at); - smartlist_add(entry_state_lines, state_line); - - state_line = smartlist_new(); - smartlist_add_asprintf(state_line, "EntryGuardUnlistedSince"); - smartlist_add_asprintf(state_line, "%s", unlisted_since); - smartlist_add(entry_state_lines, state_line); - } - - /* Inject our lines in the state */ - state_insert_entry_guard_helper(state, entry_state_lines); - - /* Parse state */ - retval = entry_guards_parse_state(state, 1, &msg); - tt_int_op(retval, OP_GE, 0); - - /* Test that the guard was registered. - We need to re-get the entry guard list since its pointer was - overwritten in entry_guards_parse_state(). */ - all_entry_guards = get_entry_guards(); - tt_int_op(smartlist_len(all_entry_guards), OP_EQ, 1); - - { /* Test the entry guard structure */ - char hex_digest[1024]; - char str_time[1024]; - - const entry_guard_t *e = smartlist_get(all_entry_guards, 0); - tt_str_op(e->nickname, OP_EQ, nickname); /* Verify nickname */ - - base16_encode(hex_digest, sizeof(hex_digest), - e->identity, DIGEST_LEN); - tt_str_op(hex_digest, OP_EQ, fpr); /* Verify fingerprint */ - - tt_assert(e->is_dir_cache); /* Verify dirness */ - - tt_str_op(e->chosen_by_version, OP_EQ, tor_version); /* Verify version */ - - tt_assert(e->made_contact); /* All saved guards have been contacted */ - - tt_assert(e->bad_since); /* Verify bad_since timestamp */ - format_iso_time(str_time, e->bad_since); - tt_str_op(str_time, OP_EQ, unlisted_since); - - /* The rest should be unset */ - tt_assert(!e->unreachable_since); - tt_assert(!e->can_retry); - tt_assert(!e->pb.path_bias_noticed); - tt_assert(!e->pb.path_bias_warned); - tt_assert(!e->pb.path_bias_extreme); - tt_assert(!e->pb.path_bias_disabled); - tt_assert(!e->pb.path_bias_use_noticed); - tt_assert(!e->pb.path_bias_use_extreme); - tt_assert(!e->last_attempted); - } - - done: - state_lines_free(entry_state_lines); - or_state_free(state); - tor_free(msg); -} - -/** Similar to test_entry_guards_parse_state_simple() but aims to test - the PathBias-related details of the entry guard. */ -static void -test_entry_guards_parse_state_pathbias(void *arg) -{ - or_options_t *options = get_options_mutable(); - options->UseDeprecatedGuardAlgorithm = 1; - or_state_t *state = or_state_new(); - const smartlist_t *all_entry_guards = get_entry_guards(); - char *msg = NULL; - int retval; - smartlist_t *entry_state_lines = smartlist_new(); - - /* Path bias details of the fake guard */ - const double circ_attempts = 9; - const double circ_successes = 8; - const double successful_closed = 4; - const double collapsed = 2; - const double unusable = 0; - const double timeouts = 1; - - (void) arg; - - /* The global entry guards smartlist should be empty now. */ - tt_int_op(smartlist_len(all_entry_guards), OP_EQ, 0); - - { /* Prepare the state entry */ - - /* Prepare the smartlist to hold the key/value of each line */ - smartlist_t *state_line = smartlist_new(); - smartlist_add_asprintf(state_line, "EntryGuard"); - smartlist_add_asprintf(state_line, - "givethanks B29D536DD1752D542E1FBB3C9CE4449D51298212 NoDirCache"); - smartlist_add(entry_state_lines, state_line); - - state_line = smartlist_new(); - smartlist_add_asprintf(state_line, "EntryGuardAddedBy"); - smartlist_add_asprintf(state_line, - "B29D536DD1752D542E1FBB3C9CE4449D51298212 0.2.5.3-alpha-dev " - "%s", get_yesterday_date_str()); - smartlist_add(entry_state_lines, state_line); - - state_line = smartlist_new(); - smartlist_add_asprintf(state_line, "EntryGuardUnlistedSince"); - smartlist_add_asprintf(state_line, "2014-06-08 16:16:50"); - smartlist_add(entry_state_lines, state_line); - - state_line = smartlist_new(); - smartlist_add_asprintf(state_line, "EntryGuardPathBias"); - smartlist_add_asprintf(state_line, "%f %f %f %f %f %f", - circ_attempts, circ_successes, successful_closed, - collapsed, unusable, timeouts); - smartlist_add(entry_state_lines, state_line); - } - - /* Inject our lines in the state */ - state_insert_entry_guard_helper(state, entry_state_lines); - - /* Parse state */ - retval = entry_guards_parse_state(state, 1, &msg); - tt_int_op(retval, OP_GE, 0); - - /* Test that the guard was registered */ - all_entry_guards = get_entry_guards(); - tt_int_op(smartlist_len(all_entry_guards), OP_EQ, 1); - - { /* Test the path bias of this guard */ - const entry_guard_t *e = smartlist_get(all_entry_guards, 0); - - tt_assert(!e->is_dir_cache); - tt_assert(!e->can_retry); - - /* XXX tt_double_op doesn't support equality. Cast to int for now. */ - tt_int_op((int)e->pb.circ_attempts, OP_EQ, (int)circ_attempts); - tt_int_op((int)e->pb.circ_successes, OP_EQ, (int)circ_successes); - tt_int_op((int)e->pb.successful_circuits_closed, OP_EQ, - (int)successful_closed); - tt_int_op((int)e->pb.timeouts, OP_EQ, (int)timeouts); - tt_int_op((int)e->pb.collapsed_circuits, OP_EQ, (int)collapsed); - tt_int_op((int)e->pb.unusable_circuits, OP_EQ, (int)unusable); - } - - done: - or_state_free(state); - state_lines_free(entry_state_lines); - tor_free(msg); -} - -/* Simple test of entry_guards_set_from_config() by specifying a - particular EntryNode and making sure it gets picked. */ -static void -test_entry_guards_set_from_config(void *arg) -{ - or_options_t *options = get_options_mutable(); - options->UseDeprecatedGuardAlgorithm = 1; - 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 node_t *chosen_entry = NULL; - int retval; - - (void) arg; - - /* Prase EntryNodes as a routerset. */ - options->EntryNodes = routerset_new(); - retval = routerset_parse(options->EntryNodes, - entrynodes_str, - "test_entrynodes"); - tt_int_op(retval, OP_GE, 0); - - /* Read nodes from EntryNodes */ - entry_guards_set_from_config(gs, options); - - /* Test that only one guard was added. */ - tt_int_op(smartlist_len(all_entry_guards), OP_EQ, 1); - - /* Make sure it was the guard we specified. */ - chosen_entry = choose_random_entry(NULL); - tt_str_op(chosen_entry->ri->nickname, OP_EQ, entrynodes_str); - - done: - routerset_free(options->EntryNodes); -} - -static void -test_entry_is_time_to_retry(void *arg) -{ - entry_guard_t *test_guard; - time_t now; - int retval; - (void)arg; - - now = time(NULL); - - test_guard = tor_malloc_zero(sizeof(entry_guard_t)); - - test_guard->last_attempted = now - 10; - test_guard->unreachable_since = now - 1; - - retval = entry_is_time_to_retry(test_guard,now); - tt_int_op(retval,OP_EQ,1); - - test_guard->unreachable_since = now - (6*60*60 - 1); - test_guard->last_attempted = now - (60*60 + 1); - - retval = entry_is_time_to_retry(test_guard,now); - tt_int_op(retval,OP_EQ,1); - - test_guard->last_attempted = now - (60*60 - 1); - - retval = entry_is_time_to_retry(test_guard,now); - tt_int_op(retval,OP_EQ,0); - - test_guard->unreachable_since = now - (6*60*60 + 1); - test_guard->last_attempted = now - (4*60*60 + 1); - - retval = entry_is_time_to_retry(test_guard,now); - tt_int_op(retval,OP_EQ,1); - - test_guard->unreachable_since = now - (3*24*60*60 - 1); - test_guard->last_attempted = now - (4*60*60 + 1); - - retval = entry_is_time_to_retry(test_guard,now); - tt_int_op(retval,OP_EQ,1); - - test_guard->unreachable_since = now - (3*24*60*60 + 1); - test_guard->last_attempted = now - (18*60*60 + 1); - - retval = entry_is_time_to_retry(test_guard,now); - tt_int_op(retval,OP_EQ,1); - - test_guard->unreachable_since = now - (7*24*60*60 - 1); - test_guard->last_attempted = now - (18*60*60 + 1); - - retval = entry_is_time_to_retry(test_guard,now); - tt_int_op(retval,OP_EQ,1); - - test_guard->last_attempted = now - (18*60*60 - 1); - - retval = entry_is_time_to_retry(test_guard,now); - tt_int_op(retval,OP_EQ,0); - - test_guard->unreachable_since = now - (7*24*60*60 + 1); - test_guard->last_attempted = now - (36*60*60 + 1); - - retval = entry_is_time_to_retry(test_guard,now); - tt_int_op(retval,OP_EQ,1); - - test_guard->unreachable_since = now - (7*24*60*60 + 1); - test_guard->last_attempted = now - (36*60*60 + 1); - - retval = entry_is_time_to_retry(test_guard,now); - tt_int_op(retval,OP_EQ,1); - - done: - tor_free(test_guard); -} - -/** XXX Do some tests that entry_is_live() */ -static void -test_entry_is_live(void *arg) -{ - smartlist_t *our_nodelist = NULL; - 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 entry_guard_t *test_entry = NULL; - const char *msg; - int which_node; - - (void) arg; - - /* The global entry guards smartlist should be empty now. */ - tt_int_op(smartlist_len(all_entry_guards), OP_EQ, 0); - - /* Walk the nodelist and add all nodes as entry guards. */ - our_nodelist = nodelist_get_list(); - tt_int_op(smartlist_len(our_nodelist), OP_EQ, HELPER_NUMBER_OF_DESCRIPTORS); - - SMARTLIST_FOREACH_BEGIN(our_nodelist, const node_t *, node) { - const node_t *node_tmp; - node_tmp = add_an_entry_guard(gs, node, 0, 1, 0, 0); - tt_assert(node_tmp); - - tt_int_op(node->is_stable, OP_EQ, 0); - tt_int_op(node->is_fast, OP_EQ, 0); - } SMARTLIST_FOREACH_END(node); - - /* Make sure the nodes were added as entry guards. */ - tt_int_op(smartlist_len(all_entry_guards), OP_EQ, - HELPER_NUMBER_OF_DESCRIPTORS); - - /* Now get a random test entry that we will use for this unit test. */ - which_node = 3; /* (chosen by fair dice roll) */ - test_entry = smartlist_get(all_entry_guards, which_node); - - /* Let's do some entry_is_live() tests! */ - - /* Require the node to be stable, but it's not. Should fail. - Also enable 'assume_reachable' because why not. */ - test_node = entry_is_live(test_entry, - ENTRY_NEED_UPTIME | ENTRY_ASSUME_REACHABLE, - &msg); - tt_assert(!test_node); - - /* Require the node to be fast, but it's not. Should fail. */ - test_node = entry_is_live(test_entry, - ENTRY_NEED_CAPACITY | ENTRY_ASSUME_REACHABLE, - &msg); - tt_assert(!test_node); - - /* Don't impose any restrictions on the node. Should succeed. */ - test_node = entry_is_live(test_entry, 0, &msg); - tt_assert(test_node); - tt_ptr_op(test_node, OP_EQ, node_get_by_id(test_entry->identity)); - - /* Require descriptor for this node. It has one so it should succeed. */ - test_node = entry_is_live(test_entry, ENTRY_NEED_DESCRIPTOR, &msg); - tt_assert(test_node); - tt_ptr_op(test_node, OP_EQ, node_get_by_id(test_entry->identity)); - - done: - ; /* XXX */ -} -#endif - #define TEST_IPV4_ADDR "123.45.67.89" #define TEST_IPV6_ADDR "[1234:5678:90ab:cdef::]" @@ -1475,12 +749,7 @@ test_entry_guard_parse_from_state_broken(void *arg) tt_int_op(smartlist_len(gs_df->sampled_entry_guards), OP_EQ, 1); guard_selection_t *gs_legacy = get_guard_selection_by_name("legacy", GS_TYPE_LEGACY, 0); -#ifdef ENABLE_LEGACY_GUARD_ALGORITHM - tt_assert(gs_legacy != NULL); - tt_int_op(smartlist_len(gs_legacy->chosen_entry_guards), OP_EQ, 0); -#else tt_assert(gs_legacy == NULL); -#endif done: config_free_lines(lines); @@ -3361,12 +2630,6 @@ test_enty_guard_should_expire_waiting(void *arg) tor_free(fake_state); } -#ifdef ENABLE_LEGACY_GUARD_ALGORITHM -static const struct testcase_setup_t fake_network = { - fake_network_setup, fake_network_cleanup -}; -#endif - static const struct testcase_setup_t big_fake_network = { big_fake_network_setup, big_fake_network_cleanup }; @@ -3383,33 +2646,6 @@ static const struct testcase_setup_t upgrade_circuits = { (void*)(arg) } struct testcase_t entrynodes_tests[] = { -#ifdef ENABLE_LEGACY_GUARD_ALGORITHM - { "entry_is_time_to_retry", test_entry_is_time_to_retry, - TT_FORK, NULL, NULL }, - { "choose_random_entry_no_guards", test_choose_random_entry_no_guards, - TT_FORK, &fake_network, NULL }, - { "choose_random_entry_one_possible_guard", - test_choose_random_entry_one_possible_guard, - TT_FORK, &fake_network, NULL }, - { "populate_live_entry_guards_1guard", - test_populate_live_entry_guards_1guard, - TT_FORK, &fake_network, NULL }, - { "populate_live_entry_guards_3guards", - test_populate_live_entry_guards_3guards, - TT_FORK, &fake_network, NULL }, - { "entry_guards_parse_state_simple", - test_entry_guards_parse_state_simple, - TT_FORK, &fake_network, NULL }, - { "entry_guards_parse_state_pathbias", - test_entry_guards_parse_state_pathbias, - TT_FORK, &fake_network, NULL }, - { "entry_guards_set_from_config", - test_entry_guards_set_from_config, - TT_FORK, &fake_network, NULL }, - { "entry_is_live", - test_entry_is_live, - TT_FORK, &fake_network, NULL }, -#endif { "node_preferred_orport", test_node_preferred_orport, 0, NULL, NULL }, diff --git a/src/test/test_routerlist.c b/src/test/test_routerlist.c index 73e8d1047c..78f1cf16b7 100644 --- a/src/test/test_routerlist.c +++ b/src/test/test_routerlist.c @@ -204,55 +204,6 @@ mock_usable_consensus_flavor(void) return mock_usable_consensus_flavor_value; } -#ifdef ENABLE_LEGACY_GUARD_ALGORITHM -static smartlist_t *mock_is_guard_list = NULL; - -static int -mock_is_node_used_as_guard(const 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; - } -} -#endif - static void test_router_pick_directory_server_impl(void *arg) { @@ -273,9 +224,6 @@ test_router_pick_directory_server_impl(void *arg) (void)arg; MOCK(usable_consensus_flavor, mock_usable_consensus_flavor); -#ifdef ENABLE_LEGACY_GUARD_ALGORITHM - MOCK(is_node_used_as_guard, mock_is_node_used_as_guard); -#endif /* With no consensus, we must be bootstrapping, regardless of time or flavor */ @@ -388,34 +336,6 @@ test_router_pick_directory_server_impl(void *arg) node_router1->is_valid = 1; node_router3->is_valid = 1; -#ifdef ENABLE_LEGACY_GUARD_ALGORITHM - flags |= PDS_FOR_GUARD; - mark_node_used_as_guard(node_router1); - mark_node_used_as_guard(node_router2); - mark_node_used_as_guard(node_router3); - rs = router_pick_directory_server_impl(V3_DIRINFO, flags, NULL); - tt_assert(rs == NULL); - mark_node_unused_as_guard(node_router1); - rs = router_pick_directory_server_impl(V3_DIRINFO, flags, NULL); - tt_assert(rs != NULL); - tt_assert(tor_memeq(rs->identity_digest, router1_id, DIGEST_LEN)); - rs = NULL; - mark_node_unused_as_guard(node_router2); - mark_node_unused_as_guard(node_router3); -#endif - - /* One not valid, one guard. This should leave one remaining */ -#ifdef ENABLE_LEGACY_GUARD_ALGORITHM - node_router1->is_valid = 0; - mark_node_used_as_guard(node_router2); - rs = router_pick_directory_server_impl(V3_DIRINFO, flags, NULL); - tt_assert(rs != NULL); - tt_assert(tor_memeq(rs->identity_digest, router3_id, DIGEST_LEN)); - rs = NULL; - node_router1->is_valid = 1; - mark_node_unused_as_guard(node_router2); -#endif - /* Manipulate overloaded */ node_router2->rs->last_dir_503_at = now; @@ -477,10 +397,6 @@ test_router_pick_directory_server_impl(void *arg) done: UNMOCK(usable_consensus_flavor); -#ifdef ENABLE_LEGACY_GUARD_ALGORITHM - UNMOCK(is_node_used_as_guard); - clear_mock_guard_list(); -#endif if (router1_id) tor_free(router1_id);