From: Bob Halley Date: Tue, 28 Jul 2020 00:19:11 +0000 (-0700) Subject: Apply the resolver search list, domain, and ndots settings in the same way X-Git-Tag: v2.1.0rc1~122 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=698e4f1c527601f2bf9ecd1d4de27cb389703ca8;p=thirdparty%2Fdnspython.git Apply the resolver search list, domain, and ndots settings in the same way that the BIND stub resolver library does. --- diff --git a/dns/resolver.py b/dns/resolver.py index 46ca30ac..9600c8e2 100644 --- a/dns/resolver.py +++ b/dns/resolver.py @@ -788,9 +788,15 @@ class Resolver: self.nameservers.append(tokens[1]) elif tokens[0] == 'domain': self.domain = dns.name.from_text(tokens[1]) + # domain and search are exclusive + self.search = [] elif tokens[0] == 'search': + # the last search wins + self.search = [] for suffix in tokens[1:]: self.search.append(dns.name.from_text(suffix)) + # We don't set domain as it is not used if + # len(self.search) > 0 elif tokens[0] == 'options': for opt in tokens[1:]: if opt == 'rotate': @@ -989,14 +995,34 @@ class Resolver: if qname.is_absolute(): qnames_to_try.append(qname) else: - if len(qname) > 1 or not search: - qnames_to_try.append(qname.concatenate(dns.name.root)) - if search and self.search: - for suffix in self.search: - if self.ndots is None or len(qname.labels) >= self.ndots: - qnames_to_try.append(qname.concatenate(suffix)) - elif search: - qnames_to_try.append(qname.concatenate(self.domain)) + abs_qname = qname.concatenate(dns.name.root) + if search: + if len(self.search) > 0: + # There is a search list, so use it exclusively + search_list = self.search[:] + elif self.domain != dns.name.root and self.domain is not None: + # We have some notion of a domain that isn't the root, so + # use it as the search list. + search_list = [self.domain] + else: + search_list = [] + # Figure out the effective ndots (default is 1) + if self.ndots is None: + ndots = 1 + else: + ndots = self.ndots + for suffix in search_list: + qnames_to_try.append(qname + suffix) + if len(qname) > ndots: + # The name has at least ndots dots, so we should try an + # absolute query first. + qnames_to_try.insert(0, abs_qname) + else: + # The name has less than ndots dots, so we should search + # first, then try the absolute name. + qnames_to_try.append(abs_qname) + else: + qnames_to_try.append(abs_qname) return qnames_to_try def resolve(self, qname, rdtype=dns.rdatatype.A, rdclass=dns.rdataclass.IN, diff --git a/tests/test_resolver.py b/tests/test_resolver.py index d61e8c92..4f5643dd 100644 --- a/tests/test_resolver.py +++ b/tests/test_resolver.py @@ -514,7 +514,7 @@ class BaseResolverTests(unittest.TestCase): qnames = res._get_qnames_to_try(qname, True) self.assertEqual(qnames, [dns.name.from_text(x) for x in - ['www.dnspython.org', 'www.dnspython.net']]) + ['www.dnspython.org', 'www.dnspython.net', 'www.']]) qnames = res._get_qnames_to_try(qname, False) self.assertEqual(qnames, [dns.name.from_text('www.')]) @@ -528,7 +528,27 @@ class BaseResolverTests(unittest.TestCase): qnames = res._get_qnames_to_try(qname, None) self.assertEqual(qnames, [dns.name.from_text(x) for x in - ['www.dnspython.org', 'www.dnspython.net']]) + ['www.dnspython.org', 'www.dnspython.net', 'www.']]) + # + # Now test ndots + # + qname = dns.name.from_text('a.b', None) + res.ndots = 1 + qnames = res._get_qnames_to_try(qname, True) + self.assertEqual(qnames, + [dns.name.from_text(x) for x in + ['a.b', 'a.b.dnspython.org', 'a.b.dnspython.net']]) + res.ndots = 2 + qnames = res._get_qnames_to_try(qname, True) + self.assertEqual(qnames, + [dns.name.from_text(x) for x in + ['a.b.dnspython.org', 'a.b.dnspython.net', 'a.b']]) + qname = dns.name.from_text('a.b.c', None) + qnames = res._get_qnames_to_try(qname, True) + self.assertEqual(qnames, + [dns.name.from_text(x) for x in + ['a.b.c', 'a.b.c.dnspython.org', + 'a.b.c.dnspython.net']]) def testSearchListsAbsolute(self): res = dns.resolver.Resolver(configure=False)