aboutsummaryrefslogtreecommitdiff
path: root/src/or/entrynodes.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/or/entrynodes.h')
-rw-r--r--src/or/entrynodes.h648
1 files changed, 549 insertions, 99 deletions
diff --git a/src/or/entrynodes.h b/src/or/entrynodes.h
index 1021e67d43..d562498313 100644
--- a/src/or/entrynodes.h
+++ b/src/or/entrynodes.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2016, The Tor Project, Inc. */
+ * Copyright (c) 2007-2017, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -12,25 +12,27 @@
#ifndef TOR_ENTRYNODES_H
#define TOR_ENTRYNODES_H
-#if 1
-/* XXXX NM I would prefer that all of this stuff be private to
- * entrynodes.c. */
+#include "handles.h"
-/** An entry_guard_t represents our information about a chosen long-term
- * first hop, known as a "helper" node in the literature. We can't just
- * use a node_t, since we want to remember these even when we
- * don't have any directory info. */
-typedef struct entry_guard_t {
- char nickname[MAX_NICKNAME_LEN+1];
- char identity[DIGEST_LEN];
- time_t chosen_on_date; /**< Approximately when was this guard added?
- * "0" if we don't know. */
- char *chosen_by_version; /**< What tor version added this guard? NULL
- * if we don't know. */
- unsigned int made_contact : 1; /**< 0 if we have never connected to this
- * router, 1 if we have. */
- unsigned int can_retry : 1; /**< Should we retry connecting to this entry,
- * in spite of having it marked as unreachable?*/
+/* Forward declare for guard_selection_t; entrynodes.c has the real struct */
+typedef struct guard_selection_s guard_selection_t;
+
+/* Forward declare for entry_guard_t; the real declaration is private. */
+typedef struct entry_guard_t entry_guard_t;
+
+/* Forward declaration for circuit_guard_state_t; the real declaration is
+ 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.
+ */
+typedef struct guard_pathbias_t {
unsigned int path_bias_noticed : 1; /**< Did we alert the user about path
* bias for this node already? */
unsigned int path_bias_warned : 1; /**< Did we alert the user about path bias
@@ -43,15 +45,6 @@ typedef struct entry_guard_t {
* use bias for this node already? */
unsigned int path_bias_use_extreme : 1; /**< Did we alert the user about path
* use bias for this node already? */
- unsigned int is_dir_cache : 1; /**< Is this node a directory cache? */
- time_t bad_since; /**< 0 if this guard is currently usable, or the time at
- * which it was observed to become (according to the
- * directory or the user configuration) unusable. */
- time_t unreachable_since; /**< 0 if we can connect to this guard, or the
- * time at which we first noticed we couldn't
- * connect to it. */
- time_t last_attempted; /**< 0 if we can connect to this guard, or the time
- * at which we last failed to connect to it. */
double circ_attempts; /**< Number of circuits this guard has "attempted" */
double circ_successes; /**< Number of successfully built circuits using
@@ -68,98 +61,559 @@ typedef struct entry_guard_t {
double use_attempts; /**< Number of circuits we tried to use with streams */
double use_successes; /**< Number of successfully used circuits using
* this guard as first hop. */
-} entry_guard_t;
+} guard_pathbias_t;
+
+#if defined(ENTRYNODES_PRIVATE)
+/**
+ * @name values for entry_guard_t.is_reachable.
+ *
+ * See entry_guard_t.is_reachable for more information.
+ */
+/**@{*/
+#define GUARD_REACHABLE_NO 0
+#define GUARD_REACHABLE_YES 1
+#define GUARD_REACHABLE_MAYBE 2
+/**@}*/
+
+/** An entry_guard_t represents our information about a chosen long-term
+ * first hop, known as a "helper" node in the literature. We can't just
+ * use a node_t, since we want to remember these even when we
+ * don't have any directory info. */
+struct entry_guard_t {
+ HANDLE_ENTRY(entry_guard, entry_guard_t);
+
+ char nickname[MAX_HEX_NICKNAME_LEN+1];
+ char identity[DIGEST_LEN];
+ ed25519_public_key_t ed_id;
+
+ /**
+ * @name new guard selection algorithm fields.
+ *
+ * Only the new (prop271) algorithm uses these. For a more full
+ * description of the algorithm, see the module documentation for
+ * entrynodes.c
+ */
+ /**@{*/
+
+ /* == Persistent fields, present for all sampled guards. */
+ /** When was this guard added to the sample? */
+ time_t sampled_on_date;
+ /** Since what date has this guard been "unlisted"? A guard counts as
+ * unlisted if we have a live consensus that does not include it, or
+ * if we have a live consensus that does not include it as a usable
+ * guard. This field is zero when the guard is listed. */
+ time_t unlisted_since_date; // can be zero
+ /** What version of Tor added this guard to the sample? */
+ char *sampled_by_version;
+ /** Is this guard listed right now? If this is set, then
+ * unlisted_since_date should be set too. */
+ unsigned currently_listed : 1;
+
+ /* == Persistent fields, for confirmed guards only */
+ /** When was this guard confirmed? (That is, when did we first use it
+ * successfully and decide to keep it?) This field is zero if this is not a
+ * confirmed guard. */
+ time_t confirmed_on_date; /* 0 if not confirmed */
+ /**
+ * In what order was this guard confirmed? Guards with lower indices
+ * appear earlier on the confirmed list. If the confirmed list is compacted,
+ * this field corresponds to the index of this guard on the confirmed list.
+ *
+ * This field is set to -1 if this guard is not confirmed.
+ */
+ int confirmed_idx; /* -1 if not confirmed; otherwise the order that this
+ * item should occur in the CONFIRMED_GUARDS ordered
+ * list */
+
+ /**
+ * Which selection does this guard belong to?
+ */
+ char *selection_name;
+ /** Bridges only: address of the bridge. */
+ tor_addr_port_t *bridge_addr;
+
+ /* ==== Non-persistent fields. */
+ /* == These are used by sampled guards */
+ /** When did we last decide to try using this guard for a circuit? 0 for
+ * "not since we started up." */
+ time_t last_tried_to_connect;
+ /** How reachable do we consider this guard to be? One of
+ * GUARD_REACHABLE_NO, GUARD_REACHABLE_YES, or GUARD_REACHABLE_MAYBE. */
+ unsigned is_reachable : 2;
+ /** Boolean: true iff this guard is pending. A pending guard is one
+ * that we have an in-progress circuit through, and which we do not plan
+ * to try again until it either succeeds or fails. Primary guards can
+ * never be pending. */
+ unsigned is_pending : 1;
+ /** If true, don't write this guard to disk. (Used for bridges with unknown
+ * identities) */
+ unsigned is_persistent : 1;
+ /** When did we get the earliest connection failure for this guard?
+ * We clear this field on a successful connect. We do _not_ clear it
+ * when we mark the guard as "MAYBE" reachable.
+ */
+ time_t failing_since;
+
+ /* == Set inclusion flags. */
+ /** If true, this guard is in the filtered set. The filtered set includes
+ * all sampled guards that our configuration allows us to use. */
+ unsigned is_filtered_guard : 1;
+ /** If true, this guard is in the usable filtered set. The usable filtered
+ * set includes all filtered guards that are not believed to be
+ * unreachable. (That is, those for which is_reachable is not
+ * GUARD_REACHABLE_NO) */
+ unsigned is_usable_filtered_guard : 1;
+ unsigned is_primary:1;
+
+ /** This string holds any fields that we are maintaining because
+ * we saw them in the state, even if we don't understand them. */
+ char *extra_state_fields;
+
+ /** Backpointer to the guard selection that this guard belongs to.
+ * The entry_guard_t must never outlive its guard_selection. */
+ guard_selection_t *in_selection;
+ /**@}*/
+
+ /** Path bias information for this guard. */
+ guard_pathbias_t pb;
+};
+
+/**
+ * Possible rules for a guard selection to follow
+ */
+typedef enum guard_selection_type_t {
+ /** Infer the type of this selection from its name. */
+ GS_TYPE_INFER=0,
+ /** Use the normal guard selection algorithm, taking our sample from the
+ * complete list of guards in the consensus. */
+ GS_TYPE_NORMAL=1,
+ /** Use the normal guard selection algorithm, taking our sample from the
+ * configured bridges, and allowing it to grow as large as all the configured
+ * bridges */
+ GS_TYPE_BRIDGE,
+ /** Use the normal guard selection algorithm, taking our sample from the
+ * set of filtered nodes. */
+ GS_TYPE_RESTRICTED,
+} guard_selection_type_t;
+
+/**
+ * All of the the context for guard selection on a particular client.
+ *
+ * We maintain multiple guard selection contexts for a client, depending
+ * aspects on its current configuration -- whether an extremely
+ * restrictive EntryNodes is used, whether UseBridges is enabled, and so
+ * on.)
+ *
+ * See the module documentation for entrynodes.c for more information
+ * about guard selection algorithms.
+ */
+struct guard_selection_s {
+ /**
+ * The name for this guard-selection object. (Must not contain spaces).
+ */
+ char *name;
+
+ /**
+ * What rules does this guard-selection object follow?
+ */
+ guard_selection_type_t type;
+
+ /**
+ * A value of 1 means that primary_entry_guards is up-to-date with respect to
+ * the consensus and status info that we currently have; 0 means we need to
+ * recalculate it before using primary_entry_guards or the is_primary flag on
+ * any guard.
+ */
+ int primary_guards_up_to_date;
+
+ /**
+ * A list of the sampled entry guards, as entry_guard_t structures.
+ * Not in any particular order. When we 'sample' a guard, we are
+ * noting it as a possible guard to pick in the future. The use of
+ * sampling here prevents us from being forced by an attacker to try
+ * every guard on the network. This list is persistent.
+ */
+ smartlist_t *sampled_entry_guards;
+
+ /**
+ * Ordered list (from highest to lowest priority) of guards that we
+ * have successfully contacted and decided to use. Every member of
+ * this list is a member of sampled_entry_guards. Every member should
+ * have confirmed_on_date set, and have confirmed_idx greater than
+ * any earlier member of the list.
+ *
+ * This list is persistent. It is a subset of the elements in
+ * sampled_entry_guards, and its pointers point to elements of
+ * sampled_entry_guards.
+ */
+ smartlist_t *confirmed_entry_guards;
+
+ /**
+ * Ordered list (from highest to lowest priority) of guards that we
+ * are willing to use the most happily. These guards may or may not
+ * yet be confirmed yet. If we can use one of these guards, we are
+ * probably not on a network that is trying to restrict our guard
+ * choices.
+ *
+ * This list is a subset of the elements in
+ * sampled_entry_guards, and its pointers point to elements of
+ * sampled_entry_guards.
+ */
+ smartlist_t *primary_entry_guards;
+
+ /** When did we last successfully build a circuit or use a circuit? */
+ time_t last_time_on_internet;
+
+ /** What confirmed_idx value should the next-added member of
+ * confirmed_entry_guards receive? */
+ int next_confirmed_idx;
+
+};
+
+struct entry_guard_handle_t;
+
+/** Types of restrictions we impose when picking guard nodes */
+typedef enum guard_restriction_type_t {
+ /* Don't pick the same guard node as our exit node (or its family) */
+ RST_EXIT_NODE = 0,
+ /* Don't pick dirguards that have previously shown to be outdated */
+ RST_OUTDATED_MD_DIRSERVER = 1
+} guard_restriction_type_t;
+
+/**
+ * A restriction to remember which entry guards are off-limits for a given
+ * circuit.
+ *
+ * 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 {
+ /* What type of restriction are we imposing? */
+ guard_restriction_type_t type;
+
+ /* In case of restriction type RST_EXIT_NODE, the guard's RSA identity
+ * digest must not equal this; and it must not be in the same family as any
+ * node with this digest. */
+ 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 {
+ /** Handle to the entry guard object for this circuit. */
+ struct entry_guard_handle_t *guard;
+ /** The time at which <b>state</b> last changed. */
+ 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 /* defined(ENTRYNODES_PRIVATE) */
+
+/* Common entry points for old and new guard code */
+int guards_update_all(void);
+const node_t *guards_choose_guard(cpath_build_state_t *state,
+ circuit_guard_state_t **guard_state_out);
+const node_t *guards_choose_dirguard(uint8_t dir_purpose,
+ circuit_guard_state_t **guard_state_out);
+
+#if 1
+/* XXXX NM I would prefer that all of this stuff be private to
+ * entrynodes.c. */
+entry_guard_t *entry_guard_get_by_id_digest_for_guard_selection(
+ guard_selection_t *gs, const char *digest);
entry_guard_t *entry_guard_get_by_id_digest(const char *digest);
+
+circuit_guard_state_t *
+get_guard_state_for_bridge_desc_fetch(const char *digest);
+
+void entry_guards_changed_for_guard_selection(guard_selection_t *gs);
void entry_guards_changed(void);
-const smartlist_t *get_entry_guards(void);
+guard_selection_t * get_guard_selection_info(void);
+int num_live_entry_guards_for_guard_selection(
+ guard_selection_t *gs,
+ int for_directory);
int num_live_entry_guards(int for_directory);
+#endif /* 1 */
-#endif
+const node_t *entry_guard_find_node(const entry_guard_t *guard);
+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);
-#ifdef ENTRYNODES_PRIVATE
-STATIC const node_t *add_an_entry_guard(const node_t *chosen,
- int reset_status, int prepend,
- int for_discovery, int for_directory);
-
-STATIC int populate_live_entry_guards(smartlist_t *live_entry_guards,
- const smartlist_t *all_entry_guards,
- const node_t *chosen_exit,
- dirinfo_type_t dirinfo_type,
- int for_directory,
- int need_uptime, int need_capacity);
-STATIC int decide_num_guards(const or_options_t *options, int for_directory);
-
-STATIC void entry_guards_set_from_config(const or_options_t *options);
-
-/** Flags to be passed to entry_is_live() to indicate what kind of
- * entry nodes we are looking for. */
+/** 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;
+
+#define circuit_guard_state_free(val) \
+ FREE_AND_NULL(circuit_guard_state_t, circuit_guard_state_free_, (val))
+
+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);
+
+/* We just connected to an entry guard. What should we do with the circuit? */
typedef enum {
- ENTRY_NEED_UPTIME = 1<<0,
- ENTRY_NEED_CAPACITY = 1<<1,
- ENTRY_ASSUME_REACHABLE = 1<<2,
- ENTRY_NEED_DESCRIPTOR = 1<<3,
-} entry_is_live_flags_t;
+ GUARD_USABLE_NEVER = -1, /* Never use the circuit */
+ GUARD_MAYBE_USABLE_LATER = 0, /* Keep it. We might use it in the future */
+ GUARD_USABLE_NOW = 1, /* Use it right now */
+} guard_usable_t;
+
+guard_usable_t entry_guard_succeeded(circuit_guard_state_t **guard_state_p);
+void entry_guard_failed(circuit_guard_state_t **guard_state_p);
+void entry_guard_cancel(circuit_guard_state_t **guard_state_p);
+void entry_guard_chan_failed(channel_t *chan);
+int entry_guards_update_all(guard_selection_t *gs);
+int entry_guards_upgrade_waiting_circuits(guard_selection_t *gs,
+ const smartlist_t *all_circuits,
+ smartlist_t *newly_complete_out);
+int entry_guard_state_should_expire(circuit_guard_state_t *guard_state);
+void entry_guards_note_internet_connectivity(guard_selection_t *gs);
+
+int update_guard_selection_choice(const or_options_t *options);
+
+int entry_guard_could_succeed(const circuit_guard_state_t *guard_state);
+
+MOCK_DECL(int,num_bridges_usable,(int use_maybe_reachable));
+
+#ifdef ENTRYNODES_PRIVATE
+/**
+ * @name Default values for the parameters for the new (prop271) entry guard
+ * algorithm.
+ */
+/**@{*/
+/**
+ * We never let our sampled guard set grow larger than this percentage
+ * of the guards on the network.
+ */
+#define DFLT_MAX_SAMPLE_THRESHOLD_PERCENT 20
+/**
+ * We never let our sampled guard set grow larger than this number of
+ * guards.
+ */
+#define DFLT_MAX_SAMPLE_SIZE 60
+/**
+ * We always try to make our sample contain at least this many guards.
+ */
+#define DFLT_MIN_FILTERED_SAMPLE_SIZE 20
+/**
+ * If a guard is unlisted for this many days in a row, we remove it.
+ */
+#define DFLT_REMOVE_UNLISTED_GUARDS_AFTER_DAYS 20
+/**
+ * We remove unconfirmed guards from the sample after this many days,
+ * regardless of whether they are listed or unlisted.
+ */
+#define DFLT_GUARD_LIFETIME_DAYS 120
+/**
+ * We remove confirmed guards from the sample if they were sampled
+ * GUARD_LIFETIME_DAYS ago and confirmed this many days ago.
+ */
+#define DFLT_GUARD_CONFIRMED_MIN_LIFETIME_DAYS 60
+/**
+ * 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.
+ */
+#define DFLT_INTERNET_LIKELY_DOWN_INTERVAL (10*60)
+/**
+ * If we're trying to connect to a nonprimary guard for at least this
+ * many seconds, and we haven't gotten the connection to work, we will treat
+ * lower-priority guards as usable.
+ */
+#define DFLT_NONPRIMARY_GUARD_CONNECT_TIMEOUT 15
+/**
+ * If a circuit has been sitting around in 'waiting for better guard' state
+ * for at least this long, we'll expire it.
+ */
+#define DFLT_NONPRIMARY_GUARD_IDLE_TIMEOUT (10*60)
+/**
+ * If our configuration retains fewer than this fraction of guards from the
+ * torrc, we are in a restricted setting.
+ */
+#define DFLT_MEANINGFUL_RESTRICTION_PERCENT 20
+/**
+ * If our configuration retains fewer than this fraction of guards from the
+ * torrc, we are in an extremely restricted setting, and should warn.
+ */
+#define DFLT_EXTREME_RESTRICTION_PERCENT 1
+/**@}*/
+
+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(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);
+STATIC double get_meaningful_restriction_threshold(void);
+STATIC double get_extreme_restriction_threshold(void);
+
+HANDLE_DECL(entry_guard, entry_guard_t, STATIC)
+#define entry_guard_handle_free(h) \
+ FREE_AND_NULL(entry_guard_handle_t, entry_guard_handle_free_, (h))
-STATIC const node_t *entry_is_live(const entry_guard_t *e,
- entry_is_live_flags_t flags,
- const char **msg);
+STATIC guard_selection_type_t guard_selection_infer_type(
+ guard_selection_type_t type_in,
+ const char *name);
+STATIC guard_selection_t *guard_selection_new(const char *name,
+ guard_selection_type_t type);
+STATIC guard_selection_t *get_guard_selection_by_name(
+ const char *name, guard_selection_type_t type, int create_if_absent);
+STATIC void guard_selection_free_(guard_selection_t *gs);
+#define guard_selection_free(gs) \
+ FREE_AND_NULL(guard_selection_t, guard_selection_free_, (gs))
+MOCK_DECL(STATIC int, entry_guard_is_listed,
+ (guard_selection_t *gs, const entry_guard_t *guard));
+STATIC const char *choose_guard_selection(const or_options_t *options,
+ const networkstatus_t *ns,
+ const guard_selection_t *old_selection,
+ guard_selection_type_t *type_out);
+STATIC entry_guard_t *get_sampled_guard_with_id(guard_selection_t *gs,
+ const uint8_t *rsa_id);
-STATIC int entry_is_time_to_retry(const entry_guard_t *e, time_t now);
+MOCK_DECL(STATIC time_t, randomize_time, (time_t now, time_t max_backdate));
-#endif
+MOCK_DECL(STATIC circuit_guard_state_t *,
+ circuit_guard_state_new,(entry_guard_t *guard, unsigned state,
+ entry_guard_restriction_t *rst));
+STATIC entry_guard_t *entry_guard_add_to_sample(guard_selection_t *gs,
+ const node_t *node);
+STATIC entry_guard_t *entry_guards_expand_sample(guard_selection_t *gs);
+STATIC char *entry_guard_encode_for_state(entry_guard_t *guard);
+STATIC entry_guard_t *entry_guard_parse_from_state(const char *s);
+#define entry_guard_free(e) \
+ FREE_AND_NULL(entry_guard_t, entry_guard_free_, (e))
+STATIC void entry_guard_free_(entry_guard_t *e);
+STATIC void entry_guards_update_filtered_sets(guard_selection_t *gs);
+STATIC int entry_guards_all_primary_guards_are_down(guard_selection_t *gs);
+/**
+ * @name Flags for sample_reachable_filtered_entry_guards()
+ */
+/**@{*/
+#define SAMPLE_EXCLUDE_CONFIRMED (1u<<0)
+#define SAMPLE_EXCLUDE_PRIMARY (1u<<1)
+#define SAMPLE_EXCLUDE_PENDING (1u<<2)
+#define SAMPLE_NO_UPDATE_PRIMARY (1u<<3)
+#define SAMPLE_EXCLUDE_NO_DESCRIPTOR (1u<<4)
+/**@}*/
+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(const 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.
+ */
+/**@{*/
+/** State for a circuit that can (so far as the guard subsystem is
+ * concerned) be used for actual traffic as soon as it is successfully
+ * opened. */
+#define GUARD_CIRC_STATE_USABLE_ON_COMPLETION 1
+/** State for an non-open circuit that we shouldn't use for actual
+ * traffic, when it completes, unless other circuits to preferable
+ * guards fail. */
+#define GUARD_CIRC_STATE_USABLE_IF_NO_BETTER_GUARD 2
+/** State for an open circuit that we shouldn't use for actual traffic
+ * unless other circuits to preferable guards fail. */
+#define GUARD_CIRC_STATE_WAITING_FOR_BETTER_GUARD 3
+/** State for a circuit that can (so far as the guard subsystem is
+ * concerned) be used for actual traffic. */
+#define GUARD_CIRC_STATE_COMPLETE 4
+/** State for a circuit that is unusable, and will not become usable. */
+#define GUARD_CIRC_STATE_DEAD 5
+/**@}*/
+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);
+STATIC unsigned entry_guards_note_guard_success(guard_selection_t *gs,
+ entry_guard_t *guard,
+ unsigned old_state);
+STATIC int entry_guard_has_higher_priority(entry_guard_t *a, entry_guard_t *b);
+STATIC char *getinfo_helper_format_single_entry_guard(const entry_guard_t *e);
+
+STATIC entry_guard_restriction_t *guard_create_exit_restriction(
+ const uint8_t *exit_id);
+
+STATIC entry_guard_restriction_t *guard_create_dirserver_md_restriction(void);
+
+STATIC void entry_guard_restriction_free_(entry_guard_restriction_t *rst);
+#define entry_guard_restriction_free(rst) \
+ FREE_AND_NULL(entry_guard_restriction_t, \
+ entry_guard_restriction_free_, (rst))
+
+#endif /* defined(ENTRYNODES_PRIVATE) */
+
+void remove_all_entry_guards_for_guard_selection(guard_selection_t *gs);
void remove_all_entry_guards(void);
-void entry_guards_compute_status(const or_options_t *options, time_t now);
-int entry_guard_register_connect_status(const char *digest, int succeeded,
- int mark_relay_status, time_t now);
-void entry_nodes_should_be_added(void);
+struct bridge_info_t;
+void entry_guard_learned_bridge_identity(const tor_addr_port_t *addrport,
+ const uint8_t *rsa_id_digest);
+
int entry_list_is_constrained(const or_options_t *options);
-const node_t *choose_random_entry(cpath_build_state_t *state);
-const node_t *choose_random_dirguard(dirinfo_type_t t);
+int guards_retry_optimistic(const or_options_t *options);
+int entry_guards_parse_state_for_guard_selection(
+ guard_selection_t *gs, or_state_t *state, int set, char **msg);
int entry_guards_parse_state(or_state_t *state, int set, char **msg);
void entry_guards_update_state(or_state_t *state);
int getinfo_helper_entry_guards(control_connection_t *conn,
const char *question, char **answer,
const char **errmsg);
-void mark_bridge_list(void);
-void sweep_bridge_list(void);
-
-int addr_is_a_configured_bridge(const tor_addr_t *addr, uint16_t port,
- const char *digest);
-int extend_info_is_a_configured_bridge(const extend_info_t *ei);
-int routerinfo_is_a_configured_bridge(const routerinfo_t *ri);
-int node_is_a_configured_bridge(const node_t *node);
-void learned_router_identity(const tor_addr_t *addr, uint16_t port,
- const char *digest);
-struct bridge_line_t;
-void bridge_add_from_config(struct bridge_line_t *bridge_line);
-void retry_bridge_descriptor_fetch_directly(const char *digest);
-void fetch_bridge_descriptors(const or_options_t *options, time_t now);
-void learned_bridge_descriptor(routerinfo_t *ri, int from_cache);
-int any_bridge_descriptors_known(void);
int entries_known_but_down(const or_options_t *options);
void entries_retry_all(const or_options_t *options);
-int any_bridge_supports_microdescriptors(void);
-const smartlist_t *get_socks_args_by_bridge_addrport(const tor_addr_t *addr,
- uint16_t port);
-
-int any_bridges_dont_support_microdescriptors(void);
+char *entry_guards_get_err_str_if_dir_info_missing(int using_mds,
+ int num_present, int num_usable);
+char *guard_selection_get_err_str_if_dir_info_missing(guard_selection_t *gs,
+ int using_mds,
+ int num_present, int num_usable);
void entry_guards_free_all(void);
-const char *find_transport_name_by_bridge_addrport(const tor_addr_t *addr,
- uint16_t port);
-struct transport_t;
-int get_transport_by_bridge_addrport(const tor_addr_t *addr, uint16_t port,
- const struct transport_t **transport);
-
-MOCK_DECL(int, transport_is_needed, (const char *transport_name));
-int validate_pluggable_transports_config(void);
-
double pathbias_get_close_success_count(entry_guard_t *guard);
double pathbias_get_use_success_count(entry_guard_t *guard);
@@ -179,9 +633,5 @@ guard_get_guardfraction_bandwidth(guardfraction_bandwidth_t *guardfraction_bw,
int orig_bandwidth,
uint32_t guardfraction_percentage);
-MOCK_DECL(smartlist_t *, list_bridge_identities, (void));
-MOCK_DECL(download_status_t *, get_bridge_dl_status_by_id,
- (const char *digest));
-
-#endif
+#endif /* !defined(TOR_ENTRYNODES_H) */