public inbox for pve-devel@lists.proxmox.com
 help / color / mirror / Atom feed
From: Lucas Barros <lucasbarros.kam@gmail.com>
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	[thread overview]
Message-ID: <20261107223019.21361-1-lucasbarros.kam@gmail.com> (raw)

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 <lucasbarros.kam@gmail.com>
---

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)




                 reply	other threads:[~2026-11-07 22:30 UTC|newest]

Thread overview: [no followups] expand[flat|nested]  mbox.gz  Atom feed

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=20261107223019.21361-1-lucasbarros.kam@gmail.com \
    --to=lucasbarros.kam@gmail.com \
    --cc=pve-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
Service provided by Proxmox Server Solutions GmbH | Privacy | Legal