From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from firstgate.proxmox.com (firstgate.proxmox.com [212.224.123.68]) by lore.proxmox.com (Postfix) with ESMTPS id 1E6DB1FF14F for ; Fri, 08 May 2026 20:46:59 +0200 (CEST) Received: from firstgate.proxmox.com (localhost [127.0.0.1]) by firstgate.proxmox.com (Proxmox) with ESMTP id E0462217BB; Fri, 8 May 2026 20:46:40 +0200 (CEST) From: Christoph Heiss To: pve-devel@lists.proxmox.com Subject: [PATCH installer 7/8] common: options: rework network address setup to handle ipv6-only Date: Fri, 8 May 2026 20:44:10 +0200 Message-ID: <20260508184546.113293-8-c.heiss@proxmox.com> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260508184546.113293-1-c.heiss@proxmox.com> References: <20260508184546.113293-1-c.heiss@proxmox.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Bm-Milter-Handled: 55990f41-d878-4baa-be0a-ee34c49e34d2 X-Bm-Transport-Timestamp: 1778265879894 X-SPAM-LEVEL: Spam detection results: 0 AWL 0.076 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 Message-ID-Hash: 7QC6FIKO2KJ5754LXKNFSZXJNIIJUZLF X-Message-ID-Hash: 7QC6FIKO2KJ5754LXKNFSZXJNIIJUZLF X-MailFrom: c.heiss@proxmox.com X-Mailman-Rule-Misses: dmarc-mitigation; no-senders; approved; loop; banned-address; emergency; member-moderation; nonmember-moderation; administrivia; implicit-dest; max-recipients; max-size; news-moderation; no-subject; digests; suspicious-header X-Mailman-Version: 3.3.10 Precedence: list List-Id: Proxmox VE development discussion List-Help: List-Owner: List-Post: List-Subscribe: List-Unsubscribe: With this, IPv6-only setups are now handled properly. Previously it would fail to actually select IPv6 addresses for the interface and DNS on such setups, instead falling back to the default IPv4 addresses set above. Signed-off-by: Christoph Heiss --- proxmox-installer-common/src/options.rs | 89 ++++++++++++------------- 1 file changed, 44 insertions(+), 45 deletions(-) diff --git a/proxmox-installer-common/src/options.rs b/proxmox-installer-common/src/options.rs index ed00b4b..8929bd4 100644 --- a/proxmox-installer-common/src/options.rs +++ b/proxmox-installer-common/src/options.rs @@ -425,59 +425,58 @@ impl NetworkOptions { pinning_opts: pinning_opts.cloned(), }; - if let Some(ip) = network.dns.dns.first() { - this.dns_server = *ip; - } - - if let Some(routes) = &network.routes - && let Some(gw) = &routes.gateway4 - && let Some(iface) = network.interfaces.get(&gw.dev) - { - // we got some ipv4 connectivity, so use that - - if let Some(opts) = pinning_opts - && let Some(pinned) = iface.to_pinned(opts) - { - this.ifname.clone_from(&pinned.name); - } else { - this.ifname.clone_from(&iface.name); - } - - if let Some(addr) = iface.addresses.iter().find(|addr| addr.is_ipv4()) { - this.gateway = gw.gateway; - this.address = *addr; - } else if let Some(gw) = &routes.gateway6 + let iface = if let Some(routes) = &network.routes { + if let Some(gw) = &routes.gateway4 && let Some(iface) = network.interfaces.get(&gw.dev) - && let Some(addr) = iface.addresses.iter().find(|addr| addr.is_ipv6()) { - // no ipv4, but ipv6 connectivity - if let Some(opts) = pinning_opts - && let Some(pinned) = iface.to_pinned(opts) - { - this.ifname.clone_from(&pinned.name); - } else { - this.ifname.clone_from(&iface.name); + this.gateway = gw.gateway; + + if let Some(addr) = iface.addresses.iter().find(|addr| addr.is_ipv4()) { + this.address = *addr; } - this.gateway = gw.gateway; - this.address = *addr; - } - } + if let Some(addr) = network.dns.dns.iter().find(|addr| addr.is_ipv4()) { + this.dns_server = *addr; + } - // In case no there are no routes defined at all (e.g. no DHCP lease), - // try to set the interface name to *some* valid values. At least one - // NIC should always be present here, as the installation will abort - // earlier in that case, so use the first one enumerated. - if this.ifname.is_empty() - && let Some(iface) = network.interfaces.values().min_by_key(|v| v.index) - { - if let Some(opts) = pinning_opts - && let Some(pinned) = iface.to_pinned(opts) + Some(iface) + } else if let Some(gw) = &routes.gateway6 + && let Some(iface) = network.interfaces.get(&gw.dev) { - this.ifname.clone_from(&pinned.name); + this.gateway = gw.gateway; + + if let Some(addr) = iface.addresses.iter().find(|addr| addr.is_ipv6()) { + this.address = *addr; + } + + if let Some(addr) = network.dns.dns.iter().find(|addr| addr.is_ipv6()) { + this.dns_server = *addr; + } + + Some(iface) } else { - this.ifname.clone_from(&iface.name); + None } + } else { + None + } + .unwrap_or_else(|| { + // Safety: In case no there are no routes defined at all (e.g. no DHCP lease), try to + // set the interface name to *some* valid values. At least one NIC must always be + // present here, as the installation will abort earlier otherwise, so use the first one + // enumerated. + network + .interfaces + .values() + .min_by_key(|v| v.index) + .expect("at least one NIC must be present") + }); + + // Use pinned network interface name, if enabled + if let Some(pinned) = pinning_opts.and_then(|opts| iface.to_pinned(opts)) { + this.ifname.clone_from(&pinned.name); + } else { + this.ifname.clone_from(&iface.name); } if let Some(ref mut opts) = this.pinning_opts { -- 2.53.0