Add ARP / RARP selectors extraction
This commit is contained in:
		@@ -45,7 +45,7 @@ pub struct NetworkFilterRuleProtocolMac {
 | 
			
		||||
 | 
			
		||||
#[derive(serde::Serialize, serde::Deserialize, Debug)]
 | 
			
		||||
#[serde(rename = "arp")]
 | 
			
		||||
pub struct NetworkFilterRuleProtocolArp {
 | 
			
		||||
pub struct NetworkFilterRuleProtocolArpXML {
 | 
			
		||||
    #[serde(
 | 
			
		||||
        rename(serialize = "@srcmacaddr"),
 | 
			
		||||
        skip_serializing_if = "Option::is_none"
 | 
			
		||||
@@ -247,11 +247,11 @@ pub struct NetworkFilterRuleXML {
 | 
			
		||||
 | 
			
		||||
    /// Match arp protocol
 | 
			
		||||
    #[serde(default, rename = "arp", skip_serializing_if = "Vec::is_empty")]
 | 
			
		||||
    pub arp_selectors: Vec<NetworkFilterRuleProtocolArp>,
 | 
			
		||||
    pub arp_selectors: Vec<NetworkFilterRuleProtocolArpXML>,
 | 
			
		||||
 | 
			
		||||
    /// Match rarp protocol
 | 
			
		||||
    #[serde(default, rename = "arp", skip_serializing_if = "Vec::is_empty")]
 | 
			
		||||
    pub rarp_selectors: Vec<NetworkFilterRuleProtocolArp>,
 | 
			
		||||
    #[serde(default, rename = "rarp", skip_serializing_if = "Vec::is_empty")]
 | 
			
		||||
    pub rarp_selectors: Vec<NetworkFilterRuleProtocolArpXML>,
 | 
			
		||||
 | 
			
		||||
    /// Match IPv4 protocol
 | 
			
		||||
    #[serde(default, rename = "ip", skip_serializing_if = "Vec::is_empty")]
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,5 @@
 | 
			
		||||
use crate::libvirt_lib_structures::nwfilter::{
 | 
			
		||||
    NetworkFilterRefXML, NetworkFilterRuleProtocolAll, NetworkFilterRuleProtocolArp,
 | 
			
		||||
    NetworkFilterRefXML, NetworkFilterRuleProtocolAll, NetworkFilterRuleProtocolArpXML,
 | 
			
		||||
    NetworkFilterRuleProtocolIpvx, NetworkFilterRuleProtocolLayer4, NetworkFilterRuleProtocolMac,
 | 
			
		||||
    NetworkFilterRuleXML, NetworkFilterXML,
 | 
			
		||||
};
 | 
			
		||||
@@ -56,6 +56,35 @@ fn extract_mac_address_or_var(
 | 
			
		||||
    Ok(n.as_ref().map(|n| n.0.to_string()))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(serde::Serialize, serde::Deserialize, Debug, Clone)]
 | 
			
		||||
pub struct NetworkFilterIPv4OrVar(pub String);
 | 
			
		||||
 | 
			
		||||
impl NetworkFilterIPv4OrVar {
 | 
			
		||||
    pub fn is_valid(&self) -> bool {
 | 
			
		||||
        is_var_def(&self.0) || net_utils::is_ipv4_address_valid(&self.0)
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl From<&String> for NetworkFilterIPv4OrVar {
 | 
			
		||||
    fn from(value: &String) -> Self {
 | 
			
		||||
        Self(value.to_string())
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn extract_ipv4_or_var(n: &Option<NetworkFilterIPv4OrVar>) -> anyhow::Result<Option<String>> {
 | 
			
		||||
    if let Some(ip) = n {
 | 
			
		||||
        if !ip.is_valid() {
 | 
			
		||||
            return Err(NetworkFilterExtraction(format!(
 | 
			
		||||
                "Invalid IPv4 address or variable! {}",
 | 
			
		||||
                ip.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') {
 | 
			
		||||
@@ -169,15 +198,15 @@ impl NetworkFilter {
 | 
			
		||||
        })
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn lib2rest_process_arp_rule(n: &NetworkFilterRuleProtocolArp) -> NetworkSelectorARP {
 | 
			
		||||
    fn lib2rest_process_arp_rule(n: &NetworkFilterRuleProtocolArpXML) -> NetworkSelectorARP {
 | 
			
		||||
        NetworkSelectorARP {
 | 
			
		||||
            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(),
 | 
			
		||||
            arpsrcipaddr: n.arpsrcipaddr.as_ref().map(|v| v.into()),
 | 
			
		||||
            arpsrcipmask: n.arpsrcipmask,
 | 
			
		||||
            arpdstipaddr: n.arpdstipaddr.clone(),
 | 
			
		||||
            arpdstipaddr: n.arpdstipaddr.as_ref().map(|v| v.into()),
 | 
			
		||||
            arpdstipmask: n.arpdstipmask,
 | 
			
		||||
            comment: n.comment.clone(),
 | 
			
		||||
        }
 | 
			
		||||
@@ -391,6 +420,22 @@ impl NetworkFilter {
 | 
			
		||||
        })
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn rest2lib_process_arp_selector(
 | 
			
		||||
        selector: &NetworkSelectorARP,
 | 
			
		||||
    ) -> anyhow::Result<NetworkFilterRuleProtocolArpXML> {
 | 
			
		||||
        Ok(NetworkFilterRuleProtocolArpXML {
 | 
			
		||||
            srcmacaddr: extract_mac_address_or_var(&selector.srcmacaddr)?,
 | 
			
		||||
            srcmacmask: extract_mac_address_or_var(&selector.srcmacmask)?,
 | 
			
		||||
            dstmacaddr: extract_mac_address_or_var(&selector.dstmacaddr)?,
 | 
			
		||||
            dstmacmask: extract_mac_address_or_var(&selector.dstmacmask)?,
 | 
			
		||||
            arpsrcipaddr: extract_ipv4_or_var(&selector.arpsrcipaddr)?,
 | 
			
		||||
            arpsrcipmask: selector.arpsrcipmask,
 | 
			
		||||
            arpdstipaddr: extract_ipv4_or_var(&selector.arpdstipaddr)?,
 | 
			
		||||
            arpdstipmask: selector.arpdstipmask,
 | 
			
		||||
            comment: extract_nw_filter_comment(&selector.comment)?,
 | 
			
		||||
        })
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn rest2lib_process_rule(rule: &NetworkFilterRule) -> anyhow::Result<NetworkFilterRuleXML> {
 | 
			
		||||
        let mut rule_xml = NetworkFilterRuleXML {
 | 
			
		||||
            action: rule.action.to_xml(),
 | 
			
		||||
@@ -428,10 +473,20 @@ impl NetworkFilter {
 | 
			
		||||
                    })
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                NetworkFilterSelector::Arp(_) => todo!(),
 | 
			
		||||
                NetworkFilterSelector::Rarp(_) => todo!(),
 | 
			
		||||
                NetworkFilterSelector::Arp(a) => {
 | 
			
		||||
                    rule_xml
 | 
			
		||||
                        .arp_selectors
 | 
			
		||||
                        .push(Self::rest2lib_process_arp_selector(a)?);
 | 
			
		||||
                }
 | 
			
		||||
                NetworkFilterSelector::Rarp(a) => {
 | 
			
		||||
                    rule_xml
 | 
			
		||||
                        .rarp_selectors
 | 
			
		||||
                        .push(Self::rest2lib_process_arp_selector(a)?);
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                NetworkFilterSelector::IPv4(_) => todo!(),
 | 
			
		||||
                NetworkFilterSelector::IPv6(_) => todo!(),
 | 
			
		||||
 | 
			
		||||
                NetworkFilterSelector::TCP(_) => todo!(),
 | 
			
		||||
                NetworkFilterSelector::UDP(_) => todo!(),
 | 
			
		||||
                NetworkFilterSelector::SCTP(_) => todo!(),
 | 
			
		||||
@@ -608,19 +663,6 @@ impl Layer4State {
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(serde::Serialize, serde::Deserialize, Debug, Clone)]
 | 
			
		||||
pub struct NetworkFilterSelectorIP {
 | 
			
		||||
    srcmacaddr: Option<String>,
 | 
			
		||||
    srcmacmask: Option<String>,
 | 
			
		||||
    dstmacaddr: Option<String>,
 | 
			
		||||
    dstmacmask: Option<String>,
 | 
			
		||||
    srcipaddr: Option<String>,
 | 
			
		||||
    srcipmask: Option<u8>,
 | 
			
		||||
    dstipaddr: Option<String>,
 | 
			
		||||
    dstipmask: Option<u8>,
 | 
			
		||||
    comment: Option<String>,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(serde::Serialize, serde::Deserialize, Debug, Clone)]
 | 
			
		||||
pub struct NetworkSelectorMac {
 | 
			
		||||
    src_mac_addr: Option<NetworkFilterMacAddressOrVar>,
 | 
			
		||||
@@ -636,13 +678,26 @@ pub struct NetworkSelectorARP {
 | 
			
		||||
    srcmacmask: Option<NetworkFilterMacAddressOrVar>,
 | 
			
		||||
    dstmacaddr: Option<NetworkFilterMacAddressOrVar>,
 | 
			
		||||
    dstmacmask: Option<NetworkFilterMacAddressOrVar>,
 | 
			
		||||
    arpsrcipaddr: Option<String>,
 | 
			
		||||
    arpsrcipaddr: Option<NetworkFilterIPv4OrVar>,
 | 
			
		||||
    arpsrcipmask: Option<u8>,
 | 
			
		||||
    arpdstipaddr: Option<String>,
 | 
			
		||||
    arpdstipaddr: Option<NetworkFilterIPv4OrVar>,
 | 
			
		||||
    arpdstipmask: Option<u8>,
 | 
			
		||||
    comment: Option<String>,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(serde::Serialize, serde::Deserialize, Debug, Clone)]
 | 
			
		||||
pub struct NetworkFilterSelectorIP {
 | 
			
		||||
    srcmacaddr: Option<String>,
 | 
			
		||||
    srcmacmask: Option<String>,
 | 
			
		||||
    dstmacaddr: Option<String>,
 | 
			
		||||
    dstmacmask: Option<String>,
 | 
			
		||||
    srcipaddr: Option<String>,
 | 
			
		||||
    srcipmask: Option<u8>,
 | 
			
		||||
    dstipaddr: Option<String>,
 | 
			
		||||
    dstipmask: Option<u8>,
 | 
			
		||||
    comment: Option<String>,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(serde::Serialize, serde::Deserialize, Debug, Clone)]
 | 
			
		||||
pub struct NetworkSelectorLayer4<IPv> {
 | 
			
		||||
    srcmacaddr: Option<NetworkFilterMacAddressOrVar>,
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,5 @@
 | 
			
		||||
use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
 | 
			
		||||
use std::str::FromStr;
 | 
			
		||||
 | 
			
		||||
pub fn extract_ipv4(ip: IpAddr) -> Ipv4Addr {
 | 
			
		||||
    match ip {
 | 
			
		||||
@@ -18,16 +19,20 @@ pub fn extract_ipv6(ip: IpAddr) -> Ipv6Addr {
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub fn is_ipv4_address_valid<D: AsRef<str>>(ip: D) -> bool {
 | 
			
		||||
    Ipv4Addr::from_str(ip.as_ref()).is_ok()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub fn is_mac_address_valid<D: AsRef<str>>(mac: D) -> bool {
 | 
			
		||||
    lazy_regex::regex!("^([a-fA-F0-9]{2}[:-]){5}[a-fA-F0-9]{2}$").is_match(mac.as_ref())
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[cfg(test)]
 | 
			
		||||
mod tests {
 | 
			
		||||
    use crate::utils::net_utils::is_mac_address_valid;
 | 
			
		||||
    use crate::utils::net_utils::{is_ipv4_address_valid, is_mac_address_valid};
 | 
			
		||||
 | 
			
		||||
    #[test]
 | 
			
		||||
    fn mac_addresses() {
 | 
			
		||||
    fn test_is_mac_address_valid() {
 | 
			
		||||
        assert!(is_mac_address_valid("FF:FF:FF:FF:FF:FF"));
 | 
			
		||||
        assert!(is_mac_address_valid("02:42:a4:6e:f2:be"));
 | 
			
		||||
 | 
			
		||||
@@ -35,4 +40,14 @@ mod tests {
 | 
			
		||||
        assert!(!is_mac_address_valid("FF:FF:FF:FF:FF:FZ"));
 | 
			
		||||
        assert!(!is_mac_address_valid("FF:FF:FF:FF:FF:FF:FF"));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #[test]
 | 
			
		||||
    fn test_is_ipv4_address_valid() {
 | 
			
		||||
        assert!(is_ipv4_address_valid("10.0.0.1"));
 | 
			
		||||
        assert!(is_ipv4_address_valid("2.56.58.156"));
 | 
			
		||||
 | 
			
		||||
        assert!(!is_ipv4_address_valid("tata"));
 | 
			
		||||
        assert!(!is_ipv4_address_valid("1.25.25.288"));
 | 
			
		||||
        assert!(!is_ipv4_address_valid("5.5.5.5.5"));
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user