From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from firstgate.proxmox.com (firstgate.proxmox.com [IPv6:2a01:7e0:0:424::9]) by lore.proxmox.com (Postfix) with ESMTPS id EB61C1FF17E for ; Thu, 30 Oct 2025 15:34:21 +0100 (CET) Received: from firstgate.proxmox.com (localhost [127.0.0.1]) by firstgate.proxmox.com (Proxmox) with ESMTP id 7682924591; Thu, 30 Oct 2025 15:34:56 +0100 (CET) From: Hannes Laimer To: pdm-devel@lists.proxmox.com Date: Thu, 30 Oct 2025 15:33:58 +0100 Message-ID: <20251030143406.193744-6-h.laimer@proxmox.com> X-Mailer: git-send-email 2.47.3 In-Reply-To: <20251030143406.193744-1-h.laimer@proxmox.com> References: <20251030143406.193744-1-h.laimer@proxmox.com> MIME-Version: 1.0 X-Bm-Milter-Handled: 55990f41-d878-4baa-be0a-ee34c49e34d2 X-Bm-Transport-Timestamp: 1761834835881 X-SPAM-LEVEL: Spam detection results: 0 AWL -0.108 Adjusted score from AWL reputation of From: address BAYES_00 -1.9 Bayes spam probability is 0 to 1% DMARC_MISSING 0.1 Missing DMARC policy KAM_DMARC_STATUS 0.01 Test Rule for DKIM or SPF Failure with Strict Alignment POISEN_SPAM_PILL 0.1 Meta: its spam POISEN_SPAM_PILL_1 0.1 random spam to be learned in bayes POISEN_SPAM_PILL_3 0.1 random spam to be learned in bayes RCVD_IN_MSPIKE_H2 0.001 Average reputation (+2) SPF_HELO_NONE 0.001 SPF: HELO does not publish an SPF Record SPF_PASS -0.001 SPF: sender matches SPF record Subject: [pdm-devel] [PATCH proxmox 5/5] pve-api-types: regenerate X-BeenThere: pdm-devel@lists.proxmox.com X-Mailman-Version: 2.1.29 Precedence: list List-Id: Proxmox Datacenter Manager development discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: Proxmox Datacenter Manager development discussion Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Errors-To: pdm-devel-bounces@lists.proxmox.com Sender: "pdm-devel" Signed-off-by: Hannes Laimer --- 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 { + 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, 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, 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, Error> { + Err(Error::Other("list_node_firewall_rules not implemented")) + } + /// Cluster node index. async fn list_nodes(&self) -> Result, 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, 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 { + 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 { + Err(Error::Other("node_firewall_options not implemented")) + } + /// Read node status async fn node_status(&self, node: &str) -> Result { Err(Error::Other("node_status not implemented")) } + /// Get VM firewall options. + async fn qemu_firewall_options( + &self, + node: &str, + vmid: u32, + ) -> Result { + 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 { + 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, 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, 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, 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, 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, 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 { + 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, ¶ms).await?.expect_json()?.data) } + /// Get host firewall options. + async fn node_firewall_options(&self, node: &str) -> Result { + 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 { 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 { + 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, ¶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 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, + + /// 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, + + /// Log ratelimiting settings + #[serde(default, skip_serializing_if = "Option::is_none")] + pub log_ratelimit: Option, + + #[serde(default, skip_serializing_if = "Option::is_none")] + pub policy_forward: Option, + + #[serde(default, skip_serializing_if = "Option::is_none")] + pub policy_in: Option, + + #[serde(default, skip_serializing_if = "Option::is_none")] + pub policy_out: Option, +} + +#[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, + + /// 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, +} + 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, + + /// Enable/disable firewall rules. + #[serde(deserialize_with = "proxmox_serde::perl::deserialize_bool")] + #[serde(default, skip_serializing_if = "Option::is_none")] + pub enable: Option, + + /// Enable default IP filters. This is equivalent to adding an empty + /// ipfilter-net 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, + + #[serde(default, skip_serializing_if = "Option::is_none")] + pub log_level_in: Option, + + #[serde(default, skip_serializing_if = "Option::is_none")] + pub log_level_out: Option, + + /// Enable/disable MAC address filter. + #[serde(deserialize_with = "proxmox_serde::perl::deserialize_bool")] + #[serde(default, skip_serializing_if = "Option::is_none")] + pub macfilter: Option, + + /// Enable NDP (Neighbor Discovery Protocol). + #[serde(deserialize_with = "proxmox_serde::perl::deserialize_bool")] + #[serde(default, skip_serializing_if = "Option::is_none")] + pub ndp: Option, + + #[serde(default, skip_serializing_if = "Option::is_none")] + pub policy_in: Option, + + #[serde(default, skip_serializing_if = "Option::is_none")] + pub policy_out: Option, + + /// Allow sending Router Advertisement. + #[serde(deserialize_with = "proxmox_serde::perl::deserialize_bool")] + #[serde(default, skip_serializing_if = "Option::is_none")] + pub radv: Option, +} + #[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, + + /// Restrict packet destination address + #[serde(default, skip_serializing_if = "Option::is_none")] + pub dest: Option, + + /// Restrict TCP/UDP destination port + #[serde(default, skip_serializing_if = "Option::is_none")] + pub dport: Option, + + /// 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, + + /// 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, + + /// 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, + + /// 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, + + #[serde(default, skip_serializing_if = "Option::is_none")] + pub log: Option, + + /// Use predefined standard macro + #[serde(default, skip_serializing_if = "Option::is_none")] + #[serde(rename = "macro")] + pub r#macro: Option, + + /// 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, + + /// Restrict packet source address + #[serde(default, skip_serializing_if = "Option::is_none")] + pub source: Option, + + /// Restrict TCP/UDP source port + #[serde(default, skip_serializing_if = "Option::is_none")] + pub sport: Option, + + /// 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, } -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(&self, serializer: S) -> Result; + fn de<'de, D>(deserializer: D) -> Result + 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 Deserialize<'a>> Ser for Vec { + fn ser(&self, serializer: S) -> Result + where + S: Serializer, + { + super::stringlist::serialize( + &self[..], + serializer, + &super::NODE_FIREWALL_OPTIONS_NF_CONNTRACK_HELPERS, + ) + } + + fn de<'de, D>(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + super::stringlist::deserialize( + deserializer, + &super::NODE_FIREWALL_OPTIONS_NF_CONNTRACK_HELPERS, + ) + } + } + + impl Ser for Option { + fn ser(&self, serializer: S) -> Result + where + S: Serializer, + { + match self { + None => serializer.serialize_none(), + Some(inner) => inner.ser(serializer), + } + } + + fn de<'de, D>(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + use std::fmt; + use std::marker::PhantomData; + + struct V(PhantomData); + + impl<'de, T: Ser> serde::de::Visitor<'de> for V { + type Value = Option; + + fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.write_str("an optional string") + } + + fn visit_none(self) -> Result { + Ok(None) + } + + fn visit_some(self, deserializer: D) -> Result + where + D: Deserializer<'de>, + { + T::de(deserializer).map(Some) + } + + fn visit_str(self, value: &str) -> Result { + use serde::de::IntoDeserializer; + T::de(value.into_deserializer()).map(Some) + } + } + + deserializer.deserialize_option(V::(PhantomData)) + } + } + + pub fn serialize(this: &T, serializer: S) -> Result + where + S: serde::Serializer, + T: Ser, + { + this.ser(serializer) + } + + pub fn deserialize<'de, T, D>(deserializer: D) -> Result + 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, + + #[serde(default, skip_serializing_if = "Option::is_none")] + pub log_level_forward: Option, + + #[serde(default, skip_serializing_if = "Option::is_none")] + pub log_level_in: Option, + + #[serde(default, skip_serializing_if = "Option::is_none")] + pub log_level_out: Option, + + /// 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, + + /// Enable NDP (Neighbor Discovery Protocol). + #[serde(deserialize_with = "proxmox_serde::perl::deserialize_bool")] + #[serde(default, skip_serializing_if = "Option::is_none")] + pub ndp: Option, + + /// 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, + + /// 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>, + + /// 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, + + /// 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, + + /// 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, + + /// 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, + + /// Enable SMURFS filter. + #[serde(deserialize_with = "proxmox_serde::perl::deserialize_bool")] + #[serde(default, skip_serializing_if = "Option::is_none")] + pub nosmurfs: Option, + + /// Enable synflood protection + #[serde(deserialize_with = "proxmox_serde::perl::deserialize_bool")] + #[serde(default, skip_serializing_if = "Option::is_none")] + pub protection_synflood: Option, + + /// 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, + + /// 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, + + #[serde(default, skip_serializing_if = "Option::is_none")] + pub smurf_log_level: Option, + + #[serde(default, skip_serializing_if = "Option::is_none")] + pub tcp_flags_log_level: Option, + + /// 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, +} + #[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(&self, serializer: S) -> Result; + fn de<'de, D>(deserializer: D) -> Result + 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 Deserialize<'a>> Ser for Vec { + fn ser(&self, serializer: S) -> Result + where + S: Serializer, + { + super::stringlist::serialize( + &self[..], + serializer, + &super::UPDATE_NODE_FIREWALL_OPTIONS_NF_CONNTRACK_HELPERS, + ) + } + + fn de<'de, D>(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + super::stringlist::deserialize( + deserializer, + &super::UPDATE_NODE_FIREWALL_OPTIONS_NF_CONNTRACK_HELPERS, + ) + } + } + + impl Ser for Option { + fn ser(&self, serializer: S) -> Result + where + S: Serializer, + { + match self { + None => serializer.serialize_none(), + Some(inner) => inner.ser(serializer), + } + } + + fn de<'de, D>(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + use std::fmt; + use std::marker::PhantomData; + + struct V(PhantomData); + + impl<'de, T: Ser> serde::de::Visitor<'de> for V { + type Value = Option; + + fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.write_str("an optional string") + } + + fn visit_none(self) -> Result { + Ok(None) + } + + fn visit_some(self, deserializer: D) -> Result + where + D: Deserializer<'de>, + { + T::de(deserializer).map(Some) + } + + fn visit_str(self, value: &str) -> Result { + use serde::de::IntoDeserializer; + T::de(value.into_deserializer()).map(Some) + } + } + + deserializer.deserialize_option(V::(PhantomData)) + } + } + + pub fn serialize(this: &T, serializer: S) -> Result + where + S: serde::Serializer, + T: Ser, + { + this.ser(serializer) + } + + pub fn deserialize<'de, T, D>(deserializer: D) -> Result + 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>, + + /// 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, + + /// Enable ebtables rules cluster wide. + #[serde(deserialize_with = "proxmox_serde::perl::deserialize_bool")] + #[serde(default, skip_serializing_if = "Option::is_none")] + pub ebtables: Option, + + /// 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, + + /// Log ratelimiting settings + #[serde(default, skip_serializing_if = "Option::is_none")] + pub log_ratelimit: Option, + + #[serde(default, skip_serializing_if = "Option::is_none")] + pub policy_forward: Option, + + #[serde(default, skip_serializing_if = "Option::is_none")] + pub policy_in: Option, + + #[serde(default, skip_serializing_if = "Option::is_none")] + pub policy_out: Option, +} + +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>, + + /// Enable DHCP. + #[serde(deserialize_with = "proxmox_serde::perl::deserialize_bool")] + #[serde(default, skip_serializing_if = "Option::is_none")] + pub dhcp: Option, + + /// 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, + + /// Enable/disable firewall rules. + #[serde(deserialize_with = "proxmox_serde::perl::deserialize_bool")] + #[serde(default, skip_serializing_if = "Option::is_none")] + pub enable: Option, + + /// Enable default IP filters. This is equivalent to adding an empty + /// ipfilter-net 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, + + #[serde(default, skip_serializing_if = "Option::is_none")] + pub log_level_in: Option, + + #[serde(default, skip_serializing_if = "Option::is_none")] + pub log_level_out: Option, + + /// Enable/disable MAC address filter. + #[serde(deserialize_with = "proxmox_serde::perl::deserialize_bool")] + #[serde(default, skip_serializing_if = "Option::is_none")] + pub macfilter: Option, + + /// Enable NDP (Neighbor Discovery Protocol). + #[serde(deserialize_with = "proxmox_serde::perl::deserialize_bool")] + #[serde(default, skip_serializing_if = "Option::is_none")] + pub ndp: Option, + + #[serde(default, skip_serializing_if = "Option::is_none")] + pub policy_in: Option, + + #[serde(default, skip_serializing_if = "Option::is_none")] + pub policy_out: Option, + + /// Allow sending Router Advertisement. + #[serde(deserialize_with = "proxmox_serde::perl::deserialize_bool")] + #[serde(default, skip_serializing_if = "Option::is_none")] + pub radv: Option, +} + +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>, + + /// 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, + + /// Enable host firewall rules. + #[serde(deserialize_with = "proxmox_serde::perl::deserialize_bool")] + #[serde(default, skip_serializing_if = "Option::is_none")] + pub enable: Option, + + #[serde(default, skip_serializing_if = "Option::is_none")] + pub log_level_forward: Option, + + #[serde(default, skip_serializing_if = "Option::is_none")] + pub log_level_in: Option, + + #[serde(default, skip_serializing_if = "Option::is_none")] + pub log_level_out: Option, + + /// 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, + + /// Enable NDP (Neighbor Discovery Protocol). + #[serde(deserialize_with = "proxmox_serde::perl::deserialize_bool")] + #[serde(default, skip_serializing_if = "Option::is_none")] + pub ndp: Option, + + /// 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, + + /// 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>, + + /// 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, + + /// 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, + + /// 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, + + /// 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, + + /// Enable SMURFS filter. + #[serde(deserialize_with = "proxmox_serde::perl::deserialize_bool")] + #[serde(default, skip_serializing_if = "Option::is_none")] + pub nosmurfs: Option, + + /// Enable synflood protection + #[serde(deserialize_with = "proxmox_serde::perl::deserialize_bool")] + #[serde(default, skip_serializing_if = "Option::is_none")] + pub protection_synflood: Option, + + /// 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, + + /// 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, + + #[serde(default, skip_serializing_if = "Option::is_none")] + pub smurf_log_level: Option, + + #[serde(default, skip_serializing_if = "Option::is_none")] + pub tcp_flags_log_level: Option, + + /// 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, +} + +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