track which namespaces we control

This commit is contained in:
Robin Appelman 2025-11-01 16:42:34 +01:00
commit 32fc90debe
5 changed files with 59 additions and 14 deletions

View file

@ -3,10 +3,12 @@ mod raw;
use crate::config::NamespaceName;
use crate::link::{LinkError, link_up_ns};
use crate::namespace::raw::{NamespaceSetupError, create_network_namespace};
use either::Either;
use nix::errno::Errno;
use nix::mount::{MntFlags, MsFlags, mount, umount2};
use std::fs::{File, create_dir, remove_file};
use std::fs::{File, create_dir, read_dir, remove_file};
use std::io::{Error as IoError, ErrorKind};
use std::iter::empty;
use std::os::unix::fs::symlink;
use std::path::{Path, PathBuf};
use thiserror::Error;
@ -15,9 +17,26 @@ use tracing::{debug, error, info};
pub struct NetNs {
name: NamespaceName,
path: PathBuf,
nsd_path: PathBuf,
}
impl NetNs {
pub fn existing() -> Result<impl Iterator<Item = NamespaceName>, NamespaceError> {
let dir = match read_dir("/var/run/netnsd") {
Ok(dir) => Ok(dir),
Err(error) if error.kind() == ErrorKind::NotFound => {
return Ok(Either::Left(empty()));
}
Err(error) => Err(NamespaceError::Scan {
path: "/var/run/netnsd".into(),
error,
}),
}?;
Ok(Either::Right(dir.flatten().flat_map(|entry| {
NamespaceName::try_from(entry.file_name()).ok()
})))
}
/// Create a new named network namespace that will be removed when dropped
pub fn new(name: NamespaceName) -> Result<Self, NamespaceError> {
let parent = Path::new("/var/run/netns");
@ -41,7 +60,8 @@ impl NetNs {
}
return Ok(NetNs {
name: name.clone(),
name,
nsd_path,
path,
});
}
@ -57,7 +77,7 @@ impl NetNs {
path: nsd_path.clone(),
})?;
}
Result::<_, NamespaceError>::Ok(NetNs { name, path })
Result::<_, NamespaceError>::Ok(NetNs { name, path, nsd_path })
})?;
ns.setup_interfaces()?;
@ -121,6 +141,10 @@ impl NetNs {
error,
path: self.path,
})?;
remove_file(&self.nsd_path).map_err(|error| NamespaceError::Delete {
error,
path: self.nsd_path,
})?;
Ok(())
}
}
@ -145,6 +169,8 @@ pub enum NamespaceError {
UnMount(Errno),
#[error("Failed to setup loopback inside namespace: {0:#}")]
Link(#[from] LinkError),
#[error("Failed to scan {} for namespaces: {error:#}", path.display())]
Scan { path: PathBuf, error: IoError },
}
impl NamespaceError {