From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from gate001.proxmox.com (gate001.proxmox.com [45.144.208.40]) by lore.proxmox.com (Postfix) with ESMTPS id 681DC1FF0EC for ; Sat, 07 Nov 2026 23:30:43 +0100 (CET) Received: from gate001.proxmox.com (localhost.localdomain [127.0.0.1]) by gate001.proxmox.com (Proxmox) with ESMTP id B64E821553; Sat, 07 Nov 2026 23:30:40 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20260707; t=1794090625; x=1794695425; darn=lists.proxmox.com; h=content-transfer-encoding:mime-version:message-id:date:subject:to :from:from:to:cc:subject:date:message-id:reply-to:content-type; bh=52PddnjN5bgUcE6qW2TGNzfTgZ+f4UCQhbjC29aA+l0=; b=SSzv7swJcxOUZNlzx4jh/lrpXn0vtkV6tYg0/2sCOkSVlcHTRE5HbImDq40DvBI/M6 NiscFjqqcPypW6oVBvq2/Z1B0/BkZIGH34OUYR73vLvbdFddEqPk1tm1A9amTVk+pNRI gR4qv9pdNQqexqz8yQFBGczm81NhqWzxtDSnKR9a0hUDENrmrN0WO8a+TzTI4iH5eDbY ND/j8KBd6NCdp0l3OxwTvNyyJedwVT2geoavLkVU5aBpPlTj5WuqdzSfHiWW4waeZyHs 4qHKGy83z7oUPCmbh4aFd14pdRAQLC4bEq3ySDZIfQD/AKDLF8GP5Te1OTXKjfsHcPKF PKJQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1794090625; x=1794695425; h=content-transfer-encoding:mime-version:message-id:date:subject:to :from:x-gm-gg:x-gm-message-state:from:to:cc:subject:date:message-id :reply-to:content-type; bh=52PddnjN5bgUcE6qW2TGNzfTgZ+f4UCQhbjC29aA+l0=; b=KDPmPQk0MLvMXjtFLdbzUw76gcuUsBE18ePOWs0mrdixTKO5rZT7R4tiL8VCRJkl53 cB0OBZ2/KQr7QMVmRhc+cFAATYfEPRvNXedjSSaHF91EDYdkjOgN1zl2Eioz8Yzjp4V8 7ExhxB2/T0FBSIzkkxALSrraTSFghkCkw7depLu2ArivHuK9SRtM90jBdrXyAGPVsm+3 dGTb5nc2cjkTKEqmamc5HHVZERBSWN/vbzRV4Q6ykmItzn4HgOYhS5Js0CAfPDk9TEPH mOfUXKjMafRGdF89VJFoJ/B9YmRSHHDm8jqxdvsZk42Sd5ftfde0fnidY51pcrzJeMx+ 8qow== X-Gm-Message-State: APuU4Z+0D+TtqjZHOkh99mwLRcIvqWkan77nn3dDaIQ1aSVWtbGr+uLD Cu1JtsBifal3VWBpMfvGcBqmDQhR/uElNwcZmcy/XJG/gnB94OQMYys1uabL7DtA X-Gm-Gg: AYBFou3NTKPvJUmnx+8BR/+nHeSH4cjLkbeo+6su04mgCyVkaqfR1i92OCuoe53R/ge 1g3JL5kjvg4DNZiqgblxlNsdSpWX6XB8KxFxJDweir58Ikm8FbUnHSFDQ7mdgwiIEywj5cgho2Z QGW/fe8wg0w7Yy4bsInmR2n/4t81naeOlj8By8kV7aXO004jd1gsCztuhFR2im+x1eHpnLwQO99 5/tlNBsLtaUtH+peipvSBk9NTeAdhjEELSEjW348uYdn02BwLt6ZGvquBC6ViYGmjSpq0jaXHzd JQFJLRQlG+cPeJvSfQWD25+oEoervP+vC0WBEW7B8jS5fdpSTTgWHrL//OYh01R5NYI0SS3EFx7 DP0EYWzTIrNi/qCbm+5p69rcGp/7hmG1/auqc5os+9aM0l28ro6FIJQOGXSK5W/mrPX7nIgwyPk yTo+6hfzre0Dxo9yBrdtc3L5lwlgVSdSzElwntOd7ZK/AQQzZhFlI8RsOVL9mayDHOfr+KqNCYc dF0DE8uK0nE5rxE2fqa5VpsZOXe+KpJLf66yZ7asL+SCXuMh9B3JvIRF1bxJopsG2uFHnG3tEKR nHUHZGEuefGZijUwMOj5p+EnulUh3WppFQkG5p6970myZ8ebcPFQZJB0ffQH+BWZuuZhID6jrfS 1Ju94YKTpJSyOqq3+br+j/VEX7TXC4ekqdiZEwXDGDesUO0tJzFSh44s= X-Received: by 2002:a05:690e:1286:b0:672:ee91:ac19 with SMTP id 956f58d0204a3-67c3da728dbmr96523d50.96.1794090625374; Sat, 07 Nov 2026 14:30:25 -0800 (PST) From: Lucas Barros To: pve-devel@lists.proxmox.com Subject: [PATCH common] fix #6357: inotify: resolv.conf: parse all search domains Date: Sat, 7 Nov 2026 19:30:19 -0300 Message-ID: <20261107223019.21361-1-lucasbarros.kam@gmail.com> X-Mailer: git-send-email 2.50.1 MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-SPAM-LEVEL: Spam detection results: 0 AWL 0.050 Adjusted score from AWL reputation of From: address DKIM_SIGNED 0.1 Message has a DKIM or DK signature, not necessarily valid DKIM_VALID -0.1 Message has at least one valid DKIM or DK signature DKIM_VALID_AU -0.1 Message has a valid DKIM or DK signature from author's domain DKIM_VALID_EF -0.1 Message has a valid DKIM or DK signature from envelope-from domain DMARC_PASS -0.1 DMARC pass policy FREEMAIL_FROM 0.001 Sender email is commonly abused enduser mail provider RCVD_IN_DNSWL_NONE -0.0001 Sender listed at https://www.dnswl.org/, no trust 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: WJ2IIPU7JN2FA6MT4AH762CEWPYQL7DL X-Message-ID-Hash: WJ2IIPU7JN2FA6MT4AH762CEWPYQL7DL X-MailFrom: lucasbarros.kam@gmail.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: The 'search' line of /etc/resolv.conf can list multiple domains, but the parser only kept the first one. Writing the DNS settings of a node with multiple search domains worked, but reading them back, for example in the node's DNS panel in the web UI, only showed the first domain, so saving the dialog again silently dropped the others. Keep the whole list, with the domains separated by a single space. This is the format the DNS API already accepts when writing, and the in-tree users of the value that fall back to the host's search domains for guests, cloud-init in qemu-server and the container setup code in pve-container, already split it on whitespace. Add a small test for the parser. Signed-off-by: Lucas Barros --- The users of the parsed value that I found are the DNS API of the node in pve-manager, get_dns_conf() in qemu-server's cloud-init code and get_dns_settings() / update_etc_hosts() in pve-container's setup code. The last two already treat it as a whitespace separated list. Note that this means guests without their own 'searchdomain' now get all search domains of the host instead of only the first one, both in their resolv.conf and, for containers, as additional names in /etc/hosts. That is what the host itself uses, so I think it is the expected behavior, but please tell me if you prefer to keep that path as is. Ran the new test/resolv_conf_test.pl, which fails on the parser before this change (3 of 7) and passes with it. I ran it on perl 5.34 with stubs for the Linux-only modules (Linux::Inotify2, syscall.ph), not on a Debian system, and did not run the rest of 'make check'. proxmox- perltidy was not available, the code was formatted by hand. This patch was prepared with the help of an LLM based coding assistant; I reviewed the change and ran the tests mentioned above myself. src/PVE/INotify.pm | 4 +-- test/Makefile | 1 + test/resolv_conf_test.pl | 65 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 68 insertions(+), 2 deletions(-) create mode 100755 test/resolv_conf_test.pl diff --git a/src/PVE/INotify.pm b/src/PVE/INotify.pm index 53b4e21..4a0355e 100644 --- a/src/PVE/INotify.pm +++ b/src/PVE/INotify.pm @@ -609,8 +609,8 @@ sub read_etc_resolv_conf { my $nscount = 0; while (my $line = <$fh>) { chomp $line; - if ($line =~ m/^(search|domain)\s+(\S+)\s*/) { - $res->{search} = $2; + if ($line =~ m/^(search|domain)\s+(\S.*)$/) { + $res->{search} = join(' ', split(/\s+/, $2)); } elsif ($line =~ m/^\s*nameserver\s+($PVE::Tools::IPRE)\s*/) { $nscount++; if ($nscount <= 3) { diff --git a/test/Makefile b/test/Makefile index 9caba10..416bc0c 100644 --- a/test/Makefile +++ b/test/Makefile @@ -19,6 +19,7 @@ TESTS = lock_file.test \ ticket_test.test \ check_pem_test.test \ split_pem_test.test \ + resolv_conf_test.test \ all: diff --git a/test/resolv_conf_test.pl b/test/resolv_conf_test.pl new file mode 100755 index 0000000..87dd716 --- /dev/null +++ b/test/resolv_conf_test.pl @@ -0,0 +1,65 @@ +#!/usr/bin/perl + +use v5.36; + +use lib '../src'; + +use Test::More; + +use PVE::INotify; + +my $read_tests = [ + { + name => 'single search domain', + input => "search example.com\nnameserver 192.0.2.1\n", + expected => { search => 'example.com', dns1 => '192.0.2.1' }, + }, + { + name => 'multiple search domains', + input => "search a.example b.example c.example\nnameserver 192.0.2.1\n", + expected => { search => 'a.example b.example c.example', dns1 => '192.0.2.1' }, + }, + { + name => 'multiple search domains with extra whitespace', + input => "search\ta.example b.example \t\nnameserver 192.0.2.1\n", + expected => { search => 'a.example b.example', dns1 => '192.0.2.1' }, + }, + { + name => 'domain keyword', + input => "domain example.com\nnameserver 192.0.2.1\n", + expected => { search => 'example.com', dns1 => '192.0.2.1' }, + }, + { + name => 'only the first three name servers', + input => "nameserver 192.0.2.1\nnameserver 192.0.2.2\n" + . "nameserver 2001:db8::1\nnameserver 192.0.2.4\n", + expected => { dns1 => '192.0.2.1', dns2 => '192.0.2.2', dns3 => '2001:db8::1' }, + }, +]; + +for my $test ($read_tests->@*) { + open(my $fh, '<', \$test->{input}) or die "failed to open in-memory file - $!\n"; + my $res = PVE::INotify::read_etc_resolv_conf('/etc/resolv.conf', $fh); + is_deeply($res, $test->{expected}, "read: $test->{name}"); +} + +{ + my $input = "search old.example\nnameserver 192.0.2.1\noptions rotate\n"; + open(my $fh, '<', \$input) or die "failed to open in-memory file - $!\n"; + my $data = PVE::INotify::update_etc_resolv_conf( + '/etc/resolv.conf', + $fh, + { search => 'a.example b.example', dns1 => '192.0.2.2' }, + ); + is( + $data, + "search a.example b.example\nnameserver 192.0.2.2\noptions rotate\n", + 'update: write multiple search domains', + ); + + open($fh, '<', \$data) or die "failed to open in-memory file - $!\n"; + my $res = PVE::INotify::read_etc_resolv_conf('/etc/resolv.conf', $fh); + is($res->{search}, 'a.example b.example', 'update: read back multiple search domains'); +} + +done_testing(); -- 2.50.1 (Apple Git-155)