Add Layer4 selectors extraction
This commit is contained in:
		@@ -227,7 +227,7 @@ pub struct NetworkFilterRuleProtocolLayer4<IPv> {
 | 
			
		||||
    pub comment: Option<String>,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(serde::Serialize, serde::Deserialize, Debug)]
 | 
			
		||||
#[derive(serde::Serialize, serde::Deserialize, Debug, Default)]
 | 
			
		||||
#[serde(rename = "rule")]
 | 
			
		||||
pub struct NetworkFilterRuleXML {
 | 
			
		||||
    #[serde(rename(serialize = "@action"))]
 | 
			
		||||
@@ -275,7 +275,7 @@ pub struct NetworkFilterRuleXML {
 | 
			
		||||
 | 
			
		||||
    /// Match ICMP protocol
 | 
			
		||||
    #[serde(default, rename = "icmp", skip_serializing_if = "Vec::is_empty")]
 | 
			
		||||
    pub imcp_selectors: Vec<NetworkFilterRuleProtocolLayer4<Ipv4Addr>>,
 | 
			
		||||
    pub icmp_selectors: Vec<NetworkFilterRuleProtocolLayer4<Ipv4Addr>>,
 | 
			
		||||
 | 
			
		||||
    /// Match TCP IPv6 protocol
 | 
			
		||||
    #[serde(default, rename = "tcp-ipv6", skip_serializing_if = "Vec::is_empty")]
 | 
			
		||||
 
 | 
			
		||||
@@ -96,14 +96,14 @@ fn extract_ip_or_var<const V: usize>(
 | 
			
		||||
    Ok(n.as_ref().map(|n| n.0.to_string()))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn extract_ip_mask<const V: usize>(n: &Option<u8>) -> anyhow::Result<Option<u8>> {
 | 
			
		||||
fn extract_ip_mask<const V: usize>(n: Option<u8>) -> anyhow::Result<Option<u8>> {
 | 
			
		||||
    if let Some(mask) = n {
 | 
			
		||||
        if !net_utils::is_mask_valid(V, *mask) {
 | 
			
		||||
            return Err(NetworkFilterExtraction(format!("Invalid IPv{V} mask! {}", mask)).into());
 | 
			
		||||
        if !net_utils::is_mask_valid(V, mask) {
 | 
			
		||||
            return Err(NetworkFilterExtraction(format!("Invalid IPv{V} mask! {mask}")).into());
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    Ok(*n)
 | 
			
		||||
    Ok(n)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn extract_nw_filter_comment(n: &Option<String>) -> anyhow::Result<Option<String>> {
 | 
			
		||||
@@ -192,6 +192,211 @@ impl NetworkFilterChain {
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(serde::Serialize, serde::Deserialize, Debug, Copy, Clone)]
 | 
			
		||||
#[serde(rename_all = "lowercase")]
 | 
			
		||||
pub enum NetworkFilterAction {
 | 
			
		||||
    /// matching the rule silently discards the packet with no further analysis
 | 
			
		||||
    Drop,
 | 
			
		||||
    /// matching the rule generates an ICMP reject message with no further analysis
 | 
			
		||||
    Reject,
 | 
			
		||||
    /// matching the rule accepts the packet with no further analysis
 | 
			
		||||
    Accept,
 | 
			
		||||
    /// matching the rule passes this filter, but returns control to the calling filter for further
 | 
			
		||||
    /// analysis
 | 
			
		||||
    Return,
 | 
			
		||||
    /// matching the rule goes on to the next rule for further analysis
 | 
			
		||||
    Continue,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl NetworkFilterAction {
 | 
			
		||||
    pub fn from_xml(xml: &str) -> anyhow::Result<Self> {
 | 
			
		||||
        Ok(match xml {
 | 
			
		||||
            "drop" => Self::Drop,
 | 
			
		||||
            "reject" => Self::Reject,
 | 
			
		||||
            "accept" => Self::Accept,
 | 
			
		||||
            "return" => Self::Return,
 | 
			
		||||
            "continue" => Self::Continue,
 | 
			
		||||
            s => {
 | 
			
		||||
                return Err(LibVirtStructError::ParseFilteringChain(format!(
 | 
			
		||||
                    "Unkown filter action {s}!"
 | 
			
		||||
                ))
 | 
			
		||||
                .into());
 | 
			
		||||
            }
 | 
			
		||||
        })
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub fn to_xml(&self) -> String {
 | 
			
		||||
        match self {
 | 
			
		||||
            Self::Drop => "drop",
 | 
			
		||||
            Self::Reject => "reject",
 | 
			
		||||
            Self::Accept => "accept",
 | 
			
		||||
            Self::Return => "return",
 | 
			
		||||
            Self::Continue => "continue",
 | 
			
		||||
        }
 | 
			
		||||
        .to_string()
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(serde::Serialize, serde::Deserialize, Debug, Clone)]
 | 
			
		||||
#[serde(rename_all = "lowercase")]
 | 
			
		||||
pub enum NetworkFilterDirection {
 | 
			
		||||
    In,
 | 
			
		||||
    Out,
 | 
			
		||||
    InOut,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl NetworkFilterDirection {
 | 
			
		||||
    pub fn from_xml(xml: &str) -> anyhow::Result<Self> {
 | 
			
		||||
        Ok(match xml {
 | 
			
		||||
            "in" => Self::In,
 | 
			
		||||
            "out" => Self::Out,
 | 
			
		||||
            "inout" => Self::InOut,
 | 
			
		||||
            s => {
 | 
			
		||||
                return Err(LibVirtStructError::ParseFilteringChain(format!(
 | 
			
		||||
                    "Unkown filter direction {s}!"
 | 
			
		||||
                ))
 | 
			
		||||
                .into());
 | 
			
		||||
            }
 | 
			
		||||
        })
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub fn to_xml(&self) -> String {
 | 
			
		||||
        match self {
 | 
			
		||||
            NetworkFilterDirection::In => "in",
 | 
			
		||||
            NetworkFilterDirection::Out => "out",
 | 
			
		||||
            NetworkFilterDirection::InOut => "inout",
 | 
			
		||||
        }
 | 
			
		||||
        .to_string()
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(serde::Serialize, serde::Deserialize, Debug, Copy, Clone)]
 | 
			
		||||
pub enum Layer4State {
 | 
			
		||||
    NEW,
 | 
			
		||||
    ESTABLISHED,
 | 
			
		||||
    RELATED,
 | 
			
		||||
    INVALID,
 | 
			
		||||
    NONE,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl Layer4State {
 | 
			
		||||
    pub fn from_xml(xml: &str) -> anyhow::Result<Self> {
 | 
			
		||||
        Ok(match xml {
 | 
			
		||||
            "NEW" => Self::NEW,
 | 
			
		||||
            "ESTABLISHED" => Self::ESTABLISHED,
 | 
			
		||||
            "RELATED" => Self::RELATED,
 | 
			
		||||
            "INVALID" => Self::INVALID,
 | 
			
		||||
            "NONE" => Self::NONE,
 | 
			
		||||
            s => {
 | 
			
		||||
                return Err(LibVirtStructError::ParseFilteringChain(format!(
 | 
			
		||||
                    "Unkown layer4 state '{s}'!"
 | 
			
		||||
                ))
 | 
			
		||||
                .into());
 | 
			
		||||
            }
 | 
			
		||||
        })
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub fn to_xml(&self) -> String {
 | 
			
		||||
        match self {
 | 
			
		||||
            Self::NEW => "NEW",
 | 
			
		||||
            Self::ESTABLISHED => "ESTABLISHED",
 | 
			
		||||
            Self::RELATED => "RELATED",
 | 
			
		||||
            Self::INVALID => "INVALID",
 | 
			
		||||
            Self::NONE => "NONE",
 | 
			
		||||
        }
 | 
			
		||||
        .to_string()
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(serde::Serialize, serde::Deserialize, Debug, Clone)]
 | 
			
		||||
pub struct NetworkSelectorMac {
 | 
			
		||||
    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<NetworkFilterMacAddressOrVar>,
 | 
			
		||||
    srcmacmask: Option<NetworkFilterMacAddressOrVar>,
 | 
			
		||||
    dstmacaddr: Option<NetworkFilterMacAddressOrVar>,
 | 
			
		||||
    dstmacmask: Option<NetworkFilterMacAddressOrVar>,
 | 
			
		||||
    arpsrcipaddr: Option<NetworkFilterIPv4OrVar>,
 | 
			
		||||
    arpsrcipmask: Option<u8>,
 | 
			
		||||
    arpdstipaddr: Option<NetworkFilterIPv4OrVar>,
 | 
			
		||||
    arpdstipmask: Option<u8>,
 | 
			
		||||
    comment: Option<String>,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(serde::Serialize, serde::Deserialize, Debug, Clone)]
 | 
			
		||||
pub struct NetworkFilterSelectorIP<const V: usize> {
 | 
			
		||||
    srcmacaddr: Option<NetworkFilterMacAddressOrVar>,
 | 
			
		||||
    srcmacmask: Option<NetworkFilterMacAddressOrVar>,
 | 
			
		||||
    dstmacaddr: Option<NetworkFilterMacAddressOrVar>,
 | 
			
		||||
    dstmacmask: Option<NetworkFilterMacAddressOrVar>,
 | 
			
		||||
    srcipaddr: Option<NetworkFilterIPOrVar<V>>,
 | 
			
		||||
    srcipmask: Option<u8>,
 | 
			
		||||
    dstipaddr: Option<NetworkFilterIPOrVar<V>>,
 | 
			
		||||
    dstipmask: Option<u8>,
 | 
			
		||||
    comment: Option<String>,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(serde::Serialize, serde::Deserialize, Debug, Clone)]
 | 
			
		||||
pub struct NetworkFilterSelectorLayer4<IPv> {
 | 
			
		||||
    srcmacaddr: Option<NetworkFilterMacAddressOrVar>,
 | 
			
		||||
    srcipaddr: Option<IPv>,
 | 
			
		||||
    srcipmask: Option<u8>,
 | 
			
		||||
    dstipaddr: Option<IPv>,
 | 
			
		||||
    dstipmask: Option<u8>,
 | 
			
		||||
    /// Start of range of source IP address
 | 
			
		||||
    srcipfrom: Option<IPv>,
 | 
			
		||||
    /// End of range of source IP address
 | 
			
		||||
    srcipto: Option<IPv>,
 | 
			
		||||
    /// Start of range of destination IP address
 | 
			
		||||
    dstipfrom: Option<IPv>,
 | 
			
		||||
    /// End of range of destination IP address
 | 
			
		||||
    dstipto: Option<IPv>,
 | 
			
		||||
    srcportstart: Option<u16>,
 | 
			
		||||
    srcportend: Option<u16>,
 | 
			
		||||
    dstportstart: Option<u16>,
 | 
			
		||||
    dstportend: Option<u16>,
 | 
			
		||||
    state: Option<Layer4State>,
 | 
			
		||||
    comment: Option<String>,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(serde::Serialize, serde::Deserialize, Debug, Clone)]
 | 
			
		||||
#[serde(tag = "type", rename_all = "lowercase")]
 | 
			
		||||
pub enum NetworkFilterSelector {
 | 
			
		||||
    All,
 | 
			
		||||
    Mac(NetworkSelectorMac),
 | 
			
		||||
    Arp(NetworkSelectorARP),
 | 
			
		||||
    Rarp(NetworkSelectorARP),
 | 
			
		||||
    IPv4(NetworkFilterSelectorIP<4>),
 | 
			
		||||
    IPv6(NetworkFilterSelectorIP<6>),
 | 
			
		||||
    TCP(NetworkFilterSelectorLayer4<Ipv4Addr>),
 | 
			
		||||
    UDP(NetworkFilterSelectorLayer4<Ipv4Addr>),
 | 
			
		||||
    SCTP(NetworkFilterSelectorLayer4<Ipv4Addr>),
 | 
			
		||||
    ICMP(NetworkFilterSelectorLayer4<Ipv4Addr>),
 | 
			
		||||
    TCPipv6(NetworkFilterSelectorLayer4<Ipv6Addr>),
 | 
			
		||||
    UDPipv6(NetworkFilterSelectorLayer4<Ipv6Addr>),
 | 
			
		||||
    SCTPipv6(NetworkFilterSelectorLayer4<Ipv6Addr>),
 | 
			
		||||
    ICMPipv6(NetworkFilterSelectorLayer4<Ipv6Addr>),
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(serde::Serialize, serde::Deserialize, Debug, Clone)]
 | 
			
		||||
pub struct NetworkFilterRule {
 | 
			
		||||
    action: NetworkFilterAction,
 | 
			
		||||
    direction: NetworkFilterDirection,
 | 
			
		||||
    /// optional; the priority of the rule controls the order in which the rule will be instantiated
 | 
			
		||||
    /// relative to other rules
 | 
			
		||||
    ///
 | 
			
		||||
    /// Valid values are in the range of -1000 to 1000.
 | 
			
		||||
    priority: Option<i32>,
 | 
			
		||||
    selectors: Vec<NetworkFilterSelector>,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// Network filter definition
 | 
			
		||||
#[derive(serde::Serialize, serde::Deserialize, Debug, Clone)]
 | 
			
		||||
pub struct NetworkFilter {
 | 
			
		||||
@@ -251,8 +456,8 @@ impl NetworkFilter {
 | 
			
		||||
 | 
			
		||||
    fn lib2rest_process_layer4_rule<IPv: Copy>(
 | 
			
		||||
        n: &NetworkFilterRuleProtocolLayer4<IPv>,
 | 
			
		||||
    ) -> anyhow::Result<NetworkSelectorLayer4<IPv>> {
 | 
			
		||||
        Ok(NetworkSelectorLayer4 {
 | 
			
		||||
    ) -> anyhow::Result<NetworkFilterSelectorLayer4<IPv>> {
 | 
			
		||||
        Ok(NetworkFilterSelectorLayer4 {
 | 
			
		||||
            srcmacaddr: n.srcmacaddr.as_ref().map(|v| v.into()),
 | 
			
		||||
            srcipaddr: n.srcipaddr,
 | 
			
		||||
            srcipmask: n.srcipmask,
 | 
			
		||||
@@ -362,7 +567,7 @@ impl NetworkFilter {
 | 
			
		||||
            );
 | 
			
		||||
            selectors.append(
 | 
			
		||||
                &mut rule
 | 
			
		||||
                    .imcp_selectors
 | 
			
		||||
                    .icmp_selectors
 | 
			
		||||
                    .iter()
 | 
			
		||||
                    .map(|r| {
 | 
			
		||||
                        Ok(NetworkFilterSelector::ICMP(
 | 
			
		||||
@@ -468,9 +673,33 @@ impl NetworkFilter {
 | 
			
		||||
            dstmacaddr: extract_mac_address_or_var(&selector.dstmacaddr)?,
 | 
			
		||||
            dstmacmask: extract_mac_address_or_var(&selector.dstmacmask)?,
 | 
			
		||||
            srcipaddr: extract_ip_or_var(&selector.srcipaddr)?,
 | 
			
		||||
            srcipmask: extract_ip_mask::<V>(&selector.srcipmask)?,
 | 
			
		||||
            srcipmask: extract_ip_mask::<V>(selector.srcipmask)?,
 | 
			
		||||
            dstipaddr: extract_ip_or_var(&selector.dstipaddr)?,
 | 
			
		||||
            dstipmask: extract_ip_mask::<V>(&selector.dstipmask)?,
 | 
			
		||||
            dstipmask: extract_ip_mask::<V>(selector.dstipmask)?,
 | 
			
		||||
            comment: extract_nw_filter_comment(&selector.comment)?,
 | 
			
		||||
        })
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn rest2lib_process_layer4_selector<IPv: Copy>(
 | 
			
		||||
        selector: &NetworkFilterSelectorLayer4<IPv>,
 | 
			
		||||
    ) -> anyhow::Result<NetworkFilterRuleProtocolLayer4<IPv>> {
 | 
			
		||||
        Ok(NetworkFilterRuleProtocolLayer4 {
 | 
			
		||||
            srcmacaddr: extract_mac_address_or_var(&selector.srcmacaddr)?,
 | 
			
		||||
            srcipaddr: selector.srcipaddr,
 | 
			
		||||
            // This IP mask is not checked
 | 
			
		||||
            srcipmask: selector.srcipmask,
 | 
			
		||||
            dstipaddr: selector.dstipaddr,
 | 
			
		||||
            // This IP mask is not checked
 | 
			
		||||
            dstipmask: selector.dstipmask,
 | 
			
		||||
            srcipfrom: selector.srcipfrom,
 | 
			
		||||
            srcipto: selector.srcipto,
 | 
			
		||||
            dstipfrom: selector.dstipfrom,
 | 
			
		||||
            dstipto: selector.dstipto,
 | 
			
		||||
            srcportstart: selector.srcportstart,
 | 
			
		||||
            srcportend: selector.srcportend,
 | 
			
		||||
            dstportstart: selector.dstportstart,
 | 
			
		||||
            dstportend: selector.dstportend,
 | 
			
		||||
            state: selector.state.map(|s| s.to_xml()),
 | 
			
		||||
            comment: extract_nw_filter_comment(&selector.comment)?,
 | 
			
		||||
        })
 | 
			
		||||
    }
 | 
			
		||||
@@ -480,20 +709,7 @@ impl NetworkFilter {
 | 
			
		||||
            action: rule.action.to_xml(),
 | 
			
		||||
            direction: rule.direction.to_xml(),
 | 
			
		||||
            priority: rule.priority,
 | 
			
		||||
            all_selectors: vec![],
 | 
			
		||||
            mac_selectors: vec![],
 | 
			
		||||
            arp_selectors: vec![],
 | 
			
		||||
            rarp_selectors: vec![],
 | 
			
		||||
            ipv4_selectors: vec![],
 | 
			
		||||
            ipv6_selectors: vec![],
 | 
			
		||||
            tcp_selectors: vec![],
 | 
			
		||||
            udp_selectors: vec![],
 | 
			
		||||
            sctp_selectors: vec![],
 | 
			
		||||
            imcp_selectors: vec![],
 | 
			
		||||
            tcp_ipv6_selectors: vec![],
 | 
			
		||||
            udp_ipv6_selectors: vec![],
 | 
			
		||||
            sctp_ipv6_selectors: vec![],
 | 
			
		||||
            imcp_ipv6_selectors: vec![],
 | 
			
		||||
            ..Default::default()
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        for sel in &rule.selectors {
 | 
			
		||||
@@ -531,14 +747,37 @@ impl NetworkFilter {
 | 
			
		||||
                    .ipv6_selectors
 | 
			
		||||
                    .push(Self::rest2lib_process_ip_selector(ip)?),
 | 
			
		||||
 | 
			
		||||
                NetworkFilterSelector::TCP(_) => todo!(),
 | 
			
		||||
                NetworkFilterSelector::UDP(_) => todo!(),
 | 
			
		||||
                NetworkFilterSelector::SCTP(_) => todo!(),
 | 
			
		||||
                NetworkFilterSelector::ICMP(_) => todo!(),
 | 
			
		||||
                NetworkFilterSelector::TCPipv6(_) => todo!(),
 | 
			
		||||
                NetworkFilterSelector::UDPipv6(_) => todo!(),
 | 
			
		||||
                NetworkFilterSelector::SCTPipv6(_) => todo!(),
 | 
			
		||||
                NetworkFilterSelector::ICMPipv6(_) => todo!(),
 | 
			
		||||
                NetworkFilterSelector::TCP(tcp) => rule_xml
 | 
			
		||||
                    .tcp_selectors
 | 
			
		||||
                    .push(Self::rest2lib_process_layer4_selector(tcp)?),
 | 
			
		||||
 | 
			
		||||
                NetworkFilterSelector::UDP(udp) => rule_xml
 | 
			
		||||
                    .udp_selectors
 | 
			
		||||
                    .push(Self::rest2lib_process_layer4_selector(udp)?),
 | 
			
		||||
 | 
			
		||||
                NetworkFilterSelector::SCTP(sctp) => rule_xml
 | 
			
		||||
                    .sctp_selectors
 | 
			
		||||
                    .push(Self::rest2lib_process_layer4_selector(sctp)?),
 | 
			
		||||
 | 
			
		||||
                NetworkFilterSelector::ICMP(icmp) => rule_xml
 | 
			
		||||
                    .icmp_selectors
 | 
			
		||||
                    .push(Self::rest2lib_process_layer4_selector(icmp)?),
 | 
			
		||||
 | 
			
		||||
                NetworkFilterSelector::TCPipv6(tcpv6) => rule_xml
 | 
			
		||||
                    .tcp_ipv6_selectors
 | 
			
		||||
                    .push(Self::rest2lib_process_layer4_selector(tcpv6)?),
 | 
			
		||||
 | 
			
		||||
                NetworkFilterSelector::UDPipv6(udpv6) => rule_xml
 | 
			
		||||
                    .udp_ipv6_selectors
 | 
			
		||||
                    .push(Self::rest2lib_process_layer4_selector(udpv6)?),
 | 
			
		||||
 | 
			
		||||
                NetworkFilterSelector::SCTPipv6(sctpv6) => rule_xml
 | 
			
		||||
                    .sctp_ipv6_selectors
 | 
			
		||||
                    .push(Self::rest2lib_process_layer4_selector(sctpv6)?),
 | 
			
		||||
 | 
			
		||||
                NetworkFilterSelector::ICMPipv6(icmpv6) => rule_xml
 | 
			
		||||
                    .imcp_ipv6_selectors
 | 
			
		||||
                    .push(Self::rest2lib_process_layer4_selector(icmpv6)?),
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@@ -591,211 +830,6 @@ impl NetworkFilter {
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(serde::Serialize, serde::Deserialize, Debug, Copy, Clone)]
 | 
			
		||||
#[serde(rename_all = "lowercase")]
 | 
			
		||||
pub enum NetworkFilterAction {
 | 
			
		||||
    /// matching the rule silently discards the packet with no further analysis
 | 
			
		||||
    Drop,
 | 
			
		||||
    /// matching the rule generates an ICMP reject message with no further analysis
 | 
			
		||||
    Reject,
 | 
			
		||||
    /// matching the rule accepts the packet with no further analysis
 | 
			
		||||
    Accept,
 | 
			
		||||
    /// matching the rule passes this filter, but returns control to the calling filter for further
 | 
			
		||||
    /// analysis
 | 
			
		||||
    Return,
 | 
			
		||||
    /// matching the rule goes on to the next rule for further analysis
 | 
			
		||||
    Continue,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl NetworkFilterAction {
 | 
			
		||||
    pub fn from_xml(xml: &str) -> anyhow::Result<Self> {
 | 
			
		||||
        Ok(match xml {
 | 
			
		||||
            "drop" => Self::Drop,
 | 
			
		||||
            "reject" => Self::Reject,
 | 
			
		||||
            "accept" => Self::Accept,
 | 
			
		||||
            "return" => Self::Return,
 | 
			
		||||
            "continue" => Self::Continue,
 | 
			
		||||
            s => {
 | 
			
		||||
                return Err(LibVirtStructError::ParseFilteringChain(format!(
 | 
			
		||||
                    "Unkown filter action {s}!"
 | 
			
		||||
                ))
 | 
			
		||||
                .into());
 | 
			
		||||
            }
 | 
			
		||||
        })
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub fn to_xml(&self) -> String {
 | 
			
		||||
        match self {
 | 
			
		||||
            Self::Drop => "drop",
 | 
			
		||||
            Self::Reject => "reject",
 | 
			
		||||
            Self::Accept => "accept",
 | 
			
		||||
            Self::Return => "return",
 | 
			
		||||
            Self::Continue => "continue",
 | 
			
		||||
        }
 | 
			
		||||
        .to_string()
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(serde::Serialize, serde::Deserialize, Debug, Clone)]
 | 
			
		||||
#[serde(rename_all = "lowercase")]
 | 
			
		||||
pub enum NetworkFilterDirection {
 | 
			
		||||
    In,
 | 
			
		||||
    Out,
 | 
			
		||||
    InOut,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl NetworkFilterDirection {
 | 
			
		||||
    pub fn from_xml(xml: &str) -> anyhow::Result<Self> {
 | 
			
		||||
        Ok(match xml {
 | 
			
		||||
            "in" => Self::In,
 | 
			
		||||
            "out" => Self::Out,
 | 
			
		||||
            "inout" => Self::InOut,
 | 
			
		||||
            s => {
 | 
			
		||||
                return Err(LibVirtStructError::ParseFilteringChain(format!(
 | 
			
		||||
                    "Unkown filter direction {s}!"
 | 
			
		||||
                ))
 | 
			
		||||
                .into());
 | 
			
		||||
            }
 | 
			
		||||
        })
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub fn to_xml(&self) -> String {
 | 
			
		||||
        match self {
 | 
			
		||||
            NetworkFilterDirection::In => "in",
 | 
			
		||||
            NetworkFilterDirection::Out => "out",
 | 
			
		||||
            NetworkFilterDirection::InOut => "inout",
 | 
			
		||||
        }
 | 
			
		||||
        .to_string()
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(serde::Serialize, serde::Deserialize, Debug, Clone)]
 | 
			
		||||
pub enum Layer4State {
 | 
			
		||||
    NEW,
 | 
			
		||||
    ESTABLISHED,
 | 
			
		||||
    RELATED,
 | 
			
		||||
    INVALID,
 | 
			
		||||
    NONE,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl Layer4State {
 | 
			
		||||
    pub fn from_xml(xml: &str) -> anyhow::Result<Self> {
 | 
			
		||||
        Ok(match xml {
 | 
			
		||||
            "NEW" => Self::NEW,
 | 
			
		||||
            "ESTABLISHED" => Self::ESTABLISHED,
 | 
			
		||||
            "RELATED" => Self::RELATED,
 | 
			
		||||
            "INVALID" => Self::INVALID,
 | 
			
		||||
            "NONE" => Self::NONE,
 | 
			
		||||
            s => {
 | 
			
		||||
                return Err(LibVirtStructError::ParseFilteringChain(format!(
 | 
			
		||||
                    "Unkown layer4 state '{s}'!"
 | 
			
		||||
                ))
 | 
			
		||||
                .into());
 | 
			
		||||
            }
 | 
			
		||||
        })
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub fn to_xml(&self) -> String {
 | 
			
		||||
        match self {
 | 
			
		||||
            Self::NEW => "NEW",
 | 
			
		||||
            Self::ESTABLISHED => "ESTABLISHED",
 | 
			
		||||
            Self::RELATED => "RELATED",
 | 
			
		||||
            Self::INVALID => "INVALID",
 | 
			
		||||
            Self::NONE => "NONE",
 | 
			
		||||
        }
 | 
			
		||||
        .to_string()
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(serde::Serialize, serde::Deserialize, Debug, Clone)]
 | 
			
		||||
pub struct NetworkSelectorMac {
 | 
			
		||||
    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<NetworkFilterMacAddressOrVar>,
 | 
			
		||||
    srcmacmask: Option<NetworkFilterMacAddressOrVar>,
 | 
			
		||||
    dstmacaddr: Option<NetworkFilterMacAddressOrVar>,
 | 
			
		||||
    dstmacmask: Option<NetworkFilterMacAddressOrVar>,
 | 
			
		||||
    arpsrcipaddr: Option<NetworkFilterIPv4OrVar>,
 | 
			
		||||
    arpsrcipmask: Option<u8>,
 | 
			
		||||
    arpdstipaddr: Option<NetworkFilterIPv4OrVar>,
 | 
			
		||||
    arpdstipmask: Option<u8>,
 | 
			
		||||
    comment: Option<String>,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(serde::Serialize, serde::Deserialize, Debug, Clone)]
 | 
			
		||||
pub struct NetworkFilterSelectorIP<const V: usize> {
 | 
			
		||||
    srcmacaddr: Option<NetworkFilterMacAddressOrVar>,
 | 
			
		||||
    srcmacmask: Option<NetworkFilterMacAddressOrVar>,
 | 
			
		||||
    dstmacaddr: Option<NetworkFilterMacAddressOrVar>,
 | 
			
		||||
    dstmacmask: Option<NetworkFilterMacAddressOrVar>,
 | 
			
		||||
    srcipaddr: Option<NetworkFilterIPOrVar<V>>,
 | 
			
		||||
    srcipmask: Option<u8>,
 | 
			
		||||
    dstipaddr: Option<NetworkFilterIPOrVar<V>>,
 | 
			
		||||
    dstipmask: Option<u8>,
 | 
			
		||||
    comment: Option<String>,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(serde::Serialize, serde::Deserialize, Debug, Clone)]
 | 
			
		||||
pub struct NetworkSelectorLayer4<IPv> {
 | 
			
		||||
    srcmacaddr: Option<NetworkFilterMacAddressOrVar>,
 | 
			
		||||
    srcipaddr: Option<IPv>,
 | 
			
		||||
    srcipmask: Option<u8>,
 | 
			
		||||
    dstipaddr: Option<IPv>,
 | 
			
		||||
    dstipmask: Option<u8>,
 | 
			
		||||
    /// Start of range of source IP address
 | 
			
		||||
    srcipfrom: Option<IPv>,
 | 
			
		||||
    /// End of range of source IP address
 | 
			
		||||
    srcipto: Option<IPv>,
 | 
			
		||||
    /// Start of range of destination IP address
 | 
			
		||||
    dstipfrom: Option<IPv>,
 | 
			
		||||
    /// End of range of destination IP address
 | 
			
		||||
    dstipto: Option<IPv>,
 | 
			
		||||
    srcportstart: Option<u16>,
 | 
			
		||||
    srcportend: Option<u16>,
 | 
			
		||||
    dstportstart: Option<u16>,
 | 
			
		||||
    dstportend: Option<u16>,
 | 
			
		||||
    state: Option<Layer4State>,
 | 
			
		||||
    comment: Option<String>,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(serde::Serialize, serde::Deserialize, Debug, Clone)]
 | 
			
		||||
#[serde(tag = "type", rename_all = "lowercase")]
 | 
			
		||||
pub enum NetworkFilterSelector {
 | 
			
		||||
    All,
 | 
			
		||||
    Mac(NetworkSelectorMac),
 | 
			
		||||
    Arp(NetworkSelectorARP),
 | 
			
		||||
    Rarp(NetworkSelectorARP),
 | 
			
		||||
    IPv4(NetworkFilterSelectorIP<4>),
 | 
			
		||||
    IPv6(NetworkFilterSelectorIP<6>),
 | 
			
		||||
    TCP(NetworkSelectorLayer4<Ipv4Addr>),
 | 
			
		||||
    UDP(NetworkSelectorLayer4<Ipv4Addr>),
 | 
			
		||||
    SCTP(NetworkSelectorLayer4<Ipv4Addr>),
 | 
			
		||||
    ICMP(NetworkSelectorLayer4<Ipv4Addr>),
 | 
			
		||||
    TCPipv6(NetworkSelectorLayer4<Ipv6Addr>),
 | 
			
		||||
    UDPipv6(NetworkSelectorLayer4<Ipv6Addr>),
 | 
			
		||||
    SCTPipv6(NetworkSelectorLayer4<Ipv6Addr>),
 | 
			
		||||
    ICMPipv6(NetworkSelectorLayer4<Ipv6Addr>),
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(serde::Serialize, serde::Deserialize, Debug, Clone)]
 | 
			
		||||
pub struct NetworkFilterRule {
 | 
			
		||||
    action: NetworkFilterAction,
 | 
			
		||||
    direction: NetworkFilterDirection,
 | 
			
		||||
    /// optional; the priority of the rule controls the order in which the rule will be instantiated
 | 
			
		||||
    /// relative to other rules
 | 
			
		||||
    ///
 | 
			
		||||
    /// Valid values are in the range of -1000 to 1000.
 | 
			
		||||
    priority: Option<i32>,
 | 
			
		||||
    selectors: Vec<NetworkFilterSelector>,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[cfg(test)]
 | 
			
		||||
mod test {
 | 
			
		||||
    use crate::libvirt_rest_structures::nw_filter::is_var_def;
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user