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.

Reviewed-by: Lukas Wagner <l.wag...@proxmox.com>
Reviewed-by: Max Carrara <m.carr...@proxmox.com>
Co-authored-by: Wolfgang Bumiller <w.bumil...@proxmox.com>
Signed-off-by: Stefan Hanreich <s.hanre...@proxmox.com>
---
 proxmox-nftables/Cargo.toml        |   5 +-
 proxmox-nftables/src/expression.rs | 124 +++++++++++++++++++++++++++--
 2 files changed, 122 insertions(+), 7 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 5478291..3b8ade0 100644
--- a/proxmox-nftables/src/expression.rs
+++ b/proxmox-nftables/src/expression.rs
@@ -2,7 +2,14 @@ use crate::types::{ElemConfig, Verdict};
 use serde::{Deserialize, Serialize};
 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")]
@@ -147,11 +154,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 +281,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 +362,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


_______________________________________________
pve-devel mailing list
pve-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel

Reply via email to