From cf8d1b5e411591dffed10cdc5ecfe78f95a63de1 Mon Sep 17 00:00:00 2001 From: Kazuki Yamaguchi Date: Fri, 26 Mar 2021 16:52:08 +0900 Subject: [PATCH 1/3] Update test code for Resolv::DNS::Config ndots Add more assertions to actually test that the ndots option is working as expected: the option controls the threshold that the search list should be attempted earlier or later. --- test/resolv/test_dns.rb | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/test/resolv/test_dns.rb b/test/resolv/test_dns.rb index d3c4b1f..a806841 100644 --- a/test/resolv/test_dns.rb +++ b/test/resolv/test_dns.rb @@ -25,18 +25,22 @@ def with_udp(host, port) end end - # [ruby-core:65836] - def test_resolve_with_2_ndots - conf = Resolv::DNS::Config.new :nameserver => ['127.0.0.1'], :ndots => 2 - assert conf.single? - - candidates = [] - conf.resolv('example.com') { |candidate, *args| - candidates << candidate - raise Resolv::DNS::Config::NXDomain - } - n = Resolv::DNS::Name.create 'example.com.' - assert_equal n, candidates.last + def test_conf_ndots + # ndots defaults to 1 + conf = Resolv::DNS::Config.new(nameserver: '127.0.0.1', search: ['local']) + conf.lazy_initialize + candidates = conf.generate_candidates('example.com') + assert_equal 2, candidates.size + assert_equal 'example.com', candidates[0].to_s + assert_equal 'example.com.local', candidates[1].to_s + + # ndots is 2: search path is used first + conf = Resolv::DNS::Config.new(nameserver: '127.0.0.1', search: ['local'], ndots: 2) + conf.lazy_initialize + candidates = conf.generate_candidates('example.com') + assert_equal 2, candidates.size + assert_equal 'example.com.local', candidates[0].to_s + assert_equal 'example.com', candidates[1].to_s end def test_query_ipv4_address From 15b9791937e1809104e044ee92b8e8cd3f7387a8 Mon Sep 17 00:00:00 2001 From: Kazuki Yamaguchi Date: Fri, 26 Mar 2021 18:09:41 +0900 Subject: [PATCH 2/3] Fix querying absolute domain name twice When search list is not explicitly specified, Resolv::DNS checks the local domain name of the running system. If it is not set either, the root domain ['.'] is used. This is conceptually correct, but the code handles the absolute name separately, which in turn creates a duplicate query. --- lib/resolv.rb | 2 +- test/resolv/test_dns.rb | 15 +++++++++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/lib/resolv.rb b/lib/resolv.rb index 3ca0f01..90e8951 100644 --- a/lib/resolv.rb +++ b/lib/resolv.rb @@ -1041,7 +1041,7 @@ def lazy_initialize if /\./ =~ hostname @search = [Label.split($')] else - @search = [[]] + @search = [] end end diff --git a/test/resolv/test_dns.rb b/test/resolv/test_dns.rb index a806841..a57ee88 100644 --- a/test/resolv/test_dns.rb +++ b/test/resolv/test_dns.rb @@ -43,6 +43,21 @@ def test_conf_ndots assert_equal 'example.com', candidates[1].to_s end + def test_conf_search + conf = Resolv::DNS::Config.new(nameserver: '127.0.0.1') + conf.lazy_initialize + candidates = conf.generate_candidates('example.com') + assert_equal candidates.size, candidates.uniq.size + assert_equal 'example.com', candidates[0].to_s + + conf = Resolv::DNS::Config.new(nameserver: '127.0.0.1', search: ['local']) + conf.lazy_initialize + candidates = conf.generate_candidates('example.com') + assert_equal 2, candidates.size + assert_equal 'example.com', candidates[0].to_s + assert_equal 'example.com.local', candidates[1].to_s + end + def test_query_ipv4_address begin OpenSSL From f2d8beb90fff2ffb855c256224c6e6c0374e36c7 Mon Sep 17 00:00:00 2001 From: Kazuki Yamaguchi Date: Fri, 26 Mar 2021 18:00:52 +0900 Subject: [PATCH 3/3] Tidy up ndots handling The current code works, but the intention was not clear at first glance. --- lib/resolv.rb | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/lib/resolv.rb b/lib/resolv.rb index 90e8951..7c7b9fb 100644 --- a/lib/resolv.rb +++ b/lib/resolv.rb @@ -1084,23 +1084,18 @@ def nameserver_port end def generate_candidates(name) - candidates = nil name = Name.create(name) if name.absolute? - candidates = [name] + [name] else + abs = Name.new(name.to_a) + search = @search.map {|domain| Name.new(name.to_a + domain)} if @ndots <= name.length - 1 - candidates = [Name.new(name.to_a)] + [abs, *search] else - candidates = [] - end - candidates.concat(@search.map {|domain| Name.new(name.to_a + domain)}) - fname = Name.create("#{name}.") - if !candidates.include?(fname) - candidates << fname + [*search, abs] end end - return candidates end InitialTimeout = 5