Can extract mac rules

This commit is contained in:
Pierre HUBERT 2023-12-29 20:40:01 +01:00
parent 7b74e7b75a
commit 8182ecd7f6
3 changed files with 103 additions and 34 deletions

View File

@ -238,8 +238,8 @@ pub struct NetworkFilterRuleXML {
pub priority: Option<i32>, pub priority: Option<i32>,
/// Match all protocols /// Match all protocols
#[serde(skip_serializing_if = "Vec::is_empty")] #[serde(default, rename = "all", skip_serializing_if = "Vec::is_empty")]
pub all: Vec<NetworkFilterRuleProtocolAll>, pub all_selectors: Vec<NetworkFilterRuleProtocolAll>,
/// Match mac protocol /// Match mac protocol
#[serde(default, rename = "mac", skip_serializing_if = "Vec::is_empty")] #[serde(default, rename = "mac", skip_serializing_if = "Vec::is_empty")]

View File

@ -11,4 +11,6 @@ enum LibVirtStructError {
DomainExtraction(String), DomainExtraction(String),
#[error("ParseFilteringChain: {0}")] #[error("ParseFilteringChain: {0}")]
ParseFilteringChain(String), ParseFilteringChain(String),
#[error("NetworkFilterExtractionError: {0}")]
NetworkFilterExtraction(String),
} }

View File

@ -5,10 +5,17 @@ use crate::libvirt_lib_structures::nwfilter::{
}; };
use crate::libvirt_lib_structures::XMLUuid; use crate::libvirt_lib_structures::XMLUuid;
use crate::libvirt_rest_structures::LibVirtStructError; use crate::libvirt_rest_structures::LibVirtStructError;
use crate::libvirt_rest_structures::LibVirtStructError::StructureExtraction; use crate::libvirt_rest_structures::LibVirtStructError::{
NetworkFilterExtraction, StructureExtraction,
};
use crate::utils::net_utils;
use lazy_regex::regex; use lazy_regex::regex;
use std::net::{Ipv4Addr, Ipv6Addr}; use std::net::{Ipv4Addr, Ipv6Addr};
pub fn is_var_def(var: &str) -> bool {
lazy_regex::regex!("^\\$[a-zA-Z0-9_]+$").is_match(var)
}
#[derive(serde::Serialize, serde::Deserialize, Debug, Clone)] #[derive(serde::Serialize, serde::Deserialize, Debug, Clone)]
pub struct NetworkFilterName(pub String); pub struct NetworkFilterName(pub String);
@ -18,6 +25,47 @@ impl NetworkFilterName {
} }
} }
#[derive(serde::Serialize, serde::Deserialize, Debug, Clone)]
pub struct NetworkFilterMacAddressOrVar(pub String);
impl NetworkFilterMacAddressOrVar {
pub fn is_valid(&self) -> bool {
is_var_def(&self.0) || net_utils::is_mac_address_valid(&self.0)
}
}
impl From<&String> for NetworkFilterMacAddressOrVar {
fn from(value: &String) -> Self {
Self(value.to_string())
}
}
fn extract_mac_address_or_var(
n: &Option<NetworkFilterMacAddressOrVar>,
) -> anyhow::Result<Option<String>> {
if let Some(mac) = n {
if !mac.is_valid() {
return Err(NetworkFilterExtraction(format!(
"Invalid mac address or variable! {}",
mac.0
))
.into());
}
}
Ok(n.as_ref().map(|n| n.0.to_string()))
}
fn extract_nw_filter_comment(n: &Option<String>) -> anyhow::Result<Option<String>> {
if let Some(comment) = n {
if comment.len() > 256 || comment.contains('\"') || comment.contains('\n') {
return Err(NetworkFilterExtraction(format!("Invalid comment! {}", comment)).into());
}
}
Ok(n.clone())
}
#[derive(serde::Serialize, serde::Deserialize, Debug, Copy, Clone)] #[derive(serde::Serialize, serde::Deserialize, Debug, Copy, Clone)]
#[serde(rename_all = "lowercase")] #[serde(rename_all = "lowercase")]
pub enum NetworkFilterChainProtocol { pub enum NetworkFilterChainProtocol {
@ -113,20 +161,20 @@ impl NetworkFilter {
fn lib2rest_process_mac_rule(n: &NetworkFilterRuleProtocolMac) -> NetworkFilterSelector { fn lib2rest_process_mac_rule(n: &NetworkFilterRuleProtocolMac) -> NetworkFilterSelector {
NetworkFilterSelector::Mac(NetworkSelectorMac { NetworkFilterSelector::Mac(NetworkSelectorMac {
src_mac_addr: n.srcmacaddr.clone(), src_mac_addr: n.srcmacaddr.as_ref().map(|v| v.into()),
src_mac_mask: n.srcmacmask.clone(), src_mac_mask: n.srcmacmask.as_ref().map(|v| v.into()),
dst_mac_addr: n.dstmacaddr.clone(), dst_mac_addr: n.dstmacaddr.as_ref().map(|v| v.into()),
dst_mac_mask: n.dstmacmask.clone(), dst_mac_mask: n.dstmacmask.as_ref().map(|v| v.into()),
comment: n.comment.clone(), comment: n.comment.clone(),
}) })
} }
fn lib2rest_process_arp_rule(n: &NetworkFilterRuleProtocolArp) -> NetworkSelectorARP { fn lib2rest_process_arp_rule(n: &NetworkFilterRuleProtocolArp) -> NetworkSelectorARP {
NetworkSelectorARP { NetworkSelectorARP {
srcmacaddr: n.srcmacaddr.clone(), srcmacaddr: n.srcmacaddr.as_ref().map(|v| v.into()),
srcmacmask: n.srcmacmask.clone(), srcmacmask: n.srcmacmask.as_ref().map(|v| v.into()),
dstmacaddr: n.dstmacaddr.clone(), dstmacaddr: n.dstmacaddr.as_ref().map(|v| v.into()),
dstmacmask: n.dstmacmask.clone(), dstmacmask: n.dstmacmask.as_ref().map(|v| v.into()),
arpsrcipaddr: n.arpsrcipaddr.clone(), arpsrcipaddr: n.arpsrcipaddr.clone(),
arpsrcipmask: n.arpsrcipmask, arpsrcipmask: n.arpsrcipmask,
arpdstipaddr: n.arpdstipaddr.clone(), arpdstipaddr: n.arpdstipaddr.clone(),
@ -153,7 +201,7 @@ impl NetworkFilter {
n: &NetworkFilterRuleProtocolLayer4<IPv>, n: &NetworkFilterRuleProtocolLayer4<IPv>,
) -> anyhow::Result<NetworkSelectorLayer4<IPv>> { ) -> anyhow::Result<NetworkSelectorLayer4<IPv>> {
Ok(NetworkSelectorLayer4 { Ok(NetworkSelectorLayer4 {
srcmacaddr: n.srcmacaddr.clone(), srcmacaddr: n.srcmacaddr.as_ref().map(|v| v.into()),
srcipaddr: n.srcipaddr, srcipaddr: n.srcipaddr,
srcipmask: n.srcipmask, srcipmask: n.srcipmask,
dstipaddr: n.dstipaddr, dstipaddr: n.dstipaddr,
@ -179,7 +227,7 @@ impl NetworkFilter {
// All selector // All selector
selectors.append( selectors.append(
&mut rule &mut rule
.all .all_selectors
.iter() .iter()
.map(Self::lib2rest_process_all_rule) .map(Self::lib2rest_process_all_rule)
.collect(), .collect(),
@ -348,7 +396,7 @@ impl NetworkFilter {
action: rule.action.to_xml(), action: rule.action.to_xml(),
direction: rule.direction.to_xml(), direction: rule.direction.to_xml(),
priority: rule.priority, priority: rule.priority,
all: vec![], all_selectors: vec![],
mac_selectors: vec![], mac_selectors: vec![],
arp_selectors: vec![], arp_selectors: vec![],
rarp_selectors: vec![], rarp_selectors: vec![],
@ -367,18 +415,17 @@ impl NetworkFilter {
for sel in &rule.selectors { for sel in &rule.selectors {
match sel { match sel {
NetworkFilterSelector::All => { NetworkFilterSelector::All => {
rule_xml.all.push(NetworkFilterRuleProtocolAll {}); rule_xml.all_selectors.push(NetworkFilterRuleProtocolAll {});
} }
NetworkFilterSelector::Mac(mac) => { NetworkFilterSelector::Mac(mac) => {
todo!() rule_xml.mac_selectors.push(NetworkFilterRuleProtocolMac {
/*rule_xml.mac_selectors.push(NetworkFilterRuleProtocolMac { srcmacaddr: extract_mac_address_or_var(&mac.src_mac_addr)?,
srcmacaddr: mac.src_mac_addr, srcmacmask: extract_mac_address_or_var(&mac.src_mac_mask)?,
srcmacmask: mac.src_mac_mask, dstmacaddr: extract_mac_address_or_var(&mac.dst_mac_addr)?,
dstmacaddr: mac., dstmacmask: extract_mac_address_or_var(&mac.dst_mac_mask)?,
dstmacmask: None, comment: extract_nw_filter_comment(&mac.comment)?,
comment: None, })
})*/
} }
NetworkFilterSelector::Arp(_) => todo!(), NetworkFilterSelector::Arp(_) => todo!(),
@ -401,12 +448,16 @@ impl NetworkFilter {
pub fn rest2lib(&self) -> anyhow::Result<NetworkFilterXML> { pub fn rest2lib(&self) -> anyhow::Result<NetworkFilterXML> {
if !self.name.is_valid() { if !self.name.is_valid() {
return Err(StructureExtraction("Network filter name is invalid!").into()); return Err(
NetworkFilterExtraction("Network filter name is invalid!".to_string()).into(),
);
} }
if let Some(priority) = self.priority { if let Some(priority) = self.priority {
if !(-1000..=1000).contains(&priority) { if !(-1000..=1000).contains(&priority) {
return Err(StructureExtraction("Network priority is invalid!").into()); return Err(
NetworkFilterExtraction("Network priority is invalid!".to_string()).into(),
);
} }
} }
@ -572,19 +623,19 @@ pub struct NetworkFilterSelectorIP {
#[derive(serde::Serialize, serde::Deserialize, Debug, Clone)] #[derive(serde::Serialize, serde::Deserialize, Debug, Clone)]
pub struct NetworkSelectorMac { pub struct NetworkSelectorMac {
src_mac_addr: Option<String>, src_mac_addr: Option<NetworkFilterMacAddressOrVar>,
src_mac_mask: Option<String>, src_mac_mask: Option<NetworkFilterMacAddressOrVar>,
dst_mac_addr: Option<String>, dst_mac_addr: Option<NetworkFilterMacAddressOrVar>,
dst_mac_mask: Option<String>, dst_mac_mask: Option<NetworkFilterMacAddressOrVar>,
comment: Option<String>, comment: Option<String>,
} }
#[derive(serde::Serialize, serde::Deserialize, Debug, Clone)] #[derive(serde::Serialize, serde::Deserialize, Debug, Clone)]
pub struct NetworkSelectorARP { pub struct NetworkSelectorARP {
srcmacaddr: Option<String>, srcmacaddr: Option<NetworkFilterMacAddressOrVar>,
srcmacmask: Option<String>, srcmacmask: Option<NetworkFilterMacAddressOrVar>,
dstmacaddr: Option<String>, dstmacaddr: Option<NetworkFilterMacAddressOrVar>,
dstmacmask: Option<String>, dstmacmask: Option<NetworkFilterMacAddressOrVar>,
arpsrcipaddr: Option<String>, arpsrcipaddr: Option<String>,
arpsrcipmask: Option<u8>, arpsrcipmask: Option<u8>,
arpdstipaddr: Option<String>, arpdstipaddr: Option<String>,
@ -594,7 +645,7 @@ pub struct NetworkSelectorARP {
#[derive(serde::Serialize, serde::Deserialize, Debug, Clone)] #[derive(serde::Serialize, serde::Deserialize, Debug, Clone)]
pub struct NetworkSelectorLayer4<IPv> { pub struct NetworkSelectorLayer4<IPv> {
srcmacaddr: Option<String>, srcmacaddr: Option<NetworkFilterMacAddressOrVar>,
srcipaddr: Option<IPv>, srcipaddr: Option<IPv>,
srcipmask: Option<u8>, srcipmask: Option<u8>,
dstipaddr: Option<IPv>, dstipaddr: Option<IPv>,
@ -645,3 +696,19 @@ pub struct NetworkFilterRule {
priority: Option<i32>, priority: Option<i32>,
selectors: Vec<NetworkFilterSelector>, selectors: Vec<NetworkFilterSelector>,
} }
#[cfg(test)]
mod test {
use crate::libvirt_rest_structures::nw_filter::is_var_def;
#[test]
pub fn var_def() {
assert!(is_var_def("$MAC"));
assert!(is_var_def("$MAC_ADDRESS"));
assert!(!is_var_def("$$MAC"));
assert!(!is_var_def("$$MACé"));
assert!(!is_var_def("$$MAC@"));
assert!(!is_var_def("$$MAC TEST"));
}
}