diff options
Diffstat (limited to 'crates/tor-circmgr/src/path')
| -rw-r--r-- | crates/tor-circmgr/src/path/hspath.rs | 53 |
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)) |
