netutils: add netconf apply subcommand

This commit is contained in:
2025-05-14 13:45:49 +03:00
parent be93d68fb1
commit 8c4a882766
5 changed files with 70 additions and 1 deletions
+1
View File
@@ -1,3 +1,4 @@
/target
/dynload-program/target
/etc/rc.d/*.ext
/etc/*.ext
+1
View File
@@ -1525,6 +1525,7 @@ dependencies = [
"serde",
"serde_json",
"thiserror",
"toml",
"url",
"yggdrasil-abi",
]
+1
View File
@@ -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"
+3
View File
@@ -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),
}
+64 -1
View File
@@ -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<IpAddr>,
pub routes: Option<Vec<RouteConfiguration>>,
}
#[derive(Debug, Deserialize)]
pub struct RouteConfiguration {
pub network: Ipv4Addr,
pub mask: u8,
pub gateway: Ipv4Addr,
}
#[derive(Debug, Deserialize)]
pub struct Configuration {
pub interfaces: HashMap<String, InterfaceConfiguration>,
}
#[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 {
}
}
}