Add IPv4 / IPv6 selectors extraction
This commit is contained in:
		@@ -57,25 +57,36 @@ fn extract_mac_address_or_var(
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#[derive(serde::Serialize, serde::Deserialize, Debug, Clone)]
 | 
					#[derive(serde::Serialize, serde::Deserialize, Debug, Clone)]
 | 
				
			||||||
pub struct NetworkFilterIPv4OrVar(pub String);
 | 
					pub struct NetworkFilterIPOrVar<const V: usize>(pub String);
 | 
				
			||||||
 | 
					pub type NetworkFilterIPv4OrVar = NetworkFilterIPOrVar<4>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl NetworkFilterIPv4OrVar {
 | 
					impl<const V: usize> NetworkFilterIPOrVar<V> {
 | 
				
			||||||
    pub fn is_valid(&self) -> bool {
 | 
					    pub fn is_valid(&self) -> bool {
 | 
				
			||||||
        is_var_def(&self.0) || net_utils::is_ipv4_address_valid(&self.0)
 | 
					        is_var_def(&self.0)
 | 
				
			||||||
 | 
					            || match V {
 | 
				
			||||||
 | 
					                4 => net_utils::is_ipv4_address_valid(&self.0),
 | 
				
			||||||
 | 
					                6 => net_utils::is_ipv6_address_valid(&self.0),
 | 
				
			||||||
 | 
					                _ => panic!("Unsupported IP version!"),
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl From<&String> for NetworkFilterIPv4OrVar {
 | 
					impl<const V: usize> From<&String> for NetworkFilterIPOrVar<V> {
 | 
				
			||||||
    fn from(value: &String) -> Self {
 | 
					    fn from(value: &String) -> Self {
 | 
				
			||||||
 | 
					        if V != 4 && V != 6 {
 | 
				
			||||||
 | 
					            panic!("Unsupported IP version!");
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
        Self(value.to_string())
 | 
					        Self(value.to_string())
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
fn extract_ipv4_or_var(n: &Option<NetworkFilterIPv4OrVar>) -> anyhow::Result<Option<String>> {
 | 
					fn extract_ip_or_var<const V: usize>(
 | 
				
			||||||
 | 
					    n: &Option<NetworkFilterIPOrVar<V>>,
 | 
				
			||||||
 | 
					) -> anyhow::Result<Option<String>> {
 | 
				
			||||||
    if let Some(ip) = n {
 | 
					    if let Some(ip) = n {
 | 
				
			||||||
        if !ip.is_valid() {
 | 
					        if !ip.is_valid() {
 | 
				
			||||||
            return Err(NetworkFilterExtraction(format!(
 | 
					            return Err(NetworkFilterExtraction(format!(
 | 
				
			||||||
                "Invalid IPv4 address or variable! {}",
 | 
					                "Invalid IPv{V} address or variable! {}",
 | 
				
			||||||
                ip.0
 | 
					                ip.0
 | 
				
			||||||
            ))
 | 
					            ))
 | 
				
			||||||
            .into());
 | 
					            .into());
 | 
				
			||||||
@@ -85,6 +96,16 @@ fn extract_ipv4_or_var(n: &Option<NetworkFilterIPv4OrVar>) -> anyhow::Result<Opt
 | 
				
			|||||||
    Ok(n.as_ref().map(|n| n.0.to_string()))
 | 
					    Ok(n.as_ref().map(|n| n.0.to_string()))
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					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());
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Ok(*n)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
fn extract_nw_filter_comment(n: &Option<String>) -> anyhow::Result<Option<String>> {
 | 
					fn extract_nw_filter_comment(n: &Option<String>) -> anyhow::Result<Option<String>> {
 | 
				
			||||||
    if let Some(comment) = n {
 | 
					    if let Some(comment) = n {
 | 
				
			||||||
        if comment.len() > 256 || comment.contains('\"') || comment.contains('\n') {
 | 
					        if comment.len() > 256 || comment.contains('\"') || comment.contains('\n') {
 | 
				
			||||||
@@ -212,15 +233,17 @@ impl NetworkFilter {
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fn lib2rest_process_ip_rule(n: &NetworkFilterRuleProtocolIpvx) -> NetworkFilterSelectorIP {
 | 
					    fn lib2rest_process_ip_rule<const V: usize>(
 | 
				
			||||||
 | 
					        n: &NetworkFilterRuleProtocolIpvx,
 | 
				
			||||||
 | 
					    ) -> NetworkFilterSelectorIP<V> {
 | 
				
			||||||
        NetworkFilterSelectorIP {
 | 
					        NetworkFilterSelectorIP {
 | 
				
			||||||
            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()),
 | 
				
			||||||
            srcipaddr: n.srcipaddr.clone(),
 | 
					            srcipaddr: n.srcipaddr.as_ref().map(|v| v.into()),
 | 
				
			||||||
            srcipmask: n.srcipmask,
 | 
					            srcipmask: n.srcipmask,
 | 
				
			||||||
            dstipaddr: n.dstipaddr.clone(),
 | 
					            dstipaddr: n.dstipaddr.as_ref().map(|v| v.into()),
 | 
				
			||||||
            dstipmask: n.dstipmask,
 | 
					            dstipmask: n.dstipmask,
 | 
				
			||||||
            comment: n.comment.clone(),
 | 
					            comment: n.comment.clone(),
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@@ -428,14 +451,30 @@ impl NetworkFilter {
 | 
				
			|||||||
            srcmacmask: extract_mac_address_or_var(&selector.srcmacmask)?,
 | 
					            srcmacmask: extract_mac_address_or_var(&selector.srcmacmask)?,
 | 
				
			||||||
            dstmacaddr: extract_mac_address_or_var(&selector.dstmacaddr)?,
 | 
					            dstmacaddr: extract_mac_address_or_var(&selector.dstmacaddr)?,
 | 
				
			||||||
            dstmacmask: extract_mac_address_or_var(&selector.dstmacmask)?,
 | 
					            dstmacmask: extract_mac_address_or_var(&selector.dstmacmask)?,
 | 
				
			||||||
            arpsrcipaddr: extract_ipv4_or_var(&selector.arpsrcipaddr)?,
 | 
					            arpsrcipaddr: extract_ip_or_var(&selector.arpsrcipaddr)?,
 | 
				
			||||||
            arpsrcipmask: selector.arpsrcipmask,
 | 
					            arpsrcipmask: selector.arpsrcipmask,
 | 
				
			||||||
            arpdstipaddr: extract_ipv4_or_var(&selector.arpdstipaddr)?,
 | 
					            arpdstipaddr: extract_ip_or_var(&selector.arpdstipaddr)?,
 | 
				
			||||||
            arpdstipmask: selector.arpdstipmask,
 | 
					            arpdstipmask: selector.arpdstipmask,
 | 
				
			||||||
            comment: extract_nw_filter_comment(&selector.comment)?,
 | 
					            comment: extract_nw_filter_comment(&selector.comment)?,
 | 
				
			||||||
        })
 | 
					        })
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    fn rest2lib_process_ip_selector<const V: usize>(
 | 
				
			||||||
 | 
					        selector: &NetworkFilterSelectorIP<V>,
 | 
				
			||||||
 | 
					    ) -> anyhow::Result<NetworkFilterRuleProtocolIpvx> {
 | 
				
			||||||
 | 
					        Ok(NetworkFilterRuleProtocolIpvx {
 | 
				
			||||||
 | 
					            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)?,
 | 
				
			||||||
 | 
					            srcipaddr: extract_ip_or_var(&selector.srcipaddr)?,
 | 
				
			||||||
 | 
					            srcipmask: extract_ip_mask::<V>(&selector.srcipmask)?,
 | 
				
			||||||
 | 
					            dstipaddr: extract_ip_or_var(&selector.dstipaddr)?,
 | 
				
			||||||
 | 
					            dstipmask: extract_ip_mask::<V>(&selector.dstipmask)?,
 | 
				
			||||||
 | 
					            comment: extract_nw_filter_comment(&selector.comment)?,
 | 
				
			||||||
 | 
					        })
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fn rest2lib_process_rule(rule: &NetworkFilterRule) -> anyhow::Result<NetworkFilterRuleXML> {
 | 
					    fn rest2lib_process_rule(rule: &NetworkFilterRule) -> anyhow::Result<NetworkFilterRuleXML> {
 | 
				
			||||||
        let mut rule_xml = NetworkFilterRuleXML {
 | 
					        let mut rule_xml = NetworkFilterRuleXML {
 | 
				
			||||||
            action: rule.action.to_xml(),
 | 
					            action: rule.action.to_xml(),
 | 
				
			||||||
@@ -484,8 +523,13 @@ impl NetworkFilter {
 | 
				
			|||||||
                        .push(Self::rest2lib_process_arp_selector(a)?);
 | 
					                        .push(Self::rest2lib_process_arp_selector(a)?);
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                NetworkFilterSelector::IPv4(_) => todo!(),
 | 
					                NetworkFilterSelector::IPv4(ip) => rule_xml
 | 
				
			||||||
                NetworkFilterSelector::IPv6(_) => todo!(),
 | 
					                    .ipv4_selectors
 | 
				
			||||||
 | 
					                    .push(Self::rest2lib_process_ip_selector(ip)?),
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                NetworkFilterSelector::IPv6(ip) => rule_xml
 | 
				
			||||||
 | 
					                    .ipv6_selectors
 | 
				
			||||||
 | 
					                    .push(Self::rest2lib_process_ip_selector(ip)?),
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                NetworkFilterSelector::TCP(_) => todo!(),
 | 
					                NetworkFilterSelector::TCP(_) => todo!(),
 | 
				
			||||||
                NetworkFilterSelector::UDP(_) => todo!(),
 | 
					                NetworkFilterSelector::UDP(_) => todo!(),
 | 
				
			||||||
@@ -686,14 +730,14 @@ pub struct NetworkSelectorARP {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#[derive(serde::Serialize, serde::Deserialize, Debug, Clone)]
 | 
					#[derive(serde::Serialize, serde::Deserialize, Debug, Clone)]
 | 
				
			||||||
pub struct NetworkFilterSelectorIP {
 | 
					pub struct NetworkFilterSelectorIP<const V: usize> {
 | 
				
			||||||
    srcmacaddr: Option<String>,
 | 
					    srcmacaddr: Option<NetworkFilterMacAddressOrVar>,
 | 
				
			||||||
    srcmacmask: Option<String>,
 | 
					    srcmacmask: Option<NetworkFilterMacAddressOrVar>,
 | 
				
			||||||
    dstmacaddr: Option<String>,
 | 
					    dstmacaddr: Option<NetworkFilterMacAddressOrVar>,
 | 
				
			||||||
    dstmacmask: Option<String>,
 | 
					    dstmacmask: Option<NetworkFilterMacAddressOrVar>,
 | 
				
			||||||
    srcipaddr: Option<String>,
 | 
					    srcipaddr: Option<NetworkFilterIPOrVar<V>>,
 | 
				
			||||||
    srcipmask: Option<u8>,
 | 
					    srcipmask: Option<u8>,
 | 
				
			||||||
    dstipaddr: Option<String>,
 | 
					    dstipaddr: Option<NetworkFilterIPOrVar<V>>,
 | 
				
			||||||
    dstipmask: Option<u8>,
 | 
					    dstipmask: Option<u8>,
 | 
				
			||||||
    comment: Option<String>,
 | 
					    comment: Option<String>,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -728,8 +772,8 @@ pub enum NetworkFilterSelector {
 | 
				
			|||||||
    Mac(NetworkSelectorMac),
 | 
					    Mac(NetworkSelectorMac),
 | 
				
			||||||
    Arp(NetworkSelectorARP),
 | 
					    Arp(NetworkSelectorARP),
 | 
				
			||||||
    Rarp(NetworkSelectorARP),
 | 
					    Rarp(NetworkSelectorARP),
 | 
				
			||||||
    IPv4(NetworkFilterSelectorIP),
 | 
					    IPv4(NetworkFilterSelectorIP<4>),
 | 
				
			||||||
    IPv6(NetworkFilterSelectorIP),
 | 
					    IPv6(NetworkFilterSelectorIP<6>),
 | 
				
			||||||
    TCP(NetworkSelectorLayer4<Ipv4Addr>),
 | 
					    TCP(NetworkSelectorLayer4<Ipv4Addr>),
 | 
				
			||||||
    UDP(NetworkSelectorLayer4<Ipv4Addr>),
 | 
					    UDP(NetworkSelectorLayer4<Ipv4Addr>),
 | 
				
			||||||
    SCTP(NetworkSelectorLayer4<Ipv4Addr>),
 | 
					    SCTP(NetworkSelectorLayer4<Ipv4Addr>),
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -23,13 +23,35 @@ pub fn is_ipv4_address_valid<D: AsRef<str>>(ip: D) -> bool {
 | 
				
			|||||||
    Ipv4Addr::from_str(ip.as_ref()).is_ok()
 | 
					    Ipv4Addr::from_str(ip.as_ref()).is_ok()
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					pub fn is_ipv6_address_valid<D: AsRef<str>>(ip: D) -> bool {
 | 
				
			||||||
 | 
					    Ipv6Addr::from_str(ip.as_ref()).is_ok()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					pub fn is_ipv4_mask_valid(mask: u8) -> bool {
 | 
				
			||||||
 | 
					    mask <= 32
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					pub fn is_ipv6_mask_valid(mask: u8) -> bool {
 | 
				
			||||||
 | 
					    mask <= 64
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					pub fn is_mask_valid(ipv: usize, mask: u8) -> bool {
 | 
				
			||||||
 | 
					    match ipv {
 | 
				
			||||||
 | 
					        4 => is_ipv4_mask_valid(mask),
 | 
				
			||||||
 | 
					        6 => is_ipv6_mask_valid(mask),
 | 
				
			||||||
 | 
					        _ => panic!("Unsupported IP version"),
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub fn is_mac_address_valid<D: AsRef<str>>(mac: D) -> bool {
 | 
					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())
 | 
					    lazy_regex::regex!("^([a-fA-F0-9]{2}[:-]){5}[a-fA-F0-9]{2}$").is_match(mac.as_ref())
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#[cfg(test)]
 | 
					#[cfg(test)]
 | 
				
			||||||
mod tests {
 | 
					mod tests {
 | 
				
			||||||
    use crate::utils::net_utils::{is_ipv4_address_valid, is_mac_address_valid};
 | 
					    use crate::utils::net_utils::{
 | 
				
			||||||
 | 
					        is_ipv4_address_valid, is_ipv6_address_valid, is_mac_address_valid, is_mask_valid,
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    #[test]
 | 
					    #[test]
 | 
				
			||||||
    fn test_is_mac_address_valid() {
 | 
					    fn test_is_mac_address_valid() {
 | 
				
			||||||
@@ -49,5 +71,28 @@ mod tests {
 | 
				
			|||||||
        assert!(!is_ipv4_address_valid("tata"));
 | 
					        assert!(!is_ipv4_address_valid("tata"));
 | 
				
			||||||
        assert!(!is_ipv4_address_valid("1.25.25.288"));
 | 
					        assert!(!is_ipv4_address_valid("1.25.25.288"));
 | 
				
			||||||
        assert!(!is_ipv4_address_valid("5.5.5.5.5"));
 | 
					        assert!(!is_ipv4_address_valid("5.5.5.5.5"));
 | 
				
			||||||
 | 
					        assert!(!is_ipv4_address_valid("fe80::"));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    #[test]
 | 
				
			||||||
 | 
					    fn test_is_ipv6_address_valid() {
 | 
				
			||||||
 | 
					        assert!(is_ipv6_address_valid("fe80::"));
 | 
				
			||||||
 | 
					        assert!(is_ipv6_address_valid("fe80:dd::"));
 | 
				
			||||||
 | 
					        assert!(is_ipv6_address_valid("00:00:00:00:00::"));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        assert!(!is_ipv6_address_valid("tata"));
 | 
				
			||||||
 | 
					        assert!(!is_ipv6_address_valid("2.56.58.156"));
 | 
				
			||||||
 | 
					        assert!(!is_ipv6_address_valid("fe::dd::dd"));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    #[test]
 | 
				
			||||||
 | 
					    fn test_is_mask_valid() {
 | 
				
			||||||
 | 
					        assert!(is_mask_valid(4, 25));
 | 
				
			||||||
 | 
					        assert!(is_mask_valid(4, 32));
 | 
				
			||||||
 | 
					        assert!(is_mask_valid(6, 32));
 | 
				
			||||||
 | 
					        assert!(is_mask_valid(6, 34));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        assert!(!is_mask_valid(4, 34));
 | 
				
			||||||
 | 
					        assert!(!is_mask_valid(6, 69));
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user