From: Hannes Laimer <h.laimer@proxmox.com>
To: pdm-devel@lists.proxmox.com
Subject: [pdm-devel] [PATCH proxmox v2 4/4] pve-api-types: regenerate
Date: Wed, 5 Nov 2025 17:35:38 +0100 [thread overview]
Message-ID: <20251105163546.450094-5-h.laimer@proxmox.com> (raw)
In-Reply-To: <20251105163546.450094-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 | 1366 ++++++++++++++++++++++++--
2 files changed, 1503 insertions(+), 69 deletions(-)
diff --git a/pve-api-types/src/generated/code.rs b/pve-api-types/src/generated/code.rs
index dd90ec00..9b42076d 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
@@ -199,8 +197,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
@@ -219,9 +215,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
@@ -286,9 +280,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}/mtunnel
@@ -382,6 +374,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,
@@ -478,6 +475,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,
@@ -498,6 +500,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,
@@ -507,6 +518,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"))
@@ -517,6 +533,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,
@@ -549,6 +574,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,
@@ -585,6 +619,11 @@ 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"))
@@ -595,6 +634,15 @@ pub trait PveClient {
Err(Error::Other("qemu_cpu_capabilities 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.
@@ -712,6 +760,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(
@@ -825,6 +910,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,
@@ -972,6 +1063,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,
@@ -999,6 +1096,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,
@@ -1011,6 +1118,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";
@@ -1025,6 +1138,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,
@@ -1073,6 +1196,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,
@@ -1116,6 +1249,12 @@ where
Ok(self.0.post(url, ¶ms).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");
@@ -1128,6 +1267,16 @@ where
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.
@@ -1271,6 +1420,47 @@ where
Ok(self.0.put(url, ¶ms).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, ¶ms).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, ¶ms).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, ¶ms).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, ¶ms).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 5321cf67..daaceef7 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: {
@@ -13120,43 +13827,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_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_36() {
- 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_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,
+ 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_36() {
+ 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_37() {
+ 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_38() {
+ 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_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_39() {
+ 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_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,
},
"amd-sev": {
@@ -14024,7 +15268,7 @@ UPDATE_QEMU_CONFIG_ASYNC_VMSTATESTORAGE_RE = r##"^(?i:[a-z][a-z0-9\-_.]*[a-z0-9]
}
#[test]
-fn test_regex_compilation_37() {
+fn test_regex_compilation_40() {
use regex::Regex;
let _: &Regex = &UPDATE_QEMU_CONFIG_ASYNC_AFFINITY_RE;
let _: &Regex = &UPDATE_QEMU_CONFIG_ASYNC_BOOTDISK_RE;
@@ -14893,7 +16137,7 @@ UPDATE_QEMU_CONFIG_EFIDISK0_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_EFIDISK0_SIZE_RE;
}
@@ -14970,7 +16214,7 @@ UPDATE_QEMU_CONFIG_IDE_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_IDE_MODEL_RE;
let _: &Regex = &UPDATE_QEMU_CONFIG_IDE_SERIAL_RE;
@@ -15326,7 +16570,7 @@ UPDATE_QEMU_CONFIG_SATA_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_SATA_SERIAL_RE;
let _: &Regex = &UPDATE_QEMU_CONFIG_SATA_SIZE_RE;
@@ -15671,7 +16915,7 @@ UPDATE_QEMU_CONFIG_SCSI_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_SCSI_SERIAL_RE;
let _: &Regex = &UPDATE_QEMU_CONFIG_SCSI_SIZE_RE;
@@ -16071,7 +17315,7 @@ UPDATE_QEMU_CONFIG_TPMSTATE0_SIZE_RE = r##"^(\d+(\.\d+)?)([KMGT])?$"##;
}
#[test]
-fn test_regex_compilation_42() {
+fn test_regex_compilation_45() {
use regex::Regex;
let _: &Regex = &UPDATE_QEMU_CONFIG_TPMSTATE0_SIZE_RE;
}
@@ -16127,7 +17371,7 @@ UPDATE_QEMU_CONFIG_VIRTIO_SIZE_RE = r##"^(\d+(\.\d+)?)([KMGT])?$"##;
}
#[test]
-fn test_regex_compilation_43() {
+fn test_regex_compilation_46() {
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
next prev parent reply other threads:[~2025-11-05 16:35 UTC|newest]
Thread overview: 13+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-11-05 16:35 [pdm-devel] [PATCH proxmox{, -yew-comp, -datacenter-manager} v2 00/12] add basic integration of PVE firewall Hannes Laimer
2025-11-05 16:35 ` [pdm-devel] [PATCH proxmox v2 1/4] pve-api-types: update pve-api.json Hannes Laimer
2025-11-05 16:35 ` [pdm-devel] [PATCH proxmox v2 2/4] pve-api-types: add get/update firewall options endpoints Hannes Laimer
2025-11-05 16:35 ` [pdm-devel] [PATCH proxmox v2 3/4] pve-api-types: add list firewall rules endpoints Hannes Laimer
2025-11-05 16:35 ` Hannes Laimer [this message]
2025-11-05 16:35 ` [pdm-devel] [PATCH proxmox-yew-comp v2 1/4] form: add helpers for extractig data out of schemas Hannes Laimer
2025-11-05 16:35 ` [pdm-devel] [PATCH proxmox-yew-comp v2 2/4] firewall: add FirewallContext Hannes Laimer
2025-11-05 16:35 ` [pdm-devel] [PATCH proxmox-yew-comp v2 3/4] firewall: add options edit form Hannes Laimer
2025-11-05 16:35 ` [pdm-devel] [PATCH proxmox-yew-comp v2 4/4] firewall: add rules table Hannes Laimer
2025-11-05 16:35 ` [pdm-devel] [PATCH proxmox-datacenter-manager v2 1/4] pdm-api-types: add firewall status types Hannes Laimer
2025-11-05 16:35 ` [pdm-devel] [PATCH proxmox-datacenter-manager v2 2/4] api: firewall: add option, rules and status endpoints Hannes Laimer
2025-11-05 16:35 ` [pdm-devel] [PATCH proxmox-datacenter-manager v2 3/4] pdm-client: add api methods for firewall options, " Hannes Laimer
2025-11-05 16:35 ` [pdm-devel] [PATCH proxmox-datacenter-manager v2 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=20251105163546.450094-5-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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox