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.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, 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 _______________________________________________ pve-devel mailing list pve-devel@lists.proxmox.com https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel