[tor-commits] [tor/master] Implement support for per-circuit guard restrictions.
nickm at torproject.org
nickm at torproject.org
Fri Dec 16 16:26:19 UTC 2016
commit 87f9b42179bd23418c3e698938bdeead56da1c43
Author: Nick Mathewson <nickm at 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;
More information about the tor-commits
mailing list