|
|
|
@ -5,7 +5,7 @@ use std::net::{Ipv4Addr, Ipv6Addr};
|
|
|
|
|
#[derive(serde::Serialize, serde::Deserialize, Debug)]
|
|
|
|
|
#[serde(rename = "filterref")]
|
|
|
|
|
pub struct NetworkFilterRefXML {
|
|
|
|
|
#[serde(rename(serialize = "@filter"))]
|
|
|
|
|
#[serde(rename = "@filter")]
|
|
|
|
|
pub filter: String,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -16,225 +16,114 @@ pub struct NetworkFilterRuleProtocolAll {}
|
|
|
|
|
#[derive(serde::Serialize, serde::Deserialize, Debug)]
|
|
|
|
|
#[serde(rename = "mac")]
|
|
|
|
|
pub struct NetworkFilterRuleProtocolMac {
|
|
|
|
|
#[serde(
|
|
|
|
|
rename(serialize = "@srcmacaddr"),
|
|
|
|
|
skip_serializing_if = "Option::is_none"
|
|
|
|
|
)]
|
|
|
|
|
#[serde(rename = "@srcmacaddr", skip_serializing_if = "Option::is_none")]
|
|
|
|
|
pub srcmacaddr: Option<String>,
|
|
|
|
|
#[serde(
|
|
|
|
|
rename(serialize = "@srcmacmask"),
|
|
|
|
|
skip_serializing_if = "Option::is_none"
|
|
|
|
|
)]
|
|
|
|
|
#[serde(rename = "@scmacmask", skip_serializing_if = "Option::is_none")]
|
|
|
|
|
pub srcmacmask: Option<String>,
|
|
|
|
|
#[serde(
|
|
|
|
|
rename(serialize = "@dstmacaddr"),
|
|
|
|
|
skip_serializing_if = "Option::is_none"
|
|
|
|
|
)]
|
|
|
|
|
#[serde(rename = "@dstmacaddr", skip_serializing_if = "Option::is_none")]
|
|
|
|
|
pub dstmacaddr: Option<String>,
|
|
|
|
|
#[serde(
|
|
|
|
|
rename(serialize = "@dstmacmask"),
|
|
|
|
|
skip_serializing_if = "Option::is_none"
|
|
|
|
|
)]
|
|
|
|
|
#[serde(rename = "@dstmacmask", skip_serializing_if = "Option::is_none")]
|
|
|
|
|
pub dstmacmask: Option<String>,
|
|
|
|
|
#[serde(
|
|
|
|
|
rename(serialize = "@comment"),
|
|
|
|
|
skip_serializing_if = "Option::is_none"
|
|
|
|
|
)]
|
|
|
|
|
#[serde(rename = "@comment", skip_serializing_if = "Option::is_none")]
|
|
|
|
|
pub comment: Option<String>,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[derive(serde::Serialize, serde::Deserialize, Debug)]
|
|
|
|
|
#[serde(rename = "arp")]
|
|
|
|
|
pub struct NetworkFilterRuleProtocolArpXML {
|
|
|
|
|
#[serde(
|
|
|
|
|
rename(serialize = "@srcmacaddr"),
|
|
|
|
|
skip_serializing_if = "Option::is_none"
|
|
|
|
|
)]
|
|
|
|
|
#[serde(rename = "@srcmacaddr", skip_serializing_if = "Option::is_none")]
|
|
|
|
|
pub srcmacaddr: Option<String>,
|
|
|
|
|
#[serde(
|
|
|
|
|
rename(serialize = "@srcmacmask"),
|
|
|
|
|
skip_serializing_if = "Option::is_none"
|
|
|
|
|
)]
|
|
|
|
|
#[serde(rename = "@srcmacmask", skip_serializing_if = "Option::is_none")]
|
|
|
|
|
pub srcmacmask: Option<String>,
|
|
|
|
|
#[serde(
|
|
|
|
|
rename(serialize = "@dstmacaddr"),
|
|
|
|
|
skip_serializing_if = "Option::is_none"
|
|
|
|
|
)]
|
|
|
|
|
#[serde(rename = "@dstmacaddr", skip_serializing_if = "Option::is_none")]
|
|
|
|
|
pub dstmacaddr: Option<String>,
|
|
|
|
|
#[serde(
|
|
|
|
|
rename(serialize = "@dstmacmask"),
|
|
|
|
|
skip_serializing_if = "Option::is_none"
|
|
|
|
|
)]
|
|
|
|
|
#[serde(rename = "@dstmacmask", skip_serializing_if = "Option::is_none")]
|
|
|
|
|
pub dstmacmask: Option<String>,
|
|
|
|
|
#[serde(
|
|
|
|
|
rename(serialize = "@arpsrcipaddr"),
|
|
|
|
|
skip_serializing_if = "Option::is_none"
|
|
|
|
|
)]
|
|
|
|
|
#[serde(rename = "@arpsrcipaddr", skip_serializing_if = "Option::is_none")]
|
|
|
|
|
pub arpsrcipaddr: Option<String>,
|
|
|
|
|
#[serde(
|
|
|
|
|
rename(serialize = "@arpsrcipmask"),
|
|
|
|
|
skip_serializing_if = "Option::is_none"
|
|
|
|
|
)]
|
|
|
|
|
#[serde(rename = "@arpsrcipmask", skip_serializing_if = "Option::is_none")]
|
|
|
|
|
pub arpsrcipmask: Option<u8>,
|
|
|
|
|
#[serde(
|
|
|
|
|
rename(serialize = "@arpdstipaddr"),
|
|
|
|
|
skip_serializing_if = "Option::is_none"
|
|
|
|
|
)]
|
|
|
|
|
#[serde(rename = "@arpdstipaddr", skip_serializing_if = "Option::is_none")]
|
|
|
|
|
pub arpdstipaddr: Option<String>,
|
|
|
|
|
#[serde(
|
|
|
|
|
rename(serialize = "@arpdstipmask"),
|
|
|
|
|
skip_serializing_if = "Option::is_none"
|
|
|
|
|
)]
|
|
|
|
|
#[serde(rename = "@arpdstipmask", skip_serializing_if = "Option::is_none")]
|
|
|
|
|
pub arpdstipmask: Option<u8>,
|
|
|
|
|
|
|
|
|
|
#[serde(
|
|
|
|
|
rename(serialize = "@comment"),
|
|
|
|
|
skip_serializing_if = "Option::is_none"
|
|
|
|
|
)]
|
|
|
|
|
#[serde(rename = "@comment", skip_serializing_if = "Option::is_none")]
|
|
|
|
|
pub comment: Option<String>,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[derive(serde::Serialize, serde::Deserialize, Debug)]
|
|
|
|
|
#[serde(rename = "ipvx")]
|
|
|
|
|
pub struct NetworkFilterRuleProtocolIpvx {
|
|
|
|
|
#[serde(
|
|
|
|
|
rename(serialize = "@srcmacaddr"),
|
|
|
|
|
skip_serializing_if = "Option::is_none"
|
|
|
|
|
)]
|
|
|
|
|
#[serde(rename = "@srcmacaddr", skip_serializing_if = "Option::is_none")]
|
|
|
|
|
pub srcmacaddr: Option<String>,
|
|
|
|
|
#[serde(
|
|
|
|
|
rename(serialize = "@srcmacmask"),
|
|
|
|
|
skip_serializing_if = "Option::is_none"
|
|
|
|
|
)]
|
|
|
|
|
#[serde(rename = "@srcmacmask", skip_serializing_if = "Option::is_none")]
|
|
|
|
|
pub srcmacmask: Option<String>,
|
|
|
|
|
#[serde(
|
|
|
|
|
rename(serialize = "@dstmacaddr"),
|
|
|
|
|
skip_serializing_if = "Option::is_none"
|
|
|
|
|
)]
|
|
|
|
|
#[serde(rename = "@dstmacaddr", skip_serializing_if = "Option::is_none")]
|
|
|
|
|
pub dstmacaddr: Option<String>,
|
|
|
|
|
#[serde(
|
|
|
|
|
rename(serialize = "@dstmacmask"),
|
|
|
|
|
skip_serializing_if = "Option::is_none"
|
|
|
|
|
)]
|
|
|
|
|
#[serde(rename = "@dstmacmask", skip_serializing_if = "Option::is_none")]
|
|
|
|
|
pub dstmacmask: Option<String>,
|
|
|
|
|
#[serde(
|
|
|
|
|
rename(serialize = "@srcipaddr"),
|
|
|
|
|
skip_serializing_if = "Option::is_none"
|
|
|
|
|
)]
|
|
|
|
|
#[serde(rename = "@srcipaddr", skip_serializing_if = "Option::is_none")]
|
|
|
|
|
pub srcipaddr: Option<String>,
|
|
|
|
|
#[serde(
|
|
|
|
|
rename(serialize = "@srcipmask"),
|
|
|
|
|
skip_serializing_if = "Option::is_none"
|
|
|
|
|
)]
|
|
|
|
|
#[serde(rename = "@srcipmask", skip_serializing_if = "Option::is_none")]
|
|
|
|
|
pub srcipmask: Option<u8>,
|
|
|
|
|
#[serde(
|
|
|
|
|
rename(serialize = "@dstipaddr"),
|
|
|
|
|
skip_serializing_if = "Option::is_none"
|
|
|
|
|
)]
|
|
|
|
|
#[serde(rename = "@dstipaddr", skip_serializing_if = "Option::is_none")]
|
|
|
|
|
pub dstipaddr: Option<String>,
|
|
|
|
|
#[serde(
|
|
|
|
|
rename(serialize = "@dstipmask"),
|
|
|
|
|
skip_serializing_if = "Option::is_none"
|
|
|
|
|
)]
|
|
|
|
|
#[serde(rename = "@dstipmask", skip_serializing_if = "Option::is_none")]
|
|
|
|
|
pub dstipmask: Option<u8>,
|
|
|
|
|
|
|
|
|
|
#[serde(
|
|
|
|
|
rename(serialize = "@comment"),
|
|
|
|
|
skip_serializing_if = "Option::is_none"
|
|
|
|
|
)]
|
|
|
|
|
#[serde(rename = "@comment", skip_serializing_if = "Option::is_none")]
|
|
|
|
|
pub comment: Option<String>,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[derive(serde::Serialize, serde::Deserialize, Debug)]
|
|
|
|
|
#[serde(rename = "layer4")]
|
|
|
|
|
pub struct NetworkFilterRuleProtocolLayer4<IPv> {
|
|
|
|
|
#[serde(
|
|
|
|
|
rename(serialize = "@srcmacaddr"),
|
|
|
|
|
skip_serializing_if = "Option::is_none"
|
|
|
|
|
)]
|
|
|
|
|
#[serde(rename = "@srcmacaddr", skip_serializing_if = "Option::is_none")]
|
|
|
|
|
pub srcmacaddr: Option<String>,
|
|
|
|
|
#[serde(
|
|
|
|
|
rename(serialize = "@srcipaddr"),
|
|
|
|
|
skip_serializing_if = "Option::is_none"
|
|
|
|
|
)]
|
|
|
|
|
#[serde(rename = "@srcipaddr", skip_serializing_if = "Option::is_none")]
|
|
|
|
|
pub srcipaddr: Option<IPv>,
|
|
|
|
|
#[serde(
|
|
|
|
|
rename(serialize = "@srcipmask"),
|
|
|
|
|
skip_serializing_if = "Option::is_none"
|
|
|
|
|
)]
|
|
|
|
|
#[serde(rename = "@srcipmask", skip_serializing_if = "Option::is_none")]
|
|
|
|
|
pub srcipmask: Option<u8>,
|
|
|
|
|
#[serde(
|
|
|
|
|
rename(serialize = "@dstipaddr"),
|
|
|
|
|
skip_serializing_if = "Option::is_none"
|
|
|
|
|
)]
|
|
|
|
|
#[serde(rename = "@dstipaddr", skip_serializing_if = "Option::is_none")]
|
|
|
|
|
pub dstipaddr: Option<IPv>,
|
|
|
|
|
#[serde(
|
|
|
|
|
rename(serialize = "@dstipmask"),
|
|
|
|
|
skip_serializing_if = "Option::is_none"
|
|
|
|
|
)]
|
|
|
|
|
#[serde(rename = "@dstipmask", skip_serializing_if = "Option::is_none")]
|
|
|
|
|
pub dstipmask: Option<u8>,
|
|
|
|
|
/// Start of range of source IP address
|
|
|
|
|
#[serde(
|
|
|
|
|
rename(serialize = "@srcipfrom"),
|
|
|
|
|
skip_serializing_if = "Option::is_none"
|
|
|
|
|
)]
|
|
|
|
|
#[serde(rename = "@srcipfrom", skip_serializing_if = "Option::is_none")]
|
|
|
|
|
pub srcipfrom: Option<IPv>,
|
|
|
|
|
/// End of range of source IP address
|
|
|
|
|
#[serde(
|
|
|
|
|
rename(serialize = "@srcipto"),
|
|
|
|
|
skip_serializing_if = "Option::is_none"
|
|
|
|
|
)]
|
|
|
|
|
#[serde(rename = "@srcipto", skip_serializing_if = "Option::is_none")]
|
|
|
|
|
pub srcipto: Option<IPv>,
|
|
|
|
|
/// Start of range of destination IP address
|
|
|
|
|
#[serde(
|
|
|
|
|
rename(serialize = "@dstipfrom"),
|
|
|
|
|
skip_serializing_if = "Option::is_none"
|
|
|
|
|
)]
|
|
|
|
|
#[serde(rename = "@dstipfrom", skip_serializing_if = "Option::is_none")]
|
|
|
|
|
pub dstipfrom: Option<IPv>,
|
|
|
|
|
/// End of range of destination IP address
|
|
|
|
|
#[serde(
|
|
|
|
|
rename(serialize = "@dstipto"),
|
|
|
|
|
skip_serializing_if = "Option::is_none"
|
|
|
|
|
)]
|
|
|
|
|
#[serde(rename = "@dstipto", skip_serializing_if = "Option::is_none")]
|
|
|
|
|
pub dstipto: Option<IPv>,
|
|
|
|
|
#[serde(
|
|
|
|
|
rename(serialize = "@srcportstart"),
|
|
|
|
|
skip_serializing_if = "Option::is_none"
|
|
|
|
|
)]
|
|
|
|
|
#[serde(rename = "@srcportstart", skip_serializing_if = "Option::is_none")]
|
|
|
|
|
pub srcportstart: Option<u16>,
|
|
|
|
|
#[serde(
|
|
|
|
|
rename(serialize = "@srcportend"),
|
|
|
|
|
skip_serializing_if = "Option::is_none"
|
|
|
|
|
)]
|
|
|
|
|
#[serde(rename = "@srcportend", skip_serializing_if = "Option::is_none")]
|
|
|
|
|
pub srcportend: Option<u16>,
|
|
|
|
|
#[serde(
|
|
|
|
|
rename(serialize = "@dstportstart"),
|
|
|
|
|
skip_serializing_if = "Option::is_none"
|
|
|
|
|
)]
|
|
|
|
|
#[serde(rename = "@dstportstart", skip_serializing_if = "Option::is_none")]
|
|
|
|
|
pub dstportstart: Option<u16>,
|
|
|
|
|
#[serde(
|
|
|
|
|
rename(serialize = "@dstportend"),
|
|
|
|
|
skip_serializing_if = "Option::is_none"
|
|
|
|
|
)]
|
|
|
|
|
#[serde(rename = "@dstportend", skip_serializing_if = "Option::is_none")]
|
|
|
|
|
pub dstportend: Option<u16>,
|
|
|
|
|
#[serde(rename(serialize = "@state"), skip_serializing_if = "Option::is_none")]
|
|
|
|
|
#[serde(rename = "@state", skip_serializing_if = "Option::is_none")]
|
|
|
|
|
pub state: Option<String>,
|
|
|
|
|
|
|
|
|
|
#[serde(
|
|
|
|
|
rename(serialize = "@comment"),
|
|
|
|
|
skip_serializing_if = "Option::is_none"
|
|
|
|
|
)]
|
|
|
|
|
#[serde(rename = "@comment", skip_serializing_if = "Option::is_none")]
|
|
|
|
|
pub comment: Option<String>,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[derive(serde::Serialize, serde::Deserialize, Debug, Default)]
|
|
|
|
|
#[serde(rename = "rule")]
|
|
|
|
|
pub struct NetworkFilterRuleXML {
|
|
|
|
|
#[serde(rename(serialize = "@action"))]
|
|
|
|
|
#[serde(rename = "@action")]
|
|
|
|
|
pub action: String,
|
|
|
|
|
#[serde(rename(serialize = "@direction"))]
|
|
|
|
|
#[serde(rename = "@direction")]
|
|
|
|
|
pub direction: String,
|
|
|
|
|
#[serde(rename(serialize = "@priority"))]
|
|
|
|
|
#[serde(rename = "@priority")]
|
|
|
|
|
pub priority: Option<i32>,
|
|
|
|
|
|
|
|
|
|
/// Match all protocols
|
|
|
|
@ -297,23 +186,15 @@ pub struct NetworkFilterRuleXML {
|
|
|
|
|
#[derive(serde::Serialize, serde::Deserialize, Debug)]
|
|
|
|
|
#[serde(rename = "filter")]
|
|
|
|
|
pub struct NetworkFilterXML {
|
|
|
|
|
#[serde(rename(serialize = "@name"))]
|
|
|
|
|
#[serde(rename = "@name")]
|
|
|
|
|
pub name: String,
|
|
|
|
|
#[serde(
|
|
|
|
|
rename(serialize = "@chain"),
|
|
|
|
|
skip_serializing_if = "Option::is_none",
|
|
|
|
|
default
|
|
|
|
|
)]
|
|
|
|
|
#[serde(rename = "@chain", skip_serializing_if = "Option::is_none", default)]
|
|
|
|
|
pub chain: Option<String>,
|
|
|
|
|
#[serde(
|
|
|
|
|
skip_serializing_if = "Option::is_none",
|
|
|
|
|
rename(serialize = "@priority"),
|
|
|
|
|
default
|
|
|
|
|
)]
|
|
|
|
|
#[serde(skip_serializing_if = "Option::is_none", rename = "@priority", default)]
|
|
|
|
|
pub priority: Option<i32>,
|
|
|
|
|
#[serde(skip_serializing_if = "Option::is_none")]
|
|
|
|
|
pub uuid: Option<XMLUuid>,
|
|
|
|
|
#[serde(default, rename = "filterref", skip_serializing_if = "Vec::is_empty")]
|
|
|
|
|
#[serde(default, rename = "filterref")]
|
|
|
|
|
pub filterrefs: Vec<NetworkFilterRefXML>,
|
|
|
|
|
#[serde(default, rename = "rule", skip_serializing_if = "Vec::is_empty")]
|
|
|
|
|
pub rules: Vec<NetworkFilterRuleXML>,
|
|
|
|
@ -321,24 +202,10 @@ pub struct NetworkFilterXML {
|
|
|
|
|
|
|
|
|
|
impl NetworkFilterXML {
|
|
|
|
|
pub fn parse_xml<D: Display>(xml: D) -> anyhow::Result<Self> {
|
|
|
|
|
let xml = xml.to_string();
|
|
|
|
|
Ok(quick_xml::de::from_str(&xml.to_string())?)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// We need to put all filter refs at the same location
|
|
|
|
|
let mut filter_refs = Vec::new();
|
|
|
|
|
let xml = lazy_regex::regex_replace_all!(r#"<filterref.*/>"#, &xml, |r: &str| {
|
|
|
|
|
filter_refs.push(r.to_string());
|
|
|
|
|
|
|
|
|
|
if r.contains('\n') {
|
|
|
|
|
log::warn!("A filterref contain a new line. This is a symptom of a new unsupported child attribute of <filterref /> object!");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
""
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
let filter_refs = filter_refs.join("\n");
|
|
|
|
|
let xml = xml.replace("</filter>", &format!("{filter_refs}</filter>"));
|
|
|
|
|
log::debug!("Effective NW filter rule parsed: {xml}");
|
|
|
|
|
|
|
|
|
|
Ok(serde_xml_rs::from_str(&xml)?)
|
|
|
|
|
pub fn into_xml(self) -> anyhow::Result<String> {
|
|
|
|
|
Ok(quick_xml::se::to_string(&self)?)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|