diff --git a/userspace/.gitignore b/userspace/.gitignore index 97af3d94..4d7e7571 100644 --- a/userspace/.gitignore +++ b/userspace/.gitignore @@ -1,3 +1,4 @@ /target /dynload-program/target /etc/rc.d/*.ext +/etc/*.ext diff --git a/userspace/Cargo.lock b/userspace/Cargo.lock index a156f5ea..01219303 100644 --- a/userspace/Cargo.lock +++ b/userspace/Cargo.lock @@ -1525,6 +1525,7 @@ dependencies = [ "serde", "serde_json", "thiserror", + "toml", "url", "yggdrasil-abi", ] diff --git a/userspace/netutils/Cargo.toml b/userspace/netutils/Cargo.toml index 3f539a74..dd8b35f8 100644 --- a/userspace/netutils/Cargo.toml +++ b/userspace/netutils/Cargo.toml @@ -16,6 +16,7 @@ thiserror.workspace = true clap.workspace = true clap-num.workspace = true rand.workspace = true +toml.workspace = true url = "2.5.0" http = "1.1.0" diff --git a/userspace/netutils/src/lib.rs b/userspace/netutils/src/lib.rs index 98e359a4..f909f443 100644 --- a/userspace/netutils/src/lib.rs +++ b/userspace/netutils/src/lib.rs @@ -19,4 +19,7 @@ pub enum Error { SerializeError(#[from] serde_json::Error), #[error("Timed out")] TimedOut, + #[error("TOML deserialize error: {0}")] + TomlDeserializeErr(#[from] toml::de::Error), } + diff --git a/userspace/netutils/src/netconf.rs b/userspace/netutils/src/netconf.rs index be3417cc..ae19f0a1 100644 --- a/userspace/netutils/src/netconf.rs +++ b/userspace/netutils/src/netconf.rs @@ -1,5 +1,11 @@ #![feature(rustc_private)] -use std::{net::IpAddr, process::ExitCode, str::FromStr}; +use std::{ + collections::HashMap, + net::{IpAddr, Ipv4Addr}, + path::{Path, PathBuf}, + process::ExitCode, + str::FromStr, +}; use clap::{Args, Parser, Subcommand}; use netutils::{netconfig::NetConfig, Error}; @@ -7,6 +13,7 @@ use runtime::abi::net::{ self, netconfig::{InterfaceInfo, RouteInfo}, }; +use serde::Deserialize; #[derive(Debug, Parser)] #[clap(author, version, about, long_about = None)] @@ -17,6 +24,11 @@ pub struct Arguments { #[derive(Debug, Subcommand)] pub enum Section { + #[clap( + arg_required_else_help = true, + about = "Apply settings from configuration file" + )] + Apply(#[clap(subcommand)] ApplyAction), #[clap(arg_required_else_help = true, about = "Route query and manipulation")] Route(#[clap(subcommand)] RouteAction), #[clap( @@ -31,6 +43,12 @@ pub enum Section { Link(#[clap(subcommand)] LinkAction), } +#[derive(Debug, Args)] +pub struct ApplyAction { + #[clap(help = "Config filename")] + filename: PathBuf, +} + #[derive(Debug, Args)] pub struct RouteAction { #[clap(subcommand)] @@ -49,6 +67,24 @@ pub struct LinkAction { command: LinkCommands, } +#[derive(Debug, Deserialize)] +pub struct InterfaceConfiguration { + pub address: Option, + pub routes: Option>, +} + +#[derive(Debug, Deserialize)] +pub struct RouteConfiguration { + pub network: Ipv4Addr, + pub mask: u8, + pub gateway: Ipv4Addr, +} + +#[derive(Debug, Deserialize)] +pub struct Configuration { + pub interfaces: HashMap, +} + #[derive(Debug, Subcommand)] pub enum RouteCommands { #[clap(about = "List routes")] @@ -215,12 +251,38 @@ pub fn run_link_action(nc: &mut NetConfig, action: LinkCommands) -> Result<(), E } } +pub fn run_apply_action(nc: &mut NetConfig, filename: &Path) -> Result<(), Error> { + let config_str = std::fs::read_to_string(filename)?; + let config: Configuration = toml::from_str(&config_str)?; + + for (if_name, if_config) in config.interfaces { + let if_name = if_name.as_str(); + if let Some(address) = if_config.address { + nc.set_interface_address(if_name, address)?; + } + + // TODO drop old routes + if let Some(routes) = if_config.routes { + for route in routes { + let subnet = net::SubnetAddr::V4(net::SubnetV4Addr::from_address_mask( + route.network, + route.mask, + )); + nc.add_route(if_name, subnet, Some(route.gateway.into()))?; + } + } + } + + Ok(()) +} + pub fn run_action(section: Section) -> Result<(), Error> { let mut nc = NetConfig::open()?; match section { Section::Route(RouteAction { command }) => run_route_action(&mut nc, command), Section::Addr(AddrAction { command }) => run_addr_action(&mut nc, command), Section::Link(LinkAction { command }) => run_link_action(&mut nc, command), + Section::Apply(ApplyAction { filename }) => run_apply_action(&mut nc, filename.as_path()), } } @@ -255,3 +317,4 @@ fn main() -> ExitCode { } } } +