From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from firstgate.proxmox.com (firstgate.proxmox.com [212.224.123.68]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits)) (No client certificate requested) by lists.proxmox.com (Postfix) with ESMTPS id B724B91142 for ; Wed, 3 Apr 2024 12:47:12 +0200 (CEST) Received: from firstgate.proxmox.com (localhost [127.0.0.1]) by firstgate.proxmox.com (Proxmox) with ESMTP id 99CF015FEF for ; Wed, 3 Apr 2024 12:46:42 +0200 (CEST) Received: from proxmox-new.maurer-it.com (proxmox-new.maurer-it.com [94.136.29.106]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits)) (No client certificate requested) by firstgate.proxmox.com (Proxmox) with ESMTPS for ; Wed, 3 Apr 2024 12:46:41 +0200 (CEST) Received: from proxmox-new.maurer-it.com (localhost.localdomain [127.0.0.1]) by proxmox-new.maurer-it.com (Proxmox) with ESMTP id BA36144D24 for ; Wed, 3 Apr 2024 12:46:41 +0200 (CEST) Content-Type: text/plain; charset=UTF-8 Date: Wed, 03 Apr 2024 12:46:40 +0200 Message-Id: Cc: "Wolfgang Bumiller" To: "Proxmox VE development discussion" From: "Max Carrara" Content-Transfer-Encoding: quoted-printable Mime-Version: 1.0 X-Mailer: aerc 0.17.0-72-g6a84f1331f1c References: <20240402171629.536804-1-s.hanreich@proxmox.com> <20240402171629.536804-7-s.hanreich@proxmox.com> In-Reply-To: <20240402171629.536804-7-s.hanreich@proxmox.com> X-SPAM-LEVEL: Spam detection results: 0 AWL 0.028 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 SPF_HELO_NONE 0.001 SPF: HELO does not publish an SPF Record SPF_PASS -0.001 SPF: sender matches SPF record Subject: Re: [pve-devel] [PATCH proxmox-firewall 06/37] config: host: add helpers for host network configuration X-BeenThere: pve-devel@lists.proxmox.com X-Mailman-Version: 2.1.29 Precedence: list List-Id: Proxmox VE development discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 03 Apr 2024 10:47:12 -0000 On Tue Apr 2, 2024 at 7:15 PM CEST, Stefan Hanreich wrote: > Currently the helpers for obtaining the host network configuration > panic on error, which could be avoided by the use of > OnceLock::get_or_init, but this method is currently only available in > nightly versions. > > Generally, if there is a problem with obtaining a hostname for the > current node then something else is probably already quite broken, so > I would deem it acceptable for now, same goes for obtaining the > current network configuration. > > Co-authored-by: Wolfgang Bumiller > Signed-off-by: Stefan Hanreich > --- > proxmox-ve-config/Cargo.toml | 1 + > proxmox-ve-config/src/host/mod.rs | 1 + > proxmox-ve-config/src/host/utils.rs | 97 +++++++++++++++++++++++++++++ > proxmox-ve-config/src/lib.rs | 1 + > 4 files changed, 100 insertions(+) > create mode 100644 proxmox-ve-config/src/host/mod.rs > create mode 100644 proxmox-ve-config/src/host/utils.rs > > diff --git a/proxmox-ve-config/Cargo.toml b/proxmox-ve-config/Cargo.toml > index 7bb391e..480eb58 100644 > --- a/proxmox-ve-config/Cargo.toml > +++ b/proxmox-ve-config/Cargo.toml > @@ -13,6 +13,7 @@ license =3D "AGPL-3" > [dependencies] > log =3D "0.4" > anyhow =3D "1" > +nix =3D "0.26" > =20 > serde =3D { version =3D "1", features =3D [ "derive" ] } > serde_json =3D "1" > diff --git a/proxmox-ve-config/src/host/mod.rs b/proxmox-ve-config/src/ho= st/mod.rs > new file mode 100644 > index 0000000..b5614dd > --- /dev/null > +++ b/proxmox-ve-config/src/host/mod.rs > @@ -0,0 +1 @@ > +pub mod utils; > diff --git a/proxmox-ve-config/src/host/utils.rs b/proxmox-ve-config/src/= host/utils.rs > new file mode 100644 > index 0000000..1636f95 > --- /dev/null > +++ b/proxmox-ve-config/src/host/utils.rs > @@ -0,0 +1,97 @@ > +use std::net::{IpAddr, ToSocketAddrs}; > +use std::sync::OnceLock; > + > +use crate::firewall::types::Cidr; > + > +use nix::sys::socket::{AddressFamily, SockaddrLike}; > + > +pub fn hostname() -> &'static str { > + static HOSTNAME: OnceLock =3D OnceLock::new(); > + > + // We should rather use get_or_try_init to avoid needing to panic > + // but it is currently experimental > + HOSTNAME.get_or_init(|| { > + use nix::libc::{c_char, gethostname, sysconf, _SC_HOST_NAME_MAX}= ; > + use std::ffi::CStr; > + > + let max_len =3D unsafe { sysconf(_SC_HOST_NAME_MAX) } as usize += 1; > + let mut buffer =3D vec![0; max_len]; > + > + let ret =3D unsafe { gethostname(buffer.as_mut_ptr() as *mut c_c= har, buffer.len()) }; > + > + if ret !=3D 0 { > + // failing to get the hostname means something is *really* o= ff > + panic!("gethostname failed with returncode {ret}"); > + } > + > + let c_str =3D CStr::from_bytes_until_nul(&buffer).expect("buffer= contains a NUL byte"); > + > + String::from_utf8_lossy(c_str.to_bytes()).to_string() > + }) IMO the closures here and below could later be put into something like proxmox-sys (or similar) as freestanding functions without static data and then called here - but this is fine as it is; just an idea! > +} > + > +pub fn host_ips() -> &'static [IpAddr] { > + static IP_ADDRESSES: OnceLock> =3D OnceLock::new(); > + > + // We should rather use get_or_try_init to avoid needing to panic > + // but it is currently experimental > + IP_ADDRESSES.get_or_init(|| { > + let hostname =3D hostname(); > + > + format!("{hostname}:0") > + .to_socket_addrs() > + .expect("local hostname is resolvable") > + .map(|addr| addr.ip()) > + .collect() > + }) ^ Here as well. > +} > + > +pub fn network_interface_cidrs() -> &'static [Cidr] { > + static INTERFACES: OnceLock> =3D OnceLock::new(); > + > + // We should rather use get_or_try_init to avoid needing to panic > + // but it is currently experimental > + INTERFACES.get_or_init(|| { > + use nix::ifaddrs::getifaddrs; > + > + let mut cidrs =3D Vec::new(); > + > + let interfaces =3D getifaddrs().expect("should be able to query = network interfaces"); > + > + for interface in interfaces { > + if let (Some(address), Some(netmask)) =3D (interface.address= , interface.netmask) { > + match (address.family(), netmask.family()) { > + (Some(AddressFamily::Inet), Some(AddressFamily::Inet= )) =3D> { > + let address =3D address.as_sockaddr_in().expect(= "is an IPv4 address").ip(); > + > + let netmask =3D netmask > + .as_sockaddr_in() > + .expect("is an IPv4 address") > + .ip() > + .count_ones() > + .try_into() > + .expect("count_ones of u32 is < u8_max"); > + > + cidrs.push(Cidr::new_v4(address, netmask).expect= ("netmask is valid")); > + } > + (Some(AddressFamily::Inet6), Some(AddressFamily::Ine= t6)) =3D> { > + let address =3D address.as_sockaddr_in6().expect= ("is an IPv6 address").ip(); > + > + let netmask_address =3D > + netmask.as_sockaddr_in6().expect("is an IPv6= address").ip(); > + > + let netmask =3D u128::from_be_bytes(netmask_addr= ess.octets()) > + .count_ones() > + .try_into() > + .expect("count_ones of u128 is < u8_max"); > + > + cidrs.push(Cidr::new_v6(address, netmask).expect= ("netmask is valid")); > + } > + _ =3D> continue, > + } > + } > + } > + > + cidrs > + }) ^ And this chonker too. > +} > diff --git a/proxmox-ve-config/src/lib.rs b/proxmox-ve-config/src/lib.rs > index a0734b8..2bf9352 100644 > --- a/proxmox-ve-config/src/lib.rs > +++ b/proxmox-ve-config/src/lib.rs > @@ -1 +1,2 @@ > pub mod firewall; > +pub mod host;