From dffac251f1ac666f7e7855cfb800b8ed012ec359 Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Fri, 17 Jan 2014 13:39:04 -0500 Subject: Make the handling for usable-exit counting handle ExitNodes better It's possible to set your ExitNodes to contains only exits that don't have the Exit flag. If you do that, we'll decide that 0 of your exits are working. Instead, in that case we should look at nodes which have (or which might have) exit policies that don't reject everything. Fix for bug 10543; bugfix on 0.2.4.10-alpha. --- src/or/nodelist.c | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) (limited to 'src/or/nodelist.c') diff --git a/src/or/nodelist.c b/src/or/nodelist.c index 178f084b6..8fa170332 100644 --- a/src/or/nodelist.c +++ b/src/or/nodelist.c @@ -1329,7 +1329,8 @@ compute_frac_paths_available(const networkstatus_t *consensus, smartlist_t *mid = smartlist_new(); smartlist_t *exits = smartlist_new(); smartlist_t *myexits= smartlist_new(); - double f_guard, f_mid, f_exit, f_myexit; + smartlist_t *myexits_unflagged = smartlist_new(); + double f_guard, f_mid, f_exit, f_myexit, f_myexit_unflagged; int np, nu; /* Ignored */ const int authdir = authdir_mode_v2(options) || authdir_mode_v3(options); @@ -1350,20 +1351,42 @@ compute_frac_paths_available(const networkstatus_t *consensus, }); } + /* All nodes with exit flag */ count_usable_descriptors(&np, &nu, exits, consensus, options, now, NULL, 1); + /* All nodes with exit flag in ExitNodes option */ count_usable_descriptors(&np, &nu, myexits, consensus, options, now, options->ExitNodes, 1); + /* Now compute the nodes in the ExitNodes option where which we don't know + * what their exit policy is, or we know it permits something. */ + count_usable_descriptors(&np, &nu, myexits_unflagged, + consensus, options, now, + options->ExitNodes, 0); + SMARTLIST_FOREACH_BEGIN(myexits_unflagged, const node_t *, node) { + if (node_has_descriptor(node) && node_exit_policy_rejects_all(node)) + SMARTLIST_DEL_CURRENT(myexits_unflagged, node); + } SMARTLIST_FOREACH_END(node); f_guard = frac_nodes_with_descriptors(guards, WEIGHT_FOR_GUARD); f_mid = frac_nodes_with_descriptors(mid, WEIGHT_FOR_MID); f_exit = frac_nodes_with_descriptors(exits, WEIGHT_FOR_EXIT); f_myexit= frac_nodes_with_descriptors(myexits,WEIGHT_FOR_EXIT); + f_myexit_unflagged= + frac_nodes_with_descriptors(myexits_unflagged,WEIGHT_FOR_EXIT); + + /* If our ExitNodes list has eliminated every possible Exit node, and there + * were some possible Exit nodes, then instead consider nodes that permit + * exiting to some ports. */ + if (smartlist_len(myexits) == 0 && + smartlist_len(myexits_unflagged)) { + f_myexit = f_myexit_unflagged; + } smartlist_free(guards); smartlist_free(mid); smartlist_free(exits); smartlist_free(myexits); + smartlist_free(myexits_unflagged); /* This is a tricky point here: we don't want to make it easy for a * directory to trickle exits to us until it learns which exits we have -- cgit v1.2.3