]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
resolved: fix comments in resolve.conf for search domain overflows (#3422)
authorMartin Pitt <martin.pitt@ubuntu.com>
Fri, 3 Jun 2016 09:15:44 +0000 (11:15 +0200)
committerLennart Poettering <lennart@poettering.net>
Fri, 3 Jun 2016 09:15:44 +0000 (11:15 +0200)
Write comments about "too many search domains" and "Total length of all search
domains is too long" just once. Also put it on a separate line, as
resolv.conf(5) only specifies comments in a line by themselves.

This is ugly to do if write_resolv_conf_search() gets called once for every
search domain. So change it to receive the complete OrderedSet instead and do
the iteration by itself.

Add test cases to networkd-test.py.

https://launchpad.net/bugs/1588229

src/resolve/resolved-resolv-conf.c
test/networkd-test.py

index ff03acc772b40a68bdc7d1b9a88fd9a8386314da..fa89de4c219f01b18f0f5e6f0cc15e8e814c3a6d 100644 (file)
@@ -164,30 +164,32 @@ static void write_resolv_conf_server(DnsServer *s, FILE *f, unsigned *count) {
 }
 
 static void write_resolv_conf_search(
-                const char *domain,
-                FILE *f,
-                unsigned *count,
-                unsigned *length) {
+                OrderedSet *domains,
+                FILE *f) {
+        unsigned length = 0, count = 0;
+        Iterator i;
+        char *domain;
 
-        assert(domain);
+        assert(domains);
         assert(f);
-        assert(length);
 
-        if (*count >= MAXDNSRCH ||
-            *length + strlen(domain) > 256) {
-                if (*count == MAXDNSRCH)
-                        fputs(" # Too many search domains configured, remaining ones ignored.", f);
-                if (*length <= 256)
-                        fputs(" # Total length of all search domains is too long, remaining ones ignored.", f);
+        fputs("search", f);
 
-                return;
+        ORDERED_SET_FOREACH(domain, domains, i) {
+                if (++count > MAXDNSRCH) {
+                        fputs("\n# Too many search domains configured, remaining ones ignored.", f);
+                        break;
+                }
+                length += strlen(domain) + 1;
+                if (length > 256) {
+                        fputs("\n# Total length of all search domains is too long, remaining ones ignored.", f);
+                        break;
+                }
+                fputc(' ', f);
+                fputs(domain, f);
         }
 
-        (*length) += strlen(domain);
-        (*count)++;
-
-        fputc(' ', f);
-        fputs(domain, f);
+        fputs("\n", f);
 }
 
 static int write_resolv_conf_contents(FILE *f, OrderedSet *dns, OrderedSet *domains) {
@@ -209,15 +211,8 @@ static int write_resolv_conf_contents(FILE *f, OrderedSet *dns, OrderedSet *doma
                         write_resolv_conf_server(s, f, &count);
         }
 
-        if (!ordered_set_isempty(domains)) {
-                unsigned length = 0, count = 0;
-                char *domain;
-
-                fputs("search", f);
-                ORDERED_SET_FOREACH(domain, domains, i)
-                        write_resolv_conf_search(domain, f, &count, &length);
-                fputs("\n", f);
-        }
+        if (!ordered_set_isempty(domains))
+                write_resolv_conf_search(domains, f);
 
         return fflush_and_check(f);
 }
index d4de5adf1a516355ef05479954f2b309e09fa1d4..f94224cce2b258d81a39a72dbaec88242d330044 100755 (executable)
@@ -370,6 +370,77 @@ exec $(systemctl cat systemd-networkd.service | sed -n '/^ExecStart=/ { s/^.*=//
     def test_coldplug_dhcp_ip6(self):
         pass
 
+    def test_search_domains(self):
+
+        # we don't use this interface for this test
+        self.if_router = None
+
+        with open('/run/systemd/network/test.netdev', 'w') as f:
+            f.write('''[NetDev]
+Name=dummy0
+Kind=dummy
+MACAddress=12:34:56:78:9a:bc''')
+        with open('/run/systemd/network/test.network', 'w') as f:
+            f.write('''[Match]
+Name=dummy0
+[Network]
+Address=192.168.42.100
+DNS=192.168.42.1
+Domains= one two three four five six seven eight nine ten''')
+        self.addCleanup(os.remove, '/run/systemd/network/test.netdev')
+        self.addCleanup(os.remove, '/run/systemd/network/test.network')
+
+        subprocess.check_call(['systemctl', 'start', 'systemd-networkd'])
+
+        if os.path.islink('/etc/resolv.conf'):
+            for timeout in range(50):
+                with open('/etc/resolv.conf') as f:
+                    contents = f.read()
+                if 'search one\n' in contents:
+                    break
+                time.sleep(0.1)
+            self.assertIn('search one two three four five six\n'
+                          '# Too many search domains configured, remaining ones ignored.\n',
+                          contents)
+
+    def test_search_domains_too_long(self):
+
+        # we don't use this interface for this test
+        self.if_router = None
+
+        name_prefix = 'a' * 60
+
+        with open('/run/systemd/network/test.netdev', 'w') as f:
+            f.write('''[NetDev]
+Name=dummy0
+Kind=dummy
+MACAddress=12:34:56:78:9a:bc''')
+        with open('/run/systemd/network/test.network', 'w') as f:
+            f.write('''[Match]
+Name=dummy0
+[Network]
+Address=192.168.42.100
+DNS=192.168.42.1
+Domains=''')
+            for i in range(5):
+                f.write('%s%i ' % (name_prefix, i))
+
+        self.addCleanup(os.remove, '/run/systemd/network/test.netdev')
+        self.addCleanup(os.remove, '/run/systemd/network/test.network')
+
+        subprocess.check_call(['systemctl', 'start', 'systemd-networkd'])
+
+        if os.path.islink('/etc/resolv.conf'):
+            for timeout in range(50):
+                with open('/etc/resolv.conf') as f:
+                    contents = f.read()
+                if 'search one\n' in contents:
+                    break
+                time.sleep(0.1)
+            self.assertIn('search %(p)s0 %(p)s1 %(p)s2 %(p)s3\n'
+                          '# Total length of all search domains is too long, remaining ones ignored.' % {'p': name_prefix},
+                          contents)
+
 
 if __name__ == '__main__':
     unittest.main(testRunner=unittest.TextTestRunner(stream=sys.stdout,