summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNick Mathewson <nickm@torproject.org>2011-07-11 17:04:21 -0400
committerNick Mathewson <nickm@torproject.org>2011-07-11 17:04:21 -0400
commit597da4989e6f6a9c1a12ad3197dd6532b1a80035 (patch)
treeb31fd77d6217384300e96f2640cd924420218a40
parentb55e31aeb453875728295de664383b12e76fefdc (diff)
parentd82384658d77189cbfae9db90e6ec14af6572b5e (diff)
downloadtor-597da4989e6f6a9c1a12ad3197dd6532b1a80035.tar.gz
tor-597da4989e6f6a9c1a12ad3197dd6532b1a80035.zip
Merge branch 'bug2798'
-rw-r--r--changes/bug279810
-rw-r--r--src/or/circuitbuild.c63
2 files changed, 49 insertions, 24 deletions
diff --git a/changes/bug2798 b/changes/bug2798
new file mode 100644
index 0000000000..8fd2243b04
--- /dev/null
+++ b/changes/bug2798
@@ -0,0 +1,10 @@
+ o Major bugfixes:
+ - When configuring a large set of nodes in EntryNodes (as with
+ 'EntryNodes {cc}' or 'EntryNodes 1.1.1.1/16'), choose only a
+ random subset to be guards, and choose them in random
+ order. Bugfix on 0.2.3.1-alpha; fixes bug 2798.
+
+ o Minor features:
+ - When configuring a large set of nodes in EntryNodes, and there are
+ enough of them listed as Guard so that we don't need to consider
+ the non-guard entries, prefer the ones listed with the Guard flag.
diff --git a/src/or/circuitbuild.c b/src/or/circuitbuild.c
index abf6115cde..4397aa5c13 100644
--- a/src/or/circuitbuild.c
+++ b/src/or/circuitbuild.c
@@ -3642,7 +3642,7 @@ control_event_guard_deferred(void)
* 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(const node_t *chosen, int reset_status)
+add_an_entry_guard(const node_t *chosen, int reset_status, int prepend)
{
const node_t *node;
entry_guard_t *entry;
@@ -3674,9 +3674,9 @@ add_an_entry_guard(const node_t *chosen, int reset_status)
* this guard. For details, see the Jan 2010 or-dev thread. */
entry->chosen_on_date = time(NULL) - crypto_rand_int(3600*24*30);
entry->chosen_by_version = tor_strdup(VERSION);
- if (chosen) /* prepend */
+ if (prepend)
smartlist_insert(entry_guards, 0, entry);
- else /* append */
+ else
smartlist_add(entry_guards, entry);
control_event_guard(entry->nickname, entry->identity, "NEW");
control_event_guard_deferred();
@@ -3694,7 +3694,7 @@ pick_entry_guards(const or_options_t *options)
tor_assert(entry_guards);
while (num_live_entry_guards() < options->NumEntryGuards) {
- if (!add_an_entry_guard(NULL, 0))
+ if (!add_an_entry_guard(NULL, 0, 0))
break;
changed = 1;
}
@@ -4007,12 +4007,12 @@ entry_nodes_should_be_added(void)
should_add_entry_nodes = 1;
}
-/** Add all nodes in EntryNodes that aren't currently guard nodes to the list
- * of guard nodes, at the front. */
+/** 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_prepend_from_config(const or_options_t *options)
+entry_guards_set_from_config(const or_options_t *options)
{
- smartlist_t *entry_nodes, *entry_fps;
+ smartlist_t *entry_nodes, *worse_entry_nodes, *entry_fps;
smartlist_t *old_entry_guards_on_list, *old_entry_guards_not_on_list;
tor_assert(entry_guards);
@@ -4033,18 +4033,13 @@ entry_guards_prepend_from_config(const or_options_t *options)
}
entry_nodes = smartlist_create();
+ worse_entry_nodes = smartlist_create();
entry_fps = smartlist_create();
old_entry_guards_on_list = smartlist_create();
old_entry_guards_not_on_list = smartlist_create();
/* Split entry guards into those on the list and those not. */
- /* XXXX023 Now that we allow countries and IP ranges in EntryNodes, this is
- * potentially an enormous list. For now, we disable such values for
- * EntryNodes in options_validate(); really, this wants a better solution.
- * Perhaps we should do this calculation once whenever the list of routers
- * changes or the entrynodes setting changes.
- */
routerset_get_all_nodes(entry_nodes, options->EntryNodes,
options->ExcludeNodes, 0);
SMARTLIST_FOREACH(entry_nodes, const node_t *,node,
@@ -4057,27 +4052,47 @@ entry_guards_prepend_from_config(const or_options_t *options)
smartlist_add(old_entry_guards_not_on_list, e);
});
- /* Remove all currently configured entry guards from entry_routers. */
- SMARTLIST_FOREACH(entry_nodes, const node_t *, node, {
+ /* 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 (is_an_entry_guard(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)) {
+ 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(entry_guards);
/* First, the previously configured guards that are in EntryNodes. */
smartlist_add_all(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(entry_nodes, const node_t *, node, {
- add_an_entry_guard(node, 0);
- });
+ SMARTLIST_FOREACH_BEGIN(entry_nodes, const node_t *, node) {
+ add_an_entry_guard(node, 0, 0);
+ if (smartlist_len(entry_guards) > options->NumEntryGuards * 10)
+ break;
+ } SMARTLIST_FOREACH_END(node);
+ log_notice(LD_GENERAL, "%d entries in guards", smartlist_len(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);
@@ -4125,7 +4140,7 @@ choose_random_entry(cpath_build_state_t *state)
entry_guards = smartlist_create();
if (should_add_entry_nodes)
- entry_guards_prepend_from_config(options);
+ entry_guards_set_from_config(options);
if (!entry_list_is_constrained(options) &&
smartlist_len(entry_guards) < options->NumEntryGuards)
@@ -4150,7 +4165,7 @@ choose_random_entry(cpath_build_state_t *state)
goto choose_and_finish; /* only choose from the ones we like */
if (options->StrictNodes) {
/* in theory this case should never happen, since
- * entry_guards_prepend_from_config() drops unwanted relays */
+ * entry_guards_set_from_config() drops unwanted relays */
tor_fragile_assert();
} else {
log_info(LD_CIRC,
@@ -4188,7 +4203,7 @@ choose_random_entry(cpath_build_state_t *state)
/* 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(NULL, 0);
+ node = add_an_entry_guard(NULL, 0, 0);
if (node) {
entry_guards_changed();
/* XXX we start over here in case the new node we added shares
@@ -5024,7 +5039,7 @@ learned_bridge_descriptor(routerinfo_t *ri, int from_cache)
node = node_get_mutable_by_id(ri->cache_info.identity_digest);
tor_assert(node);
rewrite_node_address_for_bridge(bridge, node);
- add_an_entry_guard(node, 1);
+ add_an_entry_guard(node, 1, 1);
log_notice(LD_DIR, "new bridge descriptor '%s' (%s)", ri->nickname,
from_cache ? "cached" : "fresh");