Start to inflate NWFilter REST api

This commit is contained in:
Pierre HUBERT 2023-12-28 15:42:43 +01:00
parent 3849b0d51d
commit f7777fe085
2 changed files with 123 additions and 36 deletions

View File

@ -1,5 +1,6 @@
use crate::controllers::{HttpResult, LibVirtReq};
use crate::libvirt_lib_structures::XMLUuid;
use crate::libvirt_rest_structures::NetworkFilter;
use actix_web::{web, HttpResponse};
#[derive(serde::Serialize, serde::Deserialize)]
@ -18,19 +19,16 @@ pub async fn list(client: LibVirtReq) -> HttpResult {
Ok(l) => l,
};
/*let networks = networks
.into_iter()
.map(|n| NetworkInfo::from_xml(n).unwrap())
.collect::<Vec<_>>();*/
// TODO : turn into lib structure
println!("{:#?}", networks);
let networks = networks
.into_iter()
.map(|n| NetworkFilter::from_xml(n).unwrap())
.collect::<Vec<_>>();
Ok(HttpResponse::Ok().body(format!("{:#?}", networks)))
Ok(HttpResponse::Ok().json(networks))
}
/// Get the information about a single network filter
pub async fn get_single(client: LibVirtReq, req: web::Path<NetworkFilterID>) -> HttpResult {
let nwfilter = client.get_single_network_filter(req.uid).await?;
// TODO : turn into lib structure
Ok(HttpResponse::Ok().body(format!("{:#?}", nwfilter)))
let nwfilter = NetworkFilter::from_xml(client.get_single_network_filter(req.uid).await?)?;
Ok(HttpResponse::Ok().json(nwfilter))
}

View File

@ -5,9 +5,9 @@ use crate::libvirt_lib_structures::{
DomainCPUTopology, DomainCPUXML, DomainInputXML, DomainMemoryXML, DomainNetInterfaceXML,
DomainVCPUXML, DomainXML, FeaturesXML, GraphicsXML, NetIntModelXML, NetIntSourceXML,
NetMacAddress, NetworkBridgeXML, NetworkDHCPHostXML, NetworkDHCPRangeXML, NetworkDHCPXML,
NetworkDNSForwarderXML, NetworkDNSXML, NetworkDomainXML, NetworkForwardXML, NetworkIPXML,
NetworkXML, OSLoaderXML, OSTypeXML, TPMBackendXML, TPMDeviceXML, VideoModelXML, VideoXML,
XMLUuid, ACPIXML, OSXML,
NetworkDNSForwarderXML, NetworkDNSXML, NetworkDomainXML, NetworkFilterXML, NetworkForwardXML,
NetworkIPXML, NetworkXML, OSLoaderXML, OSTypeXML, TPMBackendXML, TPMDeviceXML, VideoModelXML,
VideoXML, XMLUuid, ACPIXML, OSXML,
};
use crate::libvirt_rest_structures::LibVirtStructError::StructureExtraction;
use crate::utils::disks_utils::Disk;
@ -18,6 +18,8 @@ use num::Integer;
use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
use std::ops::{Div, Mul};
// TODO : split into multiple files
#[derive(thiserror::Error, Debug)]
enum LibVirtStructError {
#[error("StructureExtractionError: {0}")]
@ -26,6 +28,8 @@ enum LibVirtStructError {
DomainExtraction(String),
#[error("MBConvertError: {0}")]
MBConvert(String),
#[error("ParseFilteringChain: {0}")]
ParseFilteringChain(String),
}
#[derive(serde::Serialize)]
@ -700,7 +704,8 @@ impl NetworkInfo {
}
}
pub enum NetworkFilterChain {
#[derive(serde::Serialize, serde::Deserialize, Debug, Copy, Clone)]
pub enum NetworkFilterChainProtocol {
Root,
Mac,
STP,
@ -711,7 +716,75 @@ pub enum NetworkFilterChain {
IPv6,
}
impl NetworkFilterChainProtocol {
pub fn from_xml(xml: &str) -> anyhow::Result<Self> {
Ok(match xml {
"root" => Self::Root,
"mac" => Self::Mac,
"stp" => Self::STP,
"vlan" => Self::VLAN,
"arp" => Self::ARP,
"rarp" => Self::RARP,
"ipv4" => Self::IPv4,
"ipv6" => Self::IPv6,
_ => {
return Err(LibVirtStructError::ParseFilteringChain(format!(
"Unknown filtering chain: {xml}! "
))
.into())
}
})
}
pub fn to_xml(&self) -> String {
match self {
Self::Root => "root",
Self::Mac => "mac",
Self::STP => "stp",
Self::VLAN => "vlan",
Self::ARP => "arp",
Self::RARP => "rarp",
Self::IPv4 => "ipv4",
Self::IPv6 => "ipv6",
}
.to_string()
}
}
#[derive(serde::Serialize, serde::Deserialize, Debug, Clone)]
pub struct NetworkFilterChain {
protocol: NetworkFilterChainProtocol,
suffix: Option<String>,
}
impl NetworkFilterChain {
pub fn from_xml(xml: &str) -> anyhow::Result<Option<Self>> {
if xml.is_empty() {
return Ok(None);
}
Ok(Some(match xml.split_once('-') {
None => Self {
protocol: NetworkFilterChainProtocol::from_xml(xml)?,
suffix: None,
},
Some((prefix, suffix)) => Self {
protocol: NetworkFilterChainProtocol::from_xml(prefix)?,
suffix: Some(suffix.to_string()),
},
}))
}
pub fn to_xml(&self) -> String {
match &self.suffix {
None => self.protocol.to_xml(),
Some(s) => format!("{}-{s}", self.protocol.to_xml()),
}
}
}
/// Network filter definition
#[derive(serde::Serialize, serde::Deserialize, Debug, Clone)]
pub struct NetworkFilter {
name: String,
chain: Option<NetworkFilterChain>,
@ -722,6 +795,24 @@ pub struct NetworkFilter {
rules: Vec<NetworkFilterRule>,
}
impl NetworkFilter {
pub fn from_xml(xml: NetworkFilterXML) -> anyhow::Result<Self> {
Ok(Self {
name: xml.name,
uuid: xml.uuid,
chain: NetworkFilterChain::from_xml(&xml.chain)?,
priority: xml.priority,
join_rules: xml
.filterrefs
.iter()
.map(|i| i.filter.to_string())
.collect(),
rules: vec![], // TODO !
})
}
}
#[derive(serde::Serialize, serde::Deserialize, Debug, Copy, Clone)]
pub enum NetworkFilterAction {
/// matching the rule silently discards the packet with no further analysis
Drop,
@ -736,12 +827,14 @@ pub enum NetworkFilterAction {
Continue,
}
#[derive(serde::Serialize, serde::Deserialize, Debug, Clone)]
pub enum NetworkFilterDirection {
In,
Out,
InOut,
}
#[derive(serde::Serialize, serde::Deserialize, Debug, Clone)]
pub enum Layer4State {
NEW,
ESTABLISHED,
@ -750,6 +843,7 @@ pub enum Layer4State {
NONE,
}
#[derive(serde::Serialize, serde::Deserialize, Debug, Clone)]
pub enum Layer4Type {
TCP,
UDP,
@ -761,6 +855,20 @@ pub enum Layer4Type {
ICMPipv6,
}
#[derive(serde::Serialize, serde::Deserialize, Debug, Clone)]
pub struct NetworkFilterSelectorIP<IPv> {
srcmacaddr: Option<String>,
srcmacmask: Option<String>,
dstmacaddr: Option<String>,
dstmacmask: Option<String>,
srcipaddr: Option<IPv>,
srcipmask: Option<u8>,
dstipaddr: Option<IPv>,
dstipmask: Option<u8>,
comment: Option<String>,
}
#[derive(serde::Serialize, serde::Deserialize, Debug, Clone)]
pub enum NetworkFilterSelector {
All,
Mac {
@ -781,28 +889,8 @@ pub enum NetworkFilterSelector {
arpdstipmask: Option<u8>,
comment: Option<String>,
},
IPv4 {
srcmacaddr: Option<String>,
srcmacmask: Option<String>,
dstmacaddr: Option<String>,
dstmacmask: Option<String>,
srcipaddr: Option<Ipv4Addr>,
srcipmask: Option<u8>,
dstipaddr: Option<Ipv4Addr>,
dstipmask: Option<u8>,
comment: Option<String>,
},
IPv6 {
srcmacaddr: Option<String>,
srcmacmask: Option<String>,
dstmacaddr: Option<String>,
dstmacmask: Option<String>,
srcipaddr: Option<Ipv6Addr>,
srcipmask: Option<u8>,
dstipaddr: Option<Ipv6Addr>,
dstipmask: Option<u8>,
comment: Option<String>,
},
IPv4(NetworkFilterSelectorIP<Ipv4Addr>),
IPv6(NetworkFilterSelectorIP<Ipv6Addr>),
Layer4 {
r#type: Layer4Type,
srcmacaddr: Option<String>,
@ -827,6 +915,7 @@ pub enum NetworkFilterSelector {
},
}
#[derive(serde::Serialize, serde::Deserialize, Debug, Clone)]
pub struct NetworkFilterRule {
action: NetworkFilterAction,
direction: NetworkFilterDirection,