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

@ -22,7 +22,7 @@
}: {
imports = [./nix/module.nix];
config = lib.mkIf (config.networking.netnsd.namespaces != {}) {
nixpkgs.overlays = [ outputs.overlays.default ];
nixpkgs.overlays = [outputs.overlays.default];
networking.netnsd.package = lib.mkDefault pkgs.netnsd;
};
};

View file

@ -1,10 +1,10 @@
mod target;
mod name;
mod source;
mod target;
pub use crate::config::target::ForwardTarget;
pub use crate::config::name::NamespaceName;
pub use crate::config::source::ForwardSource;
pub use crate::config::target::ForwardTarget;
use serde::Deserialize;
use std::collections::HashSet;
use std::fs::read_to_string;
@ -42,7 +42,9 @@ impl Config {
}
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]
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")]);

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::utils::Groups;
use nix::errno::Errno;
use nix::sched::{CloneFlags, setns};
use nix::sched::{setns, CloneFlags};
use std::fs::File;
use std::io::Error as IoError;
use std::path::{Path, PathBuf};
use std::thread::spawn;
use std::io::Error as IoError;
use thiserror::Error;
#[derive(Debug, Error)]

View file

@ -3,6 +3,8 @@ use clap::{Parser, Subcommand};
use main_error::MainResult;
use crate::config::Config;
use crate::daemon::daemon;
use crate::down::down;
use crate::up::up;
mod config;
mod daemon;
@ -10,6 +12,7 @@ mod namespace;
mod proxy;
mod link;
mod down;
mod up;
#[derive(Parser, Debug)]
pub struct Args {
@ -25,6 +28,14 @@ enum Commands {
#[clap(short, long, default_value = "/etc/netnsd/netnsd")]
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
Reload,
}
@ -38,6 +49,13 @@ fn main() -> MainResult {
let config = Config::load(config)?;
daemon(config)
}
Commands::Up {config} => {
let config = Config::load(config)?;
up(config)
}
Commands::Down => {
down()
}
Commands::Reload => reload()
}
}

View file

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

View file

@ -1,7 +1,7 @@
use nix::errno::Errno;
use nix::sched::{CloneFlags, clone};
use nix::sched::{clone, CloneFlags};
use nix::sys::signal::Signal;
use nix::sys::wait::{WaitStatus, waitpid};
use nix::sys::wait::{waitpid, WaitStatus};
use std::path::PathBuf;
use thiserror::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)
}