diff --git a/src/or/config.c b/src/or/config.c index f77f4d1879..b7b5cff35a 100644 --- a/src/or/config.c +++ b/src/or/config.c @@ -1561,6 +1561,36 @@ options_transition_requires_fresh_tls_context(const or_options_t *old_options, return 0; } +/** + * Return true if changing the configuration from old to new + * affects the guard susbsystem. + */ +static int +options_transition_affects_guards(const or_options_t *old, + const or_options_t *new) +{ + /* NOTE: Make sure this function stays in sync with + * entry_guards_set_filtered_flags */ + + tor_assert(old); + tor_assert(new); + + return + (old->UseEntryGuards != new->UseEntryGuards || + old->UseDeprecatedGuardAlgorithm != new->UseDeprecatedGuardAlgorithm || + old->UseBridges != new->UseBridges || + old->UseEntryGuards != new->UseEntryGuards || + old->ClientUseIPv4 != new->ClientUseIPv4 || + old->ClientUseIPv6 != new->ClientUseIPv6 || + old->FascistFirewall != new->FascistFirewall || + !routerset_equal(old->ExcludeNodes, new->ExcludeNodes) || + !routerset_equal(old->EntryNodes, new->EntryNodes) || + !smartlist_strings_eq(old->FirewallPorts, new->FirewallPorts) || + !config_lines_eq(old->Bridges, new->Bridges) || + !config_lines_eq(old->ReachableORAddresses, new->ReachableORAddresses) || + !config_lines_eq(old->ReachableDirAddresses, new->ReachableDirAddresses)); +} + /** Fetch the active option list, and take actions based on it. All of the * things we do should survive being done repeatedly. If present, * old_options contains the previous value of the options. @@ -1580,6 +1610,8 @@ options_act(const or_options_t *old_options) const int transition_affects_workers = old_options && options_transition_affects_workers(old_options, options); int old_ewma_enabled; + const int transition_affects_guards = + old_options && options_transition_affects_guards(old_options, options); /* disable ptrace and later, other basic debugging techniques */ { @@ -1875,6 +1907,7 @@ options_act(const or_options_t *old_options) if (old_options) { int revise_trackexithosts = 0; int revise_automap_entries = 0; + int abandon_circuits = 0; if ((options->UseEntryGuards && !old_options->UseEntryGuards) || options->UseBridges != old_options->UseBridges || (options->UseBridges && @@ -1891,6 +1924,16 @@ options_act(const or_options_t *old_options) "Changed to using entry guards or bridges, or changed " "preferred or excluded node lists. " "Abandoning previous circuits."); + abandon_circuits = 1; + } + + if (transition_affects_guards) { + if (guards_update_all()) { + abandon_circuits = 1; + } + } + + if (abandon_circuits) { circuit_mark_all_unused_circs(); circuit_mark_all_dirty_circs_as_unusable(); revise_trackexithosts = 1; diff --git a/src/or/entrynodes.c b/src/or/entrynodes.c index 81751f565c..9a753e6d25 100644 --- a/src/or/entrynodes.c +++ b/src/or/entrynodes.c @@ -91,7 +91,7 @@ * * [x] Whenever we get a new consensus, call update_from_consensus(). (LATER.) * - * [ ] Whenever the configuration changes in a relevant way, update the + * [x] Whenever the configuration changes in a relevant way, update the * filtered/usable flags. (LATER.) * * [x] Whenever we add a guard to the sample, make sure its filtered/usable @@ -696,6 +696,9 @@ static int node_passes_guard_filter(const or_options_t *options, guard_selection_t *gs, const node_t *node) { + /* NOTE: Make sure that this function stays in sync with + * options_transition_affects_entry_guards */ + (void)gs; if (routerset_contains_node(options->ExcludeNodes, node)) return 0; @@ -1636,14 +1639,16 @@ entry_guards_upgrade_waiting_circuits(guard_selection_t *gs, /** * Update all derived pieces of the guard selection state in gs. + * Return true iff we should stop using all previously generated circuits. */ -void +int entry_guards_update_all(guard_selection_t *gs) { sampled_guards_update_from_consensus(gs); entry_guards_update_filtered_sets(gs); entry_guards_update_confirmed(gs); entry_guards_update_primary(gs); + return 0; } /** @@ -4020,14 +4025,16 @@ entries_retry_all(const or_options_t *options) } /** Helper: Update the status of all entry guards, in whatever algorithm - is used. */ -void + * is used. Return true if we should stop using all previously generated + * circuits. */ +int guards_update_all(void) { if (get_options()->UseDeprecatedGuardAlgorithm) { entry_guards_compute_status(get_options(), approx_time()); + return 0; } else { - entry_guards_update_all(get_guard_selection_info()); + return entry_guards_update_all(get_guard_selection_info()); } } diff --git a/src/or/entrynodes.h b/src/or/entrynodes.h index d8468eb287..4cbfbf55bf 100644 --- a/src/or/entrynodes.h +++ b/src/or/entrynodes.h @@ -294,7 +294,7 @@ struct circuit_guard_state_t { #endif /* Common entry points for old and new guard code */ -void guards_update_all(void); +int guards_update_all(void); const node_t *guards_choose_guard(cpath_build_state_t *state, circuit_guard_state_t **guard_state_out); const node_t *guards_choose_dirguard(dirinfo_type_t info, @@ -336,7 +336,7 @@ void entry_guard_cancel(guard_selection_t *gs, circuit_guard_state_t **guard_state_p); void entry_guard_chan_failed(guard_selection_t *gs, channel_t *chan); -void entry_guards_update_all(guard_selection_t *gs); +int entry_guards_update_all(guard_selection_t *gs); int entry_guards_upgrade_waiting_circuits(guard_selection_t *gs, const smartlist_t *all_circuits, smartlist_t *newly_complete_out); diff --git a/src/or/main.c b/src/or/main.c index 65d1c1fd79..16106612a9 100644 --- a/src/or/main.c +++ b/src/or/main.c @@ -979,7 +979,10 @@ directory_info_has_arrived(time_t now, int from_cache, int suppress_logs) /* if we have enough dir info, then update our guard status with * whatever we just learned. */ - guards_update_all(); + int invalidate_circs = guards_update_all(); + // This shouldn't be able to occur at this point. + tor_assert_nonfatal(! invalidate_circs); + /* Don't even bother trying to get extrainfo until the rest of our * directory info is up-to-date */ if (options->DownloadExtraInfo)