lib/net/dns/resolver.rb in net-dns-0.5.3 vs lib/net/dns/resolver.rb in net-dns-0.6.0
- old
+ new
@@ -1,11 +1,5 @@
-#
-# $Id: Resolver.rb,v 1.11 2006/07/30 16:55:35 bluemonk Exp $
-#
-
-
-
require 'rbconfig'
require 'socket'
require 'timeout'
require 'ipaddr'
require 'logger'
@@ -13,22 +7,22 @@
require 'net/dns/resolver/timeouts'
alias old_send send
#
-# Resolver helper method
+# = Resolver helper method
#
-# Calling the resolver directly
+# Calling the resolver directly:
#
# require 'net/dns/resolver'
# puts Resolver("www.google.com").answer.size
-# #=> 5
+# #=> 5
#
-# An optional block can be passed yielding the Net::DNS::Packet object
+# An optional block can be passed yielding the Net::DNS::Packet object.
#
# Resolver("www.google.com") {|packet| puts packet.size + " bytes"}
-# #=> 484 bytes
+# #=> 484 bytes
#
def Resolver(name,type=Net::DNS::A,cls=Net::DNS::IN,&blk)
obj = Net::DNS::Resolver.start(name,type,cls)
if block_given?
yield obj
@@ -40,20 +34,12 @@
module Net # :nodoc:
module DNS
include Logger::Severity
- # =Name
- #
- # Net::DNS::Resolver - DNS resolver class
+ # = Net::DNS::Resolver - DNS resolver class
#
- # =Synopsis
- #
- # require 'net/dns/resolver'
- #
- # =Description
- #
# The Net::DNS::Resolver class implements a complete DNS resolver written
# in pure Ruby, without a single C line of code. It has all of the
# tipical properties of an evoluted resolver, and a bit of OO which
# comes from having used Ruby.
#
@@ -61,14 +47,12 @@
# written by Martin Fuhr, but turned out (in the last months) to be
# an almost complete rewriting. Well, maybe some of the features of
# the Perl version are still missing, but guys, at least this is
# readable code!
#
- # FIXME
+ # == Environment
#
- # =Environment
- #
# The Following Environment variables can also be used to configure
# the resolver:
#
# * +RES_NAMESERVERS+: A space-separated list of nameservers to query.
#
@@ -107,11 +91,22 @@
#
# # C Shell
# % setenv RES_OPTIONS "retrans:3 retry:2 debug"
#
class Resolver
-
+
+ # Argument Error for class Net::DNS::Resolver.
+ class ArgumentError < ArgumentError
+ end
+
+ class Error < StandardError
+ end
+
+ class NoResponseError < Error
+ end
+
+
# An hash with the defaults values of almost all the
# configuration parameters of a resolver object. See
# the description for each parameter to have an
# explanation of its usage.
Defaults = {
@@ -129,12 +124,13 @@
:defname => true,
:dns_search => true,
:use_tcp => false,
:ignore_truncated => false,
:packet_size => 512,
- :tcp_timeout => TcpTimeout.new(120),
- :udp_timeout => UdpTimeout.new(0)}
+ :tcp_timeout => TcpTimeout.new(5),
+ :udp_timeout => UdpTimeout.new(5),
+ }
# Create a new resolver object.
#
# Argument +config+ can either be empty or be an hash with
# some configuration parameters. To know what each parameter
@@ -150,11 +146,11 @@
# # Set some option
# res = Net::DNS::Resolver.new(:nameservers => "172.16.1.1",
# :recursive => false,
# :retry => 10)
#
- # ===Config file
+ # == Config file
#
# Net::DNS::Resolver uses a config file to read the usual
# values a resolver needs, such as nameserver list and
# domain names. On UNIX systems the defaults are read from the
# following files, in the order indicated:
@@ -189,46 +185,46 @@
# overridden by the other arguments to Resolver::new.
#
# Explicit arguments to Resolver::new override both the system's defaults
# and the values of the custom configuration file, if any.
#
- # ===Parameters
+ # == Parameters
#
# The following arguments to Resolver::new are supported:
#
- # - nameservers: an array reference of nameservers to query.
- # - searchlist: an array reference of domains.
- # - recurse
- # - debug
- # - domain
- # - port
- # - srcaddr
- # - srcport
- # - tcp_timeout
- # - udp_timeout
- # - retrans
- # - retry
- # - usevc
- # - stayopen
- # - igntc
- # - defnames
- # - dnsrch
- # - persistent_tcp
- # - persistent_udp
- # - dnssec
+ # * nameservers: an array reference of nameservers to query.
+ # * searchlist: an array reference of domains.
+ # * recurse
+ # * debug
+ # * domain
+ # * port
+ # * srcaddr
+ # * srcport
+ # * tcp_timeout
+ # * udp_timeout
+ # * retrans
+ # * retry
+ # * usevc
+ # * stayopen
+ # * igntc
+ # * defnames
+ # * dnsrch
+ # * persistent_tcp
+ # * persistent_udp
+ # * dnssec
#
# For more information on any of these options, please consult the
# method of the same name.
#
- # ===Disclaimer
+ # == Disclaimer
#
# Part of the above documentation is taken from the one in the
# Net::DNS::Resolver Perl module.
#
def initialize(config = {})
- raise ResolverArgumentError, "Argument has to be Hash" unless config.kind_of? Hash
- # config.key_downcase!
+ raise ArgumentError, "Argument has to be Hash" unless config.kind_of? Hash
+ # config.downcase_keys!
@config = Defaults.merge config
@raw = false
# New logger facility
@logger = Logger.new(@config[:log_file])
@@ -260,52 +256,52 @@
config.each do |key,val|
next if key == :log_file or key == :config_file
begin
eval "self.#{key.to_s} = val"
rescue NoMethodError
- raise ResolverArgumentError, "Option #{key} not valid"
+ raise ArgumentError, "Option #{key} not valid"
end
end
end
- # Get the resolver searchlist, returned as an array of entries
+ # Get the resolver search list, returned as an array of entries.
#
# res.searchlist
- # #=> ["example.com","a.example.com","b.example.com"]
+ # #=> ["example.com","a.example.com","b.example.com"]
#
def searchlist
@config[:searchlist].inspect
end
# Set the resolver searchlist.
- # +arg+ can be a single string or an array of strings
+ # +arg+ can be a single string or an array of strings.
#
# res.searchstring = "example.com"
# res.searchstring = ["example.com","a.example.com","b.example.com"]
#
- # Note that you can also append a new name to the searchlist
+ # Note that you can also append a new name to the searchlist.
#
# res.searchlist << "c.example.com"
# res.searchlist
- # #=> ["example.com","a.example.com","b.example.com","c.example.com"]
+ # #=> ["example.com","a.example.com","b.example.com","c.example.com"]
#
- # The default is an empty array
+ # The default is an empty array.
#
def searchlist=(arg)
case arg
when String
@config[:searchlist] = [arg] if valid? arg
@logger.info "Searchlist changed to value #{@config[:searchlist].inspect}"
when Array
@config[:searchlist] = arg if arg.all? {|x| valid? x}
@logger.info "Searchlist changed to value #{@config[:searchlist].inspect}"
else
- raise ResolverArgumentError, "Wrong argument format, neither String nor Array"
+ raise ArgumentError, "Wrong argument format, neither String nor Array"
end
end
- # Get the list of resolver nameservers, in a dotted decimal format
+ # Get the list of resolver nameservers, in a dotted decimal format-
#
# res.nameservers
# #=> ["192.168.0.1","192.168.0.2"]
#
def nameservers
@@ -315,21 +311,21 @@
end
arr
end
alias_method :nameserver, :nameservers
- # Set the list of resolver nameservers
- # +arg+ can be a single ip address or an array of addresses
+ # Set the list of resolver nameservers.
+ # +arg+ can be a single ip address or an array of addresses.
#
# res.nameservers = "192.168.0.1"
# res.nameservers = ["192.168.0.1","192.168.0.2"]
#
- # If you want you can specify the addresses as IPAddr instances
+ # If you want you can specify the addresses as IPAddr instances.
#
# ip = IPAddr.new("192.168.0.3")
# res.nameservers << ip
- # #=> ["192.168.0.1","192.168.0.2","192.168.0.3"]
+ # #=> ["192.168.0.1","192.168.0.2","192.168.0.3"]
#
# The default is 127.0.0.1 (localhost)
#
def nameservers=(arg)
case arg
@@ -355,34 +351,31 @@
return
end
when IPAddr
x
else
- raise ResolverArgumentError, "Wrong argument format"
+ raise ArgumentError, "Wrong argument format"
end
end
@logger.info "Nameservers list changed to value #{@config[:nameservers].inspect}"
else
- raise ResolverArgumentError, "Wrong argument format, neither String, Array nor IPAddr"
+ raise ArgumentError, "Wrong argument format, neither String, Array nor IPAddr"
end
end
alias_method("nameserver=","nameservers=")
- # Return a string with the default domain
- #
+ # Return a string with the default domain.
def domain
@config[:domain].inspect
end
- # Set the domain for the query
- #
+ # Set the domain for the query.
def domain=(name)
@config[:domain] = name if valid? name
end
- # Return the defined size of the packet
- #
+ # Return the defined size of the packet.
def packet_size
@config[:packet_size]
end
# Get the port number to which the resolver sends queries.
@@ -403,15 +396,15 @@
def port=(num)
if (0..65535).include? num
@config[:port] = num
@logger.info "Port number changed to #{num}"
else
- raise ResolverArgumentError, "Wrong port number #{num}"
+ raise ArgumentError, "Wrong port number #{num}"
end
end
- # Get the value of the source port number
+ # Get the value of the source port number.
#
# puts "Sending queries using port #{res.source_port}"
#
def source_port
@config[:source_port]
@@ -434,11 +427,11 @@
raise ResolverPermissionError, "Are you root?"
end
if (0..65535).include?(num)
@config[:source_port] = num
else
- raise ResolverArgumentError, "Wrong port number #{num}"
+ raise ArgumentError, "Wrong port number #{num}"
end
end
alias srcport= source_port=
# Get the local address from which the resolver sends queries
@@ -448,12 +441,11 @@
def source_address
@config[:source_address].to_s
end
alias srcaddr source_address
- # Set the local source address from which the resolver sends its
- # queries.
+ # Set the local source address from which the resolver sends its queries.
#
# res.source_address = "172.16.100.1"
# res.source_address = IPAddr.new("172.16.100.1")
#
# You can specify +arg+ as either a string containing the ip address
@@ -470,16 +462,15 @@
#
# Note that if you want to set a non-binded source address you need
# root priviledges, as raw sockets will be used to generate packets.
# The class will then generate an exception if you're not root.
#
- # The default is 0.0.0.0, meaning any local address (chosen on routing
- # needs).
+ # The default is 0.0.0.0, meaning any local address (chosen on routing needs).
#
def source_address=(addr)
unless addr.respond_to? :to_s
- raise ResolverArgumentError, "Wrong address argument #{addr}"
+ raise ArgumentError, "Wrong address argument #{addr}"
end
begin
port = rand(64000)+1024
@logger.warn "Try to determine state of source address #{addr} with port #{port}"
@@ -511,46 +502,43 @@
end
end
alias srcaddr= source_address=
# Return the retrasmission interval (in seconds) the resolvers has
- # been set on
- #
+ # been set on.
def retry_interval
@config[:retry_interval]
end
alias retrans retry_interval
- # Set the retrasmission interval in seconds. Default 5 seconds
- #
+ # Set the retrasmission interval in seconds. Default 5 seconds.
def retry_interval=(num)
if num > 0
@config[:retry_interval] = num
@logger.info "Retransmission interval changed to #{num} seconds"
else
- raise ResolverArgumentError, "Interval must be positive"
+ raise ArgumentError, "Interval must be positive"
end
end
alias retrans= retry_interval=
- # The number of times the resolver will try a query
+ # The number of times the resolver will try a query.
#
# puts "Will try a max of #{res.retry_number} queries"
#
def retry_number
@config[:retry_number]
end
# Set the number of times the resolver will try a query.
- # Default 4 times
- #
+ # Default 4 times.
def retry_number=(num)
if num.kind_of? Integer and num > 0
@config[:retry_number] = num
@logger.info "Retrasmissions number changed to #{num}"
else
- raise ResolverArgumentError, "Retry value must be a positive integer"
+ raise ArgumentError, "Retry value must be a positive integer"
end
end
alias_method('retry=', 'retry_number=')
# This method will return true if the resolver is configured to
@@ -575,16 +563,16 @@
case bool
when TrueClass,FalseClass
@config[:recursive] = bool
@logger.info("Recursive state changed to #{bool}")
else
- raise ResolverArgumentError, "Argument must be boolean"
+ raise ArgumentError, "Argument must be boolean"
end
end
alias_method :recurse=, :recursive=
- # Return a string rapresenting the resolver state, suitable
+ # Return a string representing the resolver state, suitable
# for printing on the screen.
#
# puts "Resolver state:"
# puts res.state
#
@@ -627,31 +615,30 @@
case bool
when TrueClass,FalseClass
@config[:defname] = bool
@logger.info("Defname state changed to #{bool}")
else
- raise ResolverArgumentError, "Argument must be boolean"
+ raise ArgumentError, "Argument must be boolean"
end
end
- # Get the state of the dns_search flag
+ # Get the state of the dns_search flag.
def dns_search
@config[:dns_search]
end
alias_method :dnsrch, :dns_search
# Set the flag +dns_search+ in a boolean state. If +dns_search+
# is true, when using the Resolver#search method will be applied
# the search list. Default is true.
- #
def dns_search=(bool)
case bool
when TrueClass,FalseClass
@config[:dns_search] = bool
@logger.info("DNS search state changed to #{bool}")
else
- raise ResolverArgumentError, "Argument must be boolean"
+ raise ArgumentError, "Argument must be boolean"
end
end
alias_method("dnsrch=","dns_search=")
# Get the state of the use_tcp flag.
@@ -676,11 +663,11 @@
case bool
when TrueClass,FalseClass
@config[:use_tcp] = bool
@logger.info("Use tcp flag changed to #{bool}")
else
- raise ResolverArgumentError, "Argument must be boolean"
+ raise ArgumentError, "Argument must be boolean"
end
end
alias usevc= use_tcp=
def ignore_truncated?
@@ -692,11 +679,11 @@
case bool
when TrueClass,FalseClass
@config[:ignore_truncated] = bool
@logger.info("Ignore truncated flag changed to #{bool}")
else
- raise ResolverArgumentError, "Argument must be boolean"
+ raise ArgumentError, "Argument must be boolean"
end
end
# Return an object representing the value of the stored TCP
# timeout the resolver will use in is queries. This object
@@ -710,12 +697,11 @@
# #=> Timeout of 150 seconds
#
# puts "You set a timeout of " + res.tcp_timeout.pretty_to_s
# #=> You set a timeout of 2 minutes and 30 seconds
#
- # If the timeout is infinite, a string "infinite" will
- # be returned.
+ # If the timeout is infinite, a string "infinite" will be returned.
#
def tcp_timeout
@config[:tcp_timeout].to_s
end
@@ -723,20 +709,21 @@
# will be performed using TCP. A value of 0 means that
# the timeout will be infinite.
# The value is stored internally as a +TcpTimeout+ object, see
# the description for Resolver#tcp_timeout
#
- # Default is 120 seconds
+ # Default is 5 seconds.
+ #
def tcp_timeout=(secs)
@config[:tcp_timeout] = TcpTimeout.new(secs)
@logger.info("New TCP timeout value: #{@config[:tcp_timeout]} seconds")
end
# Return an object representing the value of the stored UDP
# timeout the resolver will use in is queries. This object
# is an instance of the class +UdpTimeout+, and two methods
- # are available for printing informations: UdpTimeout#to_s
+ # are available for printing information: UdpTimeout#to_s
# and UdpTimeout#pretty_to_s.
#
# Here's some example:
#
# puts "Timeout of #{res.udp_timeout} seconds" # implicit to_s
@@ -754,14 +741,15 @@
# Set the value of UDP timeout for resolver queries that
# will be performed using UDP. A value of 0 means that
# the timeout will not be used, and the resolver will use
# only +retry_number+ and +retry_interval+ parameters.
- # That is the default.
+ #
+ # Default is 5 seconds.
#
# The value is stored internally as a +UdpTimeout+ object, see
- # the description for Resolver#udp_timeout
+ # the description for Resolver#udp_timeout.
#
def udp_timeout=(secs)
@config[:udp_timeout] = UdpTimeout.new(secs)
@logger.info("New UDP timeout value: #{@config[:udp_timeout]} seconds")
end
@@ -801,11 +789,11 @@
def logger=(logger)
if logger.kind_of? Logger
@logger.close
@logger = logger
else
- raise ResolverArgumentError, "Argument must be an instance of Logger class"
+ raise ArgumentError, "Argument must be an instance of Logger class"
end
end
# Set the log level for the built-in logging facility.
#
@@ -993,12 +981,13 @@
end
ans = self.old_send(method,packet,packet_data)
unless ans
- @logger.fatal "No response from nameservers list: aborting"
- raise NoResponseError
+ message = "No response from nameservers list"
+ @logger.fatal(message)
+ raise NoResponseError, message
end
@logger.info "Received #{ans[0].size} bytes from #{ans[1][2]+":"+ans[1][1].to_s}"
response = Net::DNS::Packet.parse(ans[0],ans[1])
@@ -1031,12 +1020,10 @@
#
# It actually uses the same methods a normal Resolver query would
# use, but automatically sort the results based on preferences
# and returns an ordered array.
#
- # Example:
- #
# res = Net::DNS::Resolver.new
# res.mx("google.com")
#
def mx(name,cls=Net::DNS::IN)
arr = []
@@ -1044,26 +1031,22 @@
arr << entry if entry.type == 'MX'
end
return arr.sort_by {|a| a.preference}
end
- #
# Quick resolver method. Bypass the configuration using
# the defaults.
#
- # Example:
+ # Net::DNS::Resolver.start "www.google.com"
#
- # puts Net::DNS::Resolver.start "www.google.com"
- #
def self.start(*params)
self.new.search(*params)
end
private
- # Parse a configuration file specified as the argument.
- #
+ # Parses a configuration file specified as the argument.
def parse_config_file
if self.class.platform_windows?
require 'win32/resolv'
arr = Win32::Resolv.get_resolv_info
self.domain = arr[0]
@@ -1082,11 +1065,11 @@
end
end
end
end
- # Parse environment variables
+ # Parses environment variables.
def parse_environment_variables
if ENV['RES_NAMESERVERS']
self.nameservers = ENV['RES_NAMESERVERS'].split(" ")
end
if ENV['RES_SEARCHLIST']
@@ -1099,11 +1082,11 @@
ENV['RES_OPTIONS'].split(" ").each do |opt|
name,val = opt.split(":")
begin
eval("self.#{name} = #{val}")
rescue NoMethodError
- raise ResolverArgumentError, "Invalid ENV option #{name}"
+ raise ArgumentError, "Invalid ENV option #{name}"
end
end
end
end
@@ -1217,11 +1200,11 @@
ans
end
def valid?(name)
if name =~ /[^-\w\.]/
- raise ResolverArgumentError, "Invalid domain name #{name}"
+ raise ArgumentError, "Invalid domain name #{name}"
else
true
end
end
@@ -1237,46 +1220,8 @@
!!(Config::CONFIG["host_os"] =~ /msdos|mswin|djgpp|mingw/i)
end
end
- end # class Resolver
- 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}
- # hsh.key_downcase!
- # #=> {"test"=>1,"foobar"=>2}
- #
- def key_downcase!
- hsh = Hash.new
- self.each do |key,val|
- hsh[key.downcase] = val
end
- self.replace(hsh)
end
-end
-
-class Hash # :nodoc:
- include ExtendHash
-end
-
-
-
-
-
-
-
-
-
-
-
-
+end
\ No newline at end of file