commit 87f9b42179bd23418c3e698938bdeead56da1c43 Author: Nick Mathewson nickm@torproject.org Date: Wed Nov 30 08:49:39 2016 -0500
Implement support for per-circuit guard restrictions.
This is an important thing I hadn't considered when writing prop271: sometimes you have to restrict what guard you use for a particular circuit. Most frequently, that would be because you plan to use a certain node as your exit, and so you can't choose that for your guard.
This change means that the upgrade-waiting-circuits algorithm needs a slight tweak too: circuit A cannot block circuit B from upgrading if circuit B needs to follow a restriction that circuit A does not follow. --- src/or/circuitbuild.c | 15 +++++- src/or/circuitbuild.h | 1 + src/or/entrynodes.c | 122 ++++++++++++++++++++++++++++++++++++++------- src/or/entrynodes.h | 38 +++++++++++++- src/test/test_entrynodes.c | 92 +++++++++++++++++----------------- 5 files changed, 200 insertions(+), 68 deletions(-)
diff --git a/src/or/circuitbuild.c b/src/or/circuitbuild.c index c7e116e..0790309 100644 --- a/src/or/circuitbuild.c +++ b/src/or/circuitbuild.c @@ -2515,8 +2515,8 @@ extend_info_dup(extend_info_t *info) return newinfo; }
-/** Return the routerinfo_t for the chosen exit router in <b>state</b>. - * If there is no chosen exit, or if we don't know the routerinfo_t for +/** Return the node_t for the chosen exit router in <b>state</b>. + * If there is no chosen exit, or if we don't know the node_t for * the chosen exit, return NULL. */ const node_t * @@ -2527,6 +2527,17 @@ build_state_get_exit_node(cpath_build_state_t *state) return node_get_by_id(state->chosen_exit->identity_digest); }
+/** Return the RSA ID digest for the chosen exit router in <b>state</b>. + * If there is no chosen exit, return NULL. + */ +const uint8_t * +build_state_get_exit_rsa_id(cpath_build_state_t *state) +{ + if (!state || !state->chosen_exit) + return NULL; + return (const uint8_t *) state->chosen_exit->identity_digest; +} + /** Return the nickname for the chosen exit router in <b>state</b>. If * there is no chosen exit, or if we don't know the routerinfo_t for the * chosen exit, return NULL. diff --git a/src/or/circuitbuild.h b/src/or/circuitbuild.h index 2c83a16..b85dbec 100644 --- a/src/or/circuitbuild.h +++ b/src/or/circuitbuild.h @@ -61,6 +61,7 @@ int extend_info_supports_ntor(const extend_info_t* ei); int circuit_can_use_tap(const origin_circuit_t *circ); int circuit_has_usable_onion_key(const origin_circuit_t *circ); int extend_info_has_preferred_onion_key(const extend_info_t* ei); +const uint8_t *build_state_get_exit_rsa_id(cpath_build_state_t *state); const node_t *build_state_get_exit_node(cpath_build_state_t *state); const char *build_state_get_exit_nickname(cpath_build_state_t *state);
diff --git a/src/or/entrynodes.c b/src/or/entrynodes.c index dd3a890..9b38641 100644 --- a/src/or/entrynodes.c +++ b/src/or/entrynodes.c @@ -168,6 +168,8 @@ static entry_guard_t *entry_guard_add_to_sample_impl(guard_selection_t *gs, const tor_addr_port_t *bridge_addrport); static entry_guard_t *get_sampled_guard_by_bridge_addr(guard_selection_t *gs, const tor_addr_port_t *addrport); +static int entry_guard_obeys_restriction(const entry_guard_t *guard, + const entry_guard_restriction_t *rst);
/** Return 0 if we should apply guardfraction information found in the * consensus. A specific consensus can be specified with the @@ -878,13 +880,20 @@ entry_guard_learned_bridge_identity(const tor_addr_port_t *addrport, /** * Return the number of sampled guards in <b>gs</b> that are "filtered" * (that is, we're willing to connect to them) and that are "usable" - * (that is, either "reachable" or "maybe reachable"). */ + * (that is, either "reachable" or "maybe reachable"). + * + * If a restriction is provided in <b>rst</b>, do not count any guards that + * violate it. + */ STATIC int -num_reachable_filtered_guards(guard_selection_t *gs) +num_reachable_filtered_guards(guard_selection_t *gs, + const entry_guard_restriction_t *rst) { int n_reachable_filtered_guards = 0; SMARTLIST_FOREACH_BEGIN(gs->sampled_entry_guards, entry_guard_t *, guard) { entry_guard_consider_retry(guard); + if (! entry_guard_obeys_restriction(guard, rst)) + continue; if (guard->is_usable_filtered_guard) ++n_reachable_filtered_guards; } SMARTLIST_FOREACH_END(guard); @@ -1003,7 +1012,7 @@ entry_guards_expand_sample(guard_selection_t *gs) tor_assert(gs); int n_sampled = smartlist_len(gs->sampled_entry_guards); entry_guard_t *added_guard = NULL; - int n_usable_filtered_guards = num_reachable_filtered_guards(gs); + int n_usable_filtered_guards = num_reachable_filtered_guards(gs, NULL); int n_guards = 0; smartlist_t *eligible_guards = get_eligible_guards(gs, &n_guards);
@@ -1324,6 +1333,22 @@ entry_guard_passes_filter(const or_options_t *options, guard_selection_t *gs, }
/** + * Return true iff <b>guard</b> obeys the restrictions defined in <b>rst</b>. + * (If <b>rst</b> is NULL, there are no restrictions.) + */ +static int +entry_guard_obeys_restriction(const entry_guard_t *guard, + const entry_guard_restriction_t *rst) +{ + tor_assert(guard); + if (! rst) + return 1; // No restriction? No problem. + + // Only one kind of restriction exists right now + return tor_memneq(guard->identity, rst->exclude_id, DIGEST_LEN); +} + +/** * Update the <b>is_filtered_guard</b> and <b>is_usable_filtered_guard</b> * flags on <b>guard</b>. */ void @@ -1373,9 +1398,13 @@ entry_guards_update_filtered_sets(guard_selection_t *gs) * * Make sure that the sample is big enough, and that all the filter flags * are set correctly, before calling this function. + * + * If a restriction is provided in <b>rst</b>, do not return any guards that + * violate it. **/ STATIC entry_guard_t * sample_reachable_filtered_entry_guards(guard_selection_t *gs, + const entry_guard_restriction_t *rst, unsigned flags) { tor_assert(gs); @@ -1389,7 +1418,7 @@ sample_reachable_filtered_entry_guards(guard_selection_t *gs, entry_guard_consider_retry(guard); } SMARTLIST_FOREACH_END(guard);
- const int n_reachable_filtered = num_reachable_filtered_guards(gs); + const int n_reachable_filtered = num_reachable_filtered_guards(gs, rst);
log_info(LD_GUARD, "Trying to sample a reachable guard: We know of %d " "in the USABLE_FILTERED set.", n_reachable_filtered); @@ -1407,6 +1436,8 @@ sample_reachable_filtered_entry_guards(guard_selection_t *gs, smartlist_t *reachable_filtered_sample = smartlist_new(); SMARTLIST_FOREACH_BEGIN(gs->sampled_entry_guards, entry_guard_t *, guard) { entry_guard_consider_retry(guard);// redundant, but cheap. + if (! entry_guard_obeys_restriction(guard, rst)) + continue; if (! guard->is_usable_filtered_guard) continue; if (exclude_confirmed && guard->confirmed_idx >= 0) @@ -1568,7 +1599,7 @@ entry_guards_update_primary(guard_selection_t *gs)
/* Finally, fill out the list with sampled guards. */ while (smartlist_len(new_primary_guards) < N_PRIMARY_GUARDS) { - entry_guard_t *guard = sample_reachable_filtered_entry_guards(gs, + entry_guard_t *guard = sample_reachable_filtered_entry_guards(gs, NULL, SAMPLE_EXCLUDE_CONFIRMED| SAMPLE_EXCLUDE_PRIMARY| SAMPLE_NO_UPDATE_PRIMARY); @@ -1708,7 +1739,9 @@ entry_guards_note_internet_connectivity(guard_selection_t *gs) * of the circuit. */ STATIC entry_guard_t * -select_entry_guard_for_circuit(guard_selection_t *gs, unsigned *state_out) +select_entry_guard_for_circuit(guard_selection_t *gs, + const entry_guard_restriction_t *rst, + unsigned *state_out) { /*XXXX prop271 consider splitting this function up. */ tor_assert(gs); @@ -1721,6 +1754,8 @@ select_entry_guard_for_circuit(guard_selection_t *gs, unsigned *state_out) <maybe> or <yes>, return the first such guard." */ SMARTLIST_FOREACH_BEGIN(gs->primary_entry_guards, entry_guard_t *, guard) { entry_guard_consider_retry(guard); + if (! entry_guard_obeys_restriction(guard, rst)) + continue; if (guard->is_reachable != GUARD_REACHABLE_NO) { *state_out = GUARD_CIRC_STATE_USABLE_ON_COMPLETION; guard->last_tried_to_connect = approx_time(); @@ -1737,6 +1772,8 @@ select_entry_guard_for_circuit(guard_selection_t *gs, unsigned *state_out) SMARTLIST_FOREACH_BEGIN(gs->confirmed_entry_guards, entry_guard_t *, guard) { if (guard->is_primary) continue; /* we already considered this one. */ + if (! entry_guard_obeys_restriction(guard, rst)) + continue; entry_guard_consider_retry(guard); if (guard->is_usable_filtered_guard && ! guard->is_pending) { guard->is_pending = 1; @@ -1755,6 +1792,7 @@ select_entry_guard_for_circuit(guard_selection_t *gs, unsigned *state_out) { entry_guard_t *guard; guard = sample_reachable_filtered_entry_guards(gs, + rst, SAMPLE_EXCLUDE_CONFIRMED | SAMPLE_EXCLUDE_PRIMARY | SAMPLE_EXCLUDE_PENDING); @@ -1925,6 +1963,13 @@ entry_guard_has_higher_priority(entry_guard_t *a, entry_guard_t *b) } }
+/** Release all storage held in <b>restriction</b> */ +static void +entry_guard_restriction_free(entry_guard_restriction_t *rst) +{ + tor_free(rst); +} + /** * Release all storage held in <b>state</b>. */ @@ -1933,6 +1978,7 @@ circuit_guard_state_free(circuit_guard_state_t *state) { if (!state) return; + entry_guard_restriction_free(state->restrictions); entry_guard_handle_free(state->guard); tor_free(state); } @@ -1942,9 +1988,14 @@ circuit_guard_state_free(circuit_guard_state_t *state) * in *<b>chosen_node_out</b>. Set *<b>guard_state_out</b> to an opaque * state object that will record whether the circuit is ready to be used * or not. Return 0 on success; on failure, return -1. + * + * If a restriction is provided in <b>rst</b>, do not return any guards that + * violate it, and remember that restriction in <b>guard_state_out</b> for + * later use. (Takes ownership of the <b>rst</b> object.) */ int entry_guard_pick_for_circuit(guard_selection_t *gs, + entry_guard_restriction_t *rst, const node_t **chosen_node_out, circuit_guard_state_t **guard_state_out) { @@ -1955,23 +2006,27 @@ entry_guard_pick_for_circuit(guard_selection_t *gs, *guard_state_out = NULL;
unsigned state = 0; - entry_guard_t *guard = select_entry_guard_for_circuit(gs, &state); + entry_guard_t *guard = select_entry_guard_for_circuit(gs, rst, &state); if (! guard) - return -1; + goto fail; if (BUG(state == 0)) - return -1; + goto fail; const node_t *node = node_get_by_id(guard->identity); // XXXX prop271 check Ed ID. if (! node) - return -1; + goto fail;
*chosen_node_out = node; *guard_state_out = tor_malloc_zero(sizeof(circuit_guard_state_t)); (*guard_state_out)->guard = entry_guard_handle_new(guard); (*guard_state_out)->state = state; (*guard_state_out)->state_set_at = approx_time(); + (*guard_state_out)->restrictions = rst;
return 0; + fail: + entry_guard_restriction_free(rst); + return -1; }
/** @@ -2098,9 +2153,14 @@ entry_guards_all_primary_guards_are_down(guard_selection_t *gs) }
/** Wrapper for entry_guard_has_higher_priority that compares the - * guard-priorities of a pair of circuits. */ + * guard-priorities of a pair of circuits. + * + * If a restriction is provided in <b>rst</b>, then do not consider + * <b>a</b> to have higher priority if it violates the restriction. + */ static int circ_state_has_higher_priority(origin_circuit_t *a, + const entry_guard_restriction_t *rst, origin_circuit_t *b) { circuit_guard_state_t *state_a = origin_circuit_get_guard_state(a); @@ -2118,6 +2178,9 @@ circ_state_has_higher_priority(origin_circuit_t *a, } else if (! guard_b) { /* Known guard -- higher priority than any unknown guard. */ return 1; + } else if (! entry_guard_obeys_restriction(guard_a, rst)) { + /* Restriction violated; guard_a cannot have higher priority. */ + return 0; } else { /* Both known -- compare.*/ return entry_guard_has_higher_priority(guard_a, guard_b); @@ -2175,13 +2238,13 @@ entry_guards_upgrade_waiting_circuits(guard_selection_t *gs, if (state->state == GUARD_CIRC_STATE_WAITING_FOR_BETTER_GUARD) { ++n_waiting; if (! best_waiting_circuit || - circ_state_has_higher_priority(circ, best_waiting_circuit)) { + circ_state_has_higher_priority(circ, NULL, best_waiting_circuit)) { best_waiting_circuit = circ; } } else if (state->state == GUARD_CIRC_STATE_COMPLETE) { ++n_complete; if (! best_complete_circuit || - circ_state_has_higher_priority(circ, best_complete_circuit)) { + circ_state_has_higher_priority(circ, NULL, best_complete_circuit)) { best_complete_circuit = circ; } } @@ -2193,8 +2256,15 @@ entry_guards_upgrade_waiting_circuits(guard_selection_t *gs, goto no_change; }
+ /* We'll need to keep track of what restrictions were used when picking this + * circuit, so that we don't allow any circuit without those restrictions to + * block it. */ + const entry_guard_restriction_t *rst_on_best_waiting = + origin_circuit_get_guard_state(best_waiting_circuit)->restrictions; + if (best_complete_circuit) { if (circ_state_has_higher_priority(best_complete_circuit, + rst_on_best_waiting, best_waiting_circuit)) { /* "If any circuit is <complete>, then do not use any <waiting_for_better_guard> or <usable_if_no_better_guard> circuits @@ -2225,8 +2295,10 @@ entry_guards_upgrade_waiting_circuits(guard_selection_t *gs, continue; if (state->state != GUARD_CIRC_STATE_USABLE_IF_NO_BETTER_GUARD) continue; - if (state->state_set_at > state_set_at_cutoff && - circ_state_has_higher_priority(circ, best_waiting_circuit)) + if (state->state_set_at <= state_set_at_cutoff) + continue; + if (circ_state_has_higher_priority(circ, rst_on_best_waiting, + best_waiting_circuit)) ++n_blockers_found; } SMARTLIST_FOREACH_END(circ);
@@ -2246,9 +2318,14 @@ entry_guards_upgrade_waiting_circuits(guard_selection_t *gs, circuit_guard_state_t *state = origin_circuit_get_guard_state(circ); if (BUG(state == NULL)) continue; + if (circ != best_waiting_circuit && rst_on_best_waiting) { + /* Can't upgrade other circ with same priority as best; might + be blocked. */ + continue; + } if (state->state != GUARD_CIRC_STATE_WAITING_FOR_BETTER_GUARD) continue; - if (circ_state_has_higher_priority(best_waiting_circuit, circ)) + if (circ_state_has_higher_priority(best_waiting_circuit, NULL, circ)) continue;
state->state = GUARD_CIRC_STATE_COMPLETE; @@ -4759,10 +4836,18 @@ guards_choose_guard(cpath_build_state_t *state, if (get_options()->UseDeprecatedGuardAlgorithm) { return choose_random_entry(state); } else { - // XXXX prop271 we need to look at the chosen exit node if any, and - // not duplicate it. const node_t *r = NULL; + const uint8_t *exit_id = NULL; + entry_guard_restriction_t *rst = NULL; + // XXXX prop271 spec deviation -- use of restriction here. + if (state && (exit_id = build_state_get_exit_rsa_id(state))) { + /* We're building to a targeted exit node, so that node can't be + * chosen as our guard for this circuit. */ + rst = tor_malloc_zero(sizeof(entry_guard_restriction_t)); + memcpy(rst->exclude_id, exit_id, DIGEST_LEN); + } if (entry_guard_pick_for_circuit(get_guard_selection_info(), + rst, &r, guard_state_out) < 0) { tor_assert(r == NULL); @@ -4788,6 +4873,7 @@ guards_choose_dirguard(dirinfo_type_t info, * microdescriptors. -NM */ const node_t *r = NULL; if (entry_guard_pick_for_circuit(get_guard_selection_info(), + NULL, &r, guard_state_out) < 0) { tor_assert(r == NULL); diff --git a/src/or/entrynodes.h b/src/or/entrynodes.h index 4ea60e8..753d6f7 100644 --- a/src/or/entrynodes.h +++ b/src/or/entrynodes.h @@ -24,6 +24,10 @@ typedef struct entry_guard_t entry_guard_t; private. */ typedef struct circuit_guard_state_t circuit_guard_state_t;
+/* Forward declaration for entry_guard_restriction_t; the real declaration is + private. */ +typedef struct entry_guard_restriction_t entry_guard_restriction_t; + /* 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. @@ -311,6 +315,24 @@ struct guard_selection_s { struct entry_guard_handle_t;
/** + * A restriction to remember which entry guards are off-limits for a given + * circuit. + * + * Right now, we only use restrictions to block a single guard from being + * selected; this mechanism is designed to be more extensible in the future, + * however. + * + * Note: This mechanism is NOT for recording which guards are never to be + * used: only which guards cannot be used on <em>one particular circuit</em>. + */ +struct entry_guard_restriction_t { + /** + * The guard's RSA identity digest must not equal this. + */ + uint8_t exclude_id[DIGEST_LEN]; +}; + +/** * Per-circuit state to track whether we'll be able to use the circuit. */ struct circuit_guard_state_t { @@ -320,6 +342,14 @@ struct circuit_guard_state_t { time_t state_set_at; /** One of GUARD_CIRC_STATE_* */ uint8_t state; + + /** + * A set of restrictions that were placed on this guard when we selected it + * for this particular circuit. We need to remember the restrictions here, + * since any guard that breaks these restrictions will not block this + * circuit from becoming COMPLETE. + */ + entry_guard_restriction_t *restrictions; }; #endif
@@ -356,6 +386,7 @@ guard_pathbias_t *entry_guard_get_pathbias_state(entry_guard_t *guard);
void circuit_guard_state_free(circuit_guard_state_t *state); int entry_guard_pick_for_circuit(guard_selection_t *gs, + entry_guard_restriction_t *rst, const node_t **chosen_node_out, circuit_guard_state_t **guard_state_out); typedef enum { @@ -491,12 +522,14 @@ STATIC int entry_guards_all_primary_guards_are_down(guard_selection_t *gs); /**@}*/ STATIC entry_guard_t *sample_reachable_filtered_entry_guards( guard_selection_t *gs, + const entry_guard_restriction_t *rst, unsigned flags); STATIC void entry_guard_consider_retry(entry_guard_t *guard); STATIC void make_guard_confirmed(guard_selection_t *gs, entry_guard_t *guard); STATIC void entry_guards_update_confirmed(guard_selection_t *gs); STATIC void entry_guards_update_primary(guard_selection_t *gs); -STATIC int num_reachable_filtered_guards(guard_selection_t *gs); +STATIC int num_reachable_filtered_guards(guard_selection_t *gs, + const entry_guard_restriction_t *rst); STATIC void sampled_guards_update_from_consensus(guard_selection_t *gs); /** * @name Possible guard-states for a circuit. @@ -522,7 +555,8 @@ STATIC void sampled_guards_update_from_consensus(guard_selection_t *gs); STATIC void entry_guards_note_guard_failure(guard_selection_t *gs, entry_guard_t *guard); STATIC entry_guard_t *select_entry_guard_for_circuit(guard_selection_t *gs, - unsigned *state_out); + const entry_guard_restriction_t *rst, + unsigned *state_out); STATIC void mark_primary_guards_maybe_reachable(guard_selection_t *gs); STATIC unsigned entry_guards_note_guard_success(guard_selection_t *gs, entry_guard_t *guard, diff --git a/src/test/test_entrynodes.c b/src/test/test_entrynodes.c index e3a9d18..0921e20 100644 --- a/src/test/test_entrynodes.c +++ b/src/test/test_entrynodes.c @@ -1353,7 +1353,7 @@ test_entry_guard_node_filter(void *arg) tt_assert(g[i]->is_filtered_guard == 1); tt_assert(g[i]->is_usable_filtered_guard == 1); } - tt_int_op(num_reachable_filtered_guards(gs), OP_EQ, NUM); + tt_int_op(num_reachable_filtered_guards(gs, NULL), OP_EQ, NUM);
/* Make sure refiltering doesn't hurt */ entry_guards_update_filtered_sets(gs); @@ -1361,7 +1361,7 @@ test_entry_guard_node_filter(void *arg) tt_assert(g[i]->is_filtered_guard == 1); tt_assert(g[i]->is_usable_filtered_guard == 1); } - tt_int_op(num_reachable_filtered_guards(gs), OP_EQ, NUM); + tt_int_op(num_reachable_filtered_guards(gs, NULL), OP_EQ, NUM);
/* Now start doing things to make the guards get filtered out, 1 by 1. */
@@ -1401,7 +1401,7 @@ test_entry_guard_node_filter(void *arg) tt_assert(g[i]->is_filtered_guard == (i == 5 || i == 6)); tt_assert(g[i]->is_usable_filtered_guard == (i == 6)); } - tt_int_op(num_reachable_filtered_guards(gs), OP_EQ, 1); + tt_int_op(num_reachable_filtered_guards(gs, NULL), OP_EQ, 1);
/* Now make sure we have no live consensus, and no nodes. Nothing should * pass the filter any more. */ @@ -1415,7 +1415,7 @@ test_entry_guard_node_filter(void *arg) tt_assert(g[i]->is_filtered_guard == 0); tt_assert(g[i]->is_usable_filtered_guard == 0); } - tt_int_op(num_reachable_filtered_guards(gs), OP_EQ, 0); + tt_int_op(num_reachable_filtered_guards(gs, NULL), OP_EQ, 0);
done: guard_selection_free(gs); @@ -1434,11 +1434,11 @@ test_entry_guard_expand_sample(void *arg)
// Every sampled guard here should be filtered and reachable for now. tt_int_op(smartlist_len(gs->sampled_entry_guards), OP_EQ, - num_reachable_filtered_guards(gs)); + num_reachable_filtered_guards(gs, NULL));
/* Make sure we got the right number. */ tt_int_op(DFLT_MIN_FILTERED_SAMPLE_SIZE, OP_EQ, - num_reachable_filtered_guards(gs)); + num_reachable_filtered_guards(gs, NULL));
// Make sure everything we got was from our fake node list, and everything // was unique. @@ -1457,7 +1457,7 @@ test_entry_guard_expand_sample(void *arg) guard = entry_guards_expand_sample(gs); tt_assert(! guard); // no guard was added. tt_int_op(DFLT_MIN_FILTERED_SAMPLE_SIZE, OP_EQ, - num_reachable_filtered_guards(gs)); + num_reachable_filtered_guards(gs, NULL));
// Make a few guards unreachable. guard = smartlist_get(gs->sampled_entry_guards, 0); @@ -1467,21 +1467,21 @@ test_entry_guard_expand_sample(void *arg) guard = smartlist_get(gs->sampled_entry_guards, 2); guard->is_usable_filtered_guard = 0; tt_int_op(DFLT_MIN_FILTERED_SAMPLE_SIZE - 3, OP_EQ, - num_reachable_filtered_guards(gs)); + num_reachable_filtered_guards(gs, NULL));
// This time, expanding the sample will add some more guards. guard = entry_guards_expand_sample(gs); tt_assert(guard); // no guard was added. tt_int_op(DFLT_MIN_FILTERED_SAMPLE_SIZE, OP_EQ, - num_reachable_filtered_guards(gs)); + num_reachable_filtered_guards(gs, NULL)); tt_int_op(smartlist_len(gs->sampled_entry_guards), OP_EQ, - num_reachable_filtered_guards(gs)+3); + num_reachable_filtered_guards(gs, NULL)+3);
// Still idempotent. guard = entry_guards_expand_sample(gs); tt_assert(! guard); // no guard was added. tt_int_op(DFLT_MIN_FILTERED_SAMPLE_SIZE, OP_EQ, - num_reachable_filtered_guards(gs)); + num_reachable_filtered_guards(gs, NULL));
// Now, do a nasty trick: tell the filter to exclude 31/32 of the guards. // This will cause the sample size to get reeeeally huge, while the @@ -1497,7 +1497,7 @@ test_entry_guard_expand_sample(void *arg) entry_guards_update_filtered_sets(gs);
// Surely (p ~ 1-2**-60), one of our guards has been excluded. - tt_int_op(num_reachable_filtered_guards(gs), OP_LT, + tt_int_op(num_reachable_filtered_guards(gs, NULL), OP_LT, DFLT_MIN_FILTERED_SAMPLE_SIZE);
// Try to regenerate the guards. @@ -1505,7 +1505,7 @@ test_entry_guard_expand_sample(void *arg) tt_assert(guard); // no guard was added.
/* this time, it's possible that we didn't add enough sampled guards. */ - tt_int_op(num_reachable_filtered_guards(gs), OP_LE, + tt_int_op(num_reachable_filtered_guards(gs, NULL), OP_LE, DFLT_MIN_FILTERED_SAMPLE_SIZE); /* but we definitely didn't exceed the sample maximum. */ tt_int_op(smartlist_len(gs->sampled_entry_guards), OP_LE, @@ -1538,7 +1538,7 @@ test_entry_guard_expand_sample_small_net(void *arg) tt_assert(guard); // the last guard returned -- some guard was added. tt_int_op(smartlist_len(gs->sampled_entry_guards), OP_GT, 0); tt_int_op(smartlist_len(gs->sampled_entry_guards), OP_LT, 10); - tt_int_op(num_reachable_filtered_guards(gs), OP_EQ, 0); + tt_int_op(num_reachable_filtered_guards(gs, NULL), OP_EQ, 0); done: guard_selection_free(gs); } @@ -1562,7 +1562,7 @@ test_entry_guard_update_from_consensus_status(void *arg) /* First, sample some guards. */ entry_guards_expand_sample(gs); int n_sampled_pre = smartlist_len(gs->sampled_entry_guards); - int n_filtered_pre = num_reachable_filtered_guards(gs); + int n_filtered_pre = num_reachable_filtered_guards(gs, NULL); tt_i64_op(n_sampled_pre, OP_EQ, n_filtered_pre); tt_i64_op(n_sampled_pre, OP_GT, 10);
@@ -1584,7 +1584,7 @@ test_entry_guard_update_from_consensus_status(void *arg) dummy_consensus = NULL; sampled_guards_update_from_consensus(gs); tt_i64_op(smartlist_len(gs->sampled_entry_guards), OP_EQ, n_sampled_pre); - tt_i64_op(num_reachable_filtered_guards(gs), OP_EQ, n_filtered_pre); + tt_i64_op(num_reachable_filtered_guards(gs, NULL), OP_EQ, n_filtered_pre); /* put the networkstatus back. */ dummy_consensus = ns_tmp; ns_tmp = NULL; @@ -1596,7 +1596,7 @@ test_entry_guard_update_from_consensus_status(void *arg) sampled_guards_update_from_consensus(gs);
tt_i64_op(smartlist_len(gs->sampled_entry_guards), OP_EQ, n_sampled_pre); - tt_i64_op(num_reachable_filtered_guards(gs), OP_EQ, n_filtered_pre - 5); + tt_i64_op(num_reachable_filtered_guards(gs, NULL), OP_EQ, n_filtered_pre-5); for (i = 0; i < 5; ++i) { entry_guard_t *g = smartlist_get(gs->sampled_entry_guards, i); tt_assert(! g->currently_listed); @@ -1666,7 +1666,7 @@ test_entry_guard_update_from_consensus_repair(void *arg) /* First, sample some guards. */ entry_guards_expand_sample(gs); int n_sampled_pre = smartlist_len(gs->sampled_entry_guards); - int n_filtered_pre = num_reachable_filtered_guards(gs); + int n_filtered_pre = num_reachable_filtered_guards(gs, NULL); tt_i64_op(n_sampled_pre, OP_EQ, n_filtered_pre); tt_i64_op(n_sampled_pre, OP_GT, 10);
@@ -1694,7 +1694,7 @@ test_entry_guard_update_from_consensus_repair(void *arg) teardown_capture_of_logs();
tt_int_op(smartlist_len(gs->sampled_entry_guards), OP_EQ, n_sampled_pre); - tt_int_op(num_reachable_filtered_guards(gs), OP_EQ, n_filtered_pre - 3); + tt_int_op(num_reachable_filtered_guards(gs, NULL), OP_EQ, n_filtered_pre-3); for (i = 3; i < n_sampled_pre; ++i) { /* these will become listed. */ entry_guard_t *g = smartlist_get(gs->sampled_entry_guards, i); @@ -1731,7 +1731,7 @@ test_entry_guard_update_from_consensus_remove(void *arg) /* First, sample some guards. */ entry_guards_expand_sample(gs); int n_sampled_pre = smartlist_len(gs->sampled_entry_guards); - int n_filtered_pre = num_reachable_filtered_guards(gs); + int n_filtered_pre = num_reachable_filtered_guards(gs, NULL); tt_i64_op(n_sampled_pre, OP_EQ, n_filtered_pre); tt_i64_op(n_sampled_pre, OP_GT, 10);
@@ -1912,7 +1912,7 @@ test_entry_guard_sample_reachable_filtered(void *arg)
entry_guards_update_filtered_sets(gs); gs->primary_guards_up_to_date = 1; - tt_int_op(num_reachable_filtered_guards(gs), OP_EQ, n_guards - 1); + tt_int_op(num_reachable_filtered_guards(gs, NULL), OP_EQ, n_guards - 1); tt_int_op(smartlist_len(gs->sampled_entry_guards), OP_EQ, n_guards);
// +1 since the one we made disabled will make another one get added. @@ -1934,7 +1934,7 @@ test_entry_guard_sample_reachable_filtered(void *arg) const int excluded_flags = tests[j].flag; const int excluded_idx = tests[j].idx; for (i = 0; i < N; ++i) { - g = sample_reachable_filtered_entry_guards(gs, excluded_flags); + g = sample_reachable_filtered_entry_guards(gs, NULL, excluded_flags); tor_assert(g); int pos = smartlist_pos(gs->sampled_entry_guards, g); tt_int_op(smartlist_len(gs->sampled_entry_guards), OP_EQ, n_guards); @@ -1965,7 +1965,7 @@ test_entry_guard_sample_reachable_filtered_empty(void *arg) SMARTLIST_FOREACH(big_fake_net_nodes, node_t *, n, n->is_possible_guard = 0);
- entry_guard_t *g = sample_reachable_filtered_entry_guards(gs, 0); + entry_guard_t *g = sample_reachable_filtered_entry_guards(gs, NULL, 0); tt_ptr_op(g, OP_EQ, NULL);
done: @@ -2162,7 +2162,7 @@ test_entry_guard_select_for_circuit_no_confirmed(void *arg) entry_guards_update_primary(gs); unsigned state = 9999;
- entry_guard_t *g = select_entry_guard_for_circuit(gs, &state); + entry_guard_t *g = select_entry_guard_for_circuit(gs, NULL, &state);
tt_assert(g); tt_assert(g->is_primary); @@ -2172,7 +2172,7 @@ test_entry_guard_select_for_circuit_no_confirmed(void *arg) tt_i64_op(g->last_tried_to_connect, OP_EQ, approx_time());
// If we do that again, we should get the same guard. - entry_guard_t *g2 = select_entry_guard_for_circuit(gs, &state); + entry_guard_t *g2 = select_entry_guard_for_circuit(gs, NULL, &state); tt_ptr_op(g2, OP_EQ, g);
// if we mark that guard down, we should get a different primary guard. @@ -2181,7 +2181,7 @@ test_entry_guard_select_for_circuit_no_confirmed(void *arg) g->unreachable_since = approx_time() - 10; g->last_tried_to_connect = approx_time() - 10; state = 9999; - g2 = select_entry_guard_for_circuit(gs, &state); + g2 = select_entry_guard_for_circuit(gs, NULL, &state); tt_ptr_op(g2, OP_NE, g); tt_assert(g2); tt_assert(g2->is_primary); @@ -2195,7 +2195,7 @@ test_entry_guard_select_for_circuit_no_confirmed(void *arg) g->unreachable_since = approx_time() - 72*60*60; g->last_tried_to_connect = approx_time() - 72*60*60; state = 9999; - g2 = select_entry_guard_for_circuit(gs, &state); + g2 = select_entry_guard_for_circuit(gs, NULL, &state); tt_ptr_op(g2, OP_EQ, g); tt_assert(g2); tt_uint_op(state, OP_EQ, GUARD_CIRC_STATE_USABLE_ON_COMPLETION); @@ -2210,7 +2210,7 @@ test_entry_guard_select_for_circuit_no_confirmed(void *arg) guard->unreachable_since = approx_time() - 30; }); state = 9999; - g2 = select_entry_guard_for_circuit(gs, &state); + g2 = select_entry_guard_for_circuit(gs, NULL, &state); tt_assert(g2); tt_assert(!g2->is_primary); tt_int_op(g2->confirmed_idx, OP_EQ, -1); @@ -2254,7 +2254,7 @@ test_entry_guard_select_for_circuit_confirmed(void *arg) unsigned state = 9999;
// As above, this gives us a primary guard. - entry_guard_t *g = select_entry_guard_for_circuit(gs, &state); + entry_guard_t *g = select_entry_guard_for_circuit(gs, NULL, &state); tt_assert(g); tt_assert(g->is_primary); tt_int_op(g->confirmed_idx, OP_EQ, 0); @@ -2271,7 +2271,7 @@ test_entry_guard_select_for_circuit_confirmed(void *arg)
// ... we should get a confirmed guard. state = 9999; - g = select_entry_guard_for_circuit(gs, &state); + g = select_entry_guard_for_circuit(gs, NULL, &state); tt_assert(g); tt_assert(! g->is_primary); tt_int_op(g->confirmed_idx, OP_EQ, smartlist_len(gs->primary_entry_guards)); @@ -2282,7 +2282,7 @@ test_entry_guard_select_for_circuit_confirmed(void *arg) // And if we try again, we should get a different confirmed guard, since // that one is pending. state = 9999; - entry_guard_t *g2 = select_entry_guard_for_circuit(gs, &state); + entry_guard_t *g2 = select_entry_guard_for_circuit(gs, NULL, &state); tt_assert(g2); tt_assert(! g2->is_primary); tt_ptr_op(g2, OP_NE, g); @@ -2297,12 +2297,12 @@ test_entry_guard_select_for_circuit_confirmed(void *arg) const int n_remaining_confirmed = N_CONFIRMED - 2 - smartlist_len(gs->primary_entry_guards); for (i = 0; i < n_remaining_confirmed; ++i) { - g = select_entry_guard_for_circuit(gs, &state); + g = select_entry_guard_for_circuit(gs, NULL, &state); tt_int_op(g->confirmed_idx, OP_GE, 0); tt_assert(g); } state = 9999; - g = select_entry_guard_for_circuit(gs, &state); + g = select_entry_guard_for_circuit(gs, NULL, &state); tt_assert(g); tt_assert(g->is_pending); tt_int_op(g->confirmed_idx, OP_EQ, -1); @@ -2329,7 +2329,7 @@ test_entry_guard_select_for_circuit_highlevel_primary(void *arg) * Make sure that the pick-for-circuit API basically works. We'll get * a primary guard, so it'll be usable on completion. */ - int r = entry_guard_pick_for_circuit(gs, &node, &guard); + int r = entry_guard_pick_for_circuit(gs, NULL, &node, &guard);
tt_assert(r == 0); tt_assert(node); @@ -2361,7 +2361,7 @@ test_entry_guard_select_for_circuit_highlevel_primary(void *arg) /* Try again. We'll also get a primary guard this time. (The same one, in fact.) But this time, we'll say the connection has failed. */ update_approx_time(start+35); - r = entry_guard_pick_for_circuit(gs, &node, &guard); + r = entry_guard_pick_for_circuit(gs, NULL, &node, &guard); tt_assert(r == 0); tt_assert(node); tt_assert(guard); @@ -2396,7 +2396,7 @@ test_entry_guard_select_for_circuit_highlevel_primary(void *arg) * (still primary) guard. */ update_approx_time(start+60); - r = entry_guard_pick_for_circuit(gs, &node, &guard); + r = entry_guard_pick_for_circuit(gs, NULL, &node, &guard); tt_assert(r == 0); tt_assert(node); tt_assert(guard); @@ -2448,7 +2448,7 @@ test_entry_guard_select_for_circuit_highlevel_confirm_other(void *arg)
/* Primary guards are down! */ for (i = 0; i < N_PRIMARY; ++i) { - r = entry_guard_pick_for_circuit(gs, &node, &guard); + r = entry_guard_pick_for_circuit(gs, NULL, &node, &guard); tt_assert(node); tt_assert(guard); tt_assert(r == 0); @@ -2461,7 +2461,7 @@ test_entry_guard_select_for_circuit_highlevel_confirm_other(void *arg)
/* Next guard should be non-primary. */ node = NULL; - r = entry_guard_pick_for_circuit(gs, &node, &guard); + r = entry_guard_pick_for_circuit(gs, NULL, &node, &guard); tt_assert(node); tt_assert(guard); tt_assert(r == 0); @@ -2513,7 +2513,7 @@ test_entry_guard_select_for_circuit_highlevel_primary_retry(void *arg) /* Make primary guards confirmed (so they won't be superseded by a later * guard), then mark them down. */ for (i = 0; i < N_PRIMARY; ++i) { - r = entry_guard_pick_for_circuit(gs, &node, &guard); + r = entry_guard_pick_for_circuit(gs, NULL, &node, &guard); tt_assert(node); tt_assert(guard); tt_assert(r == 0); @@ -2529,7 +2529,7 @@ test_entry_guard_select_for_circuit_highlevel_primary_retry(void *arg) }
/* Get another guard that we might try. */ - r = entry_guard_pick_for_circuit(gs, &node, &guard); + r = entry_guard_pick_for_circuit(gs, NULL, &node, &guard); tt_assert(node); tt_assert(guard); tt_assert(r == 0); @@ -2556,7 +2556,7 @@ test_entry_guard_select_for_circuit_highlevel_primary_retry(void *arg) });
/* Have a circuit to a primary guard succeed. */ - r = entry_guard_pick_for_circuit(gs, &node, &guard2); + r = entry_guard_pick_for_circuit(gs, NULL, &node, &guard2); tt_assert(r == 0); tt_int_op(guard2->state, OP_EQ, GUARD_CIRC_STATE_USABLE_ON_COMPLETION); u = entry_guard_succeeded(&guard2); @@ -2585,7 +2585,7 @@ test_entry_guard_select_and_cancel(void *arg) /* Once more, we mark all the primary guards down. */ entry_guards_note_internet_connectivity(gs); for (i = 0; i < N_PRIMARY; ++i) { - r = entry_guard_pick_for_circuit(gs, &node, &guard); + r = entry_guard_pick_for_circuit(gs, NULL, &node, &guard); tt_int_op(guard->state, OP_EQ, GUARD_CIRC_STATE_USABLE_ON_COMPLETION); g = entry_guard_handle_get(guard->guard); tt_int_op(g->is_primary, OP_EQ, 1); @@ -2600,7 +2600,7 @@ test_entry_guard_select_and_cancel(void *arg) tt_assert(entry_guards_all_primary_guards_are_down(gs));
/* Now get another guard we could try... */ - r = entry_guard_pick_for_circuit(gs, &node, &guard); + r = entry_guard_pick_for_circuit(gs, NULL, &node, &guard); tt_assert(node); tt_assert(guard); tt_assert(r == 0); @@ -2659,7 +2659,7 @@ upgrade_circuits_setup(const struct testcase_t *testcase) data->start = approx_time(); entry_guards_note_internet_connectivity(gs); for (i = 0; i < N_PRIMARY; ++i) { - entry_guard_pick_for_circuit(gs, &node, &guard); + entry_guard_pick_for_circuit(gs, NULL, &node, &guard); g = entry_guard_handle_get(guard->guard); make_guard_confirmed(gs, g); entry_guard_failed(&guard); @@ -2670,7 +2670,7 @@ upgrade_circuits_setup(const struct testcase_t *testcase) data->all_origin_circuits = smartlist_new();
update_approx_time(data->start + 27); - entry_guard_pick_for_circuit(gs, &node, &data->guard1_state); + entry_guard_pick_for_circuit(gs, NULL, &node, &data->guard1_state); origin_circuit_t *circ; data->circ1 = circ = origin_circuit_new(); circ->base_.purpose = CIRCUIT_PURPOSE_C_GENERAL; @@ -2678,7 +2678,7 @@ upgrade_circuits_setup(const struct testcase_t *testcase) smartlist_add(data->all_origin_circuits, circ);
update_approx_time(data->start + 30); - entry_guard_pick_for_circuit(gs, &node, &data->guard2_state); + entry_guard_pick_for_circuit(gs, NULL, &node, &data->guard2_state); data->circ2 = circ = origin_circuit_new(); circ->base_.purpose = CIRCUIT_PURPOSE_C_GENERAL; circ->guard_state = data->guard2_state;
tor-commits@lists.torproject.org