Sam Roberts
1/19/2005 3:04:00 PM
resolv.rb:877 does
raise ResolvError.new("DNS resolv error: #{name}")
This means that when Resolv::DNS fails to find at least one record for
a query, it raises an error, preventing the next resolver in @resolvers
from being checked (see Resolv#each_address()).
Symptoms:
- you can't do a DNS lookup, then fallback to a Hosts lookup:
resolv = Resolv.new([Resolv::DNS.new, Resolv::Hosts.new])
resolv.getaddress("localhost")
# This will fail (unless your DNS server has an entry for "localhost",
# some do). Doing the opposite (the default) does work, i.e. doing
# the hosts lookup, then the DNS lookup.
- resolv.rb:228 (and probably 256) are no-ops
Instead of getting ResolvError.new("no address for #{name}') raised as
it appears was intended, you will always get the lower level "DNS
resolv error".
- if you have two DNS resolvers registered the second will never be
reached
You might do this if the first uses resolv.conf for its configuration,
and you add a second with a default config specified with a Hash:
resolv = Resolv.new([Resolv::DNS.new, Resolv::DNS.new( ... my config ...) ])
- If you write you own resolver module, then the failure of the DNS
module prevents the next resolver from being used to attempt the
lookup.
Cheers,
Sam
Example patch:
===================================================================
--- 1.8-resolv.rb (revision 11)
+++ 1.8-resolv.rb (working copy)
@@ -226,6 +226,8 @@
def getaddress(name)
each_address(name) {|address| return address}
raise ResolvError.new("no address for #{name}")
+# - this line is a no-op, it isn't reached because an internal DNS error is
+# raised instead.
end
def getaddresses(name)
@@ -872,7 +874,8 @@
rescue OtherResolvError
raise ResolvError.new("DNS error: #{$!.message}")
end
- raise ResolvError.new("DNS resolv error: #{name}")
+# raise ResolvError.new("DNS resolv error: #{name}")
+# - this shouldn't be fatal, the next resolver might be able to resolve this name!
end
class NXDomain < ResolvError
Test code:
#!/usr/bin/ruby
require 'pp'
require 'socket'
require 'resolv'
puts "(C library resolver) localhost -->"
addr = IPSocket.getaddress("localhost")
pp addr
# This is the default, args = [Resolv::Hosts.new, Resolv::DNS.new]
resolv = Resolv.new
puts "(Hosts, DNS) localhost -->"
addr = resolv.getaddress("localhost")
pp addr
puts "OK - address resolves!"
begin
puts "(Hosts, DNS) asergh.net -->"
addr = resolv.getaddress("asergh.net")
pp addr
rescue
pp $!
unless($!.to_s =~ /^no address for/)
puts "BUG - this should have hit resolv.rb:228, instead it is returning a DNS-specific error!"
end
end
# This is trying DNS lookup before host lookup
resolv = Resolv.new([Resolv::DNS.new, Resolv::Hosts.new])
begin
puts "(resolv) localhost -->"
addr = resolv.getaddress("localhost")
pp addr
rescue
pp $!
puts "BUG - this failed to find localhost when the resolvers were reordered!"
end