aboutsummaryrefslogtreecommitdiff
path: root/src/feature/client/entrynodes.h
blob: 4b236dc80cc0ed4ba629978eb6fc2ea548bd4a2b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
/* Copyright (c) 2001 Matej Pfajfar.
 * Copyright (c) 2001-2004, Roger Dingledine.
 * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
 * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */

/**
 * \file entrynodes.h
 * \brief Header file for circuitbuild.c.
 **/

#ifndef TOR_ENTRYNODES_H
#define TOR_ENTRYNODES_H

#include "lib/container/handles.h"

/* Forward declare for guard_selection_t; entrynodes.c has the real struct */
typedef struct guard_selection_t 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
                                      * for this node already? */
  unsigned int path_bias_extreme : 1; /**< Did we alert the user about path
                                       * bias for this node already? */
  unsigned int path_bias_disabled : 1; /**< Have we disabled this node because
                                        * of path bias issues? */
  unsigned int path_bias_use_noticed : 1; /**< Did we alert the user about path
                                       * 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? */

  double circ_attempts; /**< Number of circuits this guard has "attempted" */
  double circ_successes; /**< Number of successfully built circuits using
                               * this guard as first hop. */
  double successful_circuits_closed; /**< Number of circuits that carried
                                        * streams successfully. */
  double collapsed_circuits; /**< Number of fully built circuits that were
                                 * remotely closed before any streams were
                                 * attempted. */
  double unusable_circuits; /**< Number of circuits for which streams were
                                *  attempted, but none succeeded. */
  double timeouts; /**< Number of 'right-censored' circuit timeouts for this
                       * guard. */
  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. */
} guard_pathbias_t;

#if defined(ENTRYNODES_PRIVATE)
#include "lib/crypt_ops/crypto_ed25519.h"

/**
 * @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 sampled? Guards with
   * lower indices appear earlier on the sampled list, the confirmed list and
   * the primary list as a result of Prop 310
   */
  int sampled_idx;

  /**
   * 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_t {
  /**
   * 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.
   * The ordering of the list should be by sampled idx. The reasoning behind
   * it is linked to Proposal 310.
   *
   * 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;

  /** What sampled_idx value should the next-added member of
   * sampled_entry_guards receive? This should follow the size of the sampled
   * list until sampled relays get pruned for some reason
   */
  int next_sampled_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,
                                  uint8_t purpose,
                                  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);
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 */

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);

/** 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 {
  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 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);

MOCK_DECL(STATIC time_t, randomize_time, (time_t now, time_t max_backdate));

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, int
    dense_sampled_index);
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 first_reachable_filtered_entry_guard()
 */
/**@{*/
#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 *first_reachable_filtered_entry_guard(
                                    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);

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);
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);

int entries_known_but_down(const or_options_t *options);
void entries_retry_all(const or_options_t *options);

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);

double pathbias_get_close_success_count(entry_guard_t *guard);
double pathbias_get_use_success_count(entry_guard_t *guard);

/** Contains the bandwidth of a relay as a guard and as a non-guard
 *  after the guardfraction has been considered. */
typedef struct guardfraction_bandwidth_t {
  /** Bandwidth as a guard after guardfraction has been considered. */
  int guard_bw;
  /** Bandwidth as a non-guard after guardfraction has been considered. */
  int non_guard_bw;
} guardfraction_bandwidth_t;

int should_apply_guardfraction(const networkstatus_t *ns);

void
guard_get_guardfraction_bandwidth(guardfraction_bandwidth_t *guardfraction_bw,
                                  int orig_bandwidth,
                                  uint32_t guardfraction_percentage);

#endif /* !defined(TOR_ENTRYNODES_H) */