mirror of
https://codeberg.org/icewind/netnsd.git
synced 2026-06-03 17:14:06 +02:00
register managed namespaces with symlinks
This commit is contained in:
parent
3a8b684600
commit
d168b4bf4d
4 changed files with 54 additions and 5 deletions
0
src/down.rs
Normal file
0
src/down.rs
Normal file
|
|
@ -9,6 +9,7 @@ mod daemon;
|
||||||
mod namespace;
|
mod namespace;
|
||||||
mod proxy;
|
mod proxy;
|
||||||
mod link;
|
mod link;
|
||||||
|
mod down;
|
||||||
|
|
||||||
#[derive(Parser, Debug)]
|
#[derive(Parser, Debug)]
|
||||||
pub struct Args {
|
pub struct Args {
|
||||||
|
|
|
||||||
|
|
@ -5,8 +5,9 @@ use crate::link::{LinkError, link_up_ns};
|
||||||
use crate::namespace::raw::{NamespaceSetupError, create_network_namespace};
|
use crate::namespace::raw::{NamespaceSetupError, create_network_namespace};
|
||||||
use nix::errno::Errno;
|
use nix::errno::Errno;
|
||||||
use nix::mount::{MntFlags, MsFlags, mount, umount2};
|
use nix::mount::{MntFlags, MsFlags, mount, umount2};
|
||||||
use std::fs::{File, create_dir_all, remove_file};
|
use std::fs::{File, create_dir, remove_file};
|
||||||
use std::io::{Error as IoError, ErrorKind};
|
use std::io::{Error as IoError, ErrorKind};
|
||||||
|
use std::os::unix::fs::symlink;
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
use tracing::{debug, error, info};
|
use tracing::{debug, error, info};
|
||||||
|
|
@ -20,13 +21,25 @@ impl NetNs {
|
||||||
/// Create a new named network namespace that will be removed when dropped
|
/// Create a new named network namespace that will be removed when dropped
|
||||||
pub fn new(name: NamespaceName) -> Result<Self, NamespaceError> {
|
pub fn new(name: NamespaceName) -> Result<Self, NamespaceError> {
|
||||||
let parent = Path::new("/var/run/netns");
|
let parent = Path::new("/var/run/netns");
|
||||||
create_dir_all(parent).map_err(NamespaceError::Parent)?;
|
let nsd_parent = Path::new("/var/run/netnsd");
|
||||||
|
setup_tmpfs(parent)?;
|
||||||
|
setup_tmpfs(nsd_parent)?;
|
||||||
|
|
||||||
let path = parent.join(&name);
|
let path = parent.join(&name);
|
||||||
|
let nsd_path = nsd_parent.join(&name);
|
||||||
|
|
||||||
match File::create_new(&path) {
|
match File::create_new(&path) {
|
||||||
Ok(_) => {}
|
Ok(_) => {}
|
||||||
Err(e) if e.kind() == ErrorKind::AlreadyExists => {
|
Err(e) if e.kind() == ErrorKind::AlreadyExists => {
|
||||||
info!(%name, "using existing network namespace");
|
info!(%name, "using existing network namespace");
|
||||||
|
|
||||||
|
if !nsd_path.is_symlink() {
|
||||||
|
symlink(&path, &nsd_path).map_err(|error| NamespaceError::Symlink {
|
||||||
|
error,
|
||||||
|
path: nsd_path.clone(),
|
||||||
|
})?;
|
||||||
|
}
|
||||||
|
|
||||||
return Ok(NetNs {
|
return Ok(NetNs {
|
||||||
name: name.clone(),
|
name: name.clone(),
|
||||||
path,
|
path,
|
||||||
|
|
@ -38,6 +51,12 @@ impl NetNs {
|
||||||
|
|
||||||
let ns = create_network_namespace(move |ns| {
|
let ns = create_network_namespace(move |ns| {
|
||||||
bind_namespace(&ns, &path)?;
|
bind_namespace(&ns, &path)?;
|
||||||
|
if !nsd_path.is_symlink() {
|
||||||
|
symlink(&path, &nsd_path).map_err(|error| NamespaceError::Symlink {
|
||||||
|
error,
|
||||||
|
path: nsd_path.clone(),
|
||||||
|
})?;
|
||||||
|
}
|
||||||
Result::<_, NamespaceError>::Ok(NetNs { name, path })
|
Result::<_, NamespaceError>::Ok(NetNs { name, path })
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
|
|
@ -47,6 +66,31 @@ impl NetNs {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn setup_tmpfs(path: &Path) -> Result<(), NamespaceError> {
|
||||||
|
let created = match create_dir(path) {
|
||||||
|
Ok(_) => Ok(true),
|
||||||
|
Err(error) if error.kind() == ErrorKind::AlreadyExists => Ok(false),
|
||||||
|
Err(error) => Err(NamespaceError::Parent {
|
||||||
|
path: path.into(),
|
||||||
|
error,
|
||||||
|
}),
|
||||||
|
}?;
|
||||||
|
if created {
|
||||||
|
mount(
|
||||||
|
Some("tmpfs"),
|
||||||
|
path.as_os_str(),
|
||||||
|
Some("tmpfs"),
|
||||||
|
MsFlags::empty(),
|
||||||
|
Some("size=16k,mode=1755"),
|
||||||
|
)
|
||||||
|
.map_err(|error| NamespaceError::ParentTmpfs {
|
||||||
|
path: path.into(),
|
||||||
|
error,
|
||||||
|
})?
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
fn bind_namespace(namespace: &Path, path: &Path) -> Result<(), NamespaceError> {
|
fn bind_namespace(namespace: &Path, path: &Path) -> Result<(), NamespaceError> {
|
||||||
debug!(namespace = %namespace.display(), path = %path.display(), "mounting namespace");
|
debug!(namespace = %namespace.display(), path = %path.display(), "mounting namespace");
|
||||||
mount(
|
mount(
|
||||||
|
|
@ -75,7 +119,7 @@ impl NetNs {
|
||||||
umount2(&self.path, MntFlags::MNT_DETACH).map_err(NamespaceError::UnMount)?;
|
umount2(&self.path, MntFlags::MNT_DETACH).map_err(NamespaceError::UnMount)?;
|
||||||
remove_file(&self.path).map_err(|error| NamespaceError::Delete {
|
remove_file(&self.path).map_err(|error| NamespaceError::Delete {
|
||||||
error,
|
error,
|
||||||
path: self.path
|
path: self.path,
|
||||||
})?;
|
})?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
@ -83,12 +127,16 @@ impl NetNs {
|
||||||
|
|
||||||
#[derive(Debug, Error)]
|
#[derive(Debug, Error)]
|
||||||
pub enum NamespaceError {
|
pub enum NamespaceError {
|
||||||
#[error("Failed to create parent directory for namespaces (/var/run/netns): {0:#}")]
|
#[error("Failed to create parent directory for namespaces {}: {error:#}", path.display())]
|
||||||
Parent(IoError),
|
Parent { path: PathBuf, error: IoError },
|
||||||
|
#[error("Failed to create parent tmpfs for namespaces {}: {error:#}", path.display())]
|
||||||
|
ParentTmpfs { path: PathBuf, error: Errno },
|
||||||
#[error("Failed to create namespace file {}: {error:#}", path.display())]
|
#[error("Failed to create namespace file {}: {error:#}", path.display())]
|
||||||
Create { path: PathBuf, error: IoError },
|
Create { path: PathBuf, error: IoError },
|
||||||
#[error("Failed to delete namespace file {}: {error:#}", path.display())]
|
#[error("Failed to delete namespace file {}: {error:#}", path.display())]
|
||||||
Delete { path: PathBuf, error: IoError },
|
Delete { path: PathBuf, error: IoError },
|
||||||
|
#[error("Failed to register namespace symlink {}: {error:#}", path.display())]
|
||||||
|
Symlink { path: PathBuf, error: IoError },
|
||||||
#[error("Failed to setup namespace: {0:#}")]
|
#[error("Failed to setup namespace: {0:#}")]
|
||||||
Setup(#[from] NamespaceSetupError),
|
Setup(#[from] NamespaceSetupError),
|
||||||
#[error("Failed to bind-mount netns handle: {0:?}")]
|
#[error("Failed to bind-mount netns handle: {0:?}")]
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue