Browse Source

Merge branch 'ticket20831_v2'

Nick Mathewson 7 years ago
parent
commit
990a863d7c
9 changed files with 152 additions and 70 deletions
  1. 6 0
      changes/ticket20831
  2. 0 9
      doc/tor.1.txt
  3. 1 1
      src/or/config.c
  4. 2 3
      src/or/directory.c
  5. 75 16
      src/or/entrynodes.c
  6. 21 2
      src/or/entrynodes.h
  7. 0 2
      src/or/or.h
  8. 4 10
      src/test/test_dir.c
  9. 43 27
      src/test/test_entrynodes.c

+ 6 - 0
changes/ticket20831

@@ -0,0 +1,6 @@
+  o Removed features:
+    - The UseDirectoryGuards torrc options is
+      no longer present: all users that use entry guards will also use
+      directory guards. Related to proposal 271; implements part of
+      ticket 20831.
+

+ 0 - 9
doc/tor.1.txt

@@ -1217,15 +1217,6 @@ The following options are useful only for clients (that is, if
     Authorities, Single Onion Services, and Tor2web clients. In these cases,
     the this option is ignored. (Default: 1)
 
-[[UseEntryGuardsAsDirGuards]] **UseEntryGuardsAsDirGuards** **0**|**1**::
-    If this option is set to 1, and UseEntryGuards is also set to 1,
-    we try to use our entry guards as directory
-    guards, and failing that, pick more nodes to act as our directory guards.
-    This helps prevent an adversary from enumerating clients. It's only
-    available for clients (non-relay, non-bridge) that aren't configured to
-    download any non-default directory material.  It doesn't currently
-    do anything when we lack a live consensus. (Default: 1)
-
 [[GuardfractionFile]] **GuardfractionFile** __FILENAME__::
     V3 authoritative directories only. Configures the location of the
     guardfraction file which contains information about how long relays

+ 1 - 1
src/or/config.c

@@ -496,7 +496,7 @@ static config_var_t option_vars_[] = {
   V(UpdateBridgesFromAuthority,  BOOL,     "0"),
   V(UseBridges,                  BOOL,     "0"),
   VAR("UseEntryGuards",          BOOL,     UseEntryGuards_option, "1"),
-  V(UseEntryGuardsAsDirGuards,   BOOL,     "1"),
+  OBSOLETE("UseEntryGuardsAsDirGuards"),
   V(UseGuardFraction,            AUTOBOOL, "auto"),
   V(UseMicrodescriptors,         AUTOBOOL, "auto"),
   OBSOLETE("UseNTorHandshake"),

+ 2 - 3
src/or/directory.c

@@ -442,10 +442,9 @@ should_use_directory_guards(const or_options_t *options)
   /* Public (non-bridge) servers never use directory guards. */
   if (public_server_mode(options))
     return 0;
-  /* If guards are disabled, or directory guards are disabled, we can't
-   * use directory guards.
+  /* If guards are disabled, we can't use directory guards.
    */
-  if (!options->UseEntryGuards || !options->UseEntryGuardsAsDirGuards)
+  if (!options->UseEntryGuards)
     return 0;
   /* If we're configured to fetch directory info aggressively or of a
    * nonstandard type, don't use directory guards. */

+ 75 - 16
src/or/entrynodes.c

@@ -440,22 +440,30 @@ get_remove_unlisted_guards_after_days(void)
  * regardless of whether they are listed or unlisted.
  */
 STATIC int
-get_guard_lifetime_days(void)
+get_guard_lifetime(void)
 {
-  return networkstatus_get_param(NULL,
+  if (get_options()->GuardLifetime >= 86400)
+    return get_options()->GuardLifetime;
+  int32_t days;
+  days = networkstatus_get_param(NULL,
                                  "guard-lifetime-days",
                                  DFLT_GUARD_LIFETIME_DAYS, 1, 365*10);
+  return days * 86400;
 }
 /**
  * We remove confirmed guards from the sample if they were sampled
  * GUARD_LIFETIME_DAYS ago and confirmed this many days ago.
  */
 STATIC int
-get_guard_confirmed_min_lifetime_days(void)
+get_guard_confirmed_min_lifetime(void)
 {
-  return networkstatus_get_param(NULL, "guard-confirmed-min-lifetime-days",
+  if (get_options()->GuardLifetime >= 86400)
+    return get_options()->GuardLifetime;
+  int32_t days;
+  days = networkstatus_get_param(NULL, "guard-confirmed-min-lifetime-days",
                                  DFLT_GUARD_CONFIRMED_MIN_LIFETIME_DAYS,
                                  1, 365*10);
+  return days * 86400;
 }
 /**
  * How many guards do we try to keep on our primary guard list?
@@ -463,9 +471,43 @@ get_guard_confirmed_min_lifetime_days(void)
 STATIC int
 get_n_primary_guards(void)
 {
-  return networkstatus_get_param(NULL, "guard-n-primary-guards",
+  const int n = get_options()->NumEntryGuards;
+  const int n_dir = get_options()->NumDirectoryGuards;
+  if (n > 5) {
+    return MAX(n_dir, n + n / 2);
+  } else if (n >= 1) {
+    return MAX(n_dir, n * 2);
+  }
+
+  return networkstatus_get_param(NULL,
+                                 "guard-n-primary-guards",
                                  DFLT_N_PRIMARY_GUARDS, 1, INT32_MAX);
 }
+/**
+ * Return the number of the live primary guards we should look at when
+ * making a circuit.
+ */
+STATIC int
+get_n_primary_guards_to_use(guard_usage_t usage)
+{
+  int configured;
+  const char *param_name;
+  int param_default;
+  if (usage == GUARD_USAGE_DIRGUARD) {
+    configured = get_options()->NumDirectoryGuards;
+    param_name = "guard-n-primary-dir-guards-to-use";
+    param_default = DFLT_N_PRIMARY_DIR_GUARDS_TO_USE;
+  } else {
+    configured = get_options()->NumEntryGuards;
+    param_name = "guard-n-primary-guards-to-use";
+    param_default = DFLT_N_PRIMARY_GUARDS_TO_USE;
+  }
+  if (configured >= 1) {
+    return configured;
+  }
+  return networkstatus_get_param(NULL,
+                                 param_name, param_default, 1, INT32_MAX);
+}
 /**
  * If we haven't successfully built or used a circuit in this long, then
  * consider that the internet is probably down.
@@ -793,7 +835,7 @@ entry_guard_add_to_sample_impl(guard_selection_t *gs,
                                const char *nickname,
                                const tor_addr_port_t *bridge_addrport)
 {
-  const int GUARD_LIFETIME = get_guard_lifetime_days() * 86400;
+  const int GUARD_LIFETIME = get_guard_lifetime();
   tor_assert(gs);
 
   // XXXX prop271 take ed25519 identity here too.
@@ -1238,9 +1280,9 @@ sampled_guards_update_from_consensus(guard_selection_t *gs)
   const time_t remove_if_unlisted_since =
     approx_time() - REMOVE_UNLISTED_GUARDS_AFTER;
   const time_t maybe_remove_if_sampled_before =
-    approx_time() - (get_guard_lifetime_days() * 86400);
+    approx_time() - get_guard_lifetime();
   const time_t remove_if_confirmed_before =
-    approx_time() - (get_guard_confirmed_min_lifetime_days() * 86400);
+    approx_time() - get_guard_confirmed_min_lifetime();
 
   /* Then: remove the ones that have been junk for too long */
   SMARTLIST_FOREACH_BEGIN(gs->sampled_entry_guards, entry_guard_t *, guard) {
@@ -1267,14 +1309,14 @@ sampled_guards_update_from_consensus(guard_selection_t *gs)
         log_info(LD_GUARD, "Removing sampled guard %s: it was sampled "
                  "over %d days ago, but never confirmed.",
                  entry_guard_describe(guard),
-                 get_guard_lifetime_days());
+                 get_guard_lifetime() / 86400);
       } else if (guard->confirmed_on_date < remove_if_confirmed_before) {
         remove = 1;
         log_info(LD_GUARD, "Removing sampled guard %s: it was sampled "
                  "over %d days ago, and confirmed over %d days ago.",
                  entry_guard_describe(guard),
-                 get_guard_lifetime_days(),
-                 get_guard_confirmed_min_lifetime_days());
+                 get_guard_lifetime() / 86400,
+                 get_guard_confirmed_min_lifetime() / 86400);
       }
     }
 
@@ -1569,7 +1611,7 @@ make_guard_confirmed(guard_selection_t *gs, entry_guard_t *guard)
   if (BUG(smartlist_contains(gs->confirmed_entry_guards, guard)))
     return; // LCOV_EXCL_LINE
 
-  const int GUARD_LIFETIME = get_guard_lifetime_days() * 86400;
+  const int GUARD_LIFETIME = get_guard_lifetime();
   guard->confirmed_on_date = randomize_time(approx_time(), GUARD_LIFETIME/10);
 
   log_info(LD_GUARD, "Marking %s as a confirmed guard (index %d)",
@@ -1787,6 +1829,7 @@ entry_guards_note_internet_connectivity(guard_selection_t *gs)
  */
 STATIC entry_guard_t *
 select_entry_guard_for_circuit(guard_selection_t *gs,
+                               guard_usage_t usage,
                                const entry_guard_restriction_t *rst,
                                unsigned *state_out)
 {
@@ -1797,6 +1840,9 @@ select_entry_guard_for_circuit(guard_selection_t *gs,
   if (!gs->primary_guards_up_to_date)
     entry_guards_update_primary(gs);
 
+  int num_entry_guards = get_n_primary_guards_to_use(usage);
+  smartlist_t *usable_primary_guards = smartlist_new();
+
   /* "If any entry in PRIMARY_GUARDS has {is_reachable} status of
       <maybe> or <yes>, return the first such guard." */
   SMARTLIST_FOREACH_BEGIN(gs->primary_entry_guards, entry_guard_t *, guard) {
@@ -1806,12 +1852,21 @@ select_entry_guard_for_circuit(guard_selection_t *gs,
     if (guard->is_reachable != GUARD_REACHABLE_NO) {
       *state_out = GUARD_CIRC_STATE_USABLE_ON_COMPLETION;
       guard->last_tried_to_connect = approx_time();
-      log_info(LD_GUARD, "Selected primary guard %s for circuit.",
-               entry_guard_describe(guard));
-      return guard;
+      smartlist_add(usable_primary_guards, guard);
+      if (smartlist_len(usable_primary_guards) >= num_entry_guards)
+        break;
     }
   } SMARTLIST_FOREACH_END(guard);
 
+  if (smartlist_len(usable_primary_guards)) {
+    entry_guard_t *guard = smartlist_choose(usable_primary_guards);
+    smartlist_free(usable_primary_guards);
+    log_info(LD_GUARD, "Selected primary guard %s for circuit.",
+             entry_guard_describe(guard));
+    return guard;
+  }
+  smartlist_free(usable_primary_guards);
+
   /* "Otherwise, if the ordered intersection of {CONFIRMED_GUARDS}
       and {USABLE_FILTERED_GUARDS} is nonempty, return the first
       entry in that intersection that has {is_pending} set to
@@ -2048,6 +2103,7 @@ circuit_guard_state_free(circuit_guard_state_t *state)
  */
 int
 entry_guard_pick_for_circuit(guard_selection_t *gs,
+                             guard_usage_t usage,
                              entry_guard_restriction_t *rst,
                              const node_t **chosen_node_out,
                              circuit_guard_state_t **guard_state_out)
@@ -2059,7 +2115,8 @@ 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, rst, &state);
+  entry_guard_t *guard =
+    select_entry_guard_for_circuit(gs, usage, rst, &state);
   if (! guard)
     goto fail;
   if (BUG(state == 0))
@@ -4954,6 +5011,7 @@ guards_choose_guard(cpath_build_state_t *state,
       memcpy(rst->exclude_id, exit_id, DIGEST_LEN);
     }
     if (entry_guard_pick_for_circuit(get_guard_selection_info(),
+                                     GUARD_USAGE_TRAFFIC,
                                      rst,
                                      &r,
                                      guard_state_out) < 0) {
@@ -4986,6 +5044,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(),
+                                     GUARD_USAGE_DIRGUARD,
                                      NULL,
                                      &r,
                                      guard_state_out) < 0) {

+ 21 - 2
src/or/entrynodes.h

@@ -397,8 +397,16 @@ const char *entry_guard_get_rsa_id_digest(const entry_guard_t *guard);
 const char *entry_guard_describe(const entry_guard_t *guard);
 guard_pathbias_t *entry_guard_get_pathbias_state(entry_guard_t *guard);
 
+/** Enum to specify how we're going to use a given guard, when we're picking
+ * one for immediate use. */
+typedef enum {
+  GUARD_USAGE_TRAFFIC = 0,
+  GUARD_USAGE_DIRGUARD = 1
+} guard_usage_t;
+
 void circuit_guard_state_free(circuit_guard_state_t *state);
 int entry_guard_pick_for_circuit(guard_selection_t *gs,
+                                 guard_usage_t usage,
                                  entry_guard_restriction_t *rst,
                                  const node_t **chosen_node_out,
                                  circuit_guard_state_t **guard_state_out);
@@ -471,6 +479,15 @@ int num_bridges_usable(void);
  * How many guards do we try to keep on our primary guard list?
  */
 #define DFLT_N_PRIMARY_GUARDS 3
+/**
+ * Of the live guards on the primary guard list, how many do we consider when
+ * choosing a guard to use?
+ */
+#define DFLT_N_PRIMARY_GUARDS_TO_USE 1
+/**
+ * As DFLT_N_PRIMARY_GUARDS, but for choosing which directory guard to use.
+ */
+#define DFLT_N_PRIMARY_DIR_GUARDS_TO_USE 3
 /**
  * If we haven't successfully built or used a circuit in this long, then
  * consider that the internet is probably down.
@@ -503,9 +520,10 @@ STATIC double get_max_sample_threshold(void);
 STATIC int get_max_sample_size_absolute(void);
 STATIC int get_min_filtered_sample_size(void);
 STATIC int get_remove_unlisted_guards_after_days(void);
-STATIC int get_guard_lifetime_days(void);
-STATIC int get_guard_confirmed_min_lifetime_days(void);
+STATIC int get_guard_lifetime(void);
+STATIC int get_guard_confirmed_min_lifetime(void);
 STATIC int get_n_primary_guards(void);
+STATIC int get_n_primary_guards_to_use(guard_usage_t usage);
 STATIC int get_internet_likely_down_interval(void);
 STATIC int get_nonprimary_guard_connect_timeout(void);
 STATIC int get_nonprimary_guard_idle_timeout(void);
@@ -584,6 +602,7 @@ 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,
+                                          guard_usage_t usage,
                                           const entry_guard_restriction_t *rst,
                                           unsigned *state_out);
 STATIC void mark_primary_guards_maybe_reachable(guard_selection_t *gs);

+ 0 - 2
src/or/or.h

@@ -4062,8 +4062,6 @@ typedef struct {
   int UseEntryGuards;
 
   int NumEntryGuards; /**< How many entry guards do we try to establish? */
-  int UseEntryGuardsAsDirGuards; /** Boolean: Do we try to get directory info
-                                  * from a smallish number of fixed nodes? */
 
   /** If 1, we use any guardfraction information we see in the
    * consensus.  If 0, we don't.  If -1, let the consensus parameter

+ 4 - 10
src/test/test_dir.c

@@ -4359,7 +4359,6 @@ test_dir_should_use_directory_guards(void *data)
   tt_int_op(should_use_directory_guards(options), OP_EQ, 0);
   tt_int_op(CALLED(public_server_mode), OP_EQ, 1);
 
-  options->UseEntryGuardsAsDirGuards = 1;
   options->UseEntryGuards = 1;
   options->DownloadExtraInfo = 0;
   options->FetchDirInfoEarly = 0;
@@ -4373,29 +4372,24 @@ test_dir_should_use_directory_guards(void *data)
   tt_int_op(CALLED(public_server_mode), OP_EQ, 3);
   options->UseEntryGuards = 1;
 
-  options->UseEntryGuardsAsDirGuards = 0;
-  tt_int_op(should_use_directory_guards(options), OP_EQ, 0);
-  tt_int_op(CALLED(public_server_mode), OP_EQ, 4);
-  options->UseEntryGuardsAsDirGuards = 1;
-
   options->DownloadExtraInfo = 1;
   tt_int_op(should_use_directory_guards(options), OP_EQ, 0);
-  tt_int_op(CALLED(public_server_mode), OP_EQ, 5);
+  tt_int_op(CALLED(public_server_mode), OP_EQ, 4);
   options->DownloadExtraInfo = 0;
 
   options->FetchDirInfoEarly = 1;
   tt_int_op(should_use_directory_guards(options), OP_EQ, 0);
-  tt_int_op(CALLED(public_server_mode), OP_EQ, 6);
+  tt_int_op(CALLED(public_server_mode), OP_EQ, 5);
   options->FetchDirInfoEarly = 0;
 
   options->FetchDirInfoExtraEarly = 1;
   tt_int_op(should_use_directory_guards(options), OP_EQ, 0);
-  tt_int_op(CALLED(public_server_mode), OP_EQ, 7);
+  tt_int_op(CALLED(public_server_mode), OP_EQ, 6);
   options->FetchDirInfoExtraEarly = 0;
 
   options->FetchUselessDescriptors = 1;
   tt_int_op(should_use_directory_guards(options), OP_EQ, 0);
-  tt_int_op(CALLED(public_server_mode), OP_EQ, 8);
+  tt_int_op(CALLED(public_server_mode), OP_EQ, 7);
   options->FetchUselessDescriptors = 0;
 
   done:

+ 43 - 27
src/test/test_entrynodes.c

@@ -2447,7 +2447,8 @@ 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, NULL, &state);
+  entry_guard_t *g = select_entry_guard_for_circuit(gs, GUARD_USAGE_TRAFFIC,
+                                                    NULL, &state);
 
   tt_assert(g);
   tt_assert(g->is_primary);
@@ -2457,7 +2458,8 @@ 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, NULL, &state);
+  entry_guard_t *g2 = select_entry_guard_for_circuit(gs, GUARD_USAGE_TRAFFIC,
+                                                     NULL, &state);
   tt_ptr_op(g2, OP_EQ, g);
 
   // if we mark that guard down, we should get a different primary guard.
@@ -2466,7 +2468,7 @@ test_entry_guard_select_for_circuit_no_confirmed(void *arg)
   g->failing_since = approx_time() - 10;
   g->last_tried_to_connect = approx_time() - 10;
   state = 9999;
-  g2 = select_entry_guard_for_circuit(gs, NULL, &state);
+  g2 = select_entry_guard_for_circuit(gs, GUARD_USAGE_TRAFFIC, NULL, &state);
   tt_ptr_op(g2, OP_NE, g);
   tt_assert(g2);
   tt_assert(g2->is_primary);
@@ -2480,7 +2482,7 @@ test_entry_guard_select_for_circuit_no_confirmed(void *arg)
   g->failing_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, NULL, &state);
+  g2 = select_entry_guard_for_circuit(gs, GUARD_USAGE_TRAFFIC, NULL, &state);
   tt_ptr_op(g2, OP_EQ, g);
   tt_assert(g2);
   tt_uint_op(state, OP_EQ, GUARD_CIRC_STATE_USABLE_ON_COMPLETION);
@@ -2495,7 +2497,7 @@ test_entry_guard_select_for_circuit_no_confirmed(void *arg)
     guard->failing_since = approx_time() - 30;
   });
   state = 9999;
-  g2 = select_entry_guard_for_circuit(gs, NULL, &state);
+  g2 = select_entry_guard_for_circuit(gs, GUARD_USAGE_TRAFFIC, NULL, &state);
   tt_assert(g2);
   tt_assert(!g2->is_primary);
   tt_int_op(g2->confirmed_idx, OP_EQ, -1);
@@ -2515,16 +2517,16 @@ test_entry_guard_select_for_circuit_no_confirmed(void *arg)
   });
 
   /* Let's try again and we should get the first primary guard again */
-  g = select_entry_guard_for_circuit(gs, NULL, &state);
+  g = select_entry_guard_for_circuit(gs, GUARD_USAGE_TRAFFIC, NULL, &state);
   tt_ptr_op(g, OP_EQ, smartlist_get(gs->primary_entry_guards, 0));
-  g2 = select_entry_guard_for_circuit(gs, NULL, &state);
+  g2 = select_entry_guard_for_circuit(gs, GUARD_USAGE_TRAFFIC, NULL, &state);
   tt_ptr_op(g2, OP_EQ, g);
 
   /* But if we impose a restriction, we don't get the same guard */
   entry_guard_restriction_t rst;
   memset(&rst, 0, sizeof(rst));
   memcpy(rst.exclude_id, g->identity, DIGEST_LEN);
-  g2 = select_entry_guard_for_circuit(gs, &rst, &state);
+  g2 = select_entry_guard_for_circuit(gs, GUARD_USAGE_TRAFFIC, &rst, &state);
   tt_ptr_op(g2, OP_NE, g);
 
  done:
@@ -2552,7 +2554,8 @@ 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, NULL, &state);
+  entry_guard_t *g = select_entry_guard_for_circuit(gs, GUARD_USAGE_TRAFFIC,
+                                                    NULL, &state);
   tt_assert(g);
   tt_assert(g->is_primary);
   tt_int_op(g->confirmed_idx, OP_EQ, 0);
@@ -2569,7 +2572,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, NULL, &state);
+  g = select_entry_guard_for_circuit(gs, GUARD_USAGE_TRAFFIC, NULL, &state);
   tt_assert(g);
   tt_assert(! g->is_primary);
   tt_int_op(g->confirmed_idx, OP_EQ, smartlist_len(gs->primary_entry_guards));
@@ -2580,7 +2583,8 @@ 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, NULL, &state);
+  entry_guard_t *g2 = select_entry_guard_for_circuit(gs, GUARD_USAGE_TRAFFIC,
+                                                     NULL, &state);
   tt_assert(g2);
   tt_assert(! g2->is_primary);
   tt_ptr_op(g2, OP_NE, g);
@@ -2597,7 +2601,7 @@ test_entry_guard_select_for_circuit_confirmed(void *arg)
   entry_guard_restriction_t rst;
   memset(&rst, 0, sizeof(rst));
   memcpy(rst.exclude_id, g->identity, DIGEST_LEN);
-  g2 = select_entry_guard_for_circuit(gs, &rst, &state);
+  g2 = select_entry_guard_for_circuit(gs, GUARD_USAGE_TRAFFIC, &rst, &state);
   tt_ptr_op(g2, OP_NE, g);
   tt_int_op(g2->confirmed_idx, OP_EQ,
             smartlist_len(gs->primary_entry_guards)+3);
@@ -2607,12 +2611,12 @@ test_entry_guard_select_for_circuit_confirmed(void *arg)
   const int n_remaining_confirmed =
     N_CONFIRMED - 3 - smartlist_len(gs->primary_entry_guards);
   for (i = 0; i < n_remaining_confirmed; ++i) {
-    g = select_entry_guard_for_circuit(gs, NULL, &state);
+    g = select_entry_guard_for_circuit(gs, GUARD_USAGE_TRAFFIC, NULL, &state);
     tt_int_op(g->confirmed_idx, OP_GE, 0);
     tt_assert(g);
   }
   state = 9999;
-  g = select_entry_guard_for_circuit(gs, NULL, &state);
+  g = select_entry_guard_for_circuit(gs, GUARD_USAGE_TRAFFIC, NULL, &state);
   tt_assert(g);
   tt_assert(g->is_pending);
   tt_int_op(g->confirmed_idx, OP_EQ, -1);
@@ -2639,7 +2643,8 @@ 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, NULL, &node, &guard);
+  int r = entry_guard_pick_for_circuit(gs, GUARD_USAGE_TRAFFIC, NULL,
+                                       &node, &guard);
 
   tt_assert(r == 0);
   tt_assert(node);
@@ -2671,7 +2676,8 @@ 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, NULL, &node, &guard);
+  r = entry_guard_pick_for_circuit(gs, GUARD_USAGE_TRAFFIC, NULL,
+                                   &node, &guard);
   tt_assert(r == 0);
   tt_assert(node);
   tt_assert(guard);
@@ -2706,7 +2712,8 @@ 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, NULL, &node, &guard);
+  r = entry_guard_pick_for_circuit(gs, GUARD_USAGE_TRAFFIC, NULL,
+                                   &node, &guard);
   tt_assert(r == 0);
   tt_assert(node);
   tt_assert(guard);
@@ -2758,7 +2765,8 @@ 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, NULL, &node, &guard);
+    r = entry_guard_pick_for_circuit(gs, GUARD_USAGE_TRAFFIC, NULL,
+                                     &node, &guard);
     tt_assert(node);
     tt_assert(guard);
     tt_assert(r == 0);
@@ -2771,7 +2779,8 @@ 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, NULL, &node, &guard);
+  r = entry_guard_pick_for_circuit(gs, GUARD_USAGE_TRAFFIC, NULL,
+                                   &node, &guard);
   tt_assert(node);
   tt_assert(guard);
   tt_assert(r == 0);
@@ -2823,7 +2832,8 @@ 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, NULL, &node, &guard);
+    r = entry_guard_pick_for_circuit(gs, GUARD_USAGE_TRAFFIC, NULL,
+                                     &node, &guard);
     tt_assert(node);
     tt_assert(guard);
     tt_assert(r == 0);
@@ -2839,7 +2849,8 @@ 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, NULL, &node, &guard);
+  r = entry_guard_pick_for_circuit(gs, GUARD_USAGE_TRAFFIC, NULL,
+                                   &node, &guard);
   tt_assert(node);
   tt_assert(guard);
   tt_assert(r == 0);
@@ -2866,7 +2877,8 @@ 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, NULL, &node, &guard2);
+  r = entry_guard_pick_for_circuit(gs, GUARD_USAGE_TRAFFIC, 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);
@@ -2895,7 +2907,8 @@ 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, NULL, &node, &guard);
+    r = entry_guard_pick_for_circuit(gs, GUARD_USAGE_TRAFFIC, 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);
@@ -2910,7 +2923,8 @@ 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, NULL, &node, &guard);
+  r = entry_guard_pick_for_circuit(gs, GUARD_USAGE_TRAFFIC, NULL,
+                                   &node, &guard);
   tt_assert(node);
   tt_assert(guard);
   tt_assert(r == 0);
@@ -2969,7 +2983,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, NULL, &node, &guard);
+    entry_guard_pick_for_circuit(gs, GUARD_USAGE_TRAFFIC, NULL, &node, &guard);
     g = entry_guard_handle_get(guard->guard);
     make_guard_confirmed(gs, g);
     entry_guard_failed(&guard);
@@ -2980,7 +2994,8 @@ 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, NULL, &node, &data->guard1_state);
+  entry_guard_pick_for_circuit(gs, GUARD_USAGE_TRAFFIC, NULL,
+                               &node, &data->guard1_state);
   origin_circuit_t *circ;
   data->circ1 = circ = origin_circuit_new();
   circ->base_.purpose = CIRCUIT_PURPOSE_C_GENERAL;
@@ -2988,7 +3003,8 @@ 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, NULL, &node, &data->guard2_state);
+  entry_guard_pick_for_circuit(gs, GUARD_USAGE_TRAFFIC, NULL,
+                               &node, &data->guard2_state);
   data->circ2 = circ = origin_circuit_new();
   circ->base_.purpose = CIRCUIT_PURPOSE_C_GENERAL;
   circ->guard_state = data->guard2_state;