up and down commands

This commit is contained in:
Robin Appelman 2025-11-01 16:50:14 +01:00
commit cd00701028
10 changed files with 77 additions and 16 deletions

View file

@ -1,10 +1,10 @@
mod target;
mod name; mod name;
mod source; mod source;
mod target;
pub use crate::config::target::ForwardTarget;
pub use crate::config::name::NamespaceName; pub use crate::config::name::NamespaceName;
pub use crate::config::source::ForwardSource; pub use crate::config::source::ForwardSource;
pub use crate::config::target::ForwardTarget;
use serde::Deserialize; use serde::Deserialize;
use std::collections::HashSet; use std::collections::HashSet;
use std::fs::read_to_string; use std::fs::read_to_string;
@ -42,7 +42,9 @@ impl Config {
} }
pub fn get_namespace<'a>(&'a self, name: &NamespaceName) -> Option<&'a NamespaceConfig> { pub fn get_namespace<'a>(&'a self, name: &NamespaceName) -> Option<&'a NamespaceConfig> {
self.namespaces.iter().find(|namespace| &namespace.name == name) self.namespaces
.iter()
.find(|namespace| &namespace.name == name)
} }
} }

View file

@ -94,7 +94,7 @@ fn validate_name(name: &str) -> bool {
#[test] #[test]
fn test_de() { fn test_de() {
use serde_test::{Token, assert_de_tokens, assert_de_tokens_error}; use serde_test::{assert_de_tokens, assert_de_tokens_error, Token};
assert_de_tokens(&NamespaceName("foo".into()), &[Token::String("foo")]); assert_de_tokens(&NamespaceName("foo".into()), &[Token::String("foo")]);

View file

@ -0,0 +1,10 @@
use crate::namespace::NetNs;
use main_error::MainResult;
pub fn down() -> MainResult {
for name in NetNs::existing()? {
let ns = NetNs::new(name)?;
ns.delete()?
}
Ok(())
}

View file

@ -10,11 +10,11 @@ use neli::rtnl::Ifinfomsg;
use neli::rtnl::IfinfomsgBuilder; use neli::rtnl::IfinfomsgBuilder;
use neli::utils::Groups; use neli::utils::Groups;
use nix::errno::Errno; use nix::errno::Errno;
use nix::sched::{CloneFlags, setns}; use nix::sched::{setns, CloneFlags};
use std::fs::File; use std::fs::File;
use std::io::Error as IoError;
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
use std::thread::spawn; use std::thread::spawn;
use std::io::Error as IoError;
use thiserror::Error; use thiserror::Error;
#[derive(Debug, Error)] #[derive(Debug, Error)]

View file

@ -3,6 +3,8 @@ use clap::{Parser, Subcommand};
use main_error::MainResult; use main_error::MainResult;
use crate::config::Config; use crate::config::Config;
use crate::daemon::daemon; use crate::daemon::daemon;
use crate::down::down;
use crate::up::up;
mod config; mod config;
mod daemon; mod daemon;
@ -10,6 +12,7 @@ mod namespace;
mod proxy; mod proxy;
mod link; mod link;
mod down; mod down;
mod up;
#[derive(Parser, Debug)] #[derive(Parser, Debug)]
pub struct Args { pub struct Args {
@ -25,6 +28,14 @@ enum Commands {
#[clap(short, long, default_value = "/etc/netnsd/netnsd")] #[clap(short, long, default_value = "/etc/netnsd/netnsd")]
config: PathBuf, config: PathBuf,
}, },
/// Create the configured namespaces
Up {
/// Location of the config file
#[clap(short, long, default_value = "/etc/netnsd/netnsd")]
config: PathBuf,
},
/// Remove all network namespaces created to netnsd
Down,
/// Signal a running daemon to reload it's configuration /// Signal a running daemon to reload it's configuration
Reload, Reload,
} }
@ -38,6 +49,13 @@ fn main() -> MainResult {
let config = Config::load(config)?; let config = Config::load(config)?;
daemon(config) daemon(config)
} }
Commands::Up {config} => {
let config = Config::load(config)?;
up(config)
}
Commands::Down => {
down()
}
Commands::Reload => reload() Commands::Reload => reload()
} }
} }

View file

@ -1,12 +1,12 @@
mod raw; mod raw;
use crate::config::NamespaceName; use crate::config::NamespaceName;
use crate::link::{LinkError, link_up_ns}; use crate::link::{link_up_ns, LinkError};
use crate::namespace::raw::{NamespaceSetupError, create_network_namespace}; use crate::namespace::raw::{create_network_namespace, NamespaceSetupError};
use either::Either; use either::Either;
use nix::errno::Errno; use nix::errno::Errno;
use nix::mount::{MntFlags, MsFlags, mount, umount2}; use nix::mount::{mount, umount2, MntFlags, MsFlags};
use std::fs::{File, create_dir, read_dir, remove_file}; use std::fs::{create_dir, read_dir, remove_file, File};
use std::io::{Error as IoError, ErrorKind}; use std::io::{Error as IoError, ErrorKind};
use std::iter::empty; use std::iter::empty;
use std::os::unix::fs::symlink; use std::os::unix::fs::symlink;
@ -77,7 +77,11 @@ impl NetNs {
path: nsd_path.clone(), path: nsd_path.clone(),
})?; })?;
} }
Result::<_, NamespaceError>::Ok(NetNs { name, path, nsd_path }) Result::<_, NamespaceError>::Ok(NetNs {
name,
path,
nsd_path,
})
})?; })?;
ns.setup_interfaces()?; ns.setup_interfaces()?;

View file

@ -1,7 +1,7 @@
use nix::errno::Errno; use nix::errno::Errno;
use nix::sched::{CloneFlags, clone}; use nix::sched::{clone, CloneFlags};
use nix::sys::signal::Signal; use nix::sys::signal::Signal;
use nix::sys::wait::{WaitStatus, waitpid}; use nix::sys::wait::{waitpid, WaitStatus};
use std::path::PathBuf; use std::path::PathBuf;
use thiserror::Error; use thiserror::Error;
use tracing::error; use tracing::error;

27
src/up.rs Normal file
View file

@ -0,0 +1,27 @@
use crate::config::{Config, NamespaceName};
use crate::namespace::NetNs;
use main_error::MainResult;
pub fn up(config: Config) -> MainResult {
let mut namespaces = NetNs::existing()?
.map(NetNs::new)
.collect::<Result<Vec<_>, _>>()?;
for removed in namespaces.extract_if(.., |namespace| {
config.get_namespace(namespace.name()).is_none()
}) {
removed.delete()?;
}
for new in config.namespaces {
if !has_namespace(&namespaces, &new.name) {
namespaces.push(NetNs::new(new.name)?);
}
}
Ok(())
}
fn has_namespace(namespaces: &[NetNs], name: &NamespaceName) -> bool {
namespaces.iter().any(|existing| existing.name() == name)
}