summaryrefslogtreecommitdiff
path: root/crates/tor-circmgr/src/path/hspath.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/tor-circmgr/src/path/hspath.rs')
-rw-r--r--crates/tor-circmgr/src/path/hspath.rs53
1 files changed, 41 insertions, 12 deletions
diff --git a/crates/tor-circmgr/src/path/hspath.rs b/crates/tor-circmgr/src/path/hspath.rs
index c9ec30fd8..c3e3e3bb9 100644
--- a/crates/tor-circmgr/src/path/hspath.rs
+++ b/crates/tor-circmgr/src/path/hspath.rs
@@ -43,9 +43,12 @@
// TODO (#1339): we should be consistent with our terminology.
use rand::Rng;
+use tor_error::internal;
use tor_linkspec::OwnedChanTarget;
use tor_netdir::{NetDir, Relay};
-use tor_relay_selection::{RelayExclusion, RelaySelectionConfig, RelaySelector, RelayUsage};
+use tor_relay_selection::{
+ RelayExclusion, RelaySelectionConfig, RelaySelector, RelayUsage, SelectionInfo,
+};
use crate::{hspool::HsCircStubKind, Error, Result};
@@ -222,13 +225,20 @@ impl VanguardHsPathBuilder {
// * the L2 vanguard, because it cannot be selected again as an L3 vanguard
// (a relay won't let you extend the circuit to itself).
// * the guard, because relays won't let you extend the circuit to their previous hop
- let neighbor_exclusion = exclude_identities(&[&l2_guard, &l1_guard]);
+ let l1_l2_exclusion = exclude_identities(&[&l2_guard, &l1_guard]);
let mut hops = vec![l1_guard, l2_guard.clone()];
+ let mode = vanguards.mode();
+
+ let extra_hop_err = |info: SelectionInfo| Error::NoRelay {
+ path_kind: self.path_kind(),
+ role: "extra hop",
+ problem: info.to_string(),
+ };
// If needed, select an L3 vanguard too
- if vanguards.mode() == VanguardMode::Full {
+ if mode == VanguardMode::Full {
let l3_guard: MaybeOwnedRelay = vanguards
- .select_vanguard(rng, netdir, Layer::Layer3, &neighbor_exclusion)?
+ .select_vanguard(rng, netdir, Layer::Layer3, &l1_l2_exclusion)?
.into();
hops.push(l3_guard.clone());
@@ -239,22 +249,41 @@ impl VanguardHsPathBuilder {
// TODO: this usage has need_stable = true, but we probably
// don't necessarily need a stable relay here.
let usage = RelayUsage::middle_relay(None);
- let neighbor_exclusion = exclude_identities(&[&l2_guard, &l3_guard]);
+ let l2_l3_exclusion = exclude_identities(&[&l2_guard, &l3_guard]);
// We exclude
// * the L3 vanguard, because it cannot be selected again as the following
// extra hop (a relay won't let you extend the circuit to itself).
// * the L2 vanguard, because relays won't let you extend the circuit to their previous hop
- let selector = RelaySelector::new(usage, neighbor_exclusion);
+ let selector = RelaySelector::new(usage, l2_l3_exclusion);
let (extra_hop, info) = selector.select_relay(rng, netdir);
- let extra_hop = extra_hop.ok_or_else(|| Error::NoRelay {
- path_kind: self.path_kind(),
- role: "extra hop",
- problem: info.to_string(),
- })?;
-
+ let extra_hop = extra_hop.ok_or_else(|| extra_hop_err(info))?;
hops.push(MaybeOwnedRelay::from(extra_hop));
}
+ } else {
+ // Extend the circuit to a third, arbitrarily chosen hop, excluding the L1 and L2
+ // guards as before.
+ let usage = RelayUsage::middle_relay(None);
+ let selector = RelaySelector::new(usage, l1_l2_exclusion);
+
+ let (extra_hop, info) = selector.select_relay(rng, netdir);
+ let extra_hop = extra_hop.ok_or_else(|| extra_hop_err(info))?;
+ hops.push(MaybeOwnedRelay::from(extra_hop));
+ }
+
+ match (mode, self.0) {
+ (VanguardMode::Lite, _) => debug_assert_eq!(hops.len(), 3),
+ (VanguardMode::Full, HsCircStubKind::Stub) => debug_assert_eq!(hops.len(), 3),
+ (VanguardMode::Full, HsCircStubKind::Extended) => debug_assert_eq!(hops.len(), 4),
+ (VanguardMode::Disabled, _) => {
+ return Err(internal!(
+ "Called VanguardHsPathBuilder::pick_path(), but vanguards are disabled?!"
+ )
+ .into());
+ }
+ (_, _) => {
+ return Err(internal!("Unsupported vanguard mode {mode}").into());
+ }
}
Ok((TorPath::new_multihop_from_maybe_owned(hops), mon, usable))