Close Phase 4 overlay and Unix forwarding gaps

This commit is contained in:
Eric Wendland 2026-05-30 12:24:40 +02:00
commit b0768999db
9 changed files with 210 additions and 13 deletions

View file

@ -161,6 +161,8 @@ pub enum NodeError {
IrohPeer(String),
#[error("overlay runtime error: {0}")]
OverlayRuntime(String),
#[error("unsupported platform: {0}")]
UnsupportedPlatform(String),
}
#[derive(Clone, Debug)]
@ -635,6 +637,11 @@ pub async fn run_unix_forward(
target_path: PathBuf,
bearer_secret: Option<String>,
) -> Result<(), NodeError> {
if !geth_pipe::unix_forward_supported() {
return Err(NodeError::UnsupportedPlatform(
geth_pipe::unix_forward_unsupported_message().to_owned(),
));
}
let listen_path = geth_pipe::validate_unix_forward_path(&listen_path)?;
geth_pipe::validate_unix_forward_path(&target_path)?;
let listener = UnixListener::bind(&listen_path)?;
@ -9034,10 +9041,14 @@ pub fn handle_request(
})
}
ControlRequest::PipeSend { node: Some(_), .. } => Err(NodeError::IrohEndpointUnavailable),
ControlRequest::PipeTcpForward { .. }
| ControlRequest::PipeTcpStream { .. }
| ControlRequest::PipeUnixForward { .. }
| ControlRequest::PipeUnixStream { .. } => Err(NodeError::IrohEndpointUnavailable),
ControlRequest::PipeTcpForward { .. } | ControlRequest::PipeTcpStream { .. } => {
Err(NodeError::IrohEndpointUnavailable)
}
ControlRequest::PipeUnixForward { .. } | ControlRequest::PipeUnixStream { .. } => {
Err(NodeError::UnsupportedPlatform(
geth_pipe::unix_forward_unsupported_message().to_owned(),
))
}
ControlRequest::PipeRecv { name, peek } => {
geth_pipe::validate_pipe_name(&name)?;
let messages = pipe_messages(node, &name, !peek)?;
@ -10397,11 +10408,19 @@ fn overlay_peers(store: &Store, network: &str) -> Result<Vec<OverlayPeer>, NodeE
let cidr = overlay_membership(store, network)?
.map(|membership| membership.cidr)
.unwrap_or_else(|| geth_overlay::DEFAULT_OVERLAY_CIDR.to_owned());
let resource = geth_overlay::overlay_resource_id(network).to_string();
store
.list_peer_cards()?
.into_iter()
.map(|stored| {
let card: PeerCard = serde_json::from_str(&stored.card_json)?;
let peer = PrincipalId::new(card.node_id.to_string());
let route_authorized = can_sync_resource(
store,
&peer,
resource.as_str(),
geth_overlay::CAPABILITY_ROUTE,
)?;
Ok(OverlayPeer {
node_id: card.node_id.to_string(),
endpoint_id: card
@ -10412,7 +10431,11 @@ fn overlay_peers(store: &Store, network: &str) -> Result<Vec<OverlayPeer>, NodeE
&cidr,
card.node_id.as_str(),
)?),
state: "candidate-only".to_owned(),
state: if route_authorized {
"route-authorized-candidate".to_owned()
} else {
"candidate-only".to_owned()
},
})
})
.collect()
@ -13161,6 +13184,69 @@ mod tests {
}));
}
#[test]
fn overlay_peers_combine_trusted_route_metadata_with_untrusted_candidates() {
let store = Store::open_memory().expect("open store");
let key = AgentKey::generate();
let card = PeerCard::signed(
"node:right".into(),
&key,
vec![EndpointCandidate {
endpoint_id: "endpoint:right".to_owned(),
relay_url: None,
direct_addresses: Vec::new(),
source: DiscoverySource::Imported,
}],
UnixMillis(1),
)
.expect("peer card");
store
.upsert_peer_card(&StoredPeerCard {
peer_id: card.node_id.to_string(),
card_json: serde_json::to_string(&card).expect("card json"),
updated_at_ms: 1,
})
.expect("store peer card");
store
.put_module_state(&StoredModuleState {
module: geth_overlay::overlay_state_key("home"),
state_json: serde_json::to_string(
&geth_overlay::joined_overlay_membership(
"home",
Some("172.22.0.0/24"),
"node:left",
"secret",
1,
)
.expect("membership"),
)
.expect("membership json"),
updated_at_ms: 1,
})
.expect("store membership");
let peers = overlay_peers(&store, "home").expect("candidate peers");
assert_eq!(peers.len(), 1);
assert_eq!(peers[0].node_id, "node:right");
assert_eq!(peers[0].state, "candidate-only");
assert_eq!(
peers[0].virtual_ip,
Some(
geth_overlay::deterministic_virtual_ip("172.22.0.0/24", "node:right")
.expect("virtual ip")
)
);
grant_test_capability(
&store,
"node:right",
"resource:overlay:home",
geth_overlay::CAPABILITY_ROUTE,
);
let peers = overlay_peers(&store, "home").expect("authorized peers");
assert_eq!(peers[0].state, "route-authorized-candidate");
}
#[test]
fn lan_discovery_address_selection_uses_iroh_direct_addresses() {
let key = AgentKey::generate();