Files
tsunagi/src/dataplane/wireguard/provision/unsupported.rs
T
tsunagiandClaude Opus 5 4759e47e31 Remove tun-setup and the attach path it served
The managed interface supersedes both. They go together because apart
they are useless: attaching needs an interface somebody prepared, and
tun-setup existed only to say how to prepare one.

This also corrects what the last commit's README claimed. It said the
manual route was needed on macOS and Windows; it was not, and could not
be. The recipe printed Linux `ip` commands, and a persistent TUN that a
second process can attach to is a Linux concept — macOS creates a utun
by opening a control socket and there is nothing to hand over. So those
platforms were never served by this path, and their honest state is that
a real interface waits on a provisioner, with --no-tun meanwhile.

Gone with it: the interface-existence check, the /proc/net/if_inet6
address inspection and its DAD flag decoding, and the --interface flag,
which had one mode left.

Kept: the check that the allocated IPv4 address is really on a local
interface. The agent now assigns that address itself, so the check is no
longer telling a user what to run — it verifies the outcome instead of
trusting it, which is worth keeping precisely because the assumptions
around Linux address behaviour have been wrong here more than once. Its
message says which interface should have had the address rather than a
command to run.

Boxing Up(UpArgs) is fallout: TunSetupArgs had been masking how much
larger that variant is than its siblings.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-21 14:46:39 +01:00

81 lines
2.4 KiB
Rust

//! The provisioner for platforms that do not have one yet.
//!
//! macOS and Windows both need real work here — `utun` plus the
//! `SystemConfiguration` framework on one, the IP Helper API and a Wintun
//! adapter on the other — and neither is written. Rather than let the agent
//! come up and fail obscurely at the first packet, this refuses at the point
//! of provisioning and says what to do instead.
use crate::BoxFuture;
use crate::dataplane::PluginError;
use super::{InterfacePlan, InterfaceProvisioner, Provisioned};
/// Refuses to provision, with an explanation.
#[derive(Debug, Clone)]
pub struct UnsupportedProvisioner {
platform: &'static str,
}
impl Default for UnsupportedProvisioner {
fn default() -> Self {
Self::new()
}
}
impl UnsupportedProvisioner {
/// A provisioner naming the platform it is standing in for.
pub fn new() -> Self {
Self {
platform: std::env::consts::OS,
}
}
fn refusal(&self) -> PluginError {
PluginError::Unavailable(format!(
"managing the overlay interface is not implemented on {} yet. \
Run with `--no-tun` until it is: the tunnels still form, they just \
do not reach the operating system.",
self.platform
))
}
}
impl InterfaceProvisioner for UnsupportedProvisioner {
fn name(&self) -> &str {
"unsupported"
}
fn reconcile<'a>(
&'a self,
_plan: &'a InterfacePlan,
) -> BoxFuture<'a, Result<Provisioned, PluginError>> {
Box::pin(async move { Err(self.refusal()) })
}
fn remove<'a>(&'a self, _name: &'a str) -> BoxFuture<'a, Result<(), PluginError>> {
// Nothing was ever created, so there is nothing to clean up and no
// reason to fail a shutdown path.
Box::pin(async move { Ok(()) })
}
}
#[cfg(test)]
mod tests {
#![allow(clippy::unwrap_used, clippy::expect_used, clippy::panic)]
use super::*;
#[tokio::test]
async fn it_refuses_with_a_usable_pointer_and_still_cleans_up_quietly() {
let provisioner = UnsupportedProvisioner::new();
let plan = InterfacePlan::new("tsuntest", 1280, Vec::new());
let err = provisioner.reconcile(&plan).await.unwrap_err();
let message = err.to_string();
assert!(message.contains("--no-tun"), "{message}");
assert!(message.contains(std::env::consts::OS), "{message}");
provisioner.remove("tsuntest").await.unwrap();
}
}