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,
     Authorities, Single Onion Services, and Tor2web clients. In these cases,
     the this option is ignored. (Default: 1)
     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__::
 [[GuardfractionFile]] **GuardfractionFile** __FILENAME__::
     V3 authoritative directories only. Configures the location of the
     V3 authoritative directories only. Configures the location of the
     guardfraction file which contains information about how long relays
     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(UpdateBridgesFromAuthority,  BOOL,     "0"),
   V(UseBridges,                  BOOL,     "0"),
   V(UseBridges,                  BOOL,     "0"),
   VAR("UseEntryGuards",          BOOL,     UseEntryGuards_option, "1"),
   VAR("UseEntryGuards",          BOOL,     UseEntryGuards_option, "1"),
-  V(UseEntryGuardsAsDirGuards,   BOOL,     "1"),
+  OBSOLETE("UseEntryGuardsAsDirGuards"),
   V(UseGuardFraction,            AUTOBOOL, "auto"),
   V(UseGuardFraction,            AUTOBOOL, "auto"),
   V(UseMicrodescriptors,         AUTOBOOL, "auto"),
   V(UseMicrodescriptors,         AUTOBOOL, "auto"),
   OBSOLETE("UseNTorHandshake"),
   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. */
   /* Public (non-bridge) servers never use directory guards. */
   if (public_server_mode(options))
   if (public_server_mode(options))
     return 0;
     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;
     return 0;
   /* If we're configured to fetch directory info aggressively or of a
   /* If we're configured to fetch directory info aggressively or of a
    * nonstandard type, don't use directory guards. */
    * 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.
  * regardless of whether they are listed or unlisted.
  */
  */
 STATIC int
 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",
                                  "guard-lifetime-days",
                                  DFLT_GUARD_LIFETIME_DAYS, 1, 365*10);
                                  DFLT_GUARD_LIFETIME_DAYS, 1, 365*10);
+  return days * 86400;
 }
 }
 /**
 /**
  * We remove confirmed guards from the sample if they were sampled
  * We remove confirmed guards from the sample if they were sampled
  * GUARD_LIFETIME_DAYS ago and confirmed this many days ago.
  * GUARD_LIFETIME_DAYS ago and confirmed this many days ago.
  */
  */
 STATIC int
 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,
                                  DFLT_GUARD_CONFIRMED_MIN_LIFETIME_DAYS,
                                  1, 365*10);
                                  1, 365*10);
+  return days * 86400;
 }
 }
 /**
 /**
  * How many guards do we try to keep on our primary guard list?
  * 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
 STATIC int
 get_n_primary_guards(void)
 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);
                                  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
  * If we haven't successfully built or used a circuit in this long, then
  * consider that the internet is probably down.
  * 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 char *nickname,
                                const tor_addr_port_t *bridge_addrport)
                                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);
   tor_assert(gs);
 
 
   // XXXX prop271 take ed25519 identity here too.
   // 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 =
   const time_t remove_if_unlisted_since =
     approx_time() - REMOVE_UNLISTED_GUARDS_AFTER;
     approx_time() - REMOVE_UNLISTED_GUARDS_AFTER;
   const time_t maybe_remove_if_sampled_before =
   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 =
   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 */
   /* Then: remove the ones that have been junk for too long */
   SMARTLIST_FOREACH_BEGIN(gs->sampled_entry_guards, entry_guard_t *, guard) {
   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 "
         log_info(LD_GUARD, "Removing sampled guard %s: it was sampled "
                  "over %d days ago, but never confirmed.",
                  "over %d days ago, but never confirmed.",
                  entry_guard_describe(guard),
                  entry_guard_describe(guard),
-                 get_guard_lifetime_days());
+                 get_guard_lifetime() / 86400);
       } else if (guard->confirmed_on_date < remove_if_confirmed_before) {
       } else if (guard->confirmed_on_date < remove_if_confirmed_before) {
         remove = 1;
         remove = 1;
         log_info(LD_GUARD, "Removing sampled guard %s: it was sampled "
         log_info(LD_GUARD, "Removing sampled guard %s: it was sampled "
                  "over %d days ago, and confirmed over %d days ago.",
                  "over %d days ago, and confirmed over %d days ago.",
                  entry_guard_describe(guard),
                  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)))
   if (BUG(smartlist_contains(gs->confirmed_entry_guards, guard)))
     return; // LCOV_EXCL_LINE
     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);
   guard->confirmed_on_date = randomize_time(approx_time(), GUARD_LIFETIME/10);
 
 
   log_info(LD_GUARD, "Marking %s as a confirmed guard (index %d)",
   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 *
 STATIC entry_guard_t *
 select_entry_guard_for_circuit(guard_selection_t *gs,
 select_entry_guard_for_circuit(guard_selection_t *gs,
+                               guard_usage_t usage,
                                const entry_guard_restriction_t *rst,
                                const entry_guard_restriction_t *rst,
                                unsigned *state_out)
                                unsigned *state_out)
 {
 {
@@ -1797,6 +1840,9 @@ select_entry_guard_for_circuit(guard_selection_t *gs,
   if (!gs->primary_guards_up_to_date)
   if (!gs->primary_guards_up_to_date)
     entry_guards_update_primary(gs);
     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
   /* "If any entry in PRIMARY_GUARDS has {is_reachable} status of
       <maybe> or <yes>, return the first such guard." */
       <maybe> or <yes>, return the first such guard." */
   SMARTLIST_FOREACH_BEGIN(gs->primary_entry_guards, entry_guard_t *, 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) {
     if (guard->is_reachable != GUARD_REACHABLE_NO) {
       *state_out = GUARD_CIRC_STATE_USABLE_ON_COMPLETION;
       *state_out = GUARD_CIRC_STATE_USABLE_ON_COMPLETION;
       guard->last_tried_to_connect = approx_time();
       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);
   } 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}
   /* "Otherwise, if the ordered intersection of {CONFIRMED_GUARDS}
       and {USABLE_FILTERED_GUARDS} is nonempty, return the first
       and {USABLE_FILTERED_GUARDS} is nonempty, return the first
       entry in that intersection that has {is_pending} set to
       entry in that intersection that has {is_pending} set to
@@ -2048,6 +2103,7 @@ circuit_guard_state_free(circuit_guard_state_t *state)
  */
  */
 int
 int
 entry_guard_pick_for_circuit(guard_selection_t *gs,
 entry_guard_pick_for_circuit(guard_selection_t *gs,
+                             guard_usage_t usage,
                              entry_guard_restriction_t *rst,
                              entry_guard_restriction_t *rst,
                              const node_t **chosen_node_out,
                              const node_t **chosen_node_out,
                              circuit_guard_state_t **guard_state_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;
   *guard_state_out = NULL;
 
 
   unsigned state = 0;
   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)
   if (! guard)
     goto fail;
     goto fail;
   if (BUG(state == 0))
   if (BUG(state == 0))
@@ -4954,6 +5011,7 @@ guards_choose_guard(cpath_build_state_t *state,
       memcpy(rst->exclude_id, exit_id, DIGEST_LEN);
       memcpy(rst->exclude_id, exit_id, DIGEST_LEN);
     }
     }
     if (entry_guard_pick_for_circuit(get_guard_selection_info(),
     if (entry_guard_pick_for_circuit(get_guard_selection_info(),
+                                     GUARD_USAGE_TRAFFIC,
                                      rst,
                                      rst,
                                      &r,
                                      &r,
                                      guard_state_out) < 0) {
                                      guard_state_out) < 0) {
@@ -4986,6 +5044,7 @@ guards_choose_dirguard(dirinfo_type_t info,
      * microdescriptors. -NM */
      * microdescriptors. -NM */
     const node_t *r = NULL;
     const node_t *r = NULL;
     if (entry_guard_pick_for_circuit(get_guard_selection_info(),
     if (entry_guard_pick_for_circuit(get_guard_selection_info(),
+                                     GUARD_USAGE_DIRGUARD,
                                      NULL,
                                      NULL,
                                      &r,
                                      &r,
                                      guard_state_out) < 0) {
                                      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);
 const char *entry_guard_describe(const entry_guard_t *guard);
 guard_pathbias_t *entry_guard_get_pathbias_state(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);
 void circuit_guard_state_free(circuit_guard_state_t *state);
 int entry_guard_pick_for_circuit(guard_selection_t *gs,
 int entry_guard_pick_for_circuit(guard_selection_t *gs,
+                                 guard_usage_t usage,
                                  entry_guard_restriction_t *rst,
                                  entry_guard_restriction_t *rst,
                                  const node_t **chosen_node_out,
                                  const node_t **chosen_node_out,
                                  circuit_guard_state_t **guard_state_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?
  * How many guards do we try to keep on our primary guard list?
  */
  */
 #define DFLT_N_PRIMARY_GUARDS 3
 #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
  * If we haven't successfully built or used a circuit in this long, then
  * consider that the internet is probably down.
  * 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_max_sample_size_absolute(void);
 STATIC int get_min_filtered_sample_size(void);
 STATIC int get_min_filtered_sample_size(void);
 STATIC int get_remove_unlisted_guards_after_days(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(void);
+STATIC int get_n_primary_guards_to_use(guard_usage_t usage);
 STATIC int get_internet_likely_down_interval(void);
 STATIC int get_internet_likely_down_interval(void);
 STATIC int get_nonprimary_guard_connect_timeout(void);
 STATIC int get_nonprimary_guard_connect_timeout(void);
 STATIC int get_nonprimary_guard_idle_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,
 STATIC void entry_guards_note_guard_failure(guard_selection_t *gs,
                                             entry_guard_t *guard);
                                             entry_guard_t *guard);
 STATIC entry_guard_t *select_entry_guard_for_circuit(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,
                                           const entry_guard_restriction_t *rst,
                                           unsigned *state_out);
                                           unsigned *state_out);
 STATIC void mark_primary_guards_maybe_reachable(guard_selection_t *gs);
 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 UseEntryGuards;
 
 
   int NumEntryGuards; /**< How many entry guards do we try to establish? */
   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
   /** If 1, we use any guardfraction information we see in the
    * consensus.  If 0, we don't.  If -1, let the consensus parameter
    * 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(should_use_directory_guards(options), OP_EQ, 0);
   tt_int_op(CALLED(public_server_mode), OP_EQ, 1);
   tt_int_op(CALLED(public_server_mode), OP_EQ, 1);
 
 
-  options->UseEntryGuardsAsDirGuards = 1;
   options->UseEntryGuards = 1;
   options->UseEntryGuards = 1;
   options->DownloadExtraInfo = 0;
   options->DownloadExtraInfo = 0;
   options->FetchDirInfoEarly = 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);
   tt_int_op(CALLED(public_server_mode), OP_EQ, 3);
   options->UseEntryGuards = 1;
   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;
   options->DownloadExtraInfo = 1;
   tt_int_op(should_use_directory_guards(options), OP_EQ, 0);
   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->DownloadExtraInfo = 0;
 
 
   options->FetchDirInfoEarly = 1;
   options->FetchDirInfoEarly = 1;
   tt_int_op(should_use_directory_guards(options), OP_EQ, 0);
   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->FetchDirInfoEarly = 0;
 
 
   options->FetchDirInfoExtraEarly = 1;
   options->FetchDirInfoExtraEarly = 1;
   tt_int_op(should_use_directory_guards(options), OP_EQ, 0);
   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->FetchDirInfoExtraEarly = 0;
 
 
   options->FetchUselessDescriptors = 1;
   options->FetchUselessDescriptors = 1;
   tt_int_op(should_use_directory_guards(options), OP_EQ, 0);
   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;
   options->FetchUselessDescriptors = 0;
 
 
   done:
   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);
   entry_guards_update_primary(gs);
   unsigned state = 9999;
   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);
   tt_assert(g->is_primary);
   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());
   tt_i64_op(g->last_tried_to_connect, OP_EQ, approx_time());
 
 
   // If we do that again, we should get the same guard.
   // 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);
   tt_ptr_op(g2, OP_EQ, g);
 
 
   // if we mark that guard down, we should get a different primary guard.
   // 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->failing_since = approx_time() - 10;
   g->last_tried_to_connect = approx_time() - 10;
   g->last_tried_to_connect = approx_time() - 10;
   state = 9999;
   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_ptr_op(g2, OP_NE, g);
   tt_assert(g2);
   tt_assert(g2);
   tt_assert(g2->is_primary);
   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->failing_since = approx_time() - 72*60*60;
   g->last_tried_to_connect = approx_time() - 72*60*60;
   g->last_tried_to_connect = approx_time() - 72*60*60;
   state = 9999;
   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_ptr_op(g2, OP_EQ, g);
   tt_assert(g2);
   tt_assert(g2);
   tt_uint_op(state, OP_EQ, GUARD_CIRC_STATE_USABLE_ON_COMPLETION);
   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;
     guard->failing_since = approx_time() - 30;
   });
   });
   state = 9999;
   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);
   tt_assert(!g2->is_primary);
   tt_assert(!g2->is_primary);
   tt_int_op(g2->confirmed_idx, OP_EQ, -1);
   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 */
   /* 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));
   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);
   tt_ptr_op(g2, OP_EQ, g);
 
 
   /* But if we impose a restriction, we don't get the same guard */
   /* But if we impose a restriction, we don't get the same guard */
   entry_guard_restriction_t rst;
   entry_guard_restriction_t rst;
   memset(&rst, 0, sizeof(rst));
   memset(&rst, 0, sizeof(rst));
   memcpy(rst.exclude_id, g->identity, DIGEST_LEN);
   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_ptr_op(g2, OP_NE, g);
 
 
  done:
  done:
@@ -2552,7 +2554,8 @@ test_entry_guard_select_for_circuit_confirmed(void *arg)
   unsigned state = 9999;
   unsigned state = 9999;
 
 
   // As above, this gives us a primary guard.
   // 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);
   tt_assert(g->is_primary);
   tt_assert(g->is_primary);
   tt_int_op(g->confirmed_idx, OP_EQ, 0);
   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.
   // ... we should get a confirmed guard.
   state = 9999;
   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);
   tt_assert(! g->is_primary);
   tt_assert(! g->is_primary);
   tt_int_op(g->confirmed_idx, OP_EQ, smartlist_len(gs->primary_entry_guards));
   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
   // And if we try again, we should get a different confirmed guard, since
   // that one is pending.
   // that one is pending.
   state = 9999;
   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);
   tt_assert(! g2->is_primary);
   tt_assert(! g2->is_primary);
   tt_ptr_op(g2, OP_NE, g);
   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;
   entry_guard_restriction_t rst;
   memset(&rst, 0, sizeof(rst));
   memset(&rst, 0, sizeof(rst));
   memcpy(rst.exclude_id, g->identity, DIGEST_LEN);
   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_ptr_op(g2, OP_NE, g);
   tt_int_op(g2->confirmed_idx, OP_EQ,
   tt_int_op(g2->confirmed_idx, OP_EQ,
             smartlist_len(gs->primary_entry_guards)+3);
             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 =
   const int n_remaining_confirmed =
     N_CONFIRMED - 3 - smartlist_len(gs->primary_entry_guards);
     N_CONFIRMED - 3 - smartlist_len(gs->primary_entry_guards);
   for (i = 0; i < n_remaining_confirmed; ++i) {
   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_int_op(g->confirmed_idx, OP_GE, 0);
     tt_assert(g);
     tt_assert(g);
   }
   }
   state = 9999;
   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);
   tt_assert(g->is_pending);
   tt_assert(g->is_pending);
   tt_int_op(g->confirmed_idx, OP_EQ, -1);
   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
    * Make sure that the pick-for-circuit API basically works.  We'll get
    * a primary guard, so it'll be usable on completion.
    * 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(r == 0);
   tt_assert(node);
   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,
   /* 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. */
      in fact.)  But this time, we'll say the connection has failed. */
   update_approx_time(start+35);
   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(r == 0);
   tt_assert(node);
   tt_assert(node);
   tt_assert(guard);
   tt_assert(guard);
@@ -2706,7 +2712,8 @@ test_entry_guard_select_for_circuit_highlevel_primary(void *arg)
    * (still primary) guard.
    * (still primary) guard.
    */
    */
   update_approx_time(start+60);
   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(r == 0);
   tt_assert(node);
   tt_assert(node);
   tt_assert(guard);
   tt_assert(guard);
@@ -2758,7 +2765,8 @@ test_entry_guard_select_for_circuit_highlevel_confirm_other(void *arg)
 
 
   /* Primary guards are down! */
   /* Primary guards are down! */
   for (i = 0; i < N_PRIMARY; ++i) {
   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(node);
     tt_assert(guard);
     tt_assert(guard);
     tt_assert(r == 0);
     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. */
   /* Next guard should be non-primary. */
   node = NULL;
   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(node);
   tt_assert(guard);
   tt_assert(guard);
   tt_assert(r == 0);
   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
   /* Make primary guards confirmed (so they won't be superseded by a later
    * guard), then mark them down. */
    * guard), then mark them down. */
   for (i = 0; i < N_PRIMARY; ++i) {
   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(node);
     tt_assert(guard);
     tt_assert(guard);
     tt_assert(r == 0);
     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. */
   /* 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(node);
   tt_assert(guard);
   tt_assert(guard);
   tt_assert(r == 0);
   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. */
   /* 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_assert(r == 0);
   tt_int_op(guard2->state, OP_EQ, GUARD_CIRC_STATE_USABLE_ON_COMPLETION);
   tt_int_op(guard2->state, OP_EQ, GUARD_CIRC_STATE_USABLE_ON_COMPLETION);
   u = entry_guard_succeeded(&guard2);
   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. */
   /* Once more, we mark all the primary guards down. */
   entry_guards_note_internet_connectivity(gs);
   entry_guards_note_internet_connectivity(gs);
   for (i = 0; i < N_PRIMARY; ++i) {
   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);
     tt_int_op(guard->state, OP_EQ, GUARD_CIRC_STATE_USABLE_ON_COMPLETION);
     g = entry_guard_handle_get(guard->guard);
     g = entry_guard_handle_get(guard->guard);
     tt_int_op(g->is_primary, OP_EQ, 1);
     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));
   tt_assert(entry_guards_all_primary_guards_are_down(gs));
 
 
   /* Now get another guard we could try... */
   /* 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(node);
   tt_assert(guard);
   tt_assert(guard);
   tt_assert(r == 0);
   tt_assert(r == 0);
@@ -2969,7 +2983,7 @@ upgrade_circuits_setup(const struct testcase_t *testcase)
   data->start = approx_time();
   data->start = approx_time();
   entry_guards_note_internet_connectivity(gs);
   entry_guards_note_internet_connectivity(gs);
   for (i = 0; i < N_PRIMARY; ++i) {
   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);
     g = entry_guard_handle_get(guard->guard);
     make_guard_confirmed(gs, g);
     make_guard_confirmed(gs, g);
     entry_guard_failed(&guard);
     entry_guard_failed(&guard);
@@ -2980,7 +2994,8 @@ upgrade_circuits_setup(const struct testcase_t *testcase)
   data->all_origin_circuits = smartlist_new();
   data->all_origin_circuits = smartlist_new();
 
 
   update_approx_time(data->start + 27);
   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;
   origin_circuit_t *circ;
   data->circ1 = circ = origin_circuit_new();
   data->circ1 = circ = origin_circuit_new();
   circ->base_.purpose = CIRCUIT_PURPOSE_C_GENERAL;
   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);
   smartlist_add(data->all_origin_circuits, circ);
 
 
   update_approx_time(data->start + 30);
   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();
   data->circ2 = circ = origin_circuit_new();
   circ->base_.purpose = CIRCUIT_PURPOSE_C_GENERAL;
   circ->base_.purpose = CIRCUIT_PURPOSE_C_GENERAL;
   circ->guard_state = data->guard2_state;
   circ->guard_state = data->guard2_state;