[pve-devel] [PATCH proxmox-firewall v2 20/39] nftables: expression: implement conversion traits for firewall config
Stefan Hanreich
s.hanreich at proxmox.com
Wed Apr 17 15:53:45 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.
Reviewed-by: Lukas Wagner <l.wagner at proxmox.com>
Reviewed-by: Max Carrara <m.carrara at proxmox.com>
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, 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
More information about the pve-devel
mailing list