Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 12 additions & 1 deletion lib/resolv.rb
Original file line number Diff line number Diff line change
Expand Up @@ -581,6 +581,11 @@ def fetch_resource(name, typeclass)
# Retry via TCP:
truncated[candidate] = true
redo
elsif reply.answer.empty?
# NODATA: the name exists but has no records of the
# requested type. Continue with the next candidate in the
# search list, if any.
raise Config::NODATA.new(reply_name.to_s)
else
yield(reply, reply_name)
end
Expand Down Expand Up @@ -1293,7 +1298,7 @@ def resolv(name)
}
timeout_error = true
raise ResolvError.new("DNS resolv timeout: #{name}")
rescue NXDomain
rescue NXDomain, NODATA
end
}
rescue ResolvError
Expand All @@ -1307,6 +1312,12 @@ def resolv(name)
class NXDomain < ResolvError
end

##
# Indicates the name was found but has no data for the requested type.

class NODATA < ResolvError
end

##
# Indicates some other unhandled resolver error was encountered.

Expand Down
33 changes: 33 additions & 0 deletions test/resolv/test_dns.rb
Original file line number Diff line number Diff line change
Expand Up @@ -542,6 +542,39 @@ def test_query_ipv4_address_timeout
}
end

def test_search_list_continues_on_nodata
bug18842 = '[Bug #18842]'
with_udp('127.0.0.1', 0) {|u|
_, server_port, _, server_address = u.addr
client_thread = Thread.new {
Resolv::DNS.open(:nameserver_port => [[server_address, server_port]], :search => ['bad1.com', 'bad2.com', 'good.com'], :ndots => 5) {|dns|
dns.getaddress("example")
}
}
server_thread = Thread.new {
3.times do
msg, (_, client_port, _, client_address) = Timeout.timeout(5) {u.recvfrom(4096)}
query = Resolv::DNS::Message.decode(msg)
reply = Resolv::DNS::Message.new(query.id)
reply.qr = 1
reply.rd = query.rd
reply.ra = 1
query.each_question {|name, typeclass|
reply.add_question(name, typeclass)
if name.to_s == "example.good.com"
reply.add_answer(name, 3600, Resolv::DNS::Resource::IN::A.new("192.0.2.1"))
end
}
# No answers for the other candidates: a NODATA reply.
u.send(reply.encode, 0, client_address, client_port)
end
}
address = client_thread.value
server_thread.join
assert_equal(Resolv::IPv4.create("192.0.2.1"), address, bug18842)
}
end

def test_no_server
omit if /mswin/ =~ RUBY_PLATFORM && ENV.key?('GITHUB_ACTIONS') # not working from the beginning
u = UDPSocket.new
Expand Down