[pve-devel] [PATCH proxmox-firewall 20/37] nftables: expression: implement conversion traits for firewall config

Stefan Hanreich s.hanreich at proxmox.com
Tue Apr 2 19:16:12 CEST 2024


Some types from the firewall configuration map directly onto nftables
expressions. For those we implement conversion traits so we can
conveniently convert between the configuration types and the
respective nftables types.

Those are guarded behind a feature so the nftables crate can be used
standalone without having to pull in the proxmox-ve-config crate.

Co-authored-by: Wolfgang Bumiller <w.bumiller at proxmox.com>
Signed-off-by: Stefan Hanreich <s.hanreich at proxmox.com>
---
 proxmox-nftables/Cargo.toml        |   5 +-
 proxmox-nftables/src/expression.rs | 124 +++++++++++++++++++++++++++--
 2 files changed, 123 insertions(+), 6 deletions(-)

diff --git a/proxmox-nftables/Cargo.toml b/proxmox-nftables/Cargo.toml
index 909869b..7e607e8 100644
--- a/proxmox-nftables/Cargo.toml
+++ b/proxmox-nftables/Cargo.toml
@@ -10,6 +10,9 @@ authors = [
 description = "Proxmox VE nftables"
 license = "AGPL-3"
 
+[features]
+config-ext = ["dep:proxmox-ve-config"]
+
 [dependencies]
 log = "0.4"
 
@@ -17,4 +20,4 @@ serde = { version = "1", features = [ "derive" ] }
 serde_json = "1"
 serde_plain = "1"
 
-proxmox-ve-config = { path = "../proxmox-ve-config" }
+proxmox-ve-config = { path = "../proxmox-ve-config", optional = true }
diff --git a/proxmox-nftables/src/expression.rs b/proxmox-nftables/src/expression.rs
index da6e40f..067eccc 100644
--- a/proxmox-nftables/src/expression.rs
+++ b/proxmox-nftables/src/expression.rs
@@ -4,6 +4,15 @@ use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
 
 use crate::helper::NfVec;
 
+#[cfg(feature = "config-ext")]
+use proxmox_ve_config::firewall::types::address::{Family, IpEntry, IpList};
+#[cfg(feature = "config-ext")]
+use proxmox_ve_config::firewall::types::port::{PortEntry, PortList};
+#[cfg(feature = "config-ext")]
+use proxmox_ve_config::firewall::types::rule_match::{IcmpCode, IcmpType, Icmpv6Code, Icmpv6Type};
+#[cfg(feature = "config-ext")]
+use proxmox_ve_config::firewall::types::Cidr;
+
 #[derive(Clone, Debug, Deserialize, Serialize)]
 #[serde(rename_all = "lowercase")]
 pub enum Expression {
@@ -147,11 +156,88 @@ impl From<&Ipv4Addr> for Expression {
     }
 }
 
-#[derive(Clone, Copy, Debug, Eq, PartialEq, Deserialize, Serialize)]
-#[serde(rename_all = "lowercase")]
-pub enum IpFamily {
-    Ip,
-    Ip6,
+#[cfg(feature = "config-ext")]
+impl From<&IpList> for Expression {
+    fn from(value: &IpList) -> Self {
+        if value.len() == 1 {
+            return Expression::from(value.first().unwrap());
+        }
+
+        Expression::set(value.iter().map(Expression::from))
+    }
+}
+
+#[cfg(feature = "config-ext")]
+impl From<&IpEntry> for Expression {
+    fn from(value: &IpEntry) -> Self {
+        match value {
+            IpEntry::Cidr(cidr) => Expression::from(Prefix::from(cidr)),
+            IpEntry::Range(beg, end) => Expression::Range(Box::new((beg.into(), end.into()))),
+        }
+    }
+}
+
+#[cfg(feature = "config-ext")]
+impl From<&IcmpType> for Expression {
+    fn from(value: &IcmpType) -> Self {
+        match value {
+            IcmpType::Numeric(id) => Expression::from(*id),
+            IcmpType::Named(name) => Expression::from(*name),
+        }
+    }
+}
+
+#[cfg(feature = "config-ext")]
+impl From<&IcmpCode> for Expression {
+    fn from(value: &IcmpCode) -> Self {
+        match value {
+            IcmpCode::Numeric(id) => Expression::from(*id),
+            IcmpCode::Named(name) => Expression::from(*name),
+        }
+    }
+}
+
+#[cfg(feature = "config-ext")]
+impl From<&Icmpv6Type> for Expression {
+    fn from(value: &Icmpv6Type) -> Self {
+        match value {
+            Icmpv6Type::Numeric(id) => Expression::from(*id),
+            Icmpv6Type::Named(name) => Expression::from(*name),
+        }
+    }
+}
+
+#[cfg(feature = "config-ext")]
+impl From<&Icmpv6Code> for Expression {
+    fn from(value: &Icmpv6Code) -> Self {
+        match value {
+            Icmpv6Code::Numeric(id) => Expression::from(*id),
+            Icmpv6Code::Named(name) => Expression::from(*name),
+        }
+    }
+}
+
+#[cfg(feature = "config-ext")]
+impl From<&PortEntry> for Expression {
+    fn from(value: &PortEntry) -> Self {
+        match value {
+            PortEntry::Port(port) => Expression::from(*port),
+            PortEntry::Range(beg, end) => {
+                Expression::Range(Box::new(((*beg).into(), (*end).into())))
+            }
+        }
+    }
+}
+
+#[cfg(feature = "config-ext")]
+impl From<&PortList> for Expression {
+    fn from(value: &PortList) -> Self {
+        if value.len() == 1 {
+            return Expression::from(value.first().unwrap());
+        }
+
+        Expression::set(value.iter().map(Expression::from))
+    }
 }
 
 #[derive(Clone, Debug, Deserialize, Serialize)]
@@ -197,6 +283,24 @@ pub enum CtDirection {
     Reply,
 }
 serde_plain::derive_display_from_serialize!(CtDirection);
+
+#[derive(Clone, Copy, Debug, Eq, PartialEq, Deserialize, Serialize)]
+#[serde(rename_all = "lowercase")]
+pub enum IpFamily {
+    Ip,
+    Ip6,
+}
+
+#[cfg(feature = "config-ext")]
+impl From<Family> for IpFamily {
+    fn from(value: Family) -> Self {
+        match value {
+            Family::V4 => IpFamily::Ip,
+            Family::V6 => IpFamily::Ip6,
+        }
+    }
+}
+
 #[derive(Clone, Debug, Deserialize, Serialize)]
 #[serde(untagged)]
 pub enum Payload {
@@ -260,6 +364,16 @@ impl Prefix {
     }
 }
 
+#[cfg(feature = "config-ext")]
+impl From<&Cidr> for Prefix {
+    fn from(value: &Cidr) -> Self {
+        match value {
+            Cidr::Ipv4(cidr) => Self::new(cidr.address(), cidr.mask()),
+            Cidr::Ipv6(cidr) => Self::new(cidr.address(), cidr.mask()),
+        }
+    }
+}
+
 #[derive(Clone, Debug, Deserialize, Serialize)]
 pub struct Element {
     #[serde(flatten)]
-- 
2.39.2




More information about the pve-devel mailing list