diff --git a/lib/resolv.rb b/lib/resolv.rb index b69c704..7de3195 100644 --- a/lib/resolv.rb +++ b/lib/resolv.rb @@ -82,8 +82,8 @@ def self.each_name(address, &proc) ## # Creates a new Resolv using +resolvers+. - def initialize(resolvers=[Hosts.new, DNS.new]) - @resolvers = resolvers + def initialize(resolvers=nil) + @resolvers = resolvers || default_resolvers end ## @@ -152,6 +152,23 @@ def each_name(address) } end + private def default_resolvers # :nodoc: + resolvers = [Hosts.new, DNS.new] + + # macOS supports multiple DNS resolvers via additional configs + # (e.g. local domain resolvers, VPNs, etc.) + # ref: `man 5 resolver` on macOS/darwin + if /darwin/ =~ RUBY_PLATFORM && Dir.exist?('/etc/resolver') + Dir.each_child('/etc/resolver') do |filename| + resolver = DNS::Config.parse_resolv_conf("/etc/resolver/#{filename}") + resolver[:search] = [filename] unless resolver[:search] + resolvers << DNS.new(resolver) + end + end + + resolvers + end + ## # Indicates a failure to resolve a name or address. @@ -958,6 +975,7 @@ def Config.parse_resolv_conf(filename) nameserver = [] search = nil ndots = 1 + port = Port File.open(filename, 'rb') {|f| f.each {|line| line.sub!(/[#;].*/, '') @@ -979,10 +997,20 @@ def Config.parse_resolv_conf(filename) ndots = $1.to_i end } + when 'port' + # Only valid for macOS + next unless /darwin/ =~ RUBY_PLATFORM + next if args.empty? + port = args[0].to_i end } } - return { :nameserver => nameserver, :search => search, :ndots => ndots } + + return { + :nameserver_port => nameserver.to_enum(:each_with_index).map { |ns, i| [ns, port] }, + :search => search, + :ndots => ndots + } end def Config.default_config_hash(filename="/etc/resolv.conf") @@ -2907,4 +2935,3 @@ def DefaultResolver.replace_resolvers new_resolvers AddressRegex = /(?:#{IPv4::Regex})|(?:#{IPv6::Regex})/ end - diff --git a/test/resolv/test_dns.rb b/test/resolv/test_dns.rb index 5171604..e7023c3 100644 --- a/test/resolv/test_dns.rb +++ b/test/resolv/test_dns.rb @@ -342,6 +342,23 @@ def test_resolv_conf_by_command end end + def test_macos_resolver_port + return unless /darwin/ =~ RUBY_PLATFORM + + Tempfile.create('resolv_test_macos_resolver_port_') do |tmpfile| + tmpfile.puts "domain localdomain" + tmpfile.puts "nameserver 127.0.0.1" + tmpfile.puts "port 55353" + tmpfile.close + config_hash = Resolv::DNS::Config.parse_resolv_conf(tmpfile.path) + assert_equal({ + :nameserver_port => [['127.0.0.1', 55353]], + :search => ['localdomain'], + :ndots => 1, + }, config_hash) + end + end + def test_dots_diffences name1 = Resolv::DNS::Name.create("example.org") name2 = Resolv::DNS::Name.create("ex.ampl.eo.rg")