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>,
/// Match all protocols
#[serde(skip_serializing_if = "Vec::is_empty")]
pub all: Vec<NetworkFilterRuleProtocolAll>,
#[serde(default, rename = "all", skip_serializing_if = "Vec::is_empty")]
pub all_selectors: Vec<NetworkFilterRuleProtocolAll>,
/// Match mac protocol
#[serde(default, rename = "mac", skip_serializing_if = "Vec::is_empty")]

View File

@ -11,4 +11,6 @@ enum LibVirtStructError {
DomainExtraction(String),
#[error("ParseFilteringChain: {0}")]
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_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 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)]
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)]
#[serde(rename_all = "lowercase")]
pub enum NetworkFilterChainProtocol {
@ -113,20 +161,20 @@ impl NetworkFilter {
fn lib2rest_process_mac_rule(n: &NetworkFilterRuleProtocolMac) -> NetworkFilterSelector {
NetworkFilterSelector::Mac(NetworkSelectorMac {
src_mac_addr: n.srcmacaddr.clone(),
src_mac_mask: n.srcmacmask.clone(),
dst_mac_addr: n.dstmacaddr.clone(),
dst_mac_mask: n.dstmacmask.clone(),
src_mac_addr: n.srcmacaddr.as_ref().map(|v| v.into()),
src_mac_mask: n.srcmacmask.as_ref().map(|v| v.into()),
dst_mac_addr: n.dstmacaddr.as_ref().map(|v| v.into()),
dst_mac_mask: n.dstmacmask.as_ref().map(|v| v.into()),
comment: n.comment.clone(),
})
}
fn lib2rest_process_arp_rule(n: &NetworkFilterRuleProtocolArp) -> NetworkSelectorARP {
NetworkSelectorARP {
srcmacaddr: n.srcmacaddr.clone(),
srcmacmask: n.srcmacmask.clone(),
dstmacaddr: n.dstmacaddr.clone(),
dstmacmask: n.dstmacmask.clone(),
srcmacaddr: n.srcmacaddr.as_ref().map(|v| v.into()),
srcmacmask: n.srcmacmask.as_ref().map(|v| v.into()),
dstmacaddr: n.dstmacaddr.as_ref().map(|v| v.into()),
dstmacmask: n.dstmacmask.as_ref().map(|v| v.into()),
arpsrcipaddr: n.arpsrcipaddr.clone(),
arpsrcipmask: n.arpsrcipmask,
arpdstipaddr: n.arpdstipaddr.clone(),
@ -153,7 +201,7 @@ impl NetworkFilter {
n: &NetworkFilterRuleProtocolLayer4<IPv>,
) -> anyhow::Result<NetworkSelectorLayer4<IPv>> {
Ok(NetworkSelectorLayer4 {
srcmacaddr: n.srcmacaddr.clone(),
srcmacaddr: n.srcmacaddr.as_ref().map(|v| v.into()),
srcipaddr: n.srcipaddr,
srcipmask: n.srcipmask,
dstipaddr: n.dstipaddr,
@ -179,7 +227,7 @@ impl NetworkFilter {
// All selector
selectors.append(
&mut rule
.all
.all_selectors
.iter()
.map(Self::lib2rest_process_all_rule)
.collect(),
@ -348,7 +396,7 @@ impl NetworkFilter {
action: rule.action.to_xml(),
direction: rule.direction.to_xml(),
priority: rule.priority,
all: vec![],
all_selectors: vec![],
mac_selectors: vec![],
arp_selectors: vec![],
rarp_selectors: vec![],
@ -367,18 +415,17 @@ impl NetworkFilter {
for sel in &rule.selectors {
match sel {
NetworkFilterSelector::All => {
rule_xml.all.push(NetworkFilterRuleProtocolAll {});
rule_xml.all_selectors.push(NetworkFilterRuleProtocolAll {});
}
NetworkFilterSelector::Mac(mac) => {
todo!()
/*rule_xml.mac_selectors.push(NetworkFilterRuleProtocolMac {
srcmacaddr: mac.src_mac_addr,
srcmacmask: mac.src_mac_mask,
dstmacaddr: mac.,
dstmacmask: None,
comment: None,
})*/
rule_xml.mac_selectors.push(NetworkFilterRuleProtocolMac {
srcmacaddr: extract_mac_address_or_var(&mac.src_mac_addr)?,
srcmacmask: extract_mac_address_or_var(&mac.src_mac_mask)?,
dstmacaddr: extract_mac_address_or_var(&mac.dst_mac_addr)?,
dstmacmask: extract_mac_address_or_var(&mac.dst_mac_mask)?,
comment: extract_nw_filter_comment(&mac.comment)?,
})
}
NetworkFilterSelector::Arp(_) => todo!(),
@ -401,12 +448,16 @@ impl NetworkFilter {
pub fn rest2lib(&self) -> anyhow::Result<NetworkFilterXML> {
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 !(-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)]
pub struct NetworkSelectorMac {
src_mac_addr: Option<String>,
src_mac_mask: Option<String>,
dst_mac_addr: Option<String>,
dst_mac_mask: Option<String>,
src_mac_addr: Option<NetworkFilterMacAddressOrVar>,
src_mac_mask: Option<NetworkFilterMacAddressOrVar>,
dst_mac_addr: Option<NetworkFilterMacAddressOrVar>,
dst_mac_mask: Option<NetworkFilterMacAddressOrVar>,
comment: Option<String>,
}
#[derive(serde::Serialize, serde::Deserialize, Debug, Clone)]
pub struct NetworkSelectorARP {
srcmacaddr: Option<String>,
srcmacmask: Option<String>,
dstmacaddr: Option<String>,
dstmacmask: Option<String>,
srcmacaddr: Option<NetworkFilterMacAddressOrVar>,
srcmacmask: Option<NetworkFilterMacAddressOrVar>,
dstmacaddr: Option<NetworkFilterMacAddressOrVar>,
dstmacmask: Option<NetworkFilterMacAddressOrVar>,
arpsrcipaddr: Option<String>,
arpsrcipmask: Option<u8>,
arpdstipaddr: Option<String>,
@ -594,7 +645,7 @@ pub struct NetworkSelectorARP {
#[derive(serde::Serialize, serde::Deserialize, Debug, Clone)]
pub struct NetworkSelectorLayer4<IPv> {
srcmacaddr: Option<String>,
srcmacaddr: Option<NetworkFilterMacAddressOrVar>,
srcipaddr: Option<IPv>,
srcipmask: Option<u8>,
dstipaddr: Option<IPv>,
@ -645,3 +696,19 @@ pub struct NetworkFilterRule {
priority: Option<i32>,
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"));
}
}