feat(client): add scoped relay host route pin
Add the first route-table mutation API to `lanparty-client-route`. Given the pre-TAP best-route snapshot, the crate can now create a host route for the relay IP on that same interface and return an RAII guard that deletes the route when it is dropped. The route row is initialized with `InitializeIpForwardEntry`, uses a /32 or /128 destination prefix for the relay IP, preserves the pre-TAP interface index/LUID, and uses the remembered next hop or an on-link unspecified next hop when Windows reported no gateway. The guard tracks whether creation actually succeeded so pure row-construction tests and failed creates do not try to delete routes they did not install. This remains a crate-level boundary only. The Windows client still reports the pre-TAP route but does not yet hold a pin across TAP activation; that is the next integration slice. Test Plan: - cargo fmt --check - cargo test -p lanparty-client-route - cargo clippy -p lanparty-client-route --all-targets -- -D warnings - cargo check -p lanparty-client-route --target x86_64-pc-windows-msvc - cargo clippy -p lanparty-client-route --target x86_64-pc-windows-msvc --all-targets -- -D warnings - cargo test --workspace - cargo clippy --workspace --all-targets -- -D warnings - git diff --check Refs: PLAN.md Refs: https://learn.microsoft.com/en-us/windows-hardware/drivers/network/createipforwardentry2 Refs: https://learn.microsoft.com/en-us/windows-hardware/drivers/network/initializeipforwardentry
This commit is contained in:
@@ -1,8 +1,8 @@
|
||||
//! Windows route-table inspection for protecting the relay path.
|
||||
//!
|
||||
//! The client binary uses this crate to keep Win32 route/metric calls out of
|
||||
//! the relay session code. This crate starts with read-only route snapshots;
|
||||
//! later route pinning can build on the same typed boundary.
|
||||
//! the relay session code. The crate can snapshot the current relay route and
|
||||
//! install a scoped host route that pins the relay IP to the pre-TAP interface.
|
||||
|
||||
use std::net::IpAddr;
|
||||
|
||||
@@ -91,13 +91,24 @@ impl RouteSnapshot {
|
||||
mod windows;
|
||||
|
||||
#[cfg(windows)]
|
||||
pub use windows::best_route_to;
|
||||
pub use windows::{PinnedRelayRoute, best_route_to, pin_relay_route};
|
||||
|
||||
#[cfg(not(windows))]
|
||||
pub fn best_route_to(_destination: IpAddr) -> Result<RouteSnapshot> {
|
||||
bail!("Windows route inspection is only available on Windows");
|
||||
}
|
||||
|
||||
#[cfg(not(windows))]
|
||||
#[derive(Debug)]
|
||||
pub struct PinnedRelayRoute {
|
||||
_private: (),
|
||||
}
|
||||
|
||||
#[cfg(not(windows))]
|
||||
pub fn pin_relay_route(_route: &RouteSnapshot) -> Result<PinnedRelayRoute> {
|
||||
bail!("Windows route pinning is only available on Windows");
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
@@ -131,6 +142,23 @@ mod tests {
|
||||
assert!(best_route_to(ip("203.0.113.10")).is_err());
|
||||
}
|
||||
|
||||
#[cfg(not(windows))]
|
||||
#[test]
|
||||
fn rejects_route_pinning_on_non_windows() {
|
||||
let snapshot = RouteSnapshot::new(
|
||||
ip("203.0.113.10"),
|
||||
ip("192.0.2.44"),
|
||||
Some(ip("192.0.2.1")),
|
||||
ip("0.0.0.0"),
|
||||
0,
|
||||
12,
|
||||
34,
|
||||
25,
|
||||
);
|
||||
|
||||
assert!(pin_relay_route(&snapshot).is_err());
|
||||
}
|
||||
|
||||
fn ip(value: &str) -> IpAddr {
|
||||
value.parse().unwrap()
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user