|  | @@ -3642,7 +3642,7 @@ control_event_guard_deferred(void)
 | 
	
		
			
				|  |  |   * already in our entry_guards list, put it at the *beginning*.
 | 
	
		
			
				|  |  |   * Else, put the one we pick at the end of the list. */
 | 
	
		
			
				|  |  |  static const node_t *
 | 
	
		
			
				|  |  | -add_an_entry_guard(const node_t *chosen, int reset_status)
 | 
	
		
			
				|  |  | +add_an_entry_guard(const node_t *chosen, int reset_status, int prepend)
 | 
	
		
			
				|  |  |  {
 | 
	
		
			
				|  |  |    const node_t *node;
 | 
	
		
			
				|  |  |    entry_guard_t *entry;
 | 
	
	
		
			
				|  | @@ -3674,9 +3674,9 @@ add_an_entry_guard(const node_t *chosen, int reset_status)
 | 
	
		
			
				|  |  |     * this guard. For details, see the Jan 2010 or-dev thread. */
 | 
	
		
			
				|  |  |    entry->chosen_on_date = time(NULL) - crypto_rand_int(3600*24*30);
 | 
	
		
			
				|  |  |    entry->chosen_by_version = tor_strdup(VERSION);
 | 
	
		
			
				|  |  | -  if (chosen) /* prepend */
 | 
	
		
			
				|  |  | +  if (prepend)
 | 
	
		
			
				|  |  |      smartlist_insert(entry_guards, 0, entry);
 | 
	
		
			
				|  |  | -  else /* append */
 | 
	
		
			
				|  |  | +  else
 | 
	
		
			
				|  |  |      smartlist_add(entry_guards, entry);
 | 
	
		
			
				|  |  |    control_event_guard(entry->nickname, entry->identity, "NEW");
 | 
	
		
			
				|  |  |    control_event_guard_deferred();
 | 
	
	
		
			
				|  | @@ -3694,7 +3694,7 @@ pick_entry_guards(const or_options_t *options)
 | 
	
		
			
				|  |  |    tor_assert(entry_guards);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    while (num_live_entry_guards() < options->NumEntryGuards) {
 | 
	
		
			
				|  |  | -    if (!add_an_entry_guard(NULL, 0))
 | 
	
		
			
				|  |  | +    if (!add_an_entry_guard(NULL, 0, 0))
 | 
	
		
			
				|  |  |        break;
 | 
	
		
			
				|  |  |      changed = 1;
 | 
	
		
			
				|  |  |    }
 | 
	
	
		
			
				|  | @@ -4007,12 +4007,12 @@ entry_nodes_should_be_added(void)
 | 
	
		
			
				|  |  |    should_add_entry_nodes = 1;
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -/** Add all nodes in EntryNodes that aren't currently guard nodes to the list
 | 
	
		
			
				|  |  | - * of guard nodes, at the front. */
 | 
	
		
			
				|  |  | +/** Adjust the entry guards list so that it only contains entries from
 | 
	
		
			
				|  |  | + * EntryNodes, adding new entries from EntryNodes to the list as needed. */
 | 
	
		
			
				|  |  |  static void
 | 
	
		
			
				|  |  | -entry_guards_prepend_from_config(const or_options_t *options)
 | 
	
		
			
				|  |  | +entry_guards_set_from_config(const or_options_t *options)
 | 
	
		
			
				|  |  |  {
 | 
	
		
			
				|  |  | -  smartlist_t *entry_nodes, *entry_fps;
 | 
	
		
			
				|  |  | +  smartlist_t *entry_nodes, *worse_entry_nodes, *entry_fps;
 | 
	
		
			
				|  |  |    smartlist_t *old_entry_guards_on_list, *old_entry_guards_not_on_list;
 | 
	
		
			
				|  |  |    tor_assert(entry_guards);
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -4033,18 +4033,13 @@ entry_guards_prepend_from_config(const or_options_t *options)
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    entry_nodes = smartlist_create();
 | 
	
		
			
				|  |  | +  worse_entry_nodes = smartlist_create();
 | 
	
		
			
				|  |  |    entry_fps = smartlist_create();
 | 
	
		
			
				|  |  |    old_entry_guards_on_list = smartlist_create();
 | 
	
		
			
				|  |  |    old_entry_guards_not_on_list = smartlist_create();
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    /* Split entry guards into those on the list and those not. */
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -  /* XXXX023 Now that we allow countries and IP ranges in EntryNodes, this is
 | 
	
		
			
				|  |  | -   *  potentially an enormous list. For now, we disable such values for
 | 
	
		
			
				|  |  | -   *  EntryNodes in options_validate(); really, this wants a better solution.
 | 
	
		
			
				|  |  | -   *  Perhaps we should do this calculation once whenever the list of routers
 | 
	
		
			
				|  |  | -   *  changes or the entrynodes setting changes.
 | 
	
		
			
				|  |  | -   */
 | 
	
		
			
				|  |  |    routerset_get_all_nodes(entry_nodes, options->EntryNodes,
 | 
	
		
			
				|  |  |                            options->ExcludeNodes, 0);
 | 
	
		
			
				|  |  |    SMARTLIST_FOREACH(entry_nodes, const node_t *,node,
 | 
	
	
		
			
				|  | @@ -4057,27 +4052,47 @@ entry_guards_prepend_from_config(const or_options_t *options)
 | 
	
		
			
				|  |  |        smartlist_add(old_entry_guards_not_on_list, e);
 | 
	
		
			
				|  |  |    });
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -  /* Remove all currently configured entry guards from entry_routers. */
 | 
	
		
			
				|  |  | -  SMARTLIST_FOREACH(entry_nodes, const node_t *, node, {
 | 
	
		
			
				|  |  | +  /* Remove all currently configured guard nodes, excluded nodes, unreachable
 | 
	
		
			
				|  |  | +   * nodes, or non-Guard nodes from entry_nodes. */
 | 
	
		
			
				|  |  | +  SMARTLIST_FOREACH_BEGIN(entry_nodes, const node_t *, node) {
 | 
	
		
			
				|  |  |      if (is_an_entry_guard(node->identity)) {
 | 
	
		
			
				|  |  |        SMARTLIST_DEL_CURRENT(entry_nodes, node);
 | 
	
		
			
				|  |  | +      continue;
 | 
	
		
			
				|  |  | +    } else if (routerset_contains_node(options->ExcludeNodes, node)) {
 | 
	
		
			
				|  |  | +      SMARTLIST_DEL_CURRENT(entry_nodes, node);
 | 
	
		
			
				|  |  | +      continue;
 | 
	
		
			
				|  |  | +    } else if (!fascist_firewall_allows_node(node)) {
 | 
	
		
			
				|  |  | +      SMARTLIST_DEL_CURRENT(entry_nodes, node);
 | 
	
		
			
				|  |  | +      continue;
 | 
	
		
			
				|  |  | +    } else if (! node->is_possible_guard) {
 | 
	
		
			
				|  |  | +      smartlist_add(worse_entry_nodes, (node_t*)node);
 | 
	
		
			
				|  |  | +      SMARTLIST_DEL_CURRENT(entry_nodes, node);
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  | -  });
 | 
	
		
			
				|  |  | +  } SMARTLIST_FOREACH_END(node);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    /* Now build the new entry_guards list. */
 | 
	
		
			
				|  |  |    smartlist_clear(entry_guards);
 | 
	
		
			
				|  |  |    /* First, the previously configured guards that are in EntryNodes. */
 | 
	
		
			
				|  |  |    smartlist_add_all(entry_guards, old_entry_guards_on_list);
 | 
	
		
			
				|  |  | +  /* Next, scramble the rest of EntryNodes, putting the guards first. */
 | 
	
		
			
				|  |  | +  smartlist_shuffle(entry_nodes);
 | 
	
		
			
				|  |  | +  smartlist_shuffle(worse_entry_nodes);
 | 
	
		
			
				|  |  | +  smartlist_add_all(entry_nodes, worse_entry_nodes);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |    /* Next, the rest of EntryNodes */
 | 
	
		
			
				|  |  | -  SMARTLIST_FOREACH(entry_nodes, const node_t *, node, {
 | 
	
		
			
				|  |  | -    add_an_entry_guard(node, 0);
 | 
	
		
			
				|  |  | -  });
 | 
	
		
			
				|  |  | +  SMARTLIST_FOREACH_BEGIN(entry_nodes, const node_t *, node) {
 | 
	
		
			
				|  |  | +    add_an_entry_guard(node, 0, 0);
 | 
	
		
			
				|  |  | +    if (smartlist_len(entry_guards) > options->NumEntryGuards * 10)
 | 
	
		
			
				|  |  | +      break;
 | 
	
		
			
				|  |  | +  } SMARTLIST_FOREACH_END(node);
 | 
	
		
			
				|  |  | +  log_notice(LD_GENERAL, "%d entries in guards", smartlist_len(entry_guards));
 | 
	
		
			
				|  |  |    /* Finally, free the remaining previously configured guards that are not in
 | 
	
		
			
				|  |  |     * EntryNodes. */
 | 
	
		
			
				|  |  |    SMARTLIST_FOREACH(old_entry_guards_not_on_list, entry_guard_t *, e,
 | 
	
		
			
				|  |  |                      entry_guard_free(e));
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    smartlist_free(entry_nodes);
 | 
	
		
			
				|  |  | +  smartlist_free(worse_entry_nodes);
 | 
	
		
			
				|  |  |    smartlist_free(entry_fps);
 | 
	
		
			
				|  |  |    smartlist_free(old_entry_guards_on_list);
 | 
	
		
			
				|  |  |    smartlist_free(old_entry_guards_not_on_list);
 | 
	
	
		
			
				|  | @@ -4125,7 +4140,7 @@ choose_random_entry(cpath_build_state_t *state)
 | 
	
		
			
				|  |  |      entry_guards = smartlist_create();
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    if (should_add_entry_nodes)
 | 
	
		
			
				|  |  | -    entry_guards_prepend_from_config(options);
 | 
	
		
			
				|  |  | +    entry_guards_set_from_config(options);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    if (!entry_list_is_constrained(options) &&
 | 
	
		
			
				|  |  |        smartlist_len(entry_guards) < options->NumEntryGuards)
 | 
	
	
		
			
				|  | @@ -4150,7 +4165,7 @@ choose_random_entry(cpath_build_state_t *state)
 | 
	
		
			
				|  |  |            goto choose_and_finish; /* only choose from the ones we like */
 | 
	
		
			
				|  |  |          if (options->StrictNodes) {
 | 
	
		
			
				|  |  |            /* in theory this case should never happen, since
 | 
	
		
			
				|  |  | -           * entry_guards_prepend_from_config() drops unwanted relays */
 | 
	
		
			
				|  |  | +           * entry_guards_set_from_config() drops unwanted relays */
 | 
	
		
			
				|  |  |            tor_fragile_assert();
 | 
	
		
			
				|  |  |          } else {
 | 
	
		
			
				|  |  |            log_info(LD_CIRC,
 | 
	
	
		
			
				|  | @@ -4188,7 +4203,7 @@ choose_random_entry(cpath_build_state_t *state)
 | 
	
		
			
				|  |  |        /* XXX if guard doesn't imply fast and stable, then we need
 | 
	
		
			
				|  |  |         * to tell add_an_entry_guard below what we want, or it might
 | 
	
		
			
				|  |  |         * be a long time til we get it. -RD */
 | 
	
		
			
				|  |  | -      node = add_an_entry_guard(NULL, 0);
 | 
	
		
			
				|  |  | +      node = add_an_entry_guard(NULL, 0, 0);
 | 
	
		
			
				|  |  |        if (node) {
 | 
	
		
			
				|  |  |          entry_guards_changed();
 | 
	
		
			
				|  |  |          /* XXX we start over here in case the new node we added shares
 | 
	
	
		
			
				|  | @@ -5024,7 +5039,7 @@ learned_bridge_descriptor(routerinfo_t *ri, int from_cache)
 | 
	
		
			
				|  |  |        node = node_get_mutable_by_id(ri->cache_info.identity_digest);
 | 
	
		
			
				|  |  |        tor_assert(node);
 | 
	
		
			
				|  |  |        rewrite_node_address_for_bridge(bridge, node);
 | 
	
		
			
				|  |  | -      add_an_entry_guard(node, 1);
 | 
	
		
			
				|  |  | +      add_an_entry_guard(node, 1, 1);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |        log_notice(LD_DIR, "new bridge descriptor '%s' (%s)", ri->nickname,
 | 
	
		
			
				|  |  |                   from_cache ? "cached" : "fresh");
 |