lib/net/dns/resolver.rb in net-dns-0.2.5 vs lib/net/dns/resolver.rb in net-dns-0.3
- old
+ new
@@ -13,12 +13,12 @@
module Net # :nodoc:
module DNS
+ include Logger::Severity
-
# =Name
#
# Net::DNS::Resolver - DNS resolver class
#
# =Synopsis
@@ -106,11 +106,10 @@
:use_tcp => false,
:ignore_trucated => false,
:packet_size => 512,
:tcp_timeout => TcpTimeout.new(120),
:udp_timeout => UdpTimeout.new(0)}
-
# Create a new resolver object.
#
# Argument +config+ can either be empty or be an hash with
# some configuration parameters. To know what each parameter
@@ -206,11 +205,11 @@
@config = Defaults.merge config
@raw = false
# New logger facility
@logger = Logger.new(@config[:log_file])
- @logger.level = Logger::WARN
+ @logger.level = $DEBUG ? Logger::DEBUG : Logger::WARN
#------------------------------------------------------------
# Resolver configuration will be set in order from:
# 1) initialize arguments
# 2) ENV variables
@@ -772,23 +771,40 @@
#
# res.logger = log
#
# Note that this will destroy the precedent logger.
#
- # This is the only mode user will have to control their logger, such
- # as setting the level threshold, because no reader is set for this
- # instance variable.
- #
def logger=(logger)
if logger.kind_of? Logger
@logger.close
@logger = logger
else
raise ResolverArgumentError, "Argument must be an instance of Logger class"
end
end
+ # Set the log level for the built-in logging facility.
+ #
+ # The log level can be one of the following:
+ #
+ # - +Net::DNS::DEBUG+
+ # - +Net::DNS::INFO+
+ # - +Net::DNS::WARN+
+ # - +Net::DNS::ERROR+
+ # - +Net::DNS::FATAL+
+ #
+ # Note that if the global variable $DEBUG is set (like when the
+ # -d switch is used at the command line) the logger level is
+ # automatically set at DEGUB.
+ #
+ # For further informations, see Logger documentation in the
+ # Ruby standard library.
+ #
+ def log_level=(level)
+ @logger.level = level
+ end
+
# Performs a DNS query for the given name, applying the searchlist if
# appropriate. The search algorithm is as follows:
#
# 1. If the name contains at least one dot, try it as is.
# 2. If the name doesn't end in a dot then append each item in the search
@@ -1038,41 +1054,64 @@
packet
end
def send_tcp(packet,packet_data)
- # Generate new TCP socket or use persistent one
- if @config[:persistent_tcp] and @@tcp_socket
- socket = @@tcp_socket
- @logger.info "Using persistent socket #{socket.inspect}"
- else
- socket = Socket.new(Socket::AF_INET,Socket::SOCK_STREAM,0)
- socket.bind(Socket.pack_sockaddr_in(@config[:source_port],@config[:source_address].to_s))
- @@tcp_socket = socket if @config[:persistent_tcp]
- end
- ans = ""
- response = ""
+ ans = nil
length = [packet_data.size].pack("n")
@config[:nameservers].each do |ns|
- @config[:tcp_timeout].timeout do
+ begin
+
+ # Generate new TCP socket or use persistent one
+ if @config[:persistent_tcp] and @@tcp_socket
+ socket = @@tcp_socket
+ @logger.info "Using persistent socket #{socket.inspect}"
+ else
+ socket = Socket.new(Socket::AF_INET,Socket::SOCK_STREAM,0)
+ socket.bind(Socket.pack_sockaddr_in(@config[:source_port],@config[:source_address].to_s))
+ @@tcp_socket = socket if @config[:persistent_tcp]
+ end
+
sockaddr = Socket.pack_sockaddr_in(@config[:port],ns.to_s)
- socket.connect(sockaddr)
- socket.write(length+packet_data)
- ans = socket.recv(Net::DNS::INT16SZ)
- len = ans.unpack("n")[0]
- p len
- next if len == 0
- ans = socket.recv(len)
- next if ans.size == 0
- p ans.size
+
+ @config[:tcp_timeout].timeout do
+ socket.connect(sockaddr)
+ @logger.info "Contacting nameserver #{ns} port #{@config[:port]}"
+ socket.write(length+packet_data)
+ ans = socket.recv(Net::DNS::INT16SZ)
+ len = ans.unpack("n")[0]
+
+ if len == 0
+ @logger.warn "Receiving 0 lenght packet from nameserver #{ns}, trying next."
+ next
+ end
+
+ ans = socket.recv(len)
+ unless ans.size == len
+ @logger.warn "Malformed packet from nameserver #{ns}, trying next."
+ next
+ end
+ end
+
ans = [ans,["",@config[:port],ns.to_s,ns.to_s]]
@logger.info "Received #{ans[0].size} bytes from #{ans[1][2]+":"+ans[1][1].to_s}"
+
+ rescue TimeoutError
+ @logger.warn "Nameserver #{ns} not responding within TCP timeout, trying next one"
+ next
+ ensure
+ socket.close unless @config[:persistent_tcp]
end
- response = Net::DNS::Packet.parse(ans[0],ans[1])
end
- return response
+
+ if ans
+ return Net::DNS::Packet.parse(ans[0],ans[1])
+ else
+ @logger.fatal "No response from nameservers list: aborting"
+ raise NoResponseError
+ end
end
def send_udp(packet,packet_data)
# Generate new UDP socket or use persistent one
@@ -1088,10 +1127,11 @@
ans = nil
response = ""
@config[:nameservers].each do |ns|
begin
@config[:udp_timeout].timeout do
+ @logger.info "Contacting nameserver #{ns} port #{@config[:port]}"
socket.send(packet_data,0,ns.to_s,@config[:port])
ans = socket.recvfrom(@config[:packet_size])
end
if ans
@logger.info "Received #{ans[0].size} bytes from #{ans[1][2]+":"+ans[1][1].to_s}"
@@ -1100,11 +1140,16 @@
rescue TimeoutError
@logger.warn "Nameserver #{ns} not responding within UDP timeout, trying next one"
next
end
end
- return Net::DNS::Packet.parse(ans[0],ans[1])
+ if ans
+ return Net::DNS::Packet.parse(ans[0],ans[1])
+ else
+ @logger.fatal "No response from nameservers list: aborting"
+ raise NoResponseError
+ end
end
def valid?(name)
if name =~ /[^-\w\.]/
raise ResolverArgumentError, "Invalid domain name #{name}"
@@ -1117,10 +1162,12 @@
end # module DNS
end # module Net
class ResolverArgumentError < ArgumentError # :nodoc:
end
-
+class NoResponseError < StandardError # :nodoc:
+end
+
module ExtendHash # :nodoc:
# Returns an hash with all the
# keys turned into downcase
#
# hsh = {"Test" => 1, "FooBar" => 2}