all lists on lists.proxmox.com
 help / color / mirror / Atom feed
From: Hannes Laimer <h.laimer@proxmox.com>
To: pdm-devel@lists.proxmox.com
Subject: [pdm-devel] [PATCH proxmox 5/5] pve-api-types: regenerate
Date: Thu, 30 Oct 2025 15:33:58 +0100	[thread overview]
Message-ID: <20251030143406.193744-6-h.laimer@proxmox.com> (raw)
In-Reply-To: <20251030143406.193744-1-h.laimer@proxmox.com>

Signed-off-by: Hannes Laimer <h.laimer@proxmox.com>
---
 pve-api-types/src/generated/code.rs  |  206 +++-
 pve-api-types/src/generated/types.rs | 1364 ++++++++++++++++++++++++--
 2 files changed, 1502 insertions(+), 68 deletions(-)

diff --git a/pve-api-types/src/generated/code.rs b/pve-api-types/src/generated/code.rs
index 788e4bf5..ad6af3d1 100644
--- a/pve-api-types/src/generated/code.rs
+++ b/pve-api-types/src/generated/code.rs
@@ -60,9 +60,7 @@
 /// - /cluster/firewall/ipset/{name}
 /// - /cluster/firewall/ipset/{name}/{cidr}
 /// - /cluster/firewall/macros
-/// - /cluster/firewall/options
 /// - /cluster/firewall/refs
-/// - /cluster/firewall/rules
 /// - /cluster/firewall/rules/{pos}
 /// - /cluster/ha
 /// - /cluster/ha/groups
@@ -200,8 +198,6 @@
 /// - /nodes/{node}/execute
 /// - /nodes/{node}/firewall
 /// - /nodes/{node}/firewall/log
-/// - /nodes/{node}/firewall/options
-/// - /nodes/{node}/firewall/rules
 /// - /nodes/{node}/firewall/rules/{pos}
 /// - /nodes/{node}/hardware
 /// - /nodes/{node}/hardware/pci
@@ -220,9 +216,7 @@
 /// - /nodes/{node}/lxc/{vmid}/firewall/ipset/{name}
 /// - /nodes/{node}/lxc/{vmid}/firewall/ipset/{name}/{cidr}
 /// - /nodes/{node}/lxc/{vmid}/firewall/log
-/// - /nodes/{node}/lxc/{vmid}/firewall/options
 /// - /nodes/{node}/lxc/{vmid}/firewall/refs
-/// - /nodes/{node}/lxc/{vmid}/firewall/rules
 /// - /nodes/{node}/lxc/{vmid}/firewall/rules/{pos}
 /// - /nodes/{node}/lxc/{vmid}/interfaces
 /// - /nodes/{node}/lxc/{vmid}/move_volume
@@ -287,9 +281,7 @@
 /// - /nodes/{node}/qemu/{vmid}/firewall/ipset/{name}
 /// - /nodes/{node}/qemu/{vmid}/firewall/ipset/{name}/{cidr}
 /// - /nodes/{node}/qemu/{vmid}/firewall/log
-/// - /nodes/{node}/qemu/{vmid}/firewall/options
 /// - /nodes/{node}/qemu/{vmid}/firewall/refs
-/// - /nodes/{node}/qemu/{vmid}/firewall/rules
 /// - /nodes/{node}/qemu/{vmid}/firewall/rules/{pos}
 /// - /nodes/{node}/qemu/{vmid}/monitor
 /// - /nodes/{node}/qemu/{vmid}/move_disk
@@ -385,6 +377,11 @@ pub trait PveClient {
         Err(Error::Other("cluster_config_join not implemented"))
     }
 
+    /// Get Firewall options.
+    async fn cluster_firewall_options(&self) -> Result<ClusterFirewallOptions, Error> {
+        Err(Error::Other("cluster_firewall_options not implemented"))
+    }
+
     /// Retrieve metrics of the cluster.
     async fn cluster_metrics_export(
         &self,
@@ -481,6 +478,11 @@ pub trait PveClient {
         Err(Error::Other("list_available_updates not implemented"))
     }
 
+    /// List rules.
+    async fn list_cluster_firewall_rules(&self) -> Result<Vec<ListFirewallRules>, Error> {
+        Err(Error::Other("list_cluster_firewall_rules not implemented"))
+    }
+
     /// SDN controllers index.
     async fn list_controllers(
         &self,
@@ -501,6 +503,15 @@ pub trait PveClient {
         Err(Error::Other("list_lxc not implemented"))
     }
 
+    /// List rules.
+    async fn list_lxc_firewall_rules(
+        &self,
+        node: &str,
+        vmid: u32,
+    ) -> Result<Vec<ListFirewallRules>, Error> {
+        Err(Error::Other("list_lxc_firewall_rules not implemented"))
+    }
+
     /// List available networks
     async fn list_networks(
         &self,
@@ -510,6 +521,11 @@ pub trait PveClient {
         Err(Error::Other("list_networks not implemented"))
     }
 
+    /// List rules.
+    async fn list_node_firewall_rules(&self, node: &str) -> Result<Vec<ListFirewallRules>, Error> {
+        Err(Error::Other("list_node_firewall_rules not implemented"))
+    }
+
     /// Cluster node index.
     async fn list_nodes(&self) -> Result<Vec<ClusterNodeIndexResponse>, Error> {
         Err(Error::Other("list_nodes not implemented"))
@@ -520,6 +536,15 @@ pub trait PveClient {
         Err(Error::Other("list_qemu not implemented"))
     }
 
+    /// List rules.
+    async fn list_qemu_firewall_rules(
+        &self,
+        node: &str,
+        vmid: u32,
+    ) -> Result<Vec<ListFirewallRules>, Error> {
+        Err(Error::Other("list_qemu_firewall_rules not implemented"))
+    }
+
     /// Get status for all datastores.
     async fn list_storages(
         &self,
@@ -552,6 +577,15 @@ pub trait PveClient {
         Err(Error::Other("list_zones not implemented"))
     }
 
+    /// Get VM firewall options.
+    async fn lxc_firewall_options(
+        &self,
+        node: &str,
+        vmid: u32,
+    ) -> Result<GuestFirewallOptions, Error> {
+        Err(Error::Other("lxc_firewall_options not implemented"))
+    }
+
     /// Get container configuration.
     async fn lxc_get_config(
         &self,
@@ -588,11 +622,25 @@ pub trait PveClient {
         Err(Error::Other("migrate_qemu not implemented"))
     }
 
+    /// Get host firewall options.
+    async fn node_firewall_options(&self, node: &str) -> Result<NodeFirewallOptions, Error> {
+        Err(Error::Other("node_firewall_options not implemented"))
+    }
+
     /// Read node status
     async fn node_status(&self, node: &str) -> Result<NodeStatus, Error> {
         Err(Error::Other("node_status not implemented"))
     }
 
+    /// Get VM firewall options.
+    async fn qemu_firewall_options(
+        &self,
+        node: &str,
+        vmid: u32,
+    ) -> Result<GuestFirewallOptions, Error> {
+        Err(Error::Other("qemu_firewall_options not implemented"))
+    }
+
     /// Get the virtual machine configuration with pending configuration changes
     /// applied. Set the 'current' parameter to get the current configuration
     /// instead.
@@ -678,6 +726,43 @@ pub trait PveClient {
         Err(Error::Other("sdn_apply not implemented"))
     }
 
+    /// Set Firewall options.
+    async fn set_cluster_firewall_options(
+        &self,
+        params: UpdateClusterFirewallOptions,
+    ) -> Result<(), Error> {
+        Err(Error::Other("set_cluster_firewall_options not implemented"))
+    }
+
+    /// Set Firewall options.
+    async fn set_lxc_firewall_options(
+        &self,
+        node: &str,
+        vmid: u32,
+        params: UpdateGuestFirewallOptions,
+    ) -> Result<(), Error> {
+        Err(Error::Other("set_lxc_firewall_options not implemented"))
+    }
+
+    /// Set Firewall options.
+    async fn set_node_firewall_options(
+        &self,
+        node: &str,
+        params: UpdateNodeFirewallOptions,
+    ) -> Result<(), Error> {
+        Err(Error::Other("set_node_firewall_options not implemented"))
+    }
+
+    /// Set Firewall options.
+    async fn set_qemu_firewall_options(
+        &self,
+        node: &str,
+        vmid: u32,
+        params: UpdateGuestFirewallOptions,
+    ) -> Result<(), Error> {
+        Err(Error::Other("set_qemu_firewall_options not implemented"))
+    }
+
     /// Shutdown the container. This will trigger a clean shutdown of the
     /// container, see lxc-stop(1) for details.
     async fn shutdown_lxc_async(
@@ -791,6 +876,12 @@ where
         Ok(self.0.get(url).await?.expect_json()?.data)
     }
 
+    /// Get Firewall options.
+    async fn cluster_firewall_options(&self) -> Result<ClusterFirewallOptions, Error> {
+        let url = "/api2/extjs/cluster/firewall/options";
+        Ok(self.0.get(url).await?.expect_json()?.data)
+    }
+
     /// Retrieve metrics of the cluster.
     async fn cluster_metrics_export(
         &self,
@@ -938,6 +1029,12 @@ where
         Ok(self.0.get(url).await?.expect_json()?.data)
     }
 
+    /// List rules.
+    async fn list_cluster_firewall_rules(&self) -> Result<Vec<ListFirewallRules>, Error> {
+        let url = "/api2/extjs/cluster/firewall/rules";
+        Ok(self.0.get(url).await?.expect_json()?.data)
+    }
+
     /// SDN controllers index.
     async fn list_controllers(
         &self,
@@ -965,6 +1062,16 @@ where
         Ok(self.0.get(url).await?.expect_json()?.data)
     }
 
+    /// List rules.
+    async fn list_lxc_firewall_rules(
+        &self,
+        node: &str,
+        vmid: u32,
+    ) -> Result<Vec<ListFirewallRules>, Error> {
+        let url = &format!("/api2/extjs/nodes/{node}/lxc/{vmid}/firewall/rules");
+        Ok(self.0.get(url).await?.expect_json()?.data)
+    }
+
     /// List available networks
     async fn list_networks(
         &self,
@@ -977,6 +1084,12 @@ where
         Ok(self.0.get(url).await?.expect_json()?.data)
     }
 
+    /// List rules.
+    async fn list_node_firewall_rules(&self, node: &str) -> Result<Vec<ListFirewallRules>, Error> {
+        let url = &format!("/api2/extjs/nodes/{node}/firewall/rules");
+        Ok(self.0.get(url).await?.expect_json()?.data)
+    }
+
     /// Cluster node index.
     async fn list_nodes(&self) -> Result<Vec<ClusterNodeIndexResponse>, Error> {
         let url = "/api2/extjs/nodes";
@@ -991,6 +1104,16 @@ where
         Ok(self.0.get(url).await?.expect_json()?.data)
     }
 
+    /// List rules.
+    async fn list_qemu_firewall_rules(
+        &self,
+        node: &str,
+        vmid: u32,
+    ) -> Result<Vec<ListFirewallRules>, Error> {
+        let url = &format!("/api2/extjs/nodes/{node}/qemu/{vmid}/firewall/rules");
+        Ok(self.0.get(url).await?.expect_json()?.data)
+    }
+
     /// Get status for all datastores.
     async fn list_storages(
         &self,
@@ -1039,6 +1162,16 @@ where
         Ok(self.0.get(url).await?.expect_json()?.data)
     }
 
+    /// Get VM firewall options.
+    async fn lxc_firewall_options(
+        &self,
+        node: &str,
+        vmid: u32,
+    ) -> Result<GuestFirewallOptions, Error> {
+        let url = &format!("/api2/extjs/nodes/{node}/lxc/{vmid}/firewall/options");
+        Ok(self.0.get(url).await?.expect_json()?.data)
+    }
+
     /// Get container configuration.
     async fn lxc_get_config(
         &self,
@@ -1082,12 +1215,28 @@ where
         Ok(self.0.post(url, &params).await?.expect_json()?.data)
     }
 
+    /// Get host firewall options.
+    async fn node_firewall_options(&self, node: &str) -> Result<NodeFirewallOptions, Error> {
+        let url = &format!("/api2/extjs/nodes/{node}/firewall/options");
+        Ok(self.0.get(url).await?.expect_json()?.data)
+    }
+
     /// Read node status
     async fn node_status(&self, node: &str) -> Result<NodeStatus, Error> {
         let url = &format!("/api2/extjs/nodes/{node}/status");
         Ok(self.0.get(url).await?.expect_json()?.data)
     }
 
+    /// Get VM firewall options.
+    async fn qemu_firewall_options(
+        &self,
+        node: &str,
+        vmid: u32,
+    ) -> Result<GuestFirewallOptions, Error> {
+        let url = &format!("/api2/extjs/nodes/{node}/qemu/{vmid}/firewall/options");
+        Ok(self.0.get(url).await?.expect_json()?.data)
+    }
+
     /// Get the virtual machine configuration with pending configuration changes
     /// applied. Set the 'current' parameter to get the current configuration
     /// instead.
@@ -1196,6 +1345,47 @@ where
         Ok(self.0.put(url, &params).await?.expect_json()?.data)
     }
 
+    /// Set Firewall options.
+    async fn set_cluster_firewall_options(
+        &self,
+        params: UpdateClusterFirewallOptions,
+    ) -> Result<(), Error> {
+        let url = "/api2/extjs/cluster/firewall/options";
+        self.0.put(url, &params).await?.nodata()
+    }
+
+    /// Set Firewall options.
+    async fn set_lxc_firewall_options(
+        &self,
+        node: &str,
+        vmid: u32,
+        params: UpdateGuestFirewallOptions,
+    ) -> Result<(), Error> {
+        let url = &format!("/api2/extjs/nodes/{node}/lxc/{vmid}/firewall/options");
+        self.0.put(url, &params).await?.nodata()
+    }
+
+    /// Set Firewall options.
+    async fn set_node_firewall_options(
+        &self,
+        node: &str,
+        params: UpdateNodeFirewallOptions,
+    ) -> Result<(), Error> {
+        let url = &format!("/api2/extjs/nodes/{node}/firewall/options");
+        self.0.put(url, &params).await?.nodata()
+    }
+
+    /// Set Firewall options.
+    async fn set_qemu_firewall_options(
+        &self,
+        node: &str,
+        vmid: u32,
+        params: UpdateGuestFirewallOptions,
+    ) -> Result<(), Error> {
+        let url = &format!("/api2/extjs/nodes/{node}/qemu/{vmid}/firewall/options");
+        self.0.put(url, &params).await?.nodata()
+    }
+
     /// Shutdown the container. This will trigger a clean shutdown of the
     /// container, see lxc-stop(1) for details.
     async fn shutdown_lxc_async(
diff --git a/pve-api-types/src/generated/types.rs b/pve-api-types/src/generated/types.rs
index b8b834be..11e2929d 100644
--- a/pve-api-types/src/generated/types.rs
+++ b/pve-api-types/src/generated/types.rs
@@ -226,6 +226,101 @@ mod cluster_resource_content {
     }
 }
 
+#[api(
+    properties: {
+        ebtables: {
+            default: true,
+            optional: true,
+        },
+        enable: {
+            default: 0,
+            minimum: 0,
+            optional: true,
+            type: Integer,
+        },
+        log_ratelimit: {
+            format: &ApiStringFormat::PropertyString(&ClusterFirewallOptionsLogRatelimit::API_SCHEMA),
+            optional: true,
+            type: String,
+        },
+        policy_forward: {
+            optional: true,
+            type: FirewallFWPolicy,
+        },
+        policy_in: {
+            optional: true,
+            type: FirewallIOPolicy,
+        },
+        policy_out: {
+            optional: true,
+            type: FirewallIOPolicy,
+        },
+    },
+)]
+/// Object.
+#[derive(Debug, serde::Deserialize, serde::Serialize)]
+pub struct ClusterFirewallOptions {
+    /// Enable ebtables rules cluster wide.
+    #[serde(deserialize_with = "proxmox_serde::perl::deserialize_bool")]
+    #[serde(default, skip_serializing_if = "Option::is_none")]
+    pub ebtables: Option<bool>,
+
+    /// Enable or disable the firewall cluster wide.
+    #[serde(deserialize_with = "proxmox_serde::perl::deserialize_u64")]
+    #[serde(default, skip_serializing_if = "Option::is_none")]
+    pub enable: Option<u64>,
+
+    /// Log ratelimiting settings
+    #[serde(default, skip_serializing_if = "Option::is_none")]
+    pub log_ratelimit: Option<String>,
+
+    #[serde(default, skip_serializing_if = "Option::is_none")]
+    pub policy_forward: Option<FirewallFWPolicy>,
+
+    #[serde(default, skip_serializing_if = "Option::is_none")]
+    pub policy_in: Option<FirewallIOPolicy>,
+
+    #[serde(default, skip_serializing_if = "Option::is_none")]
+    pub policy_out: Option<FirewallIOPolicy>,
+}
+
+#[api(
+    default_key: "enable",
+    properties: {
+        burst: {
+            default: 5,
+            minimum: 0,
+            optional: true,
+            type: Integer,
+        },
+        enable: {
+            default: true,
+        },
+        rate: {
+            default: "1/second",
+            optional: true,
+            type: String,
+        },
+    },
+)]
+/// Object.
+#[derive(Debug, serde::Deserialize, serde::Serialize)]
+pub struct ClusterFirewallOptionsLogRatelimit {
+    /// Initial burst of packages which will always get logged before the rate
+    /// is applied
+    #[serde(deserialize_with = "proxmox_serde::perl::deserialize_u64")]
+    #[serde(default, skip_serializing_if = "Option::is_none")]
+    pub burst: Option<u64>,
+
+    /// Enable or disable log rate limiting
+    #[serde(deserialize_with = "proxmox_serde::perl::deserialize_bool")]
+    pub enable: bool,
+
+    /// Frequency with which the burst bucket gets refilled
+    #[serde(default, skip_serializing_if = "Option::is_none")]
+    pub rate: Option<String>,
+}
+
 const_regex! {
 
 CLUSTER_JOIN_INFO_PREFERRED_NODE_RE = r##"^(?i:[a-z0-9](?i:[a-z0-9\-]*[a-z0-9])?)$"##;
@@ -1645,6 +1740,204 @@ pub struct CreateZone {
     pub zone: String,
 }
 
+#[api]
+/// Firewall IO policies.
+#[derive(Clone, Copy, Debug, Default, Eq, PartialEq, serde::Deserialize, serde::Serialize)]
+pub enum FirewallFWPolicy {
+    #[serde(rename = "ACCEPT")]
+    /// ACCEPT.
+    Accept,
+    #[serde(rename = "DROP")]
+    #[default]
+    /// DROP.
+    Drop,
+}
+serde_plain::derive_display_from_serialize!(FirewallFWPolicy);
+serde_plain::derive_fromstr_from_deserialize!(FirewallFWPolicy);
+
+#[api]
+/// Firewall IO policies.
+#[derive(Clone, Copy, Debug, Default, Eq, PartialEq, serde::Deserialize, serde::Serialize)]
+pub enum FirewallIOPolicy {
+    #[serde(rename = "ACCEPT")]
+    #[default]
+    /// ACCEPT.
+    Accept,
+    #[serde(rename = "DROP")]
+    /// DROP.
+    Drop,
+    #[serde(rename = "REJECT")]
+    /// REJECT.
+    Reject,
+}
+serde_plain::derive_display_from_serialize!(FirewallIOPolicy);
+serde_plain::derive_fromstr_from_deserialize!(FirewallIOPolicy);
+
+#[api]
+/// Firewall log levels.
+#[derive(Clone, Copy, Debug, Default, Eq, PartialEq, serde::Deserialize, serde::Serialize)]
+pub enum FirewallLogLevel {
+    #[serde(rename = "emerg")]
+    /// emerg.
+    Emerg,
+    #[serde(rename = "alert")]
+    /// alert.
+    Alert,
+    #[serde(rename = "crit")]
+    /// crit.
+    Crit,
+    #[serde(rename = "err")]
+    /// err.
+    Error,
+    #[serde(rename = "warning")]
+    /// warning.
+    Warning,
+    #[serde(rename = "notice")]
+    /// notice.
+    Notice,
+    #[serde(rename = "info")]
+    /// info.
+    Info,
+    #[serde(rename = "debug")]
+    /// debug.
+    Debug,
+    #[serde(rename = "nolog")]
+    #[default]
+    /// nolog.
+    Nolog,
+}
+serde_plain::derive_display_from_serialize!(FirewallLogLevel);
+serde_plain::derive_fromstr_from_deserialize!(FirewallLogLevel);
+
+#[api]
+/// Firewall conntrack helper.
+#[derive(Clone, Copy, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize)]
+pub enum FwConntrackHelper {
+    #[serde(rename = "amanda")]
+    /// amanda.
+    Amanda,
+    #[serde(rename = "ftp")]
+    /// ftp.
+    Ftp,
+    #[serde(rename = "irc")]
+    /// irc.
+    Irc,
+    #[serde(rename = "netbios-ns")]
+    /// netbios-ns.
+    NetbiosNs,
+    #[serde(rename = "pptp")]
+    /// pptp.
+    Pptp,
+    #[serde(rename = "sane")]
+    /// sane.
+    Sane,
+    #[serde(rename = "sip")]
+    /// sip.
+    Sip,
+    #[serde(rename = "snmp")]
+    /// snmp.
+    Snmp,
+    #[serde(rename = "tftp")]
+    /// tftp.
+    Tftp,
+}
+serde_plain::derive_display_from_serialize!(FwConntrackHelper);
+serde_plain::derive_fromstr_from_deserialize!(FwConntrackHelper);
+
+#[api(
+    properties: {
+        dhcp: {
+            default: false,
+            optional: true,
+        },
+        enable: {
+            default: false,
+            optional: true,
+        },
+        ipfilter: {
+            default: false,
+            optional: true,
+        },
+        log_level_in: {
+            optional: true,
+            type: FirewallLogLevel,
+        },
+        log_level_out: {
+            optional: true,
+            type: FirewallLogLevel,
+        },
+        macfilter: {
+            default: true,
+            optional: true,
+        },
+        ndp: {
+            default: false,
+            optional: true,
+        },
+        policy_in: {
+            optional: true,
+            type: FirewallIOPolicy,
+        },
+        policy_out: {
+            optional: true,
+            type: FirewallIOPolicy,
+        },
+        radv: {
+            default: false,
+            optional: true,
+        },
+    },
+)]
+/// Object.
+#[derive(Debug, serde::Deserialize, serde::Serialize)]
+pub struct GuestFirewallOptions {
+    /// Enable DHCP.
+    #[serde(deserialize_with = "proxmox_serde::perl::deserialize_bool")]
+    #[serde(default, skip_serializing_if = "Option::is_none")]
+    pub dhcp: Option<bool>,
+
+    /// Enable/disable firewall rules.
+    #[serde(deserialize_with = "proxmox_serde::perl::deserialize_bool")]
+    #[serde(default, skip_serializing_if = "Option::is_none")]
+    pub enable: Option<bool>,
+
+    /// Enable default IP filters. This is equivalent to adding an empty
+    /// ipfilter-net<id> ipset for every interface. Such ipsets implicitly
+    /// contain sane default restrictions such as restricting IPv6 link local
+    /// addresses to the one derived from the interface's MAC address. For
+    /// containers the configured IP addresses will be implicitly added.
+    #[serde(deserialize_with = "proxmox_serde::perl::deserialize_bool")]
+    #[serde(default, skip_serializing_if = "Option::is_none")]
+    pub ipfilter: Option<bool>,
+
+    #[serde(default, skip_serializing_if = "Option::is_none")]
+    pub log_level_in: Option<FirewallLogLevel>,
+
+    #[serde(default, skip_serializing_if = "Option::is_none")]
+    pub log_level_out: Option<FirewallLogLevel>,
+
+    /// Enable/disable MAC address filter.
+    #[serde(deserialize_with = "proxmox_serde::perl::deserialize_bool")]
+    #[serde(default, skip_serializing_if = "Option::is_none")]
+    pub macfilter: Option<bool>,
+
+    /// Enable NDP (Neighbor Discovery Protocol).
+    #[serde(deserialize_with = "proxmox_serde::perl::deserialize_bool")]
+    #[serde(default, skip_serializing_if = "Option::is_none")]
+    pub ndp: Option<bool>,
+
+    #[serde(default, skip_serializing_if = "Option::is_none")]
+    pub policy_in: Option<FirewallIOPolicy>,
+
+    #[serde(default, skip_serializing_if = "Option::is_none")]
+    pub policy_out: Option<FirewallIOPolicy>,
+
+    /// Allow sending Router Advertisement.
+    #[serde(deserialize_with = "proxmox_serde::perl::deserialize_bool")]
+    #[serde(default, skip_serializing_if = "Option::is_none")]
+    pub radv: Option<bool>,
+}
+
 #[api]
 /// A guest's run state.
 #[derive(Clone, Copy, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize)]
@@ -1679,6 +1972,137 @@ pub enum ListControllersType {
 serde_plain::derive_display_from_serialize!(ListControllersType);
 serde_plain::derive_fromstr_from_deserialize!(ListControllersType);
 
+#[api(
+    properties: {
+        action: {
+            type: String,
+        },
+        comment: {
+            optional: true,
+            type: String,
+        },
+        dest: {
+            optional: true,
+            type: String,
+        },
+        dport: {
+            optional: true,
+            type: String,
+        },
+        enable: {
+            optional: true,
+            type: Integer,
+        },
+        "icmp-type": {
+            optional: true,
+            type: String,
+        },
+        iface: {
+            optional: true,
+            type: String,
+        },
+        ipversion: {
+            optional: true,
+            type: Integer,
+        },
+        log: {
+            optional: true,
+            type: FirewallLogLevel,
+        },
+        "macro": {
+            optional: true,
+            type: String,
+        },
+        pos: {
+            type: Integer,
+        },
+        proto: {
+            optional: true,
+            type: String,
+        },
+        source: {
+            optional: true,
+            type: String,
+        },
+        sport: {
+            optional: true,
+            type: String,
+        },
+        type: {
+            type: String,
+        },
+    },
+)]
+/// Object.
+#[derive(Clone, Debug, PartialEq, serde::Deserialize, serde::Serialize)]
+pub struct ListFirewallRules {
+    /// Rule action ('ACCEPT', 'DROP', 'REJECT') or security group name
+    pub action: String,
+
+    /// Descriptive comment
+    #[serde(default, skip_serializing_if = "Option::is_none")]
+    pub comment: Option<String>,
+
+    /// Restrict packet destination address
+    #[serde(default, skip_serializing_if = "Option::is_none")]
+    pub dest: Option<String>,
+
+    /// Restrict TCP/UDP destination port
+    #[serde(default, skip_serializing_if = "Option::is_none")]
+    pub dport: Option<String>,
+
+    /// Flag to enable/disable a rule
+    #[serde(deserialize_with = "proxmox_serde::perl::deserialize_i64")]
+    #[serde(default, skip_serializing_if = "Option::is_none")]
+    pub enable: Option<i64>,
+
+    /// Specify icmp-type. Only valid if proto equals 'icmp' or
+    /// 'icmpv6'/'ipv6-icmp'
+    #[serde(default, skip_serializing_if = "Option::is_none")]
+    #[serde(rename = "icmp-type")]
+    pub icmp_type: Option<String>,
+
+    /// Network interface name. You have to use network configuration key names
+    /// for VMs and containers
+    #[serde(default, skip_serializing_if = "Option::is_none")]
+    pub iface: Option<String>,
+
+    /// IP version (4 or 6) - automatically determined from source/dest
+    /// addresses
+    #[serde(deserialize_with = "proxmox_serde::perl::deserialize_i64")]
+    #[serde(default, skip_serializing_if = "Option::is_none")]
+    pub ipversion: Option<i64>,
+
+    #[serde(default, skip_serializing_if = "Option::is_none")]
+    pub log: Option<FirewallLogLevel>,
+
+    /// Use predefined standard macro
+    #[serde(default, skip_serializing_if = "Option::is_none")]
+    #[serde(rename = "macro")]
+    pub r#macro: Option<String>,
+
+    /// Rule position in the ruleset
+    #[serde(deserialize_with = "proxmox_serde::perl::deserialize_i64")]
+    pub pos: i64,
+
+    /// IP protocol. You can use protocol names ('tcp'/'udp') or simple numbers,
+    /// as defined in '/etc/protocols'
+    #[serde(default, skip_serializing_if = "Option::is_none")]
+    pub proto: Option<String>,
+
+    /// Restrict packet source address
+    #[serde(default, skip_serializing_if = "Option::is_none")]
+    pub source: Option<String>,
+
+    /// Restrict TCP/UDP source port
+    #[serde(default, skip_serializing_if = "Option::is_none")]
+    pub sport: Option<String>,
+
+    /// Rule type
+    #[serde(rename = "type")]
+    pub ty: String,
+}
+
 #[api]
 /// Only list specific interface types.
 #[derive(Clone, Copy, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize)]
@@ -3594,29 +4018,131 @@ pub struct MigrateQemu {
     pub with_local_disks: Option<bool>,
 }
 
-const_regex! {
+const NODE_FIREWALL_OPTIONS_NF_CONNTRACK_HELPERS: Schema =
+    proxmox_schema::ArraySchema::new("list", &FwConntrackHelper::API_SCHEMA).schema();
 
-NETWORK_INTERFACE_BOND_PRIMARY_RE = r##"^[a-zA-Z][a-zA-Z0-9_]{1,20}([:\.]\d+)?$"##;
-NETWORK_INTERFACE_BRIDGE_PORTS_RE = r##"^[a-zA-Z][a-zA-Z0-9_]{1,20}([:\.]\d+)?$"##;
-NETWORK_INTERFACE_IFACE_RE = r##"^[a-zA-Z][a-zA-Z0-9_]{1,20}([:\.]\d+)?$"##;
-NETWORK_INTERFACE_OVS_BONDS_RE = r##"^[a-zA-Z][a-zA-Z0-9_]{1,20}([:\.]\d+)?$"##;
-NETWORK_INTERFACE_OVS_BRIDGE_RE = r##"^[a-zA-Z][a-zA-Z0-9_]{1,20}([:\.]\d+)?$"##;
-NETWORK_INTERFACE_OVS_PORTS_RE = r##"^[a-zA-Z][a-zA-Z0-9_]{1,20}([:\.]\d+)?$"##;
-NETWORK_INTERFACE_SLAVES_RE = r##"^[a-zA-Z][a-zA-Z0-9_]{1,20}([:\.]\d+)?$"##;
-NETWORK_INTERFACE_VLAN_RAW_DEVICE_RE = r##"^[a-zA-Z][a-zA-Z0-9_]{1,20}([:\.]\d+)?$"##;
+mod node_firewall_options_nf_conntrack_helpers {
+    use serde::{Deserialize, Deserializer, Serialize, Serializer};
 
-}
+    #[doc(hidden)]
+    pub trait Ser: Sized {
+        fn ser<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error>;
+        fn de<'de, D>(deserializer: D) -> Result<Self, D::Error>
+        where
+            D: Deserializer<'de>;
+    }
 
-#[test]
-fn test_regex_compilation_14() {
-    use regex::Regex;
-    let _: &Regex = &NETWORK_INTERFACE_BOND_PRIMARY_RE;
-    let _: &Regex = &NETWORK_INTERFACE_BRIDGE_PORTS_RE;
-    let _: &Regex = &NETWORK_INTERFACE_IFACE_RE;
-    let _: &Regex = &NETWORK_INTERFACE_OVS_BONDS_RE;
-    let _: &Regex = &NETWORK_INTERFACE_OVS_BRIDGE_RE;
-    let _: &Regex = &NETWORK_INTERFACE_OVS_PORTS_RE;
-    let _: &Regex = &NETWORK_INTERFACE_SLAVES_RE;
+    impl<T: Serialize + for<'a> Deserialize<'a>> Ser for Vec<T> {
+        fn ser<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
+        where
+            S: Serializer,
+        {
+            super::stringlist::serialize(
+                &self[..],
+                serializer,
+                &super::NODE_FIREWALL_OPTIONS_NF_CONNTRACK_HELPERS,
+            )
+        }
+
+        fn de<'de, D>(deserializer: D) -> Result<Self, D::Error>
+        where
+            D: Deserializer<'de>,
+        {
+            super::stringlist::deserialize(
+                deserializer,
+                &super::NODE_FIREWALL_OPTIONS_NF_CONNTRACK_HELPERS,
+            )
+        }
+    }
+
+    impl<T: Ser> Ser for Option<T> {
+        fn ser<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
+        where
+            S: Serializer,
+        {
+            match self {
+                None => serializer.serialize_none(),
+                Some(inner) => inner.ser(serializer),
+            }
+        }
+
+        fn de<'de, D>(deserializer: D) -> Result<Self, D::Error>
+        where
+            D: Deserializer<'de>,
+        {
+            use std::fmt;
+            use std::marker::PhantomData;
+
+            struct V<T: Ser>(PhantomData<T>);
+
+            impl<'de, T: Ser> serde::de::Visitor<'de> for V<T> {
+                type Value = Option<T>;
+
+                fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result {
+                    f.write_str("an optional string")
+                }
+
+                fn visit_none<E: serde::de::Error>(self) -> Result<Self::Value, E> {
+                    Ok(None)
+                }
+
+                fn visit_some<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
+                where
+                    D: Deserializer<'de>,
+                {
+                    T::de(deserializer).map(Some)
+                }
+
+                fn visit_str<E: serde::de::Error>(self, value: &str) -> Result<Self::Value, E> {
+                    use serde::de::IntoDeserializer;
+                    T::de(value.into_deserializer()).map(Some)
+                }
+            }
+
+            deserializer.deserialize_option(V::<T>(PhantomData))
+        }
+    }
+
+    pub fn serialize<T, S>(this: &T, serializer: S) -> Result<S::Ok, S::Error>
+    where
+        S: serde::Serializer,
+        T: Ser,
+    {
+        this.ser(serializer)
+    }
+
+    pub fn deserialize<'de, T, D>(deserializer: D) -> Result<T, D::Error>
+    where
+        D: serde::Deserializer<'de>,
+        T: Ser,
+    {
+        T::de(deserializer)
+    }
+}
+
+const_regex! {
+
+NETWORK_INTERFACE_BOND_PRIMARY_RE = r##"^[a-zA-Z][a-zA-Z0-9_]{1,20}([:\.]\d+)?$"##;
+NETWORK_INTERFACE_BRIDGE_PORTS_RE = r##"^[a-zA-Z][a-zA-Z0-9_]{1,20}([:\.]\d+)?$"##;
+NETWORK_INTERFACE_IFACE_RE = r##"^[a-zA-Z][a-zA-Z0-9_]{1,20}([:\.]\d+)?$"##;
+NETWORK_INTERFACE_OVS_BONDS_RE = r##"^[a-zA-Z][a-zA-Z0-9_]{1,20}([:\.]\d+)?$"##;
+NETWORK_INTERFACE_OVS_BRIDGE_RE = r##"^[a-zA-Z][a-zA-Z0-9_]{1,20}([:\.]\d+)?$"##;
+NETWORK_INTERFACE_OVS_PORTS_RE = r##"^[a-zA-Z][a-zA-Z0-9_]{1,20}([:\.]\d+)?$"##;
+NETWORK_INTERFACE_SLAVES_RE = r##"^[a-zA-Z][a-zA-Z0-9_]{1,20}([:\.]\d+)?$"##;
+NETWORK_INTERFACE_VLAN_RAW_DEVICE_RE = r##"^[a-zA-Z][a-zA-Z0-9_]{1,20}([:\.]\d+)?$"##;
+
+}
+
+#[test]
+fn test_regex_compilation_14() {
+    use regex::Regex;
+    let _: &Regex = &NETWORK_INTERFACE_BOND_PRIMARY_RE;
+    let _: &Regex = &NETWORK_INTERFACE_BRIDGE_PORTS_RE;
+    let _: &Regex = &NETWORK_INTERFACE_IFACE_RE;
+    let _: &Regex = &NETWORK_INTERFACE_OVS_BONDS_RE;
+    let _: &Regex = &NETWORK_INTERFACE_OVS_BRIDGE_RE;
+    let _: &Regex = &NETWORK_INTERFACE_OVS_PORTS_RE;
+    let _: &Regex = &NETWORK_INTERFACE_SLAVES_RE;
     let _: &Regex = &NETWORK_INTERFACE_VLAN_RAW_DEVICE_RE;
 }
 #[api(
@@ -4223,6 +4749,187 @@ pub enum NetworkInterfaceVlanProtocol {
 serde_plain::derive_display_from_serialize!(NetworkInterfaceVlanProtocol);
 serde_plain::derive_fromstr_from_deserialize!(NetworkInterfaceVlanProtocol);
 
+#[api(
+    properties: {
+        enable: {
+            default: true,
+            optional: true,
+        },
+        log_level_forward: {
+            optional: true,
+            type: FirewallLogLevel,
+        },
+        log_level_in: {
+            optional: true,
+            type: FirewallLogLevel,
+        },
+        log_level_out: {
+            optional: true,
+            type: FirewallLogLevel,
+        },
+        log_nf_conntrack: {
+            default: false,
+            optional: true,
+        },
+        ndp: {
+            default: false,
+            optional: true,
+        },
+        nf_conntrack_allow_invalid: {
+            default: false,
+            optional: true,
+        },
+        nf_conntrack_helpers: {
+            default: "",
+            format: &ApiStringFormat::PropertyString(&NODE_FIREWALL_OPTIONS_NF_CONNTRACK_HELPERS),
+            optional: true,
+            type: String,
+        },
+        nf_conntrack_max: {
+            default: 262144,
+            minimum: 32768,
+            optional: true,
+            type: Integer,
+        },
+        nf_conntrack_tcp_timeout_established: {
+            default: 432000,
+            minimum: 7875,
+            optional: true,
+            type: Integer,
+        },
+        nf_conntrack_tcp_timeout_syn_recv: {
+            default: 60,
+            maximum: 60,
+            minimum: 30,
+            optional: true,
+            type: Integer,
+        },
+        nftables: {
+            default: false,
+            optional: true,
+        },
+        nosmurfs: {
+            default: false,
+            optional: true,
+        },
+        protection_synflood: {
+            default: false,
+            optional: true,
+        },
+        protection_synflood_burst: {
+            default: 1000,
+            optional: true,
+            type: Integer,
+        },
+        protection_synflood_rate: {
+            default: 200,
+            optional: true,
+            type: Integer,
+        },
+        smurf_log_level: {
+            optional: true,
+            type: FirewallLogLevel,
+        },
+        tcp_flags_log_level: {
+            optional: true,
+            type: FirewallLogLevel,
+        },
+        tcpflags: {
+            default: false,
+            optional: true,
+        },
+    },
+)]
+/// Object.
+#[derive(Debug, serde::Deserialize, serde::Serialize)]
+pub struct NodeFirewallOptions {
+    /// Enable host firewall rules.
+    #[serde(deserialize_with = "proxmox_serde::perl::deserialize_bool")]
+    #[serde(default, skip_serializing_if = "Option::is_none")]
+    pub enable: Option<bool>,
+
+    #[serde(default, skip_serializing_if = "Option::is_none")]
+    pub log_level_forward: Option<FirewallLogLevel>,
+
+    #[serde(default, skip_serializing_if = "Option::is_none")]
+    pub log_level_in: Option<FirewallLogLevel>,
+
+    #[serde(default, skip_serializing_if = "Option::is_none")]
+    pub log_level_out: Option<FirewallLogLevel>,
+
+    /// Enable logging of conntrack information.
+    #[serde(deserialize_with = "proxmox_serde::perl::deserialize_bool")]
+    #[serde(default, skip_serializing_if = "Option::is_none")]
+    pub log_nf_conntrack: Option<bool>,
+
+    /// Enable NDP (Neighbor Discovery Protocol).
+    #[serde(deserialize_with = "proxmox_serde::perl::deserialize_bool")]
+    #[serde(default, skip_serializing_if = "Option::is_none")]
+    pub ndp: Option<bool>,
+
+    /// Allow invalid packets on connection tracking.
+    #[serde(deserialize_with = "proxmox_serde::perl::deserialize_bool")]
+    #[serde(default, skip_serializing_if = "Option::is_none")]
+    pub nf_conntrack_allow_invalid: Option<bool>,
+
+    /// Enable conntrack helpers for specific protocols. Supported protocols:
+    /// amanda, ftp, irc, netbios-ns, pptp, sane, sip, snmp, tftp
+    #[serde(with = "node_firewall_options_nf_conntrack_helpers")]
+    #[serde(default, skip_serializing_if = "Option::is_none")]
+    pub nf_conntrack_helpers: Option<Vec<FwConntrackHelper>>,
+
+    /// Maximum number of tracked connections.
+    #[serde(deserialize_with = "proxmox_serde::perl::deserialize_u64")]
+    #[serde(default, skip_serializing_if = "Option::is_none")]
+    pub nf_conntrack_max: Option<u64>,
+
+    /// Conntrack established timeout.
+    #[serde(deserialize_with = "proxmox_serde::perl::deserialize_u64")]
+    #[serde(default, skip_serializing_if = "Option::is_none")]
+    pub nf_conntrack_tcp_timeout_established: Option<u64>,
+
+    /// Conntrack syn recv timeout.
+    #[serde(deserialize_with = "proxmox_serde::perl::deserialize_u8")]
+    #[serde(default, skip_serializing_if = "Option::is_none")]
+    pub nf_conntrack_tcp_timeout_syn_recv: Option<u8>,
+
+    /// Enable nftables based firewall (tech preview)
+    #[serde(deserialize_with = "proxmox_serde::perl::deserialize_bool")]
+    #[serde(default, skip_serializing_if = "Option::is_none")]
+    pub nftables: Option<bool>,
+
+    /// Enable SMURFS filter.
+    #[serde(deserialize_with = "proxmox_serde::perl::deserialize_bool")]
+    #[serde(default, skip_serializing_if = "Option::is_none")]
+    pub nosmurfs: Option<bool>,
+
+    /// Enable synflood protection
+    #[serde(deserialize_with = "proxmox_serde::perl::deserialize_bool")]
+    #[serde(default, skip_serializing_if = "Option::is_none")]
+    pub protection_synflood: Option<bool>,
+
+    /// Synflood protection rate burst by ip src.
+    #[serde(deserialize_with = "proxmox_serde::perl::deserialize_i64")]
+    #[serde(default, skip_serializing_if = "Option::is_none")]
+    pub protection_synflood_burst: Option<i64>,
+
+    /// Synflood protection rate syn/sec by ip src.
+    #[serde(deserialize_with = "proxmox_serde::perl::deserialize_i64")]
+    #[serde(default, skip_serializing_if = "Option::is_none")]
+    pub protection_synflood_rate: Option<i64>,
+
+    #[serde(default, skip_serializing_if = "Option::is_none")]
+    pub smurf_log_level: Option<FirewallLogLevel>,
+
+    #[serde(default, skip_serializing_if = "Option::is_none")]
+    pub tcp_flags_log_level: Option<FirewallLogLevel>,
+
+    /// Filter illegal combinations of TCP flags.
+    #[serde(deserialize_with = "proxmox_serde::perl::deserialize_bool")]
+    #[serde(default, skip_serializing_if = "Option::is_none")]
+    pub tcpflags: Option<bool>,
+}
+
 #[api(
     additional_properties: "additional_properties",
     properties: {
@@ -11761,43 +12468,580 @@ pub struct TaskStatus {
     pub user: String,
 }
 
-const_regex! {
+const UPDATE_NODE_FIREWALL_OPTIONS_NF_CONNTRACK_HELPERS: Schema =
+    proxmox_schema::ArraySchema::new("list", &FwConntrackHelper::API_SCHEMA).schema();
 
-UPDATE_QEMU_CONFIG_AFFINITY_RE = r##"^(\s*\d+(-\d+)?\s*)(,\s*\d+(-\d+)?\s*)?$"##;
-UPDATE_QEMU_CONFIG_BOOTDISK_RE = r##"^(ide|sata|scsi|virtio|efidisk|tpmstate)\d+$"##;
-UPDATE_QEMU_CONFIG_DELETE_RE = r##"^(?i:[a-z][a-z0-9_-]+)$"##;
-UPDATE_QEMU_CONFIG_IMPORT_WORKING_STORAGE_RE = r##"^(?i:[a-z][a-z0-9\-_.]*[a-z0-9])$"##;
-UPDATE_QEMU_CONFIG_REVERT_RE = r##"^(?i:[a-z][a-z0-9_-]+)$"##;
-UPDATE_QEMU_CONFIG_SSHKEYS_RE = r##"^[-%a-zA-Z0-9_.!~*'()]*$"##;
-UPDATE_QEMU_CONFIG_TAGS_RE = r##"^(?i)[a-z0-9_][a-z0-9_\-+.]*$"##;
-UPDATE_QEMU_CONFIG_VMSTATESTORAGE_RE = r##"^(?i:[a-z][a-z0-9\-_.]*[a-z0-9])$"##;
+mod update_node_firewall_options_nf_conntrack_helpers {
+    use serde::{Deserialize, Deserializer, Serialize, Serializer};
 
-}
+    #[doc(hidden)]
+    pub trait Ser: Sized {
+        fn ser<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error>;
+        fn de<'de, D>(deserializer: D) -> Result<Self, D::Error>
+        where
+            D: Deserializer<'de>;
+    }
 
-#[test]
-fn test_regex_compilation_35() {
-    use regex::Regex;
-    let _: &Regex = &UPDATE_QEMU_CONFIG_AFFINITY_RE;
-    let _: &Regex = &UPDATE_QEMU_CONFIG_BOOTDISK_RE;
-    let _: &Regex = &UPDATE_QEMU_CONFIG_DELETE_RE;
-    let _: &Regex = &UPDATE_QEMU_CONFIG_IMPORT_WORKING_STORAGE_RE;
-    let _: &Regex = &UPDATE_QEMU_CONFIG_REVERT_RE;
-    let _: &Regex = &UPDATE_QEMU_CONFIG_SSHKEYS_RE;
-    let _: &Regex = &UPDATE_QEMU_CONFIG_TAGS_RE;
-    let _: &Regex = &UPDATE_QEMU_CONFIG_VMSTATESTORAGE_RE;
-}
-#[api(
-    properties: {
-        acpi: {
-            default: true,
-            optional: true,
-        },
-        affinity: {
-            format: &ApiStringFormat::Pattern(&UPDATE_QEMU_CONFIG_AFFINITY_RE),
-            optional: true,
-            type: String,
-        },
-        agent: {
+    impl<T: Serialize + for<'a> Deserialize<'a>> Ser for Vec<T> {
+        fn ser<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
+        where
+            S: Serializer,
+        {
+            super::stringlist::serialize(
+                &self[..],
+                serializer,
+                &super::UPDATE_NODE_FIREWALL_OPTIONS_NF_CONNTRACK_HELPERS,
+            )
+        }
+
+        fn de<'de, D>(deserializer: D) -> Result<Self, D::Error>
+        where
+            D: Deserializer<'de>,
+        {
+            super::stringlist::deserialize(
+                deserializer,
+                &super::UPDATE_NODE_FIREWALL_OPTIONS_NF_CONNTRACK_HELPERS,
+            )
+        }
+    }
+
+    impl<T: Ser> Ser for Option<T> {
+        fn ser<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
+        where
+            S: Serializer,
+        {
+            match self {
+                None => serializer.serialize_none(),
+                Some(inner) => inner.ser(serializer),
+            }
+        }
+
+        fn de<'de, D>(deserializer: D) -> Result<Self, D::Error>
+        where
+            D: Deserializer<'de>,
+        {
+            use std::fmt;
+            use std::marker::PhantomData;
+
+            struct V<T: Ser>(PhantomData<T>);
+
+            impl<'de, T: Ser> serde::de::Visitor<'de> for V<T> {
+                type Value = Option<T>;
+
+                fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result {
+                    f.write_str("an optional string")
+                }
+
+                fn visit_none<E: serde::de::Error>(self) -> Result<Self::Value, E> {
+                    Ok(None)
+                }
+
+                fn visit_some<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
+                where
+                    D: Deserializer<'de>,
+                {
+                    T::de(deserializer).map(Some)
+                }
+
+                fn visit_str<E: serde::de::Error>(self, value: &str) -> Result<Self::Value, E> {
+                    use serde::de::IntoDeserializer;
+                    T::de(value.into_deserializer()).map(Some)
+                }
+            }
+
+            deserializer.deserialize_option(V::<T>(PhantomData))
+        }
+    }
+
+    pub fn serialize<T, S>(this: &T, serializer: S) -> Result<S::Ok, S::Error>
+    where
+        S: serde::Serializer,
+        T: Ser,
+    {
+        this.ser(serializer)
+    }
+
+    pub fn deserialize<'de, T, D>(deserializer: D) -> Result<T, D::Error>
+    where
+        D: serde::Deserializer<'de>,
+        T: Ser,
+    {
+        T::de(deserializer)
+    }
+}
+
+const_regex! {
+
+UPDATE_CLUSTER_FIREWALL_OPTIONS_DELETE_RE = r##"^(?i:[a-z][a-z0-9_-]+)$"##;
+
+}
+
+#[test]
+fn test_regex_compilation_35() {
+    use regex::Regex;
+    let _: &Regex = &UPDATE_CLUSTER_FIREWALL_OPTIONS_DELETE_RE;
+}
+#[api(
+    properties: {
+        delete: {
+            items: {
+                description: "List item of type pve-configid.",
+                format: &ApiStringFormat::Pattern(&UPDATE_CLUSTER_FIREWALL_OPTIONS_DELETE_RE),
+                type: String,
+            },
+            optional: true,
+            type: Array,
+        },
+        digest: {
+            max_length: 64,
+            optional: true,
+            type: String,
+        },
+        ebtables: {
+            default: true,
+            optional: true,
+        },
+        enable: {
+            default: 0,
+            minimum: 0,
+            optional: true,
+            type: Integer,
+        },
+        log_ratelimit: {
+            format: &ApiStringFormat::PropertyString(&ClusterFirewallOptionsLogRatelimit::API_SCHEMA),
+            optional: true,
+            type: String,
+        },
+        policy_forward: {
+            optional: true,
+            type: FirewallFWPolicy,
+        },
+        policy_in: {
+            optional: true,
+            type: FirewallIOPolicy,
+        },
+        policy_out: {
+            optional: true,
+            type: FirewallIOPolicy,
+        },
+    },
+)]
+/// Object.
+#[derive(Debug, serde::Deserialize, serde::Serialize)]
+pub struct UpdateClusterFirewallOptions {
+    /// A list of settings you want to delete.
+    #[serde(default, skip_serializing_if = "Option::is_none")]
+    pub delete: Option<Vec<String>>,
+
+    /// Prevent changes if current configuration file has a different digest.
+    /// This can be used to prevent concurrent modifications.
+    #[serde(default, skip_serializing_if = "Option::is_none")]
+    pub digest: Option<String>,
+
+    /// Enable ebtables rules cluster wide.
+    #[serde(deserialize_with = "proxmox_serde::perl::deserialize_bool")]
+    #[serde(default, skip_serializing_if = "Option::is_none")]
+    pub ebtables: Option<bool>,
+
+    /// Enable or disable the firewall cluster wide.
+    #[serde(deserialize_with = "proxmox_serde::perl::deserialize_u64")]
+    #[serde(default, skip_serializing_if = "Option::is_none")]
+    pub enable: Option<u64>,
+
+    /// Log ratelimiting settings
+    #[serde(default, skip_serializing_if = "Option::is_none")]
+    pub log_ratelimit: Option<String>,
+
+    #[serde(default, skip_serializing_if = "Option::is_none")]
+    pub policy_forward: Option<FirewallFWPolicy>,
+
+    #[serde(default, skip_serializing_if = "Option::is_none")]
+    pub policy_in: Option<FirewallIOPolicy>,
+
+    #[serde(default, skip_serializing_if = "Option::is_none")]
+    pub policy_out: Option<FirewallIOPolicy>,
+}
+
+const_regex! {
+
+UPDATE_GUEST_FIREWALL_OPTIONS_DELETE_RE = r##"^(?i:[a-z][a-z0-9_-]+)$"##;
+
+}
+
+#[test]
+fn test_regex_compilation_36() {
+    use regex::Regex;
+    let _: &Regex = &UPDATE_GUEST_FIREWALL_OPTIONS_DELETE_RE;
+}
+#[api(
+    properties: {
+        delete: {
+            items: {
+                description: "List item of type pve-configid.",
+                format: &ApiStringFormat::Pattern(&UPDATE_GUEST_FIREWALL_OPTIONS_DELETE_RE),
+                type: String,
+            },
+            optional: true,
+            type: Array,
+        },
+        dhcp: {
+            default: false,
+            optional: true,
+        },
+        digest: {
+            max_length: 64,
+            optional: true,
+            type: String,
+        },
+        enable: {
+            default: false,
+            optional: true,
+        },
+        ipfilter: {
+            default: false,
+            optional: true,
+        },
+        log_level_in: {
+            optional: true,
+            type: FirewallLogLevel,
+        },
+        log_level_out: {
+            optional: true,
+            type: FirewallLogLevel,
+        },
+        macfilter: {
+            default: true,
+            optional: true,
+        },
+        ndp: {
+            default: false,
+            optional: true,
+        },
+        policy_in: {
+            optional: true,
+            type: FirewallIOPolicy,
+        },
+        policy_out: {
+            optional: true,
+            type: FirewallIOPolicy,
+        },
+        radv: {
+            default: false,
+            optional: true,
+        },
+    },
+)]
+/// Object.
+#[derive(Debug, serde::Deserialize, serde::Serialize)]
+pub struct UpdateGuestFirewallOptions {
+    /// A list of settings you want to delete.
+    #[serde(default, skip_serializing_if = "Option::is_none")]
+    pub delete: Option<Vec<String>>,
+
+    /// Enable DHCP.
+    #[serde(deserialize_with = "proxmox_serde::perl::deserialize_bool")]
+    #[serde(default, skip_serializing_if = "Option::is_none")]
+    pub dhcp: Option<bool>,
+
+    /// Prevent changes if current configuration file has a different digest.
+    /// This can be used to prevent concurrent modifications.
+    #[serde(default, skip_serializing_if = "Option::is_none")]
+    pub digest: Option<String>,
+
+    /// Enable/disable firewall rules.
+    #[serde(deserialize_with = "proxmox_serde::perl::deserialize_bool")]
+    #[serde(default, skip_serializing_if = "Option::is_none")]
+    pub enable: Option<bool>,
+
+    /// Enable default IP filters. This is equivalent to adding an empty
+    /// ipfilter-net<id> ipset for every interface. Such ipsets implicitly
+    /// contain sane default restrictions such as restricting IPv6 link local
+    /// addresses to the one derived from the interface's MAC address. For
+    /// containers the configured IP addresses will be implicitly added.
+    #[serde(deserialize_with = "proxmox_serde::perl::deserialize_bool")]
+    #[serde(default, skip_serializing_if = "Option::is_none")]
+    pub ipfilter: Option<bool>,
+
+    #[serde(default, skip_serializing_if = "Option::is_none")]
+    pub log_level_in: Option<FirewallLogLevel>,
+
+    #[serde(default, skip_serializing_if = "Option::is_none")]
+    pub log_level_out: Option<FirewallLogLevel>,
+
+    /// Enable/disable MAC address filter.
+    #[serde(deserialize_with = "proxmox_serde::perl::deserialize_bool")]
+    #[serde(default, skip_serializing_if = "Option::is_none")]
+    pub macfilter: Option<bool>,
+
+    /// Enable NDP (Neighbor Discovery Protocol).
+    #[serde(deserialize_with = "proxmox_serde::perl::deserialize_bool")]
+    #[serde(default, skip_serializing_if = "Option::is_none")]
+    pub ndp: Option<bool>,
+
+    #[serde(default, skip_serializing_if = "Option::is_none")]
+    pub policy_in: Option<FirewallIOPolicy>,
+
+    #[serde(default, skip_serializing_if = "Option::is_none")]
+    pub policy_out: Option<FirewallIOPolicy>,
+
+    /// Allow sending Router Advertisement.
+    #[serde(deserialize_with = "proxmox_serde::perl::deserialize_bool")]
+    #[serde(default, skip_serializing_if = "Option::is_none")]
+    pub radv: Option<bool>,
+}
+
+const_regex! {
+
+UPDATE_NODE_FIREWALL_OPTIONS_DELETE_RE = r##"^(?i:[a-z][a-z0-9_-]+)$"##;
+
+}
+
+#[test]
+fn test_regex_compilation_37() {
+    use regex::Regex;
+    let _: &Regex = &UPDATE_NODE_FIREWALL_OPTIONS_DELETE_RE;
+}
+#[api(
+    properties: {
+        delete: {
+            items: {
+                description: "List item of type pve-configid.",
+                format: &ApiStringFormat::Pattern(&UPDATE_NODE_FIREWALL_OPTIONS_DELETE_RE),
+                type: String,
+            },
+            optional: true,
+            type: Array,
+        },
+        digest: {
+            max_length: 64,
+            optional: true,
+            type: String,
+        },
+        enable: {
+            default: true,
+            optional: true,
+        },
+        log_level_forward: {
+            optional: true,
+            type: FirewallLogLevel,
+        },
+        log_level_in: {
+            optional: true,
+            type: FirewallLogLevel,
+        },
+        log_level_out: {
+            optional: true,
+            type: FirewallLogLevel,
+        },
+        log_nf_conntrack: {
+            default: false,
+            optional: true,
+        },
+        ndp: {
+            default: false,
+            optional: true,
+        },
+        nf_conntrack_allow_invalid: {
+            default: false,
+            optional: true,
+        },
+        nf_conntrack_helpers: {
+            default: "",
+            format: &ApiStringFormat::PropertyString(&UPDATE_NODE_FIREWALL_OPTIONS_NF_CONNTRACK_HELPERS),
+            optional: true,
+            type: String,
+        },
+        nf_conntrack_max: {
+            default: 262144,
+            minimum: 32768,
+            optional: true,
+            type: Integer,
+        },
+        nf_conntrack_tcp_timeout_established: {
+            default: 432000,
+            minimum: 7875,
+            optional: true,
+            type: Integer,
+        },
+        nf_conntrack_tcp_timeout_syn_recv: {
+            default: 60,
+            maximum: 60,
+            minimum: 30,
+            optional: true,
+            type: Integer,
+        },
+        nftables: {
+            default: false,
+            optional: true,
+        },
+        nosmurfs: {
+            default: false,
+            optional: true,
+        },
+        protection_synflood: {
+            default: false,
+            optional: true,
+        },
+        protection_synflood_burst: {
+            default: 1000,
+            optional: true,
+            type: Integer,
+        },
+        protection_synflood_rate: {
+            default: 200,
+            optional: true,
+            type: Integer,
+        },
+        smurf_log_level: {
+            optional: true,
+            type: FirewallLogLevel,
+        },
+        tcp_flags_log_level: {
+            optional: true,
+            type: FirewallLogLevel,
+        },
+        tcpflags: {
+            default: false,
+            optional: true,
+        },
+    },
+)]
+/// Object.
+#[derive(Debug, serde::Deserialize, serde::Serialize)]
+pub struct UpdateNodeFirewallOptions {
+    /// A list of settings you want to delete.
+    #[serde(default, skip_serializing_if = "Option::is_none")]
+    pub delete: Option<Vec<String>>,
+
+    /// Prevent changes if current configuration file has a different digest.
+    /// This can be used to prevent concurrent modifications.
+    #[serde(default, skip_serializing_if = "Option::is_none")]
+    pub digest: Option<String>,
+
+    /// Enable host firewall rules.
+    #[serde(deserialize_with = "proxmox_serde::perl::deserialize_bool")]
+    #[serde(default, skip_serializing_if = "Option::is_none")]
+    pub enable: Option<bool>,
+
+    #[serde(default, skip_serializing_if = "Option::is_none")]
+    pub log_level_forward: Option<FirewallLogLevel>,
+
+    #[serde(default, skip_serializing_if = "Option::is_none")]
+    pub log_level_in: Option<FirewallLogLevel>,
+
+    #[serde(default, skip_serializing_if = "Option::is_none")]
+    pub log_level_out: Option<FirewallLogLevel>,
+
+    /// Enable logging of conntrack information.
+    #[serde(deserialize_with = "proxmox_serde::perl::deserialize_bool")]
+    #[serde(default, skip_serializing_if = "Option::is_none")]
+    pub log_nf_conntrack: Option<bool>,
+
+    /// Enable NDP (Neighbor Discovery Protocol).
+    #[serde(deserialize_with = "proxmox_serde::perl::deserialize_bool")]
+    #[serde(default, skip_serializing_if = "Option::is_none")]
+    pub ndp: Option<bool>,
+
+    /// Allow invalid packets on connection tracking.
+    #[serde(deserialize_with = "proxmox_serde::perl::deserialize_bool")]
+    #[serde(default, skip_serializing_if = "Option::is_none")]
+    pub nf_conntrack_allow_invalid: Option<bool>,
+
+    /// Enable conntrack helpers for specific protocols. Supported protocols:
+    /// amanda, ftp, irc, netbios-ns, pptp, sane, sip, snmp, tftp
+    #[serde(with = "update_node_firewall_options_nf_conntrack_helpers")]
+    #[serde(default, skip_serializing_if = "Option::is_none")]
+    pub nf_conntrack_helpers: Option<Vec<FwConntrackHelper>>,
+
+    /// Maximum number of tracked connections.
+    #[serde(deserialize_with = "proxmox_serde::perl::deserialize_u64")]
+    #[serde(default, skip_serializing_if = "Option::is_none")]
+    pub nf_conntrack_max: Option<u64>,
+
+    /// Conntrack established timeout.
+    #[serde(deserialize_with = "proxmox_serde::perl::deserialize_u64")]
+    #[serde(default, skip_serializing_if = "Option::is_none")]
+    pub nf_conntrack_tcp_timeout_established: Option<u64>,
+
+    /// Conntrack syn recv timeout.
+    #[serde(deserialize_with = "proxmox_serde::perl::deserialize_u8")]
+    #[serde(default, skip_serializing_if = "Option::is_none")]
+    pub nf_conntrack_tcp_timeout_syn_recv: Option<u8>,
+
+    /// Enable nftables based firewall (tech preview)
+    #[serde(deserialize_with = "proxmox_serde::perl::deserialize_bool")]
+    #[serde(default, skip_serializing_if = "Option::is_none")]
+    pub nftables: Option<bool>,
+
+    /// Enable SMURFS filter.
+    #[serde(deserialize_with = "proxmox_serde::perl::deserialize_bool")]
+    #[serde(default, skip_serializing_if = "Option::is_none")]
+    pub nosmurfs: Option<bool>,
+
+    /// Enable synflood protection
+    #[serde(deserialize_with = "proxmox_serde::perl::deserialize_bool")]
+    #[serde(default, skip_serializing_if = "Option::is_none")]
+    pub protection_synflood: Option<bool>,
+
+    /// Synflood protection rate burst by ip src.
+    #[serde(deserialize_with = "proxmox_serde::perl::deserialize_i64")]
+    #[serde(default, skip_serializing_if = "Option::is_none")]
+    pub protection_synflood_burst: Option<i64>,
+
+    /// Synflood protection rate syn/sec by ip src.
+    #[serde(deserialize_with = "proxmox_serde::perl::deserialize_i64")]
+    #[serde(default, skip_serializing_if = "Option::is_none")]
+    pub protection_synflood_rate: Option<i64>,
+
+    #[serde(default, skip_serializing_if = "Option::is_none")]
+    pub smurf_log_level: Option<FirewallLogLevel>,
+
+    #[serde(default, skip_serializing_if = "Option::is_none")]
+    pub tcp_flags_log_level: Option<FirewallLogLevel>,
+
+    /// Filter illegal combinations of TCP flags.
+    #[serde(deserialize_with = "proxmox_serde::perl::deserialize_bool")]
+    #[serde(default, skip_serializing_if = "Option::is_none")]
+    pub tcpflags: Option<bool>,
+}
+
+const_regex! {
+
+UPDATE_QEMU_CONFIG_AFFINITY_RE = r##"^(\s*\d+(-\d+)?\s*)(,\s*\d+(-\d+)?\s*)?$"##;
+UPDATE_QEMU_CONFIG_BOOTDISK_RE = r##"^(ide|sata|scsi|virtio|efidisk|tpmstate)\d+$"##;
+UPDATE_QEMU_CONFIG_DELETE_RE = r##"^(?i:[a-z][a-z0-9_-]+)$"##;
+UPDATE_QEMU_CONFIG_IMPORT_WORKING_STORAGE_RE = r##"^(?i:[a-z][a-z0-9\-_.]*[a-z0-9])$"##;
+UPDATE_QEMU_CONFIG_REVERT_RE = r##"^(?i:[a-z][a-z0-9_-]+)$"##;
+UPDATE_QEMU_CONFIG_SSHKEYS_RE = r##"^[-%a-zA-Z0-9_.!~*'()]*$"##;
+UPDATE_QEMU_CONFIG_TAGS_RE = r##"^(?i)[a-z0-9_][a-z0-9_\-+.]*$"##;
+UPDATE_QEMU_CONFIG_VMSTATESTORAGE_RE = r##"^(?i:[a-z][a-z0-9\-_.]*[a-z0-9])$"##;
+
+}
+
+#[test]
+fn test_regex_compilation_38() {
+    use regex::Regex;
+    let _: &Regex = &UPDATE_QEMU_CONFIG_AFFINITY_RE;
+    let _: &Regex = &UPDATE_QEMU_CONFIG_BOOTDISK_RE;
+    let _: &Regex = &UPDATE_QEMU_CONFIG_DELETE_RE;
+    let _: &Regex = &UPDATE_QEMU_CONFIG_IMPORT_WORKING_STORAGE_RE;
+    let _: &Regex = &UPDATE_QEMU_CONFIG_REVERT_RE;
+    let _: &Regex = &UPDATE_QEMU_CONFIG_SSHKEYS_RE;
+    let _: &Regex = &UPDATE_QEMU_CONFIG_TAGS_RE;
+    let _: &Regex = &UPDATE_QEMU_CONFIG_VMSTATESTORAGE_RE;
+}
+#[api(
+    properties: {
+        acpi: {
+            default: true,
+            optional: true,
+        },
+        affinity: {
+            format: &ApiStringFormat::Pattern(&UPDATE_QEMU_CONFIG_AFFINITY_RE),
+            optional: true,
+            type: String,
+        },
+        agent: {
             format: &ApiStringFormat::PropertyString(&QemuConfigAgent::API_SCHEMA),
             optional: true,
             type: String,
@@ -12684,7 +13928,7 @@ UPDATE_QEMU_CONFIG_EFIDISK0_SIZE_RE = r##"^(\d+(\.\d+)?)([KMGT])?$"##;
 }
 
 #[test]
-fn test_regex_compilation_36() {
+fn test_regex_compilation_39() {
     use regex::Regex;
     let _: &Regex = &UPDATE_QEMU_CONFIG_EFIDISK0_SIZE_RE;
 }
@@ -12761,7 +14005,7 @@ UPDATE_QEMU_CONFIG_IDE_SIZE_RE = r##"^(\d+(\.\d+)?)([KMGT])?$"##;
 }
 
 #[test]
-fn test_regex_compilation_37() {
+fn test_regex_compilation_40() {
     use regex::Regex;
     let _: &Regex = &UPDATE_QEMU_CONFIG_IDE_MODEL_RE;
     let _: &Regex = &UPDATE_QEMU_CONFIG_IDE_SERIAL_RE;
@@ -13117,7 +14361,7 @@ UPDATE_QEMU_CONFIG_SATA_SIZE_RE = r##"^(\d+(\.\d+)?)([KMGT])?$"##;
 }
 
 #[test]
-fn test_regex_compilation_38() {
+fn test_regex_compilation_41() {
     use regex::Regex;
     let _: &Regex = &UPDATE_QEMU_CONFIG_SATA_SERIAL_RE;
     let _: &Regex = &UPDATE_QEMU_CONFIG_SATA_SIZE_RE;
@@ -13462,7 +14706,7 @@ UPDATE_QEMU_CONFIG_SCSI_SIZE_RE = r##"^(\d+(\.\d+)?)([KMGT])?$"##;
 }
 
 #[test]
-fn test_regex_compilation_39() {
+fn test_regex_compilation_42() {
     use regex::Regex;
     let _: &Regex = &UPDATE_QEMU_CONFIG_SCSI_SERIAL_RE;
     let _: &Regex = &UPDATE_QEMU_CONFIG_SCSI_SIZE_RE;
@@ -13862,7 +15106,7 @@ UPDATE_QEMU_CONFIG_TPMSTATE0_SIZE_RE = r##"^(\d+(\.\d+)?)([KMGT])?$"##;
 }
 
 #[test]
-fn test_regex_compilation_40() {
+fn test_regex_compilation_43() {
     use regex::Regex;
     let _: &Regex = &UPDATE_QEMU_CONFIG_TPMSTATE0_SIZE_RE;
 }
@@ -13918,7 +15162,7 @@ UPDATE_QEMU_CONFIG_VIRTIO_SIZE_RE = r##"^(\d+(\.\d+)?)([KMGT])?$"##;
 }
 
 #[test]
-fn test_regex_compilation_41() {
+fn test_regex_compilation_44() {
     use regex::Regex;
     let _: &Regex = &UPDATE_QEMU_CONFIG_VIRTIO_SERIAL_RE;
     let _: &Regex = &UPDATE_QEMU_CONFIG_VIRTIO_SIZE_RE;
-- 
2.47.3



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


  parent reply	other threads:[~2025-10-30 14:34 UTC|newest]

Thread overview: 14+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-10-30 14:33 [pdm-devel] [PATCH proxmox{, -yew-comp, -datacenter-manager} 00/13] add basic integration of PVE firewall Hannes Laimer
2025-10-30 14:33 ` [pdm-devel] [PATCH proxmox 1/5] pve-api-types: update pve-api.json Hannes Laimer
2025-10-30 14:33 ` [pdm-devel] [PATCH proxmox 2/5] pve-api-types: add get/update firewall options endpoints Hannes Laimer
2025-10-30 14:33 ` [pdm-devel] [PATCH proxmox 3/5] pve-api-types: schema2rust: handle `macro` keyword like we do `type` Hannes Laimer
2025-10-30 14:33 ` [pdm-devel] [PATCH proxmox 4/5] pve-api-types: add list firewall rules endpoints Hannes Laimer
2025-10-30 14:33 ` Hannes Laimer [this message]
2025-10-30 14:33 ` [pdm-devel] [PATCH proxmox-yew-comp 1/4] form: add helpers for extractig data out of schemas Hannes Laimer
2025-10-30 14:34 ` [pdm-devel] [PATCH proxmox-yew-comp 2/4] firewall: add FirewallContext Hannes Laimer
2025-10-30 14:34 ` [pdm-devel] [PATCH proxmox-yew-comp 3/4] firewall: add options edit form Hannes Laimer
2025-10-30 14:34 ` [pdm-devel] [PATCH proxmox-yew-comp 4/4] firewall: add rules table Hannes Laimer
2025-10-30 14:34 ` [pdm-devel] [PATCH proxmox-datacenter-manager 1/4] pdm-api-types: add firewall status types Hannes Laimer
2025-10-30 14:34 ` [pdm-devel] [PATCH proxmox-datacenter-manager 2/4] api: firewall: add option, rules and status endpoints Hannes Laimer
2025-10-30 14:34 ` [pdm-devel] [PATCH proxmox-datacenter-manager 3/4] pdm-client: add api methods for firewall options, " Hannes Laimer
2025-10-30 14:34 ` [pdm-devel] [PATCH proxmox-datacenter-manager 4/4] ui: add firewall status tree Hannes Laimer

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20251030143406.193744-6-h.laimer@proxmox.com \
    --to=h.laimer@proxmox.com \
    --cc=pdm-devel@lists.proxmox.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.
Service provided by Proxmox Server Solutions GmbH | Privacy | Legal