pax_global_header 0000666 0000000 0000000 00000000064 12142435533 0014514 g ustar 00root root 0000000 0000000 52 comment=6c6c643d019b2142652f25a00fd3f57b9775abfd
ruby-net-dns-0.8.0/ 0000775 0000000 0000000 00000000000 12142435533 0014050 5 ustar 00root root 0000000 0000000 ruby-net-dns-0.8.0/.gitignore 0000664 0000000 0000000 00000000107 12142435533 0016036 0 ustar 00root root 0000000 0000000 # Bundler
.bundle
pkg/*
Gemfile.lock
# YARD artifacts
.yardoc
yardoc/
ruby-net-dns-0.8.0/.travis.yml 0000664 0000000 0000000 00000000365 12142435533 0016165 0 ustar 00root root 0000000 0000000 language: ruby
rvm:
- 1.8.7
- 1.9.2
- 1.9.3
- 2.0.0
# - jruby-18mode
# - jruby-19mode
- rbx-18mode
# - ruby-head
# - jruby-head
notifications:
recipients:
- weppos@weppos.net
matrix:
allow_failures:
- rvm: 2.0.0
ruby-net-dns-0.8.0/CHANGELOG.md 0000664 0000000 0000000 00000006237 12142435533 0015671 0 ustar 00root root 0000000 0000000 # Changelog
## Release 0.8.0
- FIXED: undefined local variable or method `source_address_inet6' (GH-40). [Thanks @simsicon]
- FIXED: Fixed bug on parsing multiple nameservers on different lines (GH-45). [Thanks @nicholasren]
- CHANGED: Dropped duplicate query ID filter. Query ID is now randomically generated but it's not guaranteed to be unique (GH-39). [Thanks @ebroder]
- CHANGED: require 'net/dns' is now the preferred way to load the library (GH-37). [Thanks @johnroa]
- CHANGED: Removed setup.rb installation script.
## Release 0.7.1
- FIXED: Invalid file permissions on several files (GH-35) [Thanks @jamespharaoh]
## Release 0.7.0
- ADDED: Added (experimental) Support for HINFO record.
- FIXED: Use Net::DNS::Resolver::Error class (not ResolverError, which does not exist).
- FIXED: Cleaned up require dependency and recursive require statements.
- FIXED: Use RbConfig instead of obsolete and deprecated Config (GH-28, GH-33) [Thanks @shadowbq, @eik3]
- FIXED: SRV record not required by Net::DNS::RR (GH-27) [Thanks @sebastian]
- FIXED: Resolver now supports IPv6 (GH-32) [Thanks @jamesotron]
- FIXED: Net::DNS::RR::PTR references an invalid parameter (GH-19) [Thanks @dd23]
- FIXED: Net::DNS::Question changes input arguments (GH-7) [Thanks @gfarfl]
- CHANGED: Refactoring unit test to follow most used Ruby conventions.
- CHANGED: Rewritten and simplified Net::DNS::Classes. Improved test harness.
- CHANGED: Removed Jeweler development dependency.
- CHANGED: The library is now compatible with Bundler.
- CHANGED: Minimum supported Ruby version changed to Ruby 1.8.7.
- CHANGED: Rescue NameError so unsupported record types only result in a warning.
- CHANGED: Renamed Net::DNS::Resolver#send to Net::DNS::Resolver#query to avoid overriding default meaning of send method.
## Release 0.6.1
- ADDED: Net::DNS::Packet#to_s method (alias of #inspect)
- FIXED: typo in lib/net/dns/rr/ptr.rb [Thanks Chris Lundquist]
- FIXED: warning: method redefined; discarding old inspect (GH-3) [Thanks Kevin Baker]
- FIXED: issue with rescue ArgumentError (GH-5) and with IPAddr handling (GH-6)
## Release 0.6.0
*WARNING:- If you are upgrading from a previous minor release, check out the Compatibility issue list below.
- FIXED: Added missing #to_s method to Net::DNS::Question.
- FIXED: Compatibility with Ruby 1.9
- FIXED: Types regexp order issue
- CHANGED: Refactoring unit test to follow most used Ruby conventions
- CHANGED: default timeout is now 5 seconds for both UDP and TCP
- CHANGED: Moved main dns.rb file to lib/net folder as default for GEMs. In this way it can be autoloaded when the gem is required.
### Compatibility issues
- CHANGED: RR#set_stype scope is now private to prevent invalid usage.
- CHANGED: DnsTimeout#timeout now raises LocalJumpError instead of DnsTimeoutArgumentError when block is missing.
- CHANGED: Renamed Net::DNS::RR::Types::Types to Net::DNS::RR::Types::TYPES to follow Ruby coding standards.
## Release 0.4
- many bug fixes (thanks guys!)
- a whole new class Net::DNS::Header::RCode
- new methods in Net::DNS::Resolver class to do AXFR queries
- a new SRV resource record written by Dan Janowski
- more documentation written and corrected
ruby-net-dns-0.8.0/Gemfile 0000664 0000000 0000000 00000000131 12142435533 0015336 0 ustar 00root root 0000000 0000000 source "http://rubygems.org"
# Specify your gem's dependencies in whois.gemspec
gemspec
ruby-net-dns-0.8.0/README.md 0000664 0000000 0000000 00000011070 12142435533 0015326 0 ustar 00root root 0000000 0000000 # Net::DNS
Net::DNS is a DNS library written in pure Ruby. It started as a port of Perl Net::DNS module, but it evolved in time into a full Ruby library.
## Features
- Complete OO interface
- Clean and intuitive API
- Modular and flexible
## Requirements
* Ruby >= 1.8.7
## Installation
The best way to install this library is via [RubyGems](https://rubygems.org/).
$ gem install net-dns
You might need administrator privileges on your system to install the gem.
## API Documentation
Visit the page http://rdoc.info/gems/net-dns
## Trivial resolver
The simplest way to use the library is to invoke the Resolver() method:
require 'rubygems'
require 'net/dns'
p Resolver("www.google.com")
The output is compatible with BIND zone files and it's the same you would get with the dig utility.
;; Answer received from localhost:53 (212 bytes)
;;
;; HEADER SECTION
;; id = 64075
;; qr = 1 opCode: QUERY aa = 0 tc = 0 rd = 1
;; ra = 1 ad = 0 cd = 0 rcode = NoError
;; qdCount = 1 anCount = 3 nsCount = 4 arCount = 4
;; QUESTION SECTION (1 record):
;; google.com. IN A
;; ANSWER SECTION (3 records):
google.com. 212 IN A 74.125.45.100
google.com. 212 IN A 74.125.67.100
google.com. 212 IN A 209.85.171.100
;; AUTHORITY SECTION (4 records):
google.com. 345512 IN NS ns1.google.com.
google.com. 345512 IN NS ns4.google.com.
google.com. 345512 IN NS ns2.google.com.
google.com. 345512 IN NS ns3.google.com.
;; ADDITIONAL SECTION (4 records):
ns1.google.com. 170275 IN A 216.239.32.10
ns2.google.com. 170275 IN A 216.239.34.10
ns3.google.com. 170275 IN A 216.239.36.10
ns4.google.com. 170275 IN A 216.239.38.10
An optional block can be passed yielding the Net::DNS::Packet object
Resolver("www.google.com") { |packet| puts packet.size + " bytes" }
# => 484 bytes
Same for Net::DNS::Resolver.start():
Net::DNS::Resolver.start("google.com").answer.size
# => 5
As optional parameters, +TYPE+ and +CLASS+ can be specified.
p Net::DNS::Resolver.start("google.com", Net::DNS::MX)
;; Answer received from localhost:53 (316 bytes)
;;
;; HEADER SECTION
;; id = 59980
;; qr = 1 opCode: QUERY aa = 0 tc = 0 rd = 1
;; ra = 1 ad = 0 cd = 0 rcode = NoError
;; qdCount = 1 anCount = 4 nsCount = 4 arCount = 8
;; QUESTION SECTION (1 record):
;; google.com. IN MX
;; ANSWER SECTION (4 records):
google.com. 10800 IN MX 10 smtp2.google.com.
google.com. 10800 IN MX 10 smtp3.google.com.
google.com. 10800 IN MX 10 smtp4.google.com.
google.com. 10800 IN MX 10 smtp1.google.com.
## Handling the response packet
The method Net::DNS::Resolver.start is a wrapper around Resolver.new. It returns a new Net::DNS::Packet object.
A DNS packet is divided into 5 sections:
- header section # => a Net::DNS::Header object
- question section # => a Net::DNS::Question object
- answer section # => an Array of Net::DNS::RR objects
- authority section # => an Array of Net::DNS::RR objects
- additional section # => an Array of Net::DNS::RR objects
You can access each section by calling the attribute with the same name on a Packet object:
packet = Net::DNS::Resolver.start("google.com")
header = packet.header
answer = packet.answer
puts "The packet is #{packet.data.size} bytes"
puts "It contains #{header.anCount} answer entries"
answer.any? {|ans| p ans}
The output is
The packet is 378 bytes
It contains 3 answer entries
google.com. 244 IN A 74.125.45.100
google.com. 244 IN A 74.125.67.100
google.com. 244 IN A 209.85.171.100
A better way to handle the answer section is to use the iterators directly on a Packet object:
packet.each_address do |ip|
puts "#{ip} is alive" if Ping.pingecho(ip.to_s, 10, 80)
end
Gives:
74.125.45.100 is alive
74.125.67.100 is alive
209.85.171.100 is alive
## License
Net::DNS is distributed under the same license Ruby is.
## Authors
- Marco Ceresa (@bluemonk)
- Simone Carletti (@weppos)
ruby-net-dns-0.8.0/Rakefile 0000664 0000000 0000000 00000003301 12142435533 0015512 0 ustar 00root root 0000000 0000000 require 'rubygems'
require 'bundler'
$:.unshift(File.dirname(__FILE__) + "/lib")
require 'net/dns'
# Common package properties
PKG_NAME = ENV['PKG_NAME'] || 'net-dns'
PKG_VERSION = ENV['PKG_VERSION'] || Net::DNS::VERSION
# Run test by default.
task :default => :test
spec = Gem::Specification.new do |s|
s.name = PKG_NAME
s.version = PKG_VERSION
s.summary = "Pure Ruby DNS library."
s.description = "Net::DNS is a pure Ruby DNS library, with a clean OO interface and an extensible API."
s.required_ruby_version = ">= 1.8.7"
s.authors = ["Marco Ceresa", "Simone Carletti"]
s.email = ["ceresa@gmail.com", "weppos@weppos.net"]
s.homepage = "http://github.com/bluemonk/net-dns"
s.rubyforge_project = "net-dns"
s.add_development_dependency "rake", "~> 10.0"
s.add_development_dependency "yard"
s.files = `git ls-files`.split("\n")
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
s.require_paths = %w( lib )
end
require 'rubygems/package_task'
Gem::PackageTask.new(spec) do |pkg|
pkg.gem_spec = spec
end
desc "Build the gemspec file #{spec.name}.gemspec"
task :gemspec do
file = File.dirname(__FILE__) + "/#{spec.name}.gemspec"
File.open(file, "w") {|f| f << spec.to_ruby }
end
require 'rake/testtask'
# Run all the tests in the /test folder
Rake::TestTask.new do |t|
t.libs << "test"
t.test_files = FileList["test/**/*_test.rb"]
t.verbose = true
end
require 'yard'
require 'yard/rake/yardoc_task'
YARD::Rake::YardocTask.new(:yardoc)
desc "Open an irb session preloaded with this library"
task :console do
sh "irb -rubygems -I lib -r net/dns.rb"
end
ruby-net-dns-0.8.0/THANKS.rdoc 0000664 0000000 0000000 00000000751 12142435533 0015714 0 ustar 00root root 0000000 0000000 Many thanks to these wonderful people:
- Paul Barry for his excellent article on May07 issue of LinuxJournal, for the kind words and for bug reports
- Dan Janowski (and his SRV RR)
- Joshua Abraham
- Ben April
- Gene Rogers
- Nicholas Veeser
- Gildas Cherruel
- Alex Dalitz
- Cory Wright
- Nicolas Pugnant
- Andrea Peltrin
- Giovanni Corriga
- Luca Russo
- Pierguido Lambri
- Andrea Pampuri
- _koo_
- Oyku Gencay
- Eric Liedtke
- Justin Mercier
- Daniel Berger
and all #ruby-lang people
ruby-net-dns-0.8.0/demo/ 0000775 0000000 0000000 00000000000 12142435533 0014774 5 ustar 00root root 0000000 0000000 ruby-net-dns-0.8.0/demo/check_soa.rb 0000775 0000000 0000000 00000007041 12142435533 0017245 0 ustar 00root root 0000000 0000000 #!/usr/bin/env ruby
require 'rubygems' if "#{RUBY_VERSION}" < "1.9.0"
require 'net/dns'
#------------------------------------------------------------------------------
# Get the domain from the command line.
#------------------------------------------------------------------------------
raise ArgumentError, "Usage: check_soa.rb domain\n" unless ARGV.size == 1
domain = ARGV[0]
#------------------------------------------------------------------------------
# Find all the nameservers for the domain.
#------------------------------------------------------------------------------
res = Net::DNS::Resolver.new(:defname => false, :retry => 2)
ns_req = res.query(domain, Net::DNS::NS)
unless ns_req and ns_req.header.anCount > 0
raise ArgumentError, "No nameservers found for domain: #{res.errorstring}"
end
# Send out non-recursive queries
res.recurse = false
# Do not buffer standard out
#| = 1;
#------------------------------------------------------------------------------
# Check the SOA record on each nameserver.
#------------------------------------------------------------------------------
ns_req.each_nameserver do |ns|
#----------------------------------------------------------------------
# Set the resolver to query this nameserver.
#----------------------------------------------------------------------
# In order to lookup the IP(s) of the nameserver, we need a Resolver
# object that is set to our local, recursive nameserver. So we create
# a new object just to do that.
local_res = Net::DNS::Resolver.new
a_req = local_res.query(ns, Net::DNS::A)
unless a_req
puts "Can not find address for ns: " + res.errorstring + "\n"
next
end
a_req.each_address do |ip|
#----------------------------------------------------------------------
# Ask this IP.
#----------------------------------------------------------------------
res.nameservers=ip
print "#{ns} (#{ip}): "
#----------------------------------------------------------------------
# Get the SOA record.
#----------------------------------------------------------------------
soa_req = res.send(domain, Net::DNS::SOA, Net::DNS::IN)
if soa_req == nil
puts res.errorstring, "\n"
next
end
#----------------------------------------------------------------------
# Is this nameserver authoritative for the domain?
#----------------------------------------------------------------------
unless soa_req.header.auth?
print "isn't authoritative for domain\n"
next
end
#----------------------------------------------------------------------
# We should have received exactly one answer.
#----------------------------------------------------------------------
unless soa_req.header.anCount == 1
print "expected 1 answer, got " + soa_req.header.anCount.to_s + "\n"
next
end
#----------------------------------------------------------------------
# Did we receive an SOA record?
#----------------------------------------------------------------------
unless soa_req.answer[0].class == Net::DNS::RR::SOA
print "expected SOA, got " + Net::DNS::RR::RRTypes.to_str(soa_req.answer[0].type) + "\n"
next
end
#----------------------------------------------------------------------
# Print the serial number.
#----------------------------------------------------------------------
print "has serial number " + soa_req.answer[0].serial.to_s + "\n"
end
end
ruby-net-dns-0.8.0/demo/threads.rb 0000664 0000000 0000000 00000000605 12142435533 0016754 0 ustar 00root root 0000000 0000000 require 'rubygems' if "#{RUBY_VERSION}" < "1.9.0"
require 'net/dns'
a = ["ibm.com", "sun.com", "redhat.com"]
threads = []
for dom in a
threads << Thread.new(dom) do |domain|
res = Net::DNS::Resolver.new
res.query(domain, Net::DNS::NS).each_nameserver do |ns|
puts "Domain #{domain} has nameserver #{ns}"
end
puts ""
end
end
threads.each do |t|
t.join
end
ruby-net-dns-0.8.0/fixtures/ 0000775 0000000 0000000 00000000000 12142435533 0015721 5 ustar 00root root 0000000 0000000 ruby-net-dns-0.8.0/fixtures/resolv.conf 0000664 0000000 0000000 00000000163 12142435533 0020102 0 ustar 00root root 0000000 0000000 search corporate.thoughtworks.com
nameserver 192.168.1.1
nameserver 192.168.1.2
nameserver 192.168.1.3 192.168.1.4
ruby-net-dns-0.8.0/lib/ 0000775 0000000 0000000 00000000000 12142435533 0014616 5 ustar 00root root 0000000 0000000 ruby-net-dns-0.8.0/lib/net/ 0000775 0000000 0000000 00000000000 12142435533 0015404 5 ustar 00root root 0000000 0000000 ruby-net-dns-0.8.0/lib/net/dns.rb 0000664 0000000 0000000 00000003641 12142435533 0016521 0 ustar 00root root 0000000 0000000 require 'net/dns/core_ext'
require 'net/dns/version'
require 'net/dns/resolver'
module Net
module DNS
# Packet size in bytes
PACKETSZ = 512
# Size of the header
HFIXEDSZ = 12
# Size of the question portion (type and class)
QFIXEDSZ = 4
# Size of an RR portion (type,class,lenght and ttl)
RRFIXEDSZ = 10
# Size of an int 32 bit
INT32SZ = 4
# Size of a short int
INT16SZ = 2
module QueryTypes
SIGZERO = 0
A = 1
NS = 2
MD = 3
MF = 4
CNAME = 5
SOA = 6
MB = 7
MG = 8
MR = 9
NULL = 10
WKS = 11
PTR = 12
HINFO = 13
MINFO = 14
MX = 15
TXT = 16
RP = 17
AFSDB = 18
X25 = 19
ISDN = 20
RT = 21
NSAP = 22
NSAPPTR = 23
SIG = 24
KEY = 25
PX = 26
GPOS = 27
AAAA = 28
LOC = 29
NXT = 30
EID = 31
NIMLOC = 32
SRV = 33
ATMA = 34
NAPTR = 35
KX = 36
CERT = 37
DNAME = 39
OPT = 41
DS = 43
SSHFP = 44
RRSIG = 46
NSEC = 47
DNSKEY = 48
UINFO = 100
UID = 101
GID = 102
UNSPEC = 103
TKEY = 249
TSIG = 250
IXFR = 251
AXFR = 252
MAILB = 253
MAILA = 254
ANY = 255
end
module QueryClasses
# Internet class
IN = 1
# Chaos class
CH = 3
# Hesiod class
HS = 4
# None class
NONE = 254
# Any class
ANY = 255
end
include QueryTypes
include QueryClasses
end
end
ruby-net-dns-0.8.0/lib/net/dns/ 0000775 0000000 0000000 00000000000 12142435533 0016170 5 ustar 00root root 0000000 0000000 ruby-net-dns-0.8.0/lib/net/dns/core_ext.rb 0000664 0000000 0000000 00000002001 12142435533 0020316 0 ustar 00root root 0000000 0000000 module Net # :nodoc:
module DNS
module HashKeys # :nodoc:
# Returns an hash with all the
# keys turned into downcase
#
# hsh = {"Test" => 1, "FooBar" => 2}
# hsh.downcase_keys!
# #=> {"test"=>1,"foobar"=>2}
#
def downcase_keys!
hsh = Hash.new
self.each do |key,val|
hsh[key.downcase] = val
end
self.replace(hsh)
end
end
module HashOperators # :nodoc:
# Performs a sort of group difference
# operation on hashes or arrays
#
# a = {:a=>1,:b=>2,:c=>3}
# b = {:a=>1,:b=>2}
# c = [:a,:c]
# a-b #=> {:c=>3}
# a-c #=> {:b=>2}
#
def -(other)
case other
when Hash
delete_if { |k,v| other.has_key?(k) }
when Array
delete_if { |k,v| other.include?(k) }
end
end
end
end
end
class Hash # :nodoc:
include Net::DNS::HashKeys
include Net::DNS::HashOperators
end ruby-net-dns-0.8.0/lib/net/dns/header.rb 0000664 0000000 0000000 00000053021 12142435533 0017746 0 ustar 00root root 0000000 0000000 module Net
module DNS
# DNS packet header class
#
# The Net::DNS::Header class represents the header portion of a
# DNS packet. An Header object is created whenever a new packet
# is parsed or as user request.
#
# header = Net::DNS::Header.new
# # ;; id = 18123
# # ;; qr = 0 opCode: 0 aa = 0 tc = 0 rd = 1
# # ;; ra = 0 ad = 0 cd = 0 rcode = 0
# # ;; qdCount = 1 anCount = 0 nsCount = 0 arCount = 0
#
# header.format
# # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
# # | 18123 |
# # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
# # |0| 0 |0|0|1|0|0| 0 | 0 |
# # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
# # | 1 |
# # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
# # | 0 |
# # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
# # | 0 |
# # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
# # | 0 |
# # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
#
# # packet is an instance of Net::DNS::Packet
# header = packet.header
# puts "Answer is #{header.auth? ? '' : 'non'} authoritative"
#
# A lot of methods were written to keep a compatibility layer with
# the Perl version of the library, as long as methods name which are
# more or less the same.
#
class Header
# A wrong +count+ parameter has been passed.
class WrongCountError < ArgumentError
end
# A wrong +recursive+ parameter has been passed.
class WrongRecursiveError < ArgumentError
end
# An invalid +opCode+ has been specified.
class WrongOpcodeError < ArgumentError
end
# Base error class.
class Error < StandardError
end
# DNS Header RCode handling class
#
# It should be used internally by Net::DNS::Header class. However, it's still
# possible to instantiate it directly.
#
# require 'net/dns/header'
# rcode = Net::DNS::Header::RCode.new 0
#
# The RCode class represents the RCode field in the Header portion of a
# DNS packet. This field (called Response Code) is used to get informations
# about the status of a DNS operation, such as a query or an update. These
# are the values in the original Mockapetris's standard (RFC1035):
#
# * 0 No error condition
# * 1 Format error - The name server was unable to interpret
# the query.
# * 2 Server failure - The name server was
# unable to process this query due to a
# problem with the name server.
# * 3 Name Error - Meaningful only for
# responses from an authoritative name
# server, this code means that the
# domain name referenced in the query does
# not exist.
# * 4 Not Implemented - The name server does
# not support the requested kind of query.
# * 5 Refused - The name server refuses to
# perform the specified operation for
# policy reasons. For example, a name
# server may not wish to provide the
# information to the particular requester,
# or a name server may not wish to perform
# a particular operation (e.g., zone
# transfer) for particular data.
# * 6-15 Reserved for future use.
#
# In the next DNS RFCs, codes 6-15 has been assigned to the following
# errors:
#
# * 6 YXDomain
# * 7 YXRRSet
# * 8 NXRRSet
# * 9 NotAuth
# * 10 NotZone
#
# More RCodes has to come for TSIGs and other operations.
#
class RCode
# Constant for +rcode+ Response Code No Error
NOERROR = 0
# Constant for +rcode+ Response Code Format Error
FORMAT = 1
# Constant for +rcode+ Response Code Server Format Error
SERVER = 2
# Constant for +rcode+ Response Code Name Error
NAME = 3
# Constant for +rcode+ Response Code Not Implemented Error
NOTIMPLEMENTED = 4
# Constant for +rcode+ Response Code Refused Error
REFUSED = 5
RCodeType = %w[NoError FormErr ServFail NXDomain NotImp
Refused YXDomain YXRRSet NXRRSet NotAuth NotZone]
RCodeErrorString = ["No errors",
"The name server was unable to interpret the query",
"The name server was unable to process this query due to problem with the name server",
"Domain name referenced in the query does not exists",
"The name server does not support the requested kind of query",
"The name server refuses to perform the specified operation for policy reasons",
"",
"",
"",
"",
""]
attr_reader :code, :type, :explanation
def initialize(code)
if (0..10).include? code
@code = code
@type = RCodeType[code]
@explanation = RCodeErrorString[code]
else
raise ArgumentError, "RCode `#{code}' out of range"
end
end
def to_s
@code.to_s
end
end
# Constant for +opCode+ query
QUERY = 0
# Constant for +opCode+ iquery
IQUERY = 1
# Constant for +opCode+ status
STATUS = 2
# Array with given strings
OPARR = %w[QUERY IQUERY STATUS]
# Reader for +id+ attribute
attr_reader :id
# Reader for the operational code
attr_reader :opCode
# Reader for the rCode instance
attr_reader :rCode
# Reader for question section entries number
attr_reader :qdCount
# Reader for answer section entries number
attr_reader :anCount
# Reader for authority section entries number
attr_reader :nsCount
# Reader for addictional section entries number
attr_reader :arCount
# Creates a new Net::DNS::Header object with the desired values,
# which can be specified as an Hash argument. When called without
# arguments, defaults are used. If a data string is passed, values
# are taken from parsing the string.
#
# Examples:
#
# # Create a new Net::DNS::Header object
# header = Net::DNS::Header.new
#
# # Create a new Net::DNS::Header object passing values
# header = Net::DNS::Header.new(:opCode => 1, :rd => 0)
#
# # Create a new Net::DNS::Header object with binary data
# header = Net::DNS::Header.new(data)
#
# Default values are:
#
# :id => auto generated
# :qr => 0 # Query response flag
# :aa => 0 # Authoritative answer flag
# :tc => 0 # Truncated packet flag
# :ra => 0 # Recursiond available flag
# :rCode => 0 # Response code (status of the query)
# :opCode => 0 # Operational code (purpose of the query)
# :cd => 0 # Checking disable flag
# :ad => 0 # Only relevant in DNSSEC context
# :rd => 1 # Recursion desired flag
# :qdCount => 1 # Number of questions in the dns packet
# :anCount => 0 # Number of answer RRs in the dns packet
# :nsCount => 0 # Number of authoritative RRs in the dns packet
# :arCount => 0 # Number of additional RRs in the dns packet
#
# See also each option for a detailed explanation of usage.
#
def initialize(arg = {})
if arg.kind_of? Hash
new_from_hash(arg)
else
raise ArgumentError, "Wrong argument class `#{arg.class}'"
end
end
# Creates a new Net::DNS::Header object from binary data, which is
# passed as a string object as argument.
# The configurations parameters are taken from parsing the string.
#
# Example:
#
# # Create a new Net::DNS::Header object with binary data
# header = Net::DNS::Header.new(data)
#
# header.auth?
# #=> "true" if it comes from authoritative name server
#
def self.parse(arg)
if arg.kind_of? String
o = allocate
o.send(:new_from_binary, arg)
o
else
raise ArgumentError, "Wrong argument class `#{arg.class}'"
end
end
# Inspect method, prints out all the options and relative values.
#
# p Net::DNS::Header.new
# # ;; id = 18123
# # ;; qr = 0 opCode: 0 aa = 0 tc = 0 rd = 1
# # ;; ra = 0 ad = 0 cd = 0 rcode = 0
# # ;; qdCount = 1 anCount = 0 nsCount = 0 arCount = 0
#
# This method will maybe be changed in the future to a more pretty
# way of display output.
#
def inspect
";; id = #@id\n" +
if false # @opCode == "UPDATE"
#do stuff
else
";; qr = #@qr\t" +
"opCode: #{opCode_str}\t" +
"aa = #@aa\t" +
"tc = #@tc\t" +
"rd = #@rd\n" +
";; ra = #@ra\t" +
"ad = #@ad\t" +
"cd = #@cd\t" +
"rcode = #{@rCode.type}\n" +
";; qdCount = #@qdCount\t"+
"anCount = #@anCount\t"+
"nsCount = #@nsCount\t"+
"arCount = #@arCount\n"
end
end
# The Net::DNS::Header#format method prints out the header
# in a special ascii representation of data, in a way
# similar to those often found on RFCs.
#
# p Net::DNS::Header.new.format
# # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
# # | 18123 |
# # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
# # |0| 0 |0|0|1|0|0| 0 | 0 |
# # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
# # | 1 |
# # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
# # | 0 |
# # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
# # | 0 |
# # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
# # | 0 |
# # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
#
# This can be very usefull for didactical purpouses :)
#
def format
del = ("+-" * 16) + "+\n"
len = del.length
str = del + "|" + @id.to_s.center(len-3) + "|\n"
str += del + "|" + @qr.to_s
str += "|" + @opCode.to_s.center(7)
str += "|" + @aa.to_s
str += "|" + @tc.to_s
str += "|" + @rd.to_s
str += "|" + @ra.to_s
str += "|" + @ad.to_s
str += "|" + @cd.to_s.center(3)
str += "|" + @rCode.to_s.center(7) + "|\n"
str += del + "|" + @qdCount.to_s.center(len-3) + "|\n"
str += del + "|" + @anCount.to_s.center(len-3) + "|\n"
str += del + "|" + @nsCount.to_s.center(len-3) + "|\n"
str += del + "|" + @arCount.to_s.center(len-3) + "|\n" + del
str
end
# Returns the header data in binary format, appropriate
# for use in a DNS query packet.
#
# hdata = header.data
# puts "Header is #{hdata.size} bytes"
#
def data
arr = []
arr.push(@id)
arr.push((@qr<<7)|(@opCode<<3)|(@aa<<2)|(@tc<<1)|@rd)
arr.push((@ra<<7)|(@ad<<5)|(@cd<<4)|@rCode.code)
arr.push(@qdCount)
arr.push(@anCount)
arr.push(@nsCount)
arr.push(@arCount)
arr.pack("n C2 n4")
end
# Set the ID for the current header. Useful when
# performing security tests.
#
def id=(val)
if (0..65535).include? val
@id = val
else
raise ArgumentError, "ID `#{val}' out of range"
end
end
# Checks whether the header is a query (+qr+ bit set to 0)
#
def query?
@qr == 0
end
# Set the +qr+ query response flag to be either +true+ or
# +false+. You can also use the values 0 and 1. This flag
# indicates if the DNS packet contains a query or an answer,
# so it should be set to +true+ in DNS answer packets.
# If +qr+ is +true+, the packet is a response.
#
def qr=(val)
case val
when true
@qr = 1
when false
@qr = 0
when 0,1
@qr = val
else
raise ArgumentError, ":qr must be true(or 1) or false(or 0)"
end
end
# Checks whether the header is a response
# (+qr+ bit set to 1)
#
def response?
@qr == 1
end
# Returns a string representation of the +opCode+
#
# puts "Packet is a #{header.opCode_str}"
# #=> Packet is a QUERY
#
def opCode_str
OPARR[@opCode]
end
# Set the +opCode+ variable to a new value. This fields indicates
# the type of the question present in the DNS packet; +val+ can be
# one of the values QUERY, IQUERY or STATUS.
#
# * QUERY is the standard DNS query
# * IQUERY is the inverse query
# * STATUS is used to query the nameserver for its status
#
# Example:
#
# include Net::DNS
# header = Header.new
# header.opCode = Header::STATUS
#
def opCode=(val)
if (0..2).include? val
@opCode = val
else
raise WrongOpcodeError, "Wrong opCode value (#{val}), must be QUERY, IQUERY or STATUS"
end
end
# Checks whether the response is authoritative
#
# if header.auth?
# puts "Response is authoritative"
# else
# puts "Answer is NOT authoritative"
# end
#
def auth?
@aa == 1
end
# Set the +aa+ flag (authoritative answer) to either +true+
# or +false+. You can also use 0 or 1.
#
# This flag indicates whether a DNS answer packet contains
# authoritative data, meaning that is was generated by a
# nameserver authoritative for the domain of the question.
#
# Must only be set to +true+ in DNS answer packets.
#
def aa=(val)
case val
when true
@aa = 1
when false
@aa = 0
when 0,1
@aa = val
else
raise ArgumentError, ":aa must be true(or 1) or false(or 0)"
end
end
# Checks whether the packet was truncated
#
# # Sending packet using UDP
# if header.truncated?
# puts "Warning, packet has been truncated!"
# # Sending packet using TCP
# end
# # Do something with the answer
#
def truncated?
@tc == 1
end
# Set the +tc+ flag (truncated packet) to either +true+
# ot +false+. You can also use 0 or 1.
#
# The truncated flag is used in response packets to indicate
# that the amount of data to be trasmitted exceedes the
# maximum allowed by the protocol in use, tipically UDP, and
# that the data present in the packet has been truncated.
# A different protocol (such has TCP) need to be used to
# retrieve full data.
#
# Must only be set in DNS answer packets.
#
def tc=(val)
case val
when true
@tc = 1
when false
@tc = 0
when 0,1
@tc = val
else
raise ArgumentError, ":tc must be true(or 1) or false(or 0)"
end
end
# Checks whether the packet has a recursion bit
# set, meaning that recursion is desired
#
def recursive?
@rd == 1
end
# Sets the recursion desidered bit.
# Remember that recursion query support is
# optional.
#
# header.recursive = true
# hdata = header.data # suitable for sending
#
# Consult RFC1034 and RFC1035 for a detailed explanation
# of how recursion works.
#
def recursive=(val)
case val
when true
@rd = 1
when false
@rd = 0
when 1
@rd = 1
when 0
@rd = 0
else
raise WrongRecursiveError, "Wrong value (#{val}), please specify true (1) or false (0)"
end
end
# Alias for Header#recursive= to keep compatibility
# with the Perl version.
#
def rd=(val)
self.recursive = val
end
# Checks whether recursion is available.
# This flag is usually set by nameservers to indicate
# that they support recursive-type queries.
#
def r_available?
@ra == 1
end
# Set the +ra+ flag (recursion available) to either +true+ or
# +false+. You can also use 0 and 1.
#
# This flag must only be set in DNS answer packets.
#
def ra=(val)
case val
when true
@ra = 1
when false
@ra = 0
when 0,1
@ra = val
else
raise ArgumentError, ":ra must be true(or 1) or false(or 0)"
end
end
# Checks whether checking is enabled or disabled.
#
# Checking is enabled by default.
#
def checking?
@cd == 0
end
# Set the +cd+ flag (checking disabled) to either +true+
# ot +false+. You can also use 0 or 1.
#
def cd=(val)
case val
when true
@cd = 1
when false
@cd = 0
when 0,1
@cd = val
else
raise ArgumentError, ":cd must be true(or 1) or false(or 0)"
end
end
# Checks whether +ad+ flag has been set.
#
# This flag is only relevant in DNSSEC context.
#
def verified?
@ad == 1
end
# Set the +ad+ flag to either +true+
# ot +false+. You can also use 0 or 1.
#
# The AD bit is only set on answers where signatures have
# been cryptographically verified or the server is
# authoritative for the data and is allowed to set the bit by policy.
#
def ad=(val)
case val
when true
@ad = 1
when false
@ad = 0
when 0,1
@ad = val
else
raise ArgumentError, ":ad must be true(or 1) or false(or 0)"
end
end
# Returns an error array for the header response code, or
# +nil+ if no error is generated.
#
# error, cause = header.rCode_str
# puts "Error #{error} cause by: #{cause}" if error
# #=> Error ForErr caused by: The name server
# #=> was unable to interpret the query
#
def rCode_str
return rCode.type, rCode.explanation
end
# Checks for errors in the DNS packet
#
# unless header.error?
# puts "No errors in DNS answer packet"
# end
#
def error?
@rCode.code > 0
end
# Set the rCode value. This should only be done in DNS
# answer packets.
#
def rCode=(val)
@rCode = RCode.new(val)
end
# Sets the number of entries in a question section
#
def qdCount=(val)
if (0..65535).include? val
@qdCount = val
else
raise WrongCountError, "Wrong number of count (#{val}), must be 0-65535"
end
end
# Sets the number of RRs in an answer section
#
def anCount=(val)
if (0..65535).include? val
@anCount = val
else
raise WrongCountError, "Wrong number of count (#{val}), must be 0-65535"
end
end
# Sets the number of RRs in an authority section
#
def nsCount=(val)
if (0..65535).include? val
@nsCount = val
else
raise WrongCountError, "Wrong number of count (#{val}), must be 0-65535"
end
end
# Sets the number of RRs in an addictional section
#
def arCount=(val)
if (0..65535).include? val
@arCount = val
else
raise WrongCountError, "Wrong number of count: `#{val}' must be 0-65535"
end
end
private
def new_from_scratch
@id = genID # generate ad unique id
@qr = @aa = @tc = @ra = @ad = @cd = 0
@rCode = RCode.new(0) # no error
@anCount = @nsCount = @arCount = 0
@rd = @qdCount = 1
@opCode = QUERY # standard query, default message
end
def new_from_binary(str)
unless str.size == Net::DNS::HFIXEDSZ
raise ArgumentError, "Header binary data has wrong size: `#{str.size}' bytes"
end
arr = str.unpack("n C2 n4")
@id = arr[0]
@qr = (arr[1] >> 7) & 0x01
@opCode = (arr[1] >> 3) & 0x0F
@aa = (arr[1] >> 2) & 0x01
@tc = (arr[1] >> 1) & 0x01
@rd = arr[1] & 0x1
@ra = (arr[2] >> 7) & 0x01
@ad = (arr[2] >> 5) & 0x01
@cd = (arr[2] >> 4) & 0x01
@rCode = RCode.new(arr[2] & 0xf)
@qdCount = arr[3]
@anCount = arr[4]
@nsCount = arr[5]
@arCount = arr[6]
end
def new_from_hash(hash)
new_from_scratch
hash.each do |key,val|
eval "self.#{key.to_s} = val"
end
end
def genID
rand(65535)
end
end
end
end
ruby-net-dns-0.8.0/lib/net/dns/names.rb 0000664 0000000 0000000 00000007146 12142435533 0017630 0 ustar 00root root 0000000 0000000 module Net # :nodoc:
module DNS
module Names
# Base error class.
class Error < StandardError
end
# Generic Names Error.
class ExpandError < Error
end
INT16SZ = 2
# Expand a compressed name in a DNS Packet object. Please
# see RFC1025 for an explanation of how the compression
# in DNS packets works, how may it be useful and how should
# be handled.
#
# This method accept two parameters: a raw packet data and an
# offset, which indicates the point in the packet in which the
# parsing has arrived.
#
def dn_expand(packet,offset)
name = ""
packetlen = packet.size
while true
raise ExpandError, "Offset is greater than packet lenght!" if packetlen < (offset+1)
len = packet.unpack("@#{offset} C")[0]
if len == 0
offset += 1
break
elsif (len & 0xC0) == 0xC0
raise ExpandError, "Packet ended before offset expand" if packetlen < (offset+INT16SZ)
ptr = packet.unpack("@#{offset} n")[0]
ptr &= 0x3FFF
name2 = dn_expand(packet,ptr)[0]
raise ExpandError, "Packet is malformed!" if name2 == nil
name += name2
offset += INT16SZ
break
else
offset += 1
raise ExpandError, "No expansion found" if packetlen < (offset+len)
elem = packet[offset..offset+len-1]
name += "#{elem}."
offset += len
end
end
[name, offset] # name.chomp(".") if trailing dot has to be omitted
end
def pack_name(name)
if name.size > 255
raise ArgumentError, "Name may not exceed 255 chars"
end
arr = name.split(".")
str = ""
arr.each do |elem|
if elem.size > 63
raise ArgumentError, "Label may not exceed 63 chars"
end
str += [elem.size,elem].pack("Ca*")
end
str += [0].pack("C")
str
end
def names_array(name)
arr = name.split(".")
ar = []
string = ""
arr.size.times do |i|
x = i+1
elem = arr[-x]
len = elem.size
string = ((string.reverse)+([len,elem].pack("Ca*")).reverse).reverse
ar.unshift(string)
end
return ar
end
def dn_comp(name,offset,compnames)
names = {}
ptr = 0
str = ""
arr = names_array(name)
arr.each do |entry|
if compnames.has_key?(entry)
ptr = 0xC000 | compnames[entry]
str += [ptr].pack("n")
offset += INT16SZ
break
else
len = entry.unpack("C")[0]
elem = entry[1..len]
str += [len,elem].pack("Ca*")
names.update({"#{entry}" => offset})
offset += len
end
end
return str,offset,names
end
def valid?(name)
if name =~ /^([a-z0-9]([-a-z0-9]*[a-z0-9])?\.)+((a[cdefgilmnoqrstuwxz]|aero|arpa)|(b[abdefghijmnorstvwyz]|biz)|(c[acdfghiklmnorsuvxyz]|cat|com|coop)|d[ejkmoz]|(e[ceghrstu]|edu)|f[ijkmor]|(g[abdefghilmnpqrstuwy]|gov)|h[kmnrtu]|(i[delmnoqrst]|info|int)|(j[emop]|jobs)|k[eghimnprwyz]|l[abcikrstuvy]|(m[acdghklmnopqrstuvwxyz]|mil|mobi|museum)|(n[acefgilopruz]|name|net)|(om|org)|(p[aefghklmnrstwy]|pro)|qa|r[eouw]|s[abcdeghijklmnortvyz]|(t[cdfghjklmnoprtvwz]|travel)|u[agkmsyz]|v[aceginu]|w[fs]|y[etu]|z[amw])$/i
return name
else
raise ArgumentError, "Invalid FQDN: #{name}"
end
end
end
end
end
ruby-net-dns-0.8.0/lib/net/dns/packet.rb 0000664 0000000 0000000 00000044307 12142435533 0017774 0 ustar 00root root 0000000 0000000 require 'logger'
require 'net/dns/names'
require 'net/dns/header'
require 'net/dns/question'
require 'net/dns/rr'
module Net
module DNS
#
# = Net::DNS::Packet
#
# The Net::DNS::Packet class represents an entire DNS packet,
# divided in his main section:
#
# * Header (instance of Net::DNS::Header)
# * Question (array of Net::DNS::Question objects)
# * Answer, Authority, Additional (each formed by an array of Net::DNS::RR
# objects)
#
# You can use this class whenever you need to create a DNS packet, whether
# in an user application, in a resolver instance (have a look, for instance,
# at the Net::DNS::Resolver#send method) or for a nameserver.
#
# For example:
#
# # Create a packet
# packet = Net::DNS::Packet.new("www.example.com")
# mx = Net::DNS::Packet.new("example.com", Net::DNS::MX)
#
# # Getting packet binary data, suitable for network transmission
# data = packet.data
#
# A packet object can be created from binary data too, like an
# answer packet just received from a network stream:
#
# packet = Net::DNS::Packet::parse(data)
#
# Each part of a packet can be gotten by the right accessors:
#
# header = packet.header # Instance of Net::DNS::Header class
# question = packet.question # Instance of Net::DNS::Question class
#
# # Iterate over additional RRs
# packet.additional.each do |rr|
# puts "Got an #{rr.type} record"
# end
#
# Some iterators have been written to easy the access of those RRs,
# which are often the most important. So instead of doing:
#
# packet.answer.each do |rr|
# if rr.type == Net::DNS::RR::Types::A
# # do something with +rr.address+
# end
# end
#
# we can do:
#
# packet.each_address do |ip|
# # do something with +ip+
# end
#
# Be sure you don't miss all the iterators in the class documentation.
#
# == Logging facility
#
# As Net::DNS::Resolver class, Net::DNS::Packet class has its own logging
# facility too. It work in the same way the other one do, so you can
# maybe want to override it or change the file descriptor.
#
# packet = Net::DNS::Packet.new("www.example.com")
# packet.logger = $stderr
#
# # or even
# packet.logger = Logger.new("/tmp/packet.log")
#
# If the Net::DNS::Packet class is directly instantiated by the Net::DNS::Resolver
# class, like the great majority of the time, it will use the same logger facility.
#
# Logger level will be set to Logger::Debug if $DEBUG variable is set.
#
class Packet
include Names
# Base error class.
class Error < StandardError
end
# Generic Packet Error.
class PacketError < Error
end
attr_reader :header, :question, :answer, :authority, :additional
attr_reader :answerfrom, :answersize
# Creates a new instance of Net::DNS::Packet class. Arguments are the
# canonical name of the resource, an optional type field and an optional
# class field. The record type and class can be omitted; they default
# to +A+ and +IN+.
#
# packet = Net::DNS::Packet.new("www.example.com")
# packet = Net::DNS::Packet.new("example.com", Net::DNS::MX)
# packet = Net::DNS::Packet.new("example.com", Net::DNS::TXT, Net::DNS::CH)
#
# This class no longer instantiate object from binary data coming from
# network streams. Please use Net::DNS::Packet.parse instead.
def initialize(name, type = Net::DNS::A, cls = Net::DNS::IN)
@header = Net::DNS::Header.new(:qdCount => 1)
@question = [Net::DNS::Question.new(name, type, cls)]
@answer = []
@authority = []
@additional = []
@logger = Logger.new $stdout
@logger.level = $DEBUG ? Logger::DEBUG : Logger::WARN
end
# Checks if the packet is a QUERY packet
def query?
@header.opCode == Net::DNS::Header::QUERY
end
# Returns the packet object in binary data, suitable
# for sending across a network stream.
#
# packet_data = packet.data
# puts "Packet is #{packet_data.size} bytes long"
#
def data
qdcount=ancount=nscount=arcount=0
data = @header.data
headerlength = data.length
@question.each do |question|
data += question.data
qdcount += 1
end
@answer.each do |rr|
data += rr.data#(data.length)
ancount += 1
end
@authority.each do |rr|
data += rr.data#(data.length)
nscount += 1
end
@additional.each do |rr|
data += rr.data#(data.length)
arcount += 1
end
@header.qdCount = qdcount
@header.anCount = ancount
@header.nsCount = nscount
@header.arCount = arcount
@header.data + data[Net::DNS::HFIXEDSZ..data.size]
end
# Same as Net::DNS::Packet#data, but implements name compression
# (see RFC1025) for a considerable save of bytes.
#
# packet = Net::DNS::Packet.new("www.example.com")
# puts "Size normal is #{packet.data.size} bytes"
# puts "Size compressed is #{packet.data_comp.size} bytes"
#
def data_comp
offset = 0
compnames = {}
qdcount=ancount=nscount=arcount=0
data = @header.data
headerlength = data.length
@question.each do |question|
str,offset,names = question.data
data += str
compnames.update(names)
qdcount += 1
end
@answer.each do |rr|
str,offset,names = rr.data(offset,compnames)
data += str
compnames.update(names)
ancount += 1
end
@authority.each do |rr|
str,offset,names = rr.data(offset,compnames)
data += str
compnames.update(names)
nscount += 1
end
@additional.each do |rr|
str,offset,names = rr.data(offset,compnames)
data += str
compnames.update(names)
arcount += 1
end
@header.qdCount = qdcount
@header.anCount = ancount
@header.nsCount = nscount
@header.arCount = arcount
@header.data + data[Net::DNS::HFIXEDSZ..data.size]
end
# Returns a string containing a human-readable representation
# of this Net::DNS::Packet instance.
def inspect
retval = ""
if @answerfrom != "0.0.0.0:0" and @answerfrom
retval += ";; Answer received from #@answerfrom (#{@answersize} bytes)\n;;\n"
end
retval += ";; HEADER SECTION\n"
retval += @header.inspect
retval += "\n"
section = (@header.opCode == "UPDATE") ? "ZONE" : "QUESTION"
retval += ";; #{section} SECTION (#{@header.qdCount} record#{@header.qdCount == 1 ? '' : 's'}):\n"
@question.each do |qr|
retval += ";; " + qr.inspect + "\n"
end
unless @answer.size == 0
retval += "\n"
section = (@header.opCode == "UPDATE") ? "PREREQUISITE" : "ANSWER"
retval += ";; #{section} SECTION (#{@header.anCount} record#{@header.anCount == 1 ? '' : 's'}):\n"
@answer.each do |rr|
retval += rr.inspect + "\n"
end
end
unless @authority.size == 0
retval += "\n"
section = (@header.opCode == "UPDATE") ? "UPDATE" : "AUTHORITY"
retval += ";; #{section} SECTION (#{@header.nsCount} record#{@header.nsCount == 1 ? '' : 's'}):\n"
@authority.each do |rr|
retval += rr.inspect + "\n"
end
end
unless @additional.size == 0
retval += "\n"
retval += ";; ADDITIONAL SECTION (#{@header.arCount} record#{@header.arCount == 1 ? '' : 's'}):\n"
@additional.each do |rr|
retval += rr.inspect + "\n"
end
end
retval
end
alias_method :to_s, :inspect
# Delegates to Net::DNS::Header#truncated?.
def truncated?
@header.truncated?
end
# Assigns a Net::DNS::Header object
# to this Net::DNS::Packet instance.
def header=(object)
if object.kind_of? Net::DNS::Header
@header = object
else
raise ArgumentError, "Argument must be a Net::DNS::Header object"
end
end
# Assigns a Net::DNS::Question object
# to this Net::DNS::Packet instance.
def question=(object)
case object
when Array
if object.all? {|x| x.kind_of? Net::DNS::Question}
@question = object
else
raise ArgumentError, "Some of the elements is not an Net::DNS::Question object"
end
when Net::DNS::Question
@question = [object]
else
raise ArgumentError, "Invalid argument, not a Question object nor an array of objects"
end
end
# Assigns one or an array of Net::DNS::RR objects
# to the answer section of this Net::DNS::Packet instance.
def answer=(object)
case object
when Array
if object.all? {|x| x.kind_of? Net::DNS::RR}
@answer = object
else
raise ArgumentError, "Some of the elements is not an Net::DNS::RR object"
end
when Net::DNS::RR
@answer = [object]
else
raise ArgumentError, "Invalid argument, not a RR object nor an array of objects"
end
end
# Assigns one or an array of Net::DNS::RR objects
# to the additional section of this Net::DNS::Packet instance.
def additional=(object)
case object
when Array
if object.all? {|x| x.kind_of? Net::DNS::RR}
@additional = object
else
raise ArgumentError, "Some of the elements is not an Net::DNS::RR object"
end
when Net::DNS::RR
@additional = [object]
else
raise ArgumentError, "Invalid argument, not a RR object nor an array of objects"
end
end
# Assigns one or an array of Net::DNS::RR objects
# to the authority section of this Net::DNS::Packet instance.
def authority=(object)
case object
when Array
if object.all? {|x| x.kind_of? Net::DNS::RR}
@authority = object
else
raise ArgumentError, "Some of the elements is not an Net::DNS::RR object"
end
when Net::DNS::RR
@authority = [object]
else
raise ArgumentError, "Invalid argument, not a RR object nor an array of objects"
end
end
# Iterates every address in the +answer+ section
# of this Net::DNS::Packet instance.
#
# packet.each_address do |ip|
# ping ip.to_s
# end
#
# As you can see in the documentation for the Net::DNS::RR::A class,
# the address returned is an instance of IPAddr class.
def each_address(&block)
@answer.each do |elem|
next unless elem.class == Net::DNS::RR::A
yield elem.address
end
end
# Iterates every nameserver in the +answer+ section
# of this Net::DNS::Packet instance.
#
# packet.each_nameserver do |ns|
# puts "Nameserver found: #{ns}"
# end
#
def each_nameserver(&block)
@answer.each do |elem|
next unless elem.class == Net::DNS::RR::NS
yield elem.nsdname
end
end
# Iterates every exchange record in the +answer+ section
# of this Net::DNS::Packet instance.
#
# packet.each_mx do |pref,name|
# puts "Mail exchange #{name} has preference #{pref}"
# end
#
def each_mx(&block)
@answer.each do |elem|
next unless elem.class == Net::DNS::RR::MX
yield elem.preference, elem.exchange
end
end
# Iterates every canonical name in the +answer+ section
# of this Net::DNS::Packet instance.
#
# packet.each_cname do |cname|
# puts "Canonical name: #{cname}"
# end
#
def each_cname(&block)
@answer.each do |elem|
next unless elem.class == Net::DNS::RR::CNAME
yield elem.cname
end
end
# Iterates every pointer in the +answer+ section
# of this Net::DNS::Packet instance.
#
# packet.each_ptr do |ptr|
# puts "Pointer for resource: #{ptr}"
# end
#
def each_ptr(&block)
@answer.each do |elem|
next unless elem.class == Net::DNS::RR::PTR
yield elem.ptrdname
end
end
# Returns the packet size in bytes.
#
# Resolver("www.google.com") do |packet|
# puts packet.size + " bytes"}
# end
# # => 484 bytes
#
def size
data.size
end
# Checks whether the query returned a NXDOMAIN error,
# meaning the queried domain name doesn't exist.
#
# %w[a.com google.com ibm.com d.com].each do |domain|
# response = Net::DNS::Resolver.new.send(domain)
# puts "#{domain} doesn't exist" if response.nxdomain?
# end
# # => a.com doesn't exist
# # => d.com doesn't exist
#
def nxdomain?
header.rCode.code == Net::DNS::Header::RCode::NAME
end
# Creates a new instance of Net::DNS::Packet class from binary data,
# taken out from a network stream. For example:
#
# # udp_socket is an UDPSocket waiting for a response
# ans = udp_socket.recvfrom(1500)
# packet = Net::DNS::Packet::parse(ans)
#
# An optional +from+ argument can be used to specify the information
# of the sender. If data is passed as is from a Socket#recvfrom call,
# the method will accept it.
#
# Be sure that your network data is clean from any UDP/TCP header,
# especially when using RAW sockets.
#
def self.parse(*args)
o = allocate
o.send(:new_from_data, *args)
o
end
private
# New packet from binary data
def new_from_data(data, from = nil)
unless from
if data.kind_of? Array
data, from = data
else
from = [0, 0, "0.0.0.0", "unknown"]
end
end
@answerfrom = from[2] + ":" + from[1].to_s
@answersize = data.size
@logger = Logger.new $stdout
@logger.level = $DEBUG ? Logger::DEBUG : Logger::WARN
#------------------------------------------------------------
# Header section
#------------------------------------------------------------
offset = Net::DNS::HFIXEDSZ
@header = Net::DNS::Header.parse(data[0..offset-1])
@logger.debug ";; HEADER SECTION"
@logger.debug @header.inspect
#------------------------------------------------------------
# Question section
#------------------------------------------------------------
section = @header.opCode == "UPDATE" ? "ZONE" : "QUESTION"
@logger.debug ";; #{section} SECTION (#{@header.qdCount} record#{@header.qdCount == 1 ? '': 's'})"
@question = []
@header.qdCount.times do
qobj,offset = parse_question(data,offset)
@question << qobj
@logger.debug ";; #{qobj.inspect}"
end
#------------------------------------------------------------
# Answer/prerequisite section
#------------------------------------------------------------
section = @header.opCode == "UPDATE" ? "PREREQUISITE" : "ANSWER"
@logger.debug ";; #{section} SECTION (#{@header.qdCount} record#{@header.qdCount == 1 ? '': 's'})"
@answer = []
@header.anCount.times do
begin
rrobj,offset = Net::DNS::RR.parse_packet(data,offset)
@answer << rrobj
@logger.debug rrobj.inspect
rescue NameError => e
warn "Net::DNS unsupported record type: #{e.message}"
end
end
#------------------------------------------------------------
# Authority/update section
#------------------------------------------------------------
section = @header.opCode == "UPDATE" ? "UPDATE" : "AUTHORITY"
@logger.debug ";; #{section} SECTION (#{@header.nsCount} record#{@header.nsCount == 1 ? '': 's'})"
@authority = []
@header.nsCount.times do
begin
rrobj,offset = Net::DNS::RR.parse_packet(data,offset)
@authority << rrobj
@logger.debug rrobj.inspect
rescue NameError => e
warn "Net::DNS unsupported record type: #{e.message}"
end
end
#------------------------------------------------------------
# Additional section
#------------------------------------------------------------
@logger.debug ";; ADDITIONAL SECTION (#{@header.arCount} record#{@header.arCount == 1 ? '': 's'})"
@additional = []
@header.arCount.times do
begin
rrobj,offset = Net::DNS::RR.parse_packet(data,offset)
@additional << rrobj
@logger.debug rrobj.inspect
rescue NameError => e
warn "Net::DNS supported record type: #{e.message}"
end
end
end
# Parse question section
def parse_question(data,offset)
size = (dn_expand(data, offset)[1] - offset) + (2 * Net::DNS::INT16SZ)
return [Net::DNS::Question.parse(data[offset, size]), offset + size]
rescue StandardError => e
raise PacketError, "Caught exception, maybe packet malformed => #{e.message}"
end
end
end
end
ruby-net-dns-0.8.0/lib/net/dns/question.rb 0000664 0000000 0000000 00000012700 12142435533 0020364 0 ustar 00root root 0000000 0000000 module Net
module DNS
#
# =Name
#
# Net::DNS::Question - DNS packet question class
#
# =Synopsis
#
# require 'net/dns/question'
#
# =Description
#
# This class represent the Question portion of a DNS packet. The number
# of question entries is stored in the +qdCount+ variable of an Header
# object.
#
# A new object can be created passing the name of the query and the type
# of answer desired, plus an optional argument containing the class:
#
# question = Net::DNS::Question.new("google.com.", Net::DNS::A)
# #=> "google.com. A IN"
#
# Alternatevly, a new object is created when processing a binary
# packet, as when an answer is received.
# To obtain the binary data from a question object you can use
# the method Question#data:
#
# question.data
# #=> "\006google\003com\000\000\001\000\001"
#
# A lot of methods were written to keep a compatibility layer with
# the Perl version of the library, as long as methods name which are
# more or less the same.
#
class Question
include Names
# Base error class.
class Error < StandardError
end
# An error in the +name+ part of a Question entry
class NameInvalid < Error
end
# +name+ part of a Question entry
attr_reader :qName
# +type+ part of a Question entry
attr_reader :qType
# +class+ part of a Question entry
attr_reader :qClass
# Creates a new Net::DNS::Question object:
#
# question = Net::DNS::Question.new("example.com")
# #=> "example.com A IN"
# question = Net::DNS::Question.new("example.com", Net::DNS::MX)
# #=> "example.com MX IN"
# question = Net::DNS::Question.new("example.com", Net::DNS::TXT, Net::DNS::HS)
# #=> "example.com TXT HS"
# If not specified, +type+ and +cls+ arguments defaults
# to Net::DNS::A and Net::DNS::IN respectively.
#
def initialize(name, type = Net::DNS::A, cls = Net::DNS::IN)
@qName = check_name name
@qType = Net::DNS::RR::Types.new(type)
@qClass = Net::DNS::RR::Classes.new(cls)
end
# Return a new Net::DNS::Question object created by
# parsing binary data, such as an answer from the
# nameserver.
#
# question = Net::DNS::Question.parse(data)
# puts "Queried for #{question.qName} type #{question.qType.to_s}"
# #=> Queried for example.com type A
#
def self.parse(arg)
o = allocate
o.send(:new_from_binary, arg.to_s)
o
end
# Outputs binary data from a Question object
#
# question.data
# #=> "\006google\003com\000\000\001\000\001"
#
def data
[pack_name(@qName),@qType.to_i,@qClass.to_i].pack("a*nn")
end
# Return the binary data of the objects, plus an offset
# and an Hash with references to compressed names. For use in
# Net::DNS::Packet compressed packet creation.
def comp_data
arr = @qName.split(".")
str = pack_name(@qName)
string = ""
names = {}
offset = Net::DNS::HFIXEDSZ
arr.size.times do |i|
x = i+1
elem = arr[-x]
len = elem.size
string = ((string.reverse)+([len,elem].pack("Ca*")).reverse).reverse
names[string] = offset
offset += len
end
offset += 2 * Net::DNS::INT16SZ
str += "\000"
[[str,@qType.to_i,@qClass.to_i].pack("a*nn"),offset,names]
end
#
# call-seq:
# question.inspect -> string
#
# Returns a printable version of question with nice formatting.
#
# q = Net::DNS::Question.new("google.com.", Net::DNS::A)
# q.inspect # => "google.com. IN A "
#
def inspect
if @qName.size > 29 then
len = @qName.size + 1
else
len = 29
end
[@qName, @qClass.to_s, @qType.to_s].pack("A#{len} A8 A8")
end
#
# call-seq:
# question.to_s -> string
#
# Returns a string representation of question.
# It is the same as inspect.
#
# q = Net::DNS::Question.new("google.com.", Net::DNS::A)
# q.inspect # => "google.com. IN A "
#
def to_s
"#{self.inspect}"
end
private
def build_qName(str)
result = ""
offset = 0
loop do
len = str.unpack("@#{offset} C")[0]
break if len == 0
offset += 1
result += str[offset..offset+len-1]
result += "."
offset += len
end
result
end
def check_name(input)
name = input.to_s.strip
if name =~ /[^\w\.\-_]/
raise NameInvalid, "Invalid Question Name `#{name}'"
end
name
end
def new_from_binary(data)
str,type,cls = data.unpack("a#{data.size - 4}nn")
@qName = build_qName(str)
@qType = Net::DNS::RR::Types.new type
@qClass = Net::DNS::RR::Classes.new cls
rescue StandardError => e
raise ArgumentError, "Invalid data: #{data.inspect}"
end
end
end
end
ruby-net-dns-0.8.0/lib/net/dns/resolver.rb 0000664 0000000 0000000 00000121027 12142435533 0020361 0 ustar 00root root 0000000 0000000 require 'rbconfig'
require 'socket'
require 'timeout'
require 'net/dns/packet'
require 'net/dns/resolver/timeouts'
# Resolver helper method.
#
# Calling the resolver directly:
#
# puts Resolver("www.google.com").answer.size
# # => 5
#
# An optional block can be passed yielding the Net::DNS::Packet object.
#
# Resolver("www.google.com") { |packet| puts packet.size + " bytes" }
# # => 484 bytes
#
def Resolver(name, type = Net::DNS::A, cls = Net::DNS::IN, &block)
resolver = Net::DNS::Resolver.start(name, type, cls)
if block_given?
yield resolver
else
resolver
end
end
module Net
module DNS
include Logger::Severity
# = Net::DNS::Resolver - DNS resolver class
#
# 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.
#
# This project started as a porting of the Net::DNS Perl module,
# 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!
#
# == Environment
#
# The Following Environment variables can also be used to configure
# the resolver:
#
# * +RES_NAMESERVERS+: A space-separated list of nameservers to query.
#
# # Bourne Shell
# $ RES_NAMESERVERS="192.168.1.1 192.168.2.2 192.168.3.3"
# $ export RES_NAMESERVERS
#
# # C Shell
# % setenv RES_NAMESERVERS "192.168.1.1 192.168.2.2 192.168.3.3"
#
# * +RES_SEARCHLIST+: A space-separated list of domains to put in the
# search list.
#
# # Bourne Shell
# $ RES_SEARCHLIST="example.com sub1.example.com sub2.example.com"
# $ export RES_SEARCHLIST
#
# # C Shell
# % setenv RES_SEARCHLIST "example.com sub1.example.com sub2.example.com"
#
# * +LOCALDOMAIN+: The default domain.
#
# # Bourne Shell
# $ LOCALDOMAIN=example.com
# $ export LOCALDOMAIN
#
# # C Shell
# % setenv LOCALDOMAIN example.com
#
# * +RES_OPTIONS+: A space-separated list of resolver options to set.
# Options that take values are specified as option:value.
#
# # Bourne Shell
# $ RES_OPTIONS="retrans:3 retry:2 debug"
# $ export RES_OPTIONS
#
# # C Shell
# % setenv RES_OPTIONS "retrans:3 retry:2 debug"
#
class Resolver
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 = {
:config_file => "/etc/resolv.conf",
:log_file => $stdout,
:port => 53,
:searchlist => [],
:nameservers => [IPAddr.new("127.0.0.1")],
:domain => "",
:source_port => 0,
:source_address => IPAddr.new("0.0.0.0"),
:source_address_inet6 => IPAddr.new('::'),
:retry_interval => 5,
:retry_number => 4,
:recursive => true,
:defname => true,
:dns_search => true,
:use_tcp => false,
:ignore_truncated => false,
:packet_size => 512,
:tcp_timeout => TcpTimeout.new(5),
:udp_timeout => UdpTimeout.new(5),
}
class << self
C = Object.const_get(defined?(RbConfig) ? :RbConfig : :Config)::CONFIG
# Quick resolver method. Bypass the configuration using
# the defaults.
#
# Net::DNS::Resolver.start "www.google.com"
#
def start(*params)
new.search(*params)
end
# Returns true if running on a Windows platform.
#
# Note. This method doesn't rely on the RUBY_PLATFORM constant
# because the comparison will fail when running on JRuby.
# On JRuby RUBY_PLATFORM == 'java'.
def platform_windows?
!!(C["host_os"] =~ /msdos|mswin|djgpp|mingw/i)
end
end
# Creates a new resolver object.
#
# Argument +config+ can either be empty or be an hash with
# some configuration parameters. To know what each parameter
# do, look at the description of each.
# Some example:
#
# # Use the sistem defaults
# res = Net::DNS::Resolver.new
#
# # Specify a configuration file
# res = Net::DNS::Resolver.new(:config_file => '/my/dns.conf')
#
# # Set some option
# res = Net::DNS::Resolver.new(:nameservers => "172.16.1.1",
# :recursive => false,
# :retry => 10)
#
# == 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:
#
# * /etc/resolv.conf
# * $HOME/.resolv.conf
# * ./.resolv.conf
#
# The following keywords are recognized in resolver configuration files:
#
# * domain: the default domain.
# * search: a space-separated list of domains to put in the search list.
# * nameserver: a space-separated list of nameservers to query.
#
# Files except for /etc/resolv.conf must be owned by the effective userid
# running the program or they won't be read. In addition, several environment
# variables can also contain configuration information; see Environment
# in the main description for Resolver class.
#
# On Windows Systems, an attempt is made to determine the system defaults
# using the registry. This is still a work in progress; systems with many
# dynamically configured network interfaces may confuse Net::DNS.
#
# You can include a configuration file of your own when creating a resolver
# object:
#
# # Use my own configuration file
# my $res = Net::DNS::Resolver->new(config_file => '/my/dns.conf');
#
# This is supported on both UNIX and Windows. Values pulled from a custom
# configuration file override the the system's defaults, but can still be
# 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
#
# 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
#
# For more information on any of these options, please consult the
# method of the same name.
#
# == Disclaimer
#
# Part of the above documentation is taken from the one in the
# Net::DNS::Resolver Perl module.
#
def initialize(config = {})
raise ArgumentError, "Expected `config' to be a Hash" unless config.is_a?(Hash)
# config.downcase_keys!
@config = Defaults.merge config
@raw = false
# New logger facility
@logger = Logger.new(@config[:log_file])
@logger.level = $DEBUG ? Logger::DEBUG : Logger::WARN
#------------------------------------------------------------
# Resolver configuration will be set in order from:
# 1) initialize arguments
# 2) ENV variables
# 3) config file
# 4) defaults (and /etc/resolv.conf for config)
#------------------------------------------------------------
#------------------------------------------------------------
# Parsing config file
#------------------------------------------------------------
parse_config_file
#------------------------------------------------------------
# Parsing ENV variables
#------------------------------------------------------------
parse_environment_variables
#------------------------------------------------------------
# Parsing arguments
#------------------------------------------------------------
config.each do |key,val|
next if key == :log_file or key == :config_file
begin
eval "self.#{key.to_s} = val"
rescue NoMethodError
raise ArgumentError, "Option #{key} not valid"
end
end
end
# Get the resolver search list, returned as an array of entries.
#
# res.searchlist
# #=> ["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.
#
# 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.
#
# res.searchlist << "c.example.com"
# res.searchlist
# #=> ["example.com","a.example.com","b.example.com","c.example.com"]
#
# 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 ArgumentError, "Wrong argument format, neither String nor Array"
end
end
# Get the list of resolver nameservers, in a dotted decimal format-
#
# res.nameservers
# #=> ["192.168.0.1","192.168.0.2"]
#
def nameservers
@config[:nameservers].map(&:to_s)
end
alias_method :nameserver, :nameservers
# 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.
#
# ip = IPAddr.new("192.168.0.3")
# res.nameservers << ip
# #=> ["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
when String
begin
@config[:nameservers] = [IPAddr.new(arg)]
@logger.info "Nameservers list changed to value #{@config[:nameservers].inspect}"
rescue ArgumentError # arg is in the name form, not IP
nameservers_from_name(arg)
end
when IPAddr
@config[:nameservers] = [arg]
@logger.info "Nameservers list changed to value #{@config[:nameservers].inspect}"
when Array
@config[:nameservers] = []
arg.each do |x|
@config[:nameservers] << case x
when String
begin
IPAddr.new(x)
rescue ArgumentError
nameservers_from_name(arg)
return
end
when IPAddr
x
else
raise ArgumentError, "Wrong argument format"
end
end
@logger.info "Nameservers list changed to value #{@config[:nameservers].inspect}"
else
raise ArgumentError, "Wrong argument format, neither String, Array nor IPAddr"
end
end
alias_method("nameserver=","nameservers=")
# Return a string with the default domain.
def domain
@config[:domain].inspect
end
# Set the domain for the query.
def domain=(name)
@config[:domain] = name if valid? name
end
# Return the defined size of the packet.
def packet_size
@config[:packet_size]
end
# Get the port number to which the resolver sends queries.
#
# puts "Sending queries to port #{res.port}"
#
def port
@config[:port]
end
# Set the port number to which the resolver sends queries. This can be useful
# for testing a nameserver running on a non-standard port.
#
# res.port = 10053
#
# The default is port 53.
#
def port=(num)
if (0..65535).include? num
@config[:port] = num
@logger.info "Port number changed to #{num}"
else
raise ArgumentError, "Wrong port number #{num}"
end
end
# Get the value of the source port number.
#
# puts "Sending queries using port #{res.source_port}"
#
def source_port
@config[:source_port]
end
alias srcport source_port
# Set the local source port from which the resolver sends its queries.
#
# res.source_port = 40000
#
# Note that if you want to set a port you need root priviledges, as
# raw sockets will be used to generate packets. The class will then
# generate the exception ResolverPermissionError if you're not root.
#
# The default is 0, which means that the port will be chosen by the
# underlaying layers.
#
def source_port=(num)
unless root?
raise ResolverPermissionError, "Are you root?"
end
if (0..65535).include?(num)
@config[:source_port] = num
else
raise ArgumentError, "Wrong port number #{num}"
end
end
alias srcport= source_port=
# Get the local address from which the resolver sends queries
#
# puts "Sending queries using source address #{res.source_address}"
#
def source_address
@config[:source_address].to_s
end
alias srcaddr source_address
# Get the local ipv6 address from which the resolver sends queries
#
def source_address_inet6
@config[:source_address_inet6].to_s
end
# 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
# or an instance of IPAddr class.
#
# Normally this can be used to force queries out a specific interface
# on a multi-homed host. In this case, you should of course need to
# know the addresses of the interfaces.
#
# Another way to use this option is for some kind of spoofing attacks
# towards weak nameservers, to probe the security of your network.
# This includes specifing ranged attacks such as DoS and others. For
# a paper on DNS security, checks http://www.marcoceresa.com/security/
#
# 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).
#
def source_address=(addr)
unless addr.respond_to? :to_s
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}"
a = TCPServer.new(addr.to_s,port)
rescue SystemCallError => e
case e.errno
when 98 # Port already in use!
@logger.warn "Port already in use"
retry
when 99 # Address is not valid: raw socket
@raw = true
@logger.warn "Using raw sockets"
else
raise SystemCallError, e
end
ensure
a.close
end
case addr
when String
@config[:source_address] = IPAddr.new(string)
@logger.info "Using new source address: #{@config[:source_address]}"
when IPAddr
@config[:source_address] = addr
@logger.info "Using new source address: #{@config[:source_address]}"
else
raise ArgumentError, "Unknown dest_address format"
end
end
alias srcaddr= source_address=
# Return the retrasmission interval (in seconds) the resolvers has
# been set on.
def retry_interval
@config[:retry_interval]
end
alias retrans retry_interval
# 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 ArgumentError, "Interval must be positive"
end
end
alias retrans= retry_interval=
# 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.
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 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
# perform recursive queries.
#
# print "The resolver will perform a "
# print res.recursive? ? "" : "not "
# puts "recursive query"
#
def recursive?
@config[:recursive]
end
alias_method :recurse, :recursive?
alias_method :recursive, :recursive?
# Sets whether or not the resolver should perform recursive
# queries. Default is true.
#
# res.recursive = false # perform non-recursive query
#
def recursive=(bool)
case bool
when TrueClass,FalseClass
@config[:recursive] = bool
@logger.info("Recursive state changed to #{bool}")
else
raise ArgumentError, "Argument must be boolean"
end
end
alias_method :recurse=, :recursive=
# Return a string representing the resolver state, suitable
# for printing on the screen.
#
# puts "Resolver state:"
# puts res.state
#
def state
str = ";; RESOLVER state:\n;; "
i = 1
@config.each do |key,val|
if key == :log_file or key == :config_file
str << "#{key}: #{val} \t"
else
str << "#{key}: #{eval(key.to_s)} \t"
end
str << "\n;; " if i % 2 == 0
i += 1
end
str
end
alias print state
alias inspect state
# Checks whether the +defname+ flag has been activate.
def defname?
@config[:defname]
end
alias defname defname?
# Set the flag +defname+ in a boolean state. if +defname+ is true,
# calls to Resolver#query will append the default domain to names
# that contain no dots.
# Example:
#
# # Domain example.com
# res.defname = true
# res.query("machine1")
# #=> This will perform a query for machine1.example.com
#
# Default is true.
#
def defname=(bool)
case bool
when TrueClass,FalseClass
@config[:defname] = bool
@logger.info("Defname state changed to #{bool}")
else
raise ArgumentError, "Argument must be boolean"
end
end
# 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 ArgumentError, "Argument must be boolean"
end
end
alias_method("dnsrch=","dns_search=")
# Get the state of the use_tcp flag.
#
def use_tcp?
@config[:use_tcp]
end
alias_method :usevc, :use_tcp?
alias_method :use_tcp, :use_tcp?
# If +use_tcp+ is true, the resolver will perform all queries
# using TCP virtual circuits instead of UDP datagrams, which
# is the default for the DNS protocol.
#
# res.use_tcp = true
# res.query "host.example.com"
# #=> Sending TCP segments...
#
# Default is false.
#
def use_tcp=(bool)
case bool
when TrueClass,FalseClass
@config[:use_tcp] = bool
@logger.info("Use tcp flag changed to #{bool}")
else
raise ArgumentError, "Argument must be boolean"
end
end
alias usevc= use_tcp=
def ignore_truncated?
@config[:ignore_truncated]
end
alias_method :ignore_truncated, :ignore_truncated?
def ignore_truncated=(bool)
case bool
when TrueClass,FalseClass
@config[:ignore_truncated] = bool
@logger.info("Ignore truncated flag changed to #{bool}")
else
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
# is an instance of the class +TcpTimeout+, and two methods
# are available for printing informations: TcpTimeout#to_s
# and TcpTimeout#pretty_to_s.
#
# Here's some example:
#
# puts "Timeout of #{res.tcp_timeout} seconds" # implicit to_s
# #=> 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.
#
def tcp_timeout
@config[:tcp_timeout].to_s
end
# Set the value of TCP timeout for resolver queries that
# 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 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 information: UdpTimeout#to_s
# and UdpTimeout#pretty_to_s.
#
# Here's some example:
#
# puts "Timeout of #{res.udp_timeout} seconds" # implicit to_s
# #=> Timeout of 150 seconds
#
# puts "You set a timeout of " + res.udp_timeout.pretty_to_s
# #=> You set a timeout of 2 minutes and 30 seconds
#
# If the timeout is zero, a string "not defined" will
# be returned.
#
def udp_timeout
@config[:udp_timeout].to_s
end
# 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.
#
# Default is 5 seconds.
#
# The value is stored internally as a +UdpTimeout+ object, see
# 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
# Set a new log file for the logger facility of the resolver
# class. Could be a file descriptor too:
#
# res.log_file = $stderr
#
# Note that a new logging facility will be create, destroing
# the old one, which will then be impossibile to recover.
#
def log_file=(log)
@logger.close
@config[:log_file] = log
@logger = Logger.new(@config[:log_file])
@logger.level = $DEBUG ? Logger::DEBUG : Logger::WARN
end
# This one permits to have a personal logger facility to handle
# resolver messages, instead of new built-in one, which is set up
# for a +$stdout+ (or +$stderr+) use.
#
# If you want your own logging facility you can create a new instance
# of the +Logger+ class:
#
# log = Logger.new("/tmp/resolver.log","weekly",2*1024*1024)
# log.level = Logger::DEBUG
# log.progname = "ruby_resolver"
#
# and then pass it to the resolver:
#
# res.logger = log
#
# Note that this will destroy the precedent logger.
#
def logger=(logger)
if logger.kind_of? Logger
@logger.close
@logger = logger
else
raise ArgumentError, "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
# list to the name. This is only done if +dns_search+ is true.
# 3. If the name doesn't contain any dots, try it as is.
#
# The record type and class can be omitted; they default to +A+ and +IN+.
#
# packet = res.search('mailhost')
# packet = res.search('mailhost.example.com')
# packet = res.search('example.com', Net::DNS::MX)
# packet = res.search('user.passwd.example.com', Net::DNS::TXT, Net::DNS::HS)
#
# If the name is an IP address (Ipv4 or IPv6), in the form of a string
# or a +IPAddr+ object, then an appropriate PTR query will be performed:
#
# ip = IPAddr.new("172.16.100.2")
# packet = res.search(ip)
# packet = res.search("192.168.10.254")
#
# Returns a Net::DNS::Packet object. If you need to examine the response packet
# whether it contains any answers or not, use the Resolver#query method instead.
#
def search(name,type=Net::DNS::A,cls=Net::DNS::IN)
return query(name,type,cls) if name.class == IPAddr
# If the name contains at least one dot then try it as is first.
if name.include? "."
@logger.debug "Search(#{name},#{Net::DNS::RR::Types.new(type)},#{Net::DNS::RR::Classes.new(cls)})"
ans = query(name,type,cls)
return ans if ans.header.anCount > 0
end
# If the name doesn't end in a dot then apply the search list.
if name !~ /\.$/ and @config[:dns_search]
@config[:searchlist].each do |domain|
newname = name + "." + domain
@logger.debug "Search(#{newname},#{Net::DNS::RR::Types.new(type)},#{Net::DNS::RR::Classes.new(cls)})"
ans = query(newname,type,cls)
return ans if ans.header.anCount > 0
end
end
# Finally, if the name has no dots then try it as is.
@logger.debug "Search(#{name},#{Net::DNS::RR::Types.new(type)},#{Net::DNS::RR::Classes.new(cls)})"
query(name+".",type,cls)
end
# Performs a DNS query for the given name; the search list
# is not applied. If the name doesn't contain any dots and
# +defname+ is true then the default domain will be appended.
#
# The record type and class can be omitted; they default to +A+
# and +IN+. If the name looks like an IP address (IPv4 or IPv6),
# then an appropriate PTR query will be performed.
#
# packet = res.query('mailhost')
# packet = res.query('mailhost.example.com')
# packet = res.query('example.com', Net::DNS::MX)
# packet = res.query('user.passwd.example.com', Net::DNS::TXT, Net::DNS::HS)
#
# If the name is an IP address (Ipv4 or IPv6), in the form of a string
# or a +IPAddr+ object, then an appropriate PTR query will be performed:
#
# ip = IPAddr.new("172.16.100.2")
# packet = res.query(ip)
# packet = res.query("192.168.10.254")
#
# Returns a Net::DNS::Packet object. If you need to examine the response
# packet whether it contains any answers or not, use the Resolver#query
# method instead.
#
def query(name,type=Net::DNS::A,cls=Net::DNS::IN)
return send(name,type,cls) if name.class == IPAddr
# If the name doesn't contain any dots then append the default domain.
if name !~ /\./ and name !~ /:/ and @config[:defname]
name += "." + @config[:domain]
end
@logger.debug "Query(#{name},#{Net::DNS::RR::Types.new(type)},#{Net::DNS::RR::Classes.new(cls)})"
send(name,type,cls)
end
# Performs a DNS query for the given name. Neither the
# searchlist nor the default domain will be appended.
#
# The argument list can be either a Net::DNS::Packet object
# or a name string plus optional type and class, which if
# omitted default to +A+ and +IN+.
#
# Returns a Net::DNS::Packet object.
#
# # Executes the query with a +Packet+ object
# send_packet = Net::DNS::Packet.new("host.example.com", Net::DNS::NS, Net::DNS::HS)
# packet = res.query(send_packet)
#
# # Executes the query with a host, type and cls
# packet = res.query("host.example.com")
# packet = res.query("host.example.com", Net::DNS::NS)
# packet = res.query("host.example.com", Net::DNS::NS, Net::DNS::HS)
#
# If the name is an IP address (Ipv4 or IPv6), in the form of a string
# or a IPAddr object, then an appropriate PTR query will be performed:
#
# ip = IPAddr.new("172.16.100.2")
# packet = res.query(ip)
#
# packet = res.query("172.16.100.2")
#
# Use +packet.header.ancount+ or +packet.answer+ to find out if there
# were any records in the answer section.
#
def query(argument, type = Net::DNS::A, cls = Net::DNS::IN)
if @config[:nameservers].size == 0
raise Resolver::Error, "No nameservers specified!"
end
method = :query_udp
packet = if argument.kind_of? Net::DNS::Packet
argument
else
make_query_packet(argument, type, cls)
end
# Store packet_data for performance improvements,
# so methods don't keep on calling Packet#data
packet_data = packet.data
packet_size = packet_data.size
# Choose whether use TCP, UDP or RAW
if packet_size > @config[:packet_size] # Must use TCP, either plain or raw
if @raw # Use raw sockets?
@logger.info "Sending #{packet_size} bytes using TCP over RAW socket"
method = :send_raw_tcp
else
@logger.info "Sending #{packet_size} bytes using TCP"
method = :query_tcp
end
else # Packet size is inside the boundaries
if @raw # Use raw sockets?
@logger.info "Sending #{packet_size} bytes using UDP over RAW socket"
method = :send_raw_udp
elsif use_tcp? # User requested TCP
@logger.info "Sending #{packet_size} bytes using TCP"
method = :query_tcp
else # Finally use UDP
@logger.info "Sending #{packet_size} bytes using UDP"
end
end
if type == Net::DNS::AXFR
if @raw
@logger.warn "AXFR query, switching to TCP over RAW socket"
method = :send_raw_tcp
else
@logger.warn "AXFR query, switching to TCP"
method = :query_tcp
end
end
ans = self.send(method, packet, packet_data)
unless ans
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])
if response.header.truncated? and not ignore_truncated?
@logger.warn "Packet truncated, retrying using TCP"
self.use_tcp = true
begin
return query(argument,type,cls)
ensure
self.use_tcp = false
end
end
return response
end
# Performs a zone transfer for the zone passed as a parameter.
#
# It is actually only a wrapper to a send with type set as Net::DNS::AXFR,
# since it is using the same infrastucture.
#
def axfr(name, cls = Net::DNS::IN)
@logger.info "Requested AXFR transfer, zone #{name} class #{cls}"
query(name, Net::DNS::AXFR, cls)
end
# Performs an MX query for the domain name passed as parameter.
#
# 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.
#
# res = Net::DNS::Resolver.new
# res.mx("google.com")
#
def mx(name, cls = Net::DNS::IN)
arr = []
query(name, Net::DNS::MX, cls).answer.each do |entry|
arr << entry if entry.type == 'MX'
end
arr.sort_by { |a| a.preference }
end
private
# 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].to_s
self.nameservers = arr[1]
else
nameservers = []
IO.foreach(@config[:config_file]) do |line|
line.gsub!(/\s*[;#].*/,"")
next unless line =~ /\S/
case line
when /^\s*domain\s+(\S+)/
self.domain = $1
when /^\s*search\s+(.*)/
self.searchlist = $1.split(" ")
when /^\s*nameserver\s+(.*)/
nameservers << $1.split(" ")
end
end
self.nameservers = nameservers.flatten
end
end
# Parses environment variables.
def parse_environment_variables
if ENV['RES_NAMESERVERS']
self.nameservers = ENV['RES_NAMESERVERS'].split(" ")
end
if ENV['RES_SEARCHLIST']
self.searchlist = ENV['RES_SEARCHLIST'].split(" ")
end
if ENV['LOCALDOMAIN']
self.domain = ENV['LOCALDOMAIN']
end
if ENV['RES_OPTIONS']
ENV['RES_OPTIONS'].split(" ").each do |opt|
name,val = opt.split(":")
begin
eval("self.#{name} = #{val}")
rescue NoMethodError
raise ArgumentError, "Invalid ENV option #{name}"
end
end
end
end
def nameservers_from_name(arg)
arr = []
arg.split(" ").each do |name|
Resolver.new.search(name).each_address do |ip|
arr << ip
end
end
@config[:nameservers] << arr
end
def make_query_packet(string, type, cls)
case string
when IPAddr
name = string.reverse
type = Net::DNS::PTR
@logger.warn "PTR query required for address #{string}, changing type to PTR"
when /\d/ # Contains a number, try to see if it's an IP or IPv6 address
begin
name = IPAddr.new(string.chomp(".")).reverse
type = Net::DNS::PTR
rescue ArgumentError
name = string if valid? string
end
else
name = string if valid? string
end
# Create the packet
packet = Net::DNS::Packet.new(name, type, cls)
if packet.query?
packet.header.recursive = @config[:recursive] ? 1 : 0
end
# DNSSEC and TSIG stuff to be inserted here
packet
end
def query_tcp(packet, packet_data)
ans = nil
length = [packet_data.size].pack("n")
@config[:nameservers].each do |ns|
begin
buffer = ""
socket = Socket.new(Socket::AF_INET,Socket::SOCK_STREAM,0)
socket.bind(Socket.pack_sockaddr_in(@config[:source_port],@config[:source_address].to_s))
sockaddr = Socket.pack_sockaddr_in(@config[:port],ns.to_s)
@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]
@logger.info "Receiving #{len} bytes..."
if len == 0
@logger.warn "Receiving 0 lenght packet from nameserver #{ns}, trying next."
next
end
while (buffer.size < len)
left = len - buffer.size
temp,from = socket.recvfrom(left)
buffer += temp
end
unless buffer.size == len
@logger.warn "Malformed packet from nameserver #{ns}, trying next."
next
end
end
return [buffer,["",@config[:port],ns.to_s,ns.to_s]]
rescue TimeoutError
@logger.warn "Nameserver #{ns} not responding within TCP timeout, trying next one"
next
ensure
socket.close
end
end
end
def query_udp(packet, packet_data)
socket4 = UDPSocket.new
socket4.bind(@config[:source_address].to_s,@config[:source_port])
socket6 = UDPSocket.new(Socket::AF_INET6)
socket6.bind(@config[:source_address_inet6].to_s,@config[:source_port])
ans = nil
response = ""
@config[:nameservers].each do |ns|
begin
@config[:udp_timeout].timeout do
@logger.info "Contacting nameserver #{ns} port #{@config[:port]}"
ans = if ns.ipv6?
socket6.send(packet_data, 0, ns.to_s, @config[:port])
socket6.recvfrom(@config[:packet_size])
else
socket4.send(packet_data, 0, ns.to_s, @config[:port])
socket4.recvfrom(@config[:packet_size])
end
end
break if ans
rescue TimeoutError
@logger.warn "Nameserver #{ns} not responding within UDP timeout, trying next one"
next
end
end
ans
end
# FIXME: a ? method should never raise.
def valid?(name)
if name =~ /[^-\w\.]/
raise ArgumentError, "Invalid domain name #{name}"
else
true
end
end
end
end
end
ruby-net-dns-0.8.0/lib/net/dns/resolver/ 0000775 0000000 0000000 00000000000 12142435533 0020031 5 ustar 00root root 0000000 0000000 ruby-net-dns-0.8.0/lib/net/dns/resolver/socks.rb 0000664 0000000 0000000 00000007540 12142435533 0021506 0 ustar 00root root 0000000 0000000 require 'socket'
require 'ipaddr'
class RawSocket # :nodoc:
@@id_arr = []
def initialize(src_addr,dest_addr)
# Define socket
begin
@socket = Socket.new PF_INET, SOCK_RAW, IPPROTO_RAW
rescue SystemCallError => e
raise SystemCallError, "You must be root to use raw sockets! #{e}"
end
@socket.setsockopt IPPROTO_IP, IP_HDRINCL, 1
# Checks addresses
@src_addr = check_addr src_addr
@dest_addr = check_addr dest_addr
# Source and destination port are zero
@src_port = 0
@dest_port = 0
# Set correct protocol version in the header
@version = @dest_addr.ipv4? ? "0100" : "0110"
# Total lenght: must be overridden by subclasses
@tot_lenght = 20
# Protocol: must be overridden by subclasses
@protocol = 1 # ICMP by default
# Generate a new id
# @id = genID
@id = 1234
# Generate peer sockaddr
@to = Socket.pack_sockaddr_in @dest_port, @dest_addr.to_s
end
def send(payload = '')
packet = make_ip_header([[ @version+'0101', 'B8' ], # version, hlen
[ 0, 'C' ], # tos
[ @tot_lenght + payload.size, 'n' ], # total len
[ @id, 'n' ], # id
[ 0, 'n' ], # flags, offset
[ 64, 'C' ], # ttl
[ @protocol, 'C' ], # protocol
[ 0, 'n' ], # checksum
[ @src_addr.to_i, 'N' ], # source
[ @dest_addr.to_i, 'N' ], # destination
])
packet << make_transport_header(payload.size)
packet << [payload].pack("a*")
@socket.send(packet,0,@to)
end
private
def check_addr addr
case addr
when String
IPAddr.new(addr)
when IPAddr
addr
else
raise ArgumentError, "Wrong address format: #{addr}"
end
end
def check_port port
if (1..65535).include? port and port.kind_of? Integer
port
else
raise ArgumentError, "Port #{port} not valid"
end
end
def genID
while (@@id_arr.include?(q = rand(65535)))
end
@@id_arr.push(q)
q
end
def ipchecksum(data)
checksum = data.unpack("n*").inject(0) { |s, x| s + x }
((checksum >> 16) + (checksum & 0xffff)) ^ 0xffff
end
def make_ip_header(parts)
template = ''
data = []
parts.each do |part|
data += part[0..-2]
template << part[-1]
end
data_str = data.pack(template)
checksum = ipchecksum(data_str)
data[-3] = checksum
data.pack(template)
end
def make_transport_header
""
end
end
class UdpRawSocket < RawSocket # :nodoc:
def initialize(src_addr,src_port,dest_addr,dest_port)
super(src_addr,dest_addr)
# Check ports
@src_port = check_port src_port
@dest_port = check_port dest_port
# Total lenght: must be overridden by subclasses
@tot_lenght = 20 + 8 # 8 bytes => UDP Header
# Protocol: must be overridden by subclasses
@protocol = 17 # UDP protocol
@to = Socket.pack_sockaddr_in @dest_port, @dest_addr.to_s
end
private
def make_udp_header(parts)
template = ''
data = []
parts.each do |part|
data += part[0..-2]
template << part[-1]
end
data.pack(template)
end
def make_transport_header(pay_size)
make_udp_header([
[ @src_port, 'n'], # source port
[ @dest_port, 'n' ], # destination port
[ 8 + pay_size, 'n' ], # len
[ 0, 'n' ] # checksum (mandatory)
])
end
end
ruby-net-dns-0.8.0/lib/net/dns/resolver/timeouts.rb 0000664 0000000 0000000 00000003504 12142435533 0022231 0 ustar 00root root 0000000 0000000 require 'timeout'
module Net # :nodoc:
module DNS
class Resolver
class DnsTimeout
attr_reader :seconds
def initialize(seconds)
if seconds.is_a? Numeric and seconds >= 0
@seconds = seconds
else
raise ArgumentError, "Invalid value for tcp timeout"
end
end
# Returns a string representation of the timeout corresponding
# to the number of @seconds.
def to_s
if @seconds == 0
@output.to_s
else
@seconds.to_s
end
end
def pretty_to_s
transform(@seconds)
end
# Executes the method's block. If the block execution terminates before +sec+
# seconds has passed, it returns true. If not, it terminates the execution
# and raises Timeout::Error.
# If @seconds is 0 or nil, no timeout is set.
def timeout(&block)
raise LocalJumpError, "no block given" unless block_given?
Timeout.timeout(@seconds, &block)
end
private
def transform(secs)
case secs
when 0
to_s
when 1..59
"#{secs} seconds"
when 60..3559
"#{secs / 60} minutes and #{secs % 60} seconds"
else
hours = secs / 3600
secs -= (hours * 3600)
"#{hours} hours, #{secs / 60} minutes and #{secs % 60} seconds"
end
end
end
class TcpTimeout < DnsTimeout
def initialize(seconds)
@output = "infinite"
super
end
end
class UdpTimeout < DnsTimeout
def initialize(seconds)
@output = "not defined"
super
end
end
end
end
end ruby-net-dns-0.8.0/lib/net/dns/rr.rb 0000664 0000000 0000000 00000026127 12142435533 0017150 0 ustar 00root root 0000000 0000000 require 'ipaddr'
require 'net/dns/names'
require 'net/dns/rr/types'
require 'net/dns/rr/classes'
%w(a aaaa cname hinfo mr mx ns ptr soa srv txt).each do |file|
require "net/dns/rr/#{file}"
end
module Net
module DNS
#
# = Net::DNS::RR - DNS Resource Record class
#
# The Net::DNS::RR is the base class for DNS Resource
# Record (RR) objects. A RR is a pack of data that represents
# resources for a DNS zone. The form in which this data is
# shows can be drawed as follow:
#
# "name ttl class type data"
#
# The +name+ is the name of the resource, like an canonical
# name for an +A+ record (internet ip address). The +ttl+ is the
# time to live, expressed in seconds. +type+ and +class+ are
# respectively the type of resource (+A+ for ip addresses, +NS+
# for nameservers, and so on) and the class, which is almost
# always +IN+, the Internet class. At the end, +data+ is the
# value associated to the name for that particular type of
# resource record. An example:
#
# # A record for IP address
# "www.example.com 86400 IN A 172.16.100.1"
#
# # NS record for name server
# "www.example.com 86400 IN NS ns.example.com"
#
# A new RR object can be created in 2 ways: passing a string
# such the ones above, or specifying each field as the pair
# of an hash. See the Net::DNS::RR.new method for details.
#
class RR
include Names
# Base error class.
class Error < StandardError
end
# Error in parsing binary data, maybe from a malformed packet.
class DataError < Error
end
# Regexp matching an RR string
RR_REGEXP = Regexp.new("^\\s*(\\S+)\\s*(\\d+)?\\s+(" +
Net::DNS::RR::Classes.regexp +
"|CLASS\\d+)?\\s*(" +
Net::DNS::RR::Types.regexp +
"|TYPE\\d+)?\\s*(.*)$", Regexp::IGNORECASE)
# Dimension of the sum of class, type, TTL and rdlength fields in a
# RR portion of the packet, in bytes
RRFIXEDSZ = 10
# Create a new instance of Net::DNS::RR class, or an instance of
# any of the subclass of the appropriate type.
#
# Argument can be a string or an hash. With a sting, we can pass
# a RR resource record in the canonical format:
#
# a = Net::DNS::RR.new("foo.example.com. 86400 A 10.1.2.3")
# mx = Net::DNS::RR.new("example.com. 7200 MX 10 mailhost.example.com.")
# cname = Net::DNS::RR.new("www.example.com 300 IN CNAME www1.example.com")
# txt = Net::DNS::RR.new('baz.example.com 3600 HS TXT "text record"')
#
# Incidentally, +a+, +mx+, +cname+ and +txt+ objects will be instances of
# respectively Net::DNS::RR::A, Net::DNS::RR::MX, Net::DNS::RR::CNAME and
# Net::DNS::RR::TXT classes.
#
# The name and RR data are required; all other informations are optional.
# If omitted, the +TTL+ defaults to 10800, +type+ default to +A+ and the RR class
# defaults to +IN+. Omitting the optional fields is useful for creating the
# empty RDATA sections required for certain dynamic update operations.
# All names must be fully qualified. The trailing dot (.) is optional.
#
# The preferred method is however passing an hash with keys and values:
#
# rr = Net::DNS::RR.new(
# :name => "foo.example.com",
# :ttl => 86400,
# :cls => "IN",
# :type => "A",
# :address => "10.1.2.3"
# )
#
# rr = Net::DNS::RR.new(
# :name => "foo.example.com",
# :rdata => "10.1.2.3"
# )
#
# Name and data are required; all the others fields are optionals like
# we've seen before. The data field can be specified either with the
# right name of the resource (+:address+ in the example above) or with
# the generic key +:rdata+. Consult documentation to find the exact name
# for the resource in each subclass.
#
def initialize(arg)
instance = case arg
when String
new_from_string(arg)
when Hash
new_from_hash(arg)
else
raise ArgumentError, "Invalid argument, must be a RR string or an hash of values"
end
if @type.to_s == "ANY"
@cls = Net::DNS::RR::Classes.new("IN")
end
build_pack
set_type
instance
end
# Return a new RR object of the correct type (like Net::DNS::RR::A
# if the type is A) from a binary string, usually obtained from
# network stream.
#
# This method is used when parsing a binary packet by the Packet
# class.
#
def RR.parse(data)
o = allocate
obj, offset = o.send(:new_from_binary, data, 0)
obj
end
# Same as RR.parse, but takes an entire packet binary data to
# perform name expansion. Default when analizing a packet
# just received from a network stream.
#
# Return an instance of appropriate class and the offset
# pointing at the end of the data parsed.
#
def RR.parse_packet(data, offset)
o = allocate
o.send(:new_from_binary, data, offset)
end
def name
@name
end
def ttl
@ttl
end
# Type accessor
def type
@type.to_s
end
# Class accessor
def cls
@cls.to_s
end
def value
get_inspect
end
# Data belonging to that appropriate class,
# not to be used (use real accessors instead)
def rdata
@rdata
end
# Return the RR object in binary data format, suitable
# for using in network streams.
#
# raw_data = rr.data
# puts "RR is #{raw_data.size} bytes long"
#
def data
str = pack_name(@name)
str + [@type.to_i, @cls.to_i, ttl, @rdlength].pack("n2 N n") + get_data
end
# Return the RR object in binary data format, suitable
# for using in network streams, with names compressed.
# Must pass as arguments the offset inside the packet
# and an hash of compressed names.
#
# This method is to be used in other classes and is
# not intended for user space programs.
#
# TO FIX in one of the future releases
#
def comp_data(offset,compnames)
str, offset, names = dn_comp(@name, offset, compnames)
str += [@type.to_i, @cls.to_i, ttl, @rdlength].pack("n2 N n")
offset += Net::DNS::RRFIXEDSZ
[str, offset, names]
end
# Returns a human readable representation of this record.
# The value is always a String.
#
# mx = Net::DNS::RR.new("example.com. 7200 MX 10 mailhost.example.com.")
# #=> example.com. 7200 IN MX 10 mailhost.example.com.
#
def inspect
to_s
end
# Returns a String representation of this record.
#
# mx = Net::DNS::RR.new("example.com. 7200 MX 10 mailhost.example.com.")
# mx.to_s
# #=> "example.com. 7200 IN MX 10 mailhost.example.com."
#
def to_s
items = to_a.map { |e| e.to_s }
if @name.size < 24
items.pack("A24 A8 A8 A8 A*")
else
items.join(" ")
end.to_s
end
# Returns an Array with all the attributes for this record.
#
# mx = Net::DNS::RR.new("example.com. 7200 MX 10 mailhost.example.com.")
# mx.to_a
# #=> ["example.com.", 7200, "IN", "MX", "10 mailhost.example.com."]
#
def to_a
[name, ttl, cls.to_s, type.to_s, value]
end
private
def new_from_string(rrstring)
unless rrstring =~ RR_REGEXP
raise ArgumentError,
"Format error for RR string (maybe CLASS and TYPE not valid?)"
end
# Name of RR - mandatory
begin
@name = $1.downcase
rescue NoMethodError
raise ArgumentError, "Missing name field in RR string #{rrstring}"
end
# Time to live for RR, default 3 hours
@ttl = $2 ? $2.to_i : 10800
# RR class, default to IN
@cls = Net::DNS::RR::Classes.new $3
# RR type, default to A
@type = Net::DNS::RR::Types.new $4
# All the rest is data
@rdata = $5 ? $5.strip : ""
if self.class == Net::DNS::RR
Net::DNS::RR.const_get(@type.to_s).new(rrstring)
else
subclass_new_from_string(@rdata)
self.class
end
end
def new_from_hash(args)
# Name field is mandatory
unless args.has_key? :name
raise ArgumentError, ":name field is mandatory"
end
@name = args[:name].downcase
@ttl = args[:ttl] ? args[:ttl].to_i : 10800 # Default 3 hours
@type = Net::DNS::RR::Types.new args[:type]
@cls = Net::DNS::RR::Classes.new args[:cls]
@rdata = args[:rdata] ? args[:rdata].strip : ""
@rdlength = args[:rdlength] || @rdata.size
if self.class == Net::DNS::RR
Net::DNS::RR.const_get(@type.to_s).new(args)
else
hash = args - [:name, :ttl, :type, :cls]
if hash.has_key? :rdata
subclass_new_from_string(hash[:rdata])
else
subclass_new_from_hash(hash)
end
self.class
end
end
def new_from_binary(data,offset)
if self.class == Net::DNS::RR
temp = dn_expand(data,offset)[1]
type = Net::DNS::RR::Types.new data.unpack("@#{temp} n")[0]
(eval "Net::DNS::RR::#{type}").parse_packet(data,offset)
else
@name,offset = dn_expand(data,offset)
rrtype,cls,@ttl,@rdlength = data.unpack("@#{offset} n2 N n")
@type = Net::DNS::RR::Types.new rrtype
@cls = Net::DNS::RR::Classes.new cls
offset += RRFIXEDSZ
offset = subclass_new_from_binary(data,offset)
build_pack
set_type
[self, offset]
end
end
# Methods to be overridden by subclasses
def subclass_new_from_array(arr)
end
def subclass_new_from_string(str)
end
def subclass_new_from_hash(hash)
end
def subclass_new_from_binary(data, offset)
end
def build_pack
end
def get_inspect
@rdata
end
def get_data
@rdata
end
def set_type
# TODO: Here we should probably
# raise NotImplementedError
# if we want the method to be implemented in any subclass.
end
def self.new(*args)
o = allocate
obj = o.send(:initialize,*args)
if self == Net::DNS::RR
obj
else
o
end
end
end
end
end
ruby-net-dns-0.8.0/lib/net/dns/rr/ 0000775 0000000 0000000 00000000000 12142435533 0016613 5 ustar 00root root 0000000 0000000 ruby-net-dns-0.8.0/lib/net/dns/rr/a.rb 0000664 0000000 0000000 00000006635 12142435533 0017372 0 ustar 00root root 0000000 0000000 module Net
module DNS
class RR
#
# = IPv4 Address Record (A)
#
# Class for DNS IPv4 Address (A) resource records.
#
# The resource data is an IPv4 (i.e. 32 bit long) address,
# hold in the instance variable +address+.
#
# a = Net::DNS::RR::A.new("localhost.movie.edu. 360 IN A 127.0.0.1")
#
# a = Net::DNS::RR::A.new(:name => "localhost.movie.edu.",
# :ttl => 360,
# :cls => Net::DNS::IN,
# :type => Net::DNS::A,
# :address => "127.0.0.1" )
#
# When computing binary data to transmit the RR, the RDATA section is an
# Internet address expressed as four decimal numbers separated by dots
# without any embedded space (e.g. "10.2.0.52" or "192.0.5.6").
#
class A < RR
# Gets the current IPv4 address for this record.
#
# Returns an instance of IPAddr.
def address
@address
end
# Assigns a new IPv4 address to this record, which can be in the
# form of a String or an IPAddr object.
#
# Examples
#
# a.address = "192.168.0.1"
# a.address = IPAddr.new("10.0.0.1")
#
# Returns the new allocated instance of IPAddr.
def address=(string_or_ipaddr)
@address = check_address(string_or_ipaddr)
build_pack
@address
end
# Gets the standardized value for this record,
# represented by the value of address.
#
# Returns a String.
def value
address.to_s
end
private
def subclass_new_from_hash(options)
if options.has_key?(:address)
@address = check_address(options[:address])
elsif options.has_key?(:rdata)
@address = check_address(options[:rdata])
else
raise ArgumentError, ":address or :rdata field is mandatory"
end
end
def subclass_new_from_string(str)
@address = check_address(str)
end
def subclass_new_from_binary(data, offset)
a, b, c, d = data.unpack("@#{offset} CCCC")
@address = IPAddr.new("#{a}.#{b}.#{c}.#{d}")
offset + 4
end
def set_type
@type = Net::DNS::RR::Types.new("A")
end
def get_inspect
value
end
def check_address(input)
address = case input
when IPAddr
input
when Integer # Address in numeric form
tmp = [(input >> 24), (input >> 16) & 0xFF, (input >> 8) & 0xFF, input & 0xFF]
tmp = tmp.collect { |x| x.to_s }.join(".")
IPAddr.new(tmp)
when String
IPAddr.new(input)
else
raise ArgumentError, "Invalid IP address `#{input}'"
end
if !address.ipv4?
raise(ArgumentError, "Must specify an IPv4 address")
end
address
end
def build_pack
@address_pack = @address.hton
@rdlength = @address_pack.size
end
def get_data
@address_pack
end
end
end
end
end
ruby-net-dns-0.8.0/lib/net/dns/rr/aaaa.rb 0000664 0000000 0000000 00000004561 12142435533 0020031 0 ustar 00root root 0000000 0000000 module Net
module DNS
class RR
#
# = IPv6 Address Record (AAAA)
#
# Class for DNS IPv6 Address (AAAA) resource records.
#
class AAAA < RR
# Gets the current IPv6 address for this record.
#
# Returns an instance of IPAddr.
def address
@address
end
# Assigns a new IPv6 address to this record, which can be in the
# form of a String or an IPAddr object.
#
# Examples
#
# a.address = "192.168.0.1"
# a.address = IPAddr.new("10.0.0.1")
#
# Returns the new allocated instance of IPAddr.
def address=(string_or_ipaddr)
@address = check_address(string_or_ipaddr)
build_pack
@address
end
# Gets the standardized value for this record,
# represented by the value of address.
#
# Returns a String.
def value
address.to_s
end
private
def subclass_new_from_hash(options)
if options.has_key?(:address)
@address = check_address(options[:address])
else
raise ArgumentError, ":address field is mandatory"
end
end
def subclass_new_from_string(str)
@address = check_address(str)
end
def subclass_new_from_binary(data, offset)
tokens = data.unpack("@#{offset} n8")
@address = IPAddr.new(sprintf("%x:%x:%x:%x:%x:%x:%x:%x", *tokens))
offset + 16
end
def set_type
@type = Net::DNS::RR::Types.new("AAAA")
end
def get_inspect
value
end
def check_address(input)
address = case input
when IPAddr
input
when String
IPAddr.new(input)
else
raise ArgumentError, "Invalid IP address `#{input}'"
end
if !address.ipv6?
raise(ArgumentError, "Must specify an IPv6 address")
end
address
end
def build_pack
@address_pack = @address.hton
@rdlength = @address_pack.size
end
def get_data
@address_pack
end
end
end
end
end
ruby-net-dns-0.8.0/lib/net/dns/rr/classes.rb 0000664 0000000 0000000 00000006717 12142435533 0020610 0 ustar 00root root 0000000 0000000 module Net
module DNS
class RR
#
# = Net::DNS::Classes
#
# This is an auxiliary class to handle Net::DNS::RR
# class field in a DNS packet.
#
class Classes
# Hash with the values of each RR class stored with the
# respective id number.
CLASSES = {
'IN' => 1, # RFC 1035
'CH' => 3, # RFC 1035
'HS' => 4, # RFC 1035
'NONE' => 254, # RFC 2136
'ANY' => 255, # RFC 1035
}
# The default value when class is nil in Resource Records
@@default = CLASSES["IN"]
# Creates a new object representing an RR class. Performs some
# checks on the argument validity too. Il +cls+ is +nil+, the
# default value is +ANY+ or the one set with Classes.default=
def initialize(cls)
case cls
when String
initialize_from_str(cls)
when Fixnum
initialize_from_num(cls)
when nil
initialize_from_num(@@default)
end
if @str.nil? || @num.nil?
raise ArgumentError, "Unable to create a `Classes' from `#{cls}'"
end
end
# Returns the class in number format
# (default for normal use)
#
# FIXME: inspect must return a String.
#
def inspect
@num
end
# Returns the class in string format,
# ex. "IN" or "CH" or such a string.
def to_s
@str.to_s
end
# Returns the class in numeric format,
# usable by the pack methods for data transfers.
def to_i
@num.to_i
end
# Be able to control the default class to assign when
# cls argument is +nil+. Default to +IN+
def self.default=(str)
if CLASSES[str]
@@default = CLASSES[str]
else
raise ArgumentError, "Unknown class `#{str}'"
end
end
# Returns whether cls is a valid RR class.
#
# Net::DNS::RR::Classes.valid?("IN")
# # => true
# Net::DNS::RR::Classes.valid?(1)
# # => true
# Net::DNS::RR::Classes.valid?("Q")
# # => false
# Net::DNS::RR::Classes.valid?(256)
# # => false
# Net::DNS::RR::Classes.valid?(Hash.new)
# # => ArgumentError
#
# FIXME: valid? should never raise.
#
# ==== Raises
# ArgumentError:: if cls isn't either a String or a Fixnum
#
def self.valid?(cls)
case cls
when String
CLASSES.has_key?(cls)
when Fixnum
CLASSES.invert.has_key?(cls)
else
raise ArgumentError, "Wrong cls class: #{cls.class}"
end
end
# Gives in output the keys from the +Classes+ hash
# in a format suited for regexps
def self.regexp
CLASSES.keys.sort.join("|")
end
private
# Initialize a new instance from a Class name.
def initialize_from_str(str)
key = str.to_s.upcase
@num, @str = CLASSES[key], key
end
# Initialize a new instance from the Class value.
def initialize_from_num(num)
key = num.to_i
@num, @str = key, CLASSES.invert[key]
end
end
end
end
end
ruby-net-dns-0.8.0/lib/net/dns/rr/cname.rb 0000664 0000000 0000000 00000003415 12142435533 0020226 0 ustar 00root root 0000000 0000000 module Net # :nodoc:
module DNS
class RR
#
# = Canonical Name Record (CNAME)
#
# Class for DNS CNAME resource records.
#
# A CNAME record maps an alias or nickname to the real or Canonical name
# which may lie outside the current zone.
# Canonical means expected or real name.
#
class CNAME < RR
# Gets the canonical name value.
#
# Returns a String.
def cname
@cname
end
# Gets the standardized value for this record,
# represented by the value of cname.
#
# Returns a String.
def value
cname.to_s
end
private
def subclass_new_from_hash(options)
if options.has_key?(:cname)
@cname = check_name(options[:cname])
else
raise ArgumentError, ":cname field is mandatory"
end
end
def subclass_new_from_string(str)
@cname = check_name(str)
end
def subclass_new_from_binary(data, offset)
@cname, offset = dn_expand(data, offset)
offset
end
def set_type
@type = Net::DNS::RR::Types.new("CNAME")
end
def get_inspect
value
end
def check_name(input)
name = input.to_s
unless name =~ /(\w\.?)+\s*$/ and name =~ /[a-zA-Z]/
raise ArgumentError, "Invalid Canonical Name `#{name}'"
end
name
end
def build_pack
@cname_pack = pack_name(@cname)
@rdlength = @cname_pack.size
end
def get_data
@cname_pack
end
end
end
end
end
ruby-net-dns-0.8.0/lib/net/dns/rr/hinfo.rb 0000664 0000000 0000000 00000005110 12142435533 0020240 0 ustar 00root root 0000000 0000000 module Net # :nodoc:
module DNS
class RR
#
# = System Information Record (HINFO)
#
# Class for DNS HINFO resource records.
#
# Allows definition of the Hardware type and Operating System (OS) in use at a host.
# For security reasons these records are rarely used on public servers.
# If a space exists in the field it must be enclosed in quotes.
# Single space between CPU and OS parameters.
#
class HINFO < RR
# Gets the CPU value.
#
# Returns a String.
def cpu
@cpu
end
# Gets the OS value.
#
# Returns a String.
def os
@os
end
# Gets the standardized value for this record,
# represented by the value of cpu and os.
#
# Returns a String.
def value
%Q{"#{cpu}" "#{os}"}
end
# Gets a list of all the attributes for this record.
#
# Returns an Array of values.
def to_a
[nil, nil, cls.to_s, type.to_s, value]
end
private
def subclass_new_from_hash(options)
if options.has_key?(:cpu) && options.has_key?(:os)
@cpu = options[:cpu]
@os = options[:os]
else
raise ArgumentError, ":cpu and :os fields are mandatory"
end
end
def subclass_new_from_string(str)
@cpu, @os = check_hinfo(str)
end
def subclass_new_from_binary(data, offset)
len = data.unpack("@#{offset} C").first
offset += 1
@cpu = data[offset..(offset + len)]
offset += len
len = data.unpack("@#{offset} C").first
offset += 1
@os = data[offset..(offset + len)]
offset += len
end
def set_type
@type = Net::DNS::RR::Types.new("HINFO")
end
def get_inspect
value
end
def check_hinfo(input)
if input.to_s.strip =~ /^(?:["']?(.*?)["']?)\s+(?:["']?(.*?)["']?)$/
[$1, $2]
else
raise ArgumentError, "Invalid HINFO Section `#{input}'"
end
end
def build_pack
@hinfo_pack = ""
@hinfo_pack += [cpu.size].pack("C") + cpu
@hinfo_pack += [os.size ].pack("C") + os
@rdlength = @hinfo_pack.size
end
def get_data
@hinfo_pack
end
end
end
end
end
ruby-net-dns-0.8.0/lib/net/dns/rr/mr.rb 0000664 0000000 0000000 00000003073 12142435533 0017561 0 ustar 00root root 0000000 0000000 module Net # :nodoc:
module DNS
class RR
#
# = Mail Rename Record (MR)
#
# Class for DNS MR resource records.
#
class MR < RR
# Gets the newname value.
#
# Returns a String.
def newname
@newname
end
# Gets the standardized value for this record,
# represented by the value of newname.
#
# Returns a String.
def value
newname.to_s
end
private
def subclass_new_from_hash(options)
if options.has_key?(:newname)
@newname = check_name(options[:newname])
else
raise ArgumentError, ":newname field is mandatory"
end
end
def subclass_new_from_string(str)
@newname = check_name(str)
end
def subclass_new_from_binary(data, offset)
@newname = dn_expand(data,offset)
offset
end
def set_type
@type = Net::DNS::RR::Types.new("MR")
end
def get_inspect
value
end
def check_name(input)
name = input.to_s
unless name =~ /(\w\.?)+\s*$/
raise ArgumentError, "Invalid Domain Name `#{name}'"
end
name
end
def build_pack
@newname_pack = pack_name(@newname)
@rdlength = @newname_pack.size
end
def get_data
@newname_pack
end
end
end
end
end
ruby-net-dns-0.8.0/lib/net/dns/rr/mx.rb 0000664 0000000 0000000 00000004255 12142435533 0017572 0 ustar 00root root 0000000 0000000 module Net # :nodoc:
module DNS
class RR
#
# = Mail Exchange Record (MX)
#
# Class for DNS MX resource records.
#
# A MX record specifies the name and relative preference of mail servers
# (mail exchangers in the DNS jargon) for the zone.
# The MX RR is used by SMTP (Mail) Agents to route mail for the domain.
#
class MX < RR
# Gets the preference value.
#
# Returns an Integer.
def preference
@preference
end
# Gets the exchange value.
#
# Returns a String.
def exchange
@exchange
end
# Gets the standardized value for this record,
# represented by the value of preference and exchange.
#
# Returns a String.
def value
"#{preference} #{exchange}"
end
private
def subclass_new_from_hash(options)
if options.has_key?(:preference) && options.has_key?(:exchange)
@preference = options[:preference].to_i
@exchange = options[:exchange]
else
raise ArgumentError, ":preference and :exchange fields are mandatory"
end
end
def subclass_new_from_string(str)
@preference, @exchange = check_mx(str)
end
def subclass_new_from_binary(data, offset)
@preference = data.unpack("@#{offset} n")[0]
offset += 2
@exchange, offset = dn_expand(data, offset)
offset
end
def set_type
@type = Net::DNS::RR::Types.new("MX")
end
def get_inspect
value
end
def check_mx(input)
str = input.to_s
unless str.strip =~ /^(\d+)\s+(\S+)$/
raise ArgumentError, "Invalid MX section `#{str}'"
end
[$1.to_i, $2]
end
def build_pack
@mx_pack = [@preference].pack("n") + pack_name(@exchange)
@rdlength = @mx_pack.size
end
def get_data
@mx_pack
end
end
end
end
end
ruby-net-dns-0.8.0/lib/net/dns/rr/ns.rb 0000664 0000000 0000000 00000003136 12142435533 0017563 0 ustar 00root root 0000000 0000000 module Net # :nodoc:
module DNS
class RR
#
# = Name Server Record (NS)
#
# Class for DNS NS resource records.
#
class NS < RR
# Gets the name server value.
#
# Returns a String.
def nsdname
@nsdname
end
# Gets the standardized value for this record,
# represented by the value of nsdname.
#
# Returns a String.
def value
nsdname.to_s
end
private
def subclass_new_from_hash(options)
if options.has_key?(:nsdname)
@nsdname = check_name(options[:nsdname])
else
raise ArgumentError, ":nsdname field is mandatory"
end
end
def subclass_new_from_string(str)
@nsdname = check_name(str)
end
def subclass_new_from_binary(data, offset)
@nsdname, offset = dn_expand(data, offset)
offset
end
def set_type
@type = Net::DNS::RR::Types.new("NS")
end
def get_inspect
value
end
def check_name(input)
name = input.to_s
unless name =~ /(\w\.?)+\s*$/ and name =~ /[a-zA-Z]/
raise ArgumentError, "Invalid Name Server `#{name}'"
end
name
end
def build_pack
@nsdname_pack = pack_name(@nsdname)
@rdlength = @nsdname_pack.size
end
def get_data
@nsdname_pack
end
end
end
end
end
ruby-net-dns-0.8.0/lib/net/dns/rr/null.rb 0000664 0000000 0000000 00000002060 12142435533 0020110 0 ustar 00root root 0000000 0000000 module Net # :nodoc:
module DNS
class RR
#------------------------------------------------------------
# RR type NULL
#------------------------------------------------------------
class NULL < RR
attr_reader :null
private
def build_pack
@null_pack = @null
@rdlength = @null_pack.size
end
def get_data
@null_pack
end
def get_inspect
"#@null"
end
def subclass_new_from_hash(args)
if args.has_key? :null
@null = args[:null]
else
raise ArgumentError, ":null field is mandatory but missing"
end
end
def subclass_new_from_string(str)
@null = str.strip
end
def subclass_new_from_binary(data,offset)
@null = data[offset..offset+@rdlength]
return offset + @rdlength
end
private
def set_type
@type = Net::DNS::RR::Types.new("NULL")
end
end
end
end
end
ruby-net-dns-0.8.0/lib/net/dns/rr/ptr.rb 0000664 0000000 0000000 00000003332 12142435533 0017746 0 ustar 00root root 0000000 0000000 module Net
module DNS
class RR
#
# = Pointer Record (PTR)
#
# Class for DNS Pointer (PTR) resource records.
#
# Pointer records are the opposite of A and AAAA RRs
# and are used in Reverse Map zone files to map
# an IP address (IPv4 or IPv6) to a host name.
#
class PTR < RR
# Gets the PTR value.
#
# Returns a String.
def ptrdname
@ptrdname.to_s
end
alias_method :ptr, :ptrdname
# Gets the standardized value for this record,
# represented by the value of ptrdname.
#
# Returns a String.
def value
ptrdname.to_s
end
private
def build_pack
@ptrdname_pack = pack_name(@ptrdname)
@rdlength = @ptrdname_pack.size
end
def get_data
@ptrdname_pack
end
def subclass_new_from_hash(args)
if args.has_key?(:ptrdname) or args.has_key?(:ptr)
@ptrdname = args[:ptrdname]
else
raise ArgumentError, ":ptrdname or :ptr field is mandatory"
end
end
def subclass_new_from_string(str)
@ptrdname = check_name(str)
end
def subclass_new_from_binary(data, offset)
@ptrdname, offset = dn_expand(data, offset)
offset
end
private
def set_type
@type = Net::DNS::RR::Types.new("PTR")
end
def get_inspect
value
end
def check_name(input)
IPAddr.new(str)
rescue
raise ArgumentError, "Invalid PTR Section `#{input}'"
end
end
end
end
end
ruby-net-dns-0.8.0/lib/net/dns/rr/soa.rb 0000664 0000000 0000000 00000004746 12142435533 0017735 0 ustar 00root root 0000000 0000000 module Net # :nodoc:
module DNS
class RR
#------------------------------------------------------------
# RR type SOA
#------------------------------------------------------------
class SOA < RR
attr_reader :mname, :rname, :serial, :refresh, :retry, :expire, :minimum
private
def build_pack
@soa_pack = pack_name(@mname)
@soa_pack += pack_name(@rname)
@soa_pack += [@serial,@refresh,@retry,@expire,@minimum].pack("N5")
end
def get_data
@soa_pack
end
def get_inspect
"#@mname #@rname #@serial #@refresh #@retry #@expire #@minimum"
end
def subclass_new_from_hash(args)
if args.has_key? :rdata
subclass_new_from_string(args[:rdata])
else
[:mname,:rname,:serial,:refresh,:retry,:expire,:minimum].each do |key|
raise ArgumentError, "Missing field :#{key}" unless args.has_key? key
end
@mname = args[:mname] if valid? args[:mname]
@rname = args[:rname] if valid? args[:rname]
@serial = args[:serial] if number? args[:serial]
@refresh = args[:refresh] if number? args[:refresh]
@retry = args[:retry] if number? args[:retry]
@expire = args[:expire] if number? args[:expire]
@minimum = args[:minimum] if number? args[:minimum]
end
end
def number?(num)
if num.kind_of? Integer and num > 0
true
else
raise ArgumentError, "Wrong format field: #{num} not a number or less than zero"
end
end
def subclass_new_from_string(str)
mname,rname,serial,refresh,ret,expire,minimum = str.strip.split(" ")
@mname = mname if valid? mname
@rname = rname if valid? rname
@serial,@refresh,@retry,@expire,@minimum = [serial,refresh,ret,expire,minimum].collect do |i|
i.to_i if valid? i.to_i
end
end
def subclass_new_from_binary(data,offset)
@mname,offset = dn_expand(data,offset)
@rname,offset = dn_expand(data,offset)
@serial,@refresh,@retry,@expire,@minimum = data.unpack("@#{offset} N5")
return offset + 5*Net::DNS::INT32SZ
end
private
def set_type
@type = Net::DNS::RR::Types.new("SOA")
end
end
end
end
end
ruby-net-dns-0.8.0/lib/net/dns/rr/srv.rb 0000664 0000000 0000000 00000002012 12142435533 0017745 0 ustar 00root root 0000000 0000000 module Net # :nodoc:
module DNS
class RR
#------------------------------------------------------------
# RR type SRV
#------------------------------------------------------------
class SRV < RR
attr_reader :priority, :weight, :port, :host
private
def build_pack
str = ""
end
def subclass_new_from_binary(data,offset)
off_end = offset + @rdlength
@priority, @weight, @port = data.unpack("@#{offset} n n n")
offset+=6
@host=[]
while offset < off_end
len = data.unpack("@#{offset} C")[0]
offset += 1
str = data[offset..offset+len-1]
offset += len
@host << str
end
@host=@host.join(".")
offset
end
private
def set_type
@type = Net::DNS::RR::Types.new("SRV")
end
end
end
end
end
ruby-net-dns-0.8.0/lib/net/dns/rr/txt.rb 0000664 0000000 0000000 00000002506 12142435533 0017762 0 ustar 00root root 0000000 0000000 module Net # :nodoc:
module DNS
class RR
#------------------------------------------------------------
# RR type TXT
#------------------------------------------------------------
class TXT < RR
attr_reader :txt
private
def build_pack
str = ""
@txt.split(" ").each do |txt|
str += [txt.length,txt].pack("C a*")
end
@txt_pack = str
@rdlength = @txt_pack.size
end
def get_data
@txt_pack
end
def subclass_new_from_hash(args)
if args.has_key? :txt
@txt = args[:txt].strip
else
raise ArgumentError, ":txt field is mandatory but missing"
end
end
def subclass_new_from_string(str)
@txt = str.strip
end
def subclass_new_from_binary(data,offset)
off_end = offset + @rdlength
@txt = ""
while offset < off_end
len = data.unpack("@#{offset} C")[0]
offset += 1
str = data[offset..offset+len-1]
offset += len
@txt << str << " "
end
return offset
end
private
def set_type
@type = Net::DNS::RR::Types.new("TXT")
end
end
end
end
end
ruby-net-dns-0.8.0/lib/net/dns/rr/types.rb 0000664 0000000 0000000 00000015631 12142435533 0020312 0 ustar 00root root 0000000 0000000 module Net # :nodoc:
module DNS
class RR
# This is an auxiliary class to handle RR type field in a DNS packet.
class Types
TYPES = {
'SIGZERO' => 0, # RFC2931 consider this a pseudo type
'A' => 1, # RFC 1035, Section 3.4.1
'NS' => 2, # RFC 1035, Section 3.3.11
'MD' => 3, # RFC 1035, Section 3.3.4 (obsolete)
'MF' => 4, # RFC 1035, Section 3.3.5 (obsolete)
'CNAME' => 5, # RFC 1035, Section 3.3.1
'SOA' => 6, # RFC 1035, Section 3.3.13
'MB' => 7, # RFC 1035, Section 3.3.3
'MG' => 8, # RFC 1035, Section 3.3.6
'MR' => 9, # RFC 1035, Section 3.3.8
'NULL' => 10, # RFC 1035, Section 3.3.10
'WKS' => 11, # RFC 1035, Section 3.4.2 (deprecated)
'PTR' => 12, # RFC 1035, Section 3.3.12
'HINFO' => 13, # RFC 1035, Section 3.3.2
'MINFO' => 14, # RFC 1035, Section 3.3.7
'MX' => 15, # RFC 1035, Section 3.3.9
'TXT' => 16, # RFC 1035, Section 3.3.14
'RP' => 17, # RFC 1183, Section 2.2
'AFSDB' => 18, # RFC 1183, Section 1
'X25' => 19, # RFC 1183, Section 3.1
'ISDN' => 20, # RFC 1183, Section 3.2
'RT' => 21, # RFC 1183, Section 3.3
'NSAP' => 22, # RFC 1706, Section 5
'NSAP_PTR' => 23, # RFC 1348 (obsolete)
# The following 2 RRs are impemented in Net::DNS::SEC, TODO
'SIG' => 24, # RFC 2535, Section 4.1
'KEY' => 25, # RFC 2535, Section 3.1
'PX' => 26, # RFC 2163,
'GPOS' => 27, # RFC 1712 (obsolete)
'AAAA' => 28, # RFC 1886, Section 2.1
'LOC' => 29, # RFC 1876
# The following RR is implemented in Net::DNS::SEC, TODO
'NXT' => 30, # RFC 2535, Section 5.2
'EID' => 31, # draft-ietf-nimrod-dns-xx.txt
'NIMLOC' => 32, # draft-ietf-nimrod-dns-xx.txt
'SRV' => 33, # RFC 2052
'ATMA' => 34, # ???
'NAPTR' => 35, # RFC 2168
'KX' => 36, # RFC 2230
'CERT' => 37, # RFC 2538
'DNAME' => 39, # RFC 2672
'OPT' => 41, # RFC 2671
# The following 4 RRs are implemented in Net::DNS::SEC TODO
'DS' => 43, # draft-ietf-dnsext-delegation-signer
'SSHFP' => 44, # draft-ietf-secsh-dns (No RFC # yet at time of coding)
'RRSIG' => 46, # draft-ietf-dnsext-dnssec-2535typecode-change
'NSEC' => 47, # draft-ietf-dnsext-dnssec-2535typecode-change
'DNSKEY' => 48, # draft-ietf-dnsext-dnssec-2535typecode-change
'UINFO' => 100, # non-standard
'UID' => 101, # non-standard
'GID' => 102, # non-standard
'UNSPEC' => 103, # non-standard
'TKEY' => 249, # RFC 2930
'TSIG' => 250, # RFC 2931
'IXFR' => 251, # RFC 1995
'AXFR' => 252, # RFC 1035
'MAILB' => 253, # RFC 1035 (MB, MG, MR)
'MAILA' => 254, # RFC 1035 (obsolete - see MX)
'ANY' => 255, # RFC 1035
}
# The default value when type is nil in Resource Records
@@default = TYPES["A"]
# Be able to control the default type to assign when
# type is +nil+. Default to +A+
def self.default=(str)
if TYPES.has_key? str
@@default = TYPES[str]
else
raise ArgumentError, "Unknown type #{str}"
end
end
# Checks whether +type+ is a valid RR type.
def self.valid?(type)
case type
when String
TYPES.has_key?(type)
when Fixnum
TYPES.invert.has_key?(type)
else
raise ArgumentError, "Wrong type class: #{type.class}"
end
end
# Returns the type in string format, as "A" or "NS",
# given the numeric value
def self.to_str(type)
case type
when Fixnum
if TYPES.invert.has_key? type
TYPES.invert[type]
else
raise ArgumentError, "Unknown type number #{type}"
end
else
raise ArgumentError, "Wrong type class: #{type.class}"
end
end
# Gives in output the keys from the +Types+ hash
# in a format suited for regexps
def self.regexp
# Longest ones go first, so the regex engine will match AAAA before A.
TYPES.keys.sort { |a,b| b.length <=> a.length }.join("|")
end
# Creates a new object representing an RR type. Performs some
# checks on the argument validity too. Il +type+ is +nil+, the
# default value is +ANY+ or the one set with Types.default=
def initialize(type)
case type
when String
# type in the form "A" or "NS"
new_from_string(type.upcase)
when Fixnum
# type in numeric form
new_from_num(type)
when nil
# default type, control with Types.default=
@str = TYPES.invert[@@default]
@num = @@default
else
raise ArgumentError, "Wrong type class: #{type.class}"
end
end
# Returns the type in number format
# (default for normal use)
def inspect
@num
end
# Returns the type in string format,
# i.d. "A" or "NS" or such a string.
def to_s
@str
end
# Returns the type in numeric format,
# usable by the pack methods for data transfers
def to_i
@num.to_i
end
def to_str
@num.to_s
end
private
# Constructor for string data type.
def new_from_string(type)
case type
when /^TYPE\\d+/
# TODO!!!
else
# String with name of type
if TYPES.has_key? type
@str = type
@num = TYPES[type]
else
raise ArgumentError, "Unknown type #{type}"
end
end
end
# Contructor for numeric data type.
def new_from_num(type)
if TYPES.invert.has_key? type
@num = type
@str = TYPES.invert[type]
else
raise ArgumentError, "Unkown type number #{type}"
end
end
end
end
end
end
ruby-net-dns-0.8.0/lib/net/dns/version.rb 0000664 0000000 0000000 00000000336 12142435533 0020204 0 ustar 00root root 0000000 0000000 module Net
module DNS
module Version
MAJOR = 0
MINOR = 8
PATCH = 0
BUILD = nil
STRING = [MAJOR, MINOR, PATCH, BUILD].compact.join(".")
end
VERSION = Version::STRING
end
end ruby-net-dns-0.8.0/net-dns.gemspec 0000664 0000000 0000000 00000005416 12142435533 0016773 0 ustar 00root root 0000000 0000000 # -*- encoding: utf-8 -*-
Gem::Specification.new do |s|
s.name = "net-dns"
s.version = "0.8.0"
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
s.authors = ["Marco Ceresa", "Simone Carletti"]
s.date = "2013-05-08"
s.description = "Net::DNS is a pure Ruby DNS library, with a clean OO interface and an extensible API."
s.email = ["ceresa@gmail.com", "weppos@weppos.net"]
s.files = [".gitignore", ".travis.yml", "CHANGELOG.md", "Gemfile", "README.md", "Rakefile", "THANKS.rdoc", "demo/check_soa.rb", "demo/threads.rb", "fixtures/resolv.conf", "lib/net/dns.rb", "lib/net/dns/core_ext.rb", "lib/net/dns/header.rb", "lib/net/dns/names.rb", "lib/net/dns/packet.rb", "lib/net/dns/question.rb", "lib/net/dns/resolver.rb", "lib/net/dns/resolver/socks.rb", "lib/net/dns/resolver/timeouts.rb", "lib/net/dns/rr.rb", "lib/net/dns/rr/a.rb", "lib/net/dns/rr/aaaa.rb", "lib/net/dns/rr/classes.rb", "lib/net/dns/rr/cname.rb", "lib/net/dns/rr/hinfo.rb", "lib/net/dns/rr/mr.rb", "lib/net/dns/rr/mx.rb", "lib/net/dns/rr/ns.rb", "lib/net/dns/rr/null.rb", "lib/net/dns/rr/ptr.rb", "lib/net/dns/rr/soa.rb", "lib/net/dns/rr/srv.rb", "lib/net/dns/rr/txt.rb", "lib/net/dns/rr/types.rb", "lib/net/dns/version.rb", "net-dns.gemspec", "test/header_test.rb", "test/names_test.rb", "test/packet_test.rb", "test/question_test.rb", "test/resolver/timeouts_test.rb", "test/resolver_test.rb", "test/rr/a_test.rb", "test/rr/aaaa_test.rb", "test/rr/classes_test.rb", "test/rr/cname_test.rb", "test/rr/hinfo_test.rb", "test/rr/mr_test.rb", "test/rr/mx_test.rb", "test/rr/ns_test.rb", "test/rr/types_test.rb", "test/rr_test.rb", "test/test_helper.rb"]
s.homepage = "http://github.com/bluemonk/net-dns"
s.require_paths = ["lib"]
s.required_ruby_version = Gem::Requirement.new(">= 1.8.7")
s.rubyforge_project = "net-dns"
s.rubygems_version = "2.0.3"
s.summary = "Pure Ruby DNS library."
s.test_files = ["test/header_test.rb", "test/names_test.rb", "test/packet_test.rb", "test/question_test.rb", "test/resolver/timeouts_test.rb", "test/resolver_test.rb", "test/rr/a_test.rb", "test/rr/aaaa_test.rb", "test/rr/classes_test.rb", "test/rr/cname_test.rb", "test/rr/hinfo_test.rb", "test/rr/mr_test.rb", "test/rr/mx_test.rb", "test/rr/ns_test.rb", "test/rr/types_test.rb", "test/rr_test.rb", "test/test_helper.rb"]
if s.respond_to? :specification_version then
s.specification_version = 4
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
s.add_development_dependency(%q, ["~> 10.0"])
s.add_development_dependency(%q, [">= 0"])
else
s.add_dependency(%q, ["~> 10.0"])
s.add_dependency(%q, [">= 0"])
end
else
s.add_dependency(%q, ["~> 10.0"])
s.add_dependency(%q, [">= 0"])
end
end
ruby-net-dns-0.8.0/test/ 0000775 0000000 0000000 00000000000 12142435533 0015027 5 ustar 00root root 0000000 0000000 ruby-net-dns-0.8.0/test/header_test.rb 0000664 0000000 0000000 00000011702 12142435533 0017644 0 ustar 00root root 0000000 0000000 require 'test_helper'
require 'net/dns/header'
class HeaderTest < Test::Unit::TestCase
include Net::DNS
def setup
@default = Header.new
@hash = Header.new(:id => 441,
:qr => 1,
:opCode => Header::IQUERY,
:aa => 1,
:tc => 1,
:rd => 0,
:cd => 0,
:ad => 0,
:ra => 1,
:rCode => Header::RCode::FORMAT,
:qdCount => 1,
:anCount => 2,
:nsCount => 3,
:arCount => 3)
@modified = Header.new
@modified.id = 442
@modified.qr = true
@modified.opCode = Header::IQUERY
@modified.aa = true
@modified.tc = true
@modified.rd = false
@modified.cd = false
@modified.ra = true
@modified.rCode = Header::RCode::FORMAT
@modified.qdCount = 1
@modified.anCount = 2
@modified.nsCount = 3
@modified.arCount = 3
@data = @modified.data
num = [(@data.unpack("n")[0]+1)].pack("n")
@data[0],@data[1] = num[0], num[1]
@binary = Header.parse(@data)
end
def test_simple
assert_equal(@default.query?, true)
assert_equal(@default.response?, false)
assert_equal(@default.opCode, Header::QUERY)
assert_equal(@default.auth?, false)
assert_equal(@default.truncated?, false)
assert_equal(@default.recursive?, true)
assert_equal(@default.checking?, true)
assert_equal(@default.verified?, false)
assert_equal(@default.r_available?, false)
assert_equal(@default.rCode.code, Header::RCode::NOERROR)
assert_equal(@default.qdCount, 1)
assert_equal(@default.anCount, 0)
assert_equal(@default.nsCount, 0)
assert_equal(@default.arCount, 0)
assert_equal(@hash.id, 441)
assert_equal(@hash.query?, false)
assert_equal(@hash.response?, true)
assert_equal(@hash.opCode, Header::IQUERY)
assert_equal(@hash.auth?, true)
assert_equal(@hash.truncated?, true)
assert_equal(@hash.recursive?, false)
assert_equal(@hash.checking?, true)
assert_equal(@hash.verified?, false)
assert_equal(@hash.r_available?, true)
assert_equal(@hash.rCode.code, Header::RCode::FORMAT)
assert_equal(@hash.qdCount, 1)
assert_equal(@hash.anCount, 2)
assert_equal(@hash.nsCount, 3)
assert_equal(@hash.arCount, 3)
assert_equal(@modified.id, 442)
assert_equal(@modified.query?, false)
assert_equal(@modified.response?, true)
assert_equal(@modified.opCode, Header::IQUERY)
assert_equal(@modified.auth?, true)
assert_equal(@modified.truncated?, true)
assert_equal(@modified.recursive?, false)
assert_equal(@modified.checking?, true)
assert_equal(@modified.verified?, false)
assert_equal(@modified.r_available?, true)
assert_equal(@modified.rCode.code, Header::RCode::FORMAT)
assert_equal(@modified.qdCount, 1)
assert_equal(@modified.anCount, 2)
assert_equal(@modified.nsCount, 3)
assert_equal(@modified.arCount, 3)
assert_equal(@binary.data, @data)
assert_equal(@binary.id, 443)
assert_equal(@binary.query?, false)
assert_equal(@binary.response?, true)
assert_equal(@binary.opCode, Header::IQUERY)
assert_equal(@binary.auth?, true)
assert_equal(@binary.truncated?, true)
assert_equal(@binary.recursive?, false)
assert_equal(@binary.checking?, true)
assert_equal(@binary.verified?, false)
assert_equal(@binary.r_available?, true)
assert_equal(@binary.rCode.code, Header::RCode::FORMAT)
assert_equal(@binary.qdCount, 1)
assert_equal(@binary.anCount, 2)
assert_equal(@binary.nsCount, 3)
assert_equal(@binary.arCount, 3)
assert_raises(ArgumentError) do
Header.new(Array.new)
end
assert_raises(ArgumentError) do
Header.parse(Array.new)
end
assert_raises(ArgumentError) do
Header.parse("aa")
end
assert_raises(ArgumentError) do
@default.id = 1000000
end
assert_raises(ArgumentError) do
@default.qr=2
end
assert_raises(Header::WrongOpcodeError) do
@default.opCode=4
end
assert_raises(ArgumentError) do
@default.aa=2
end
assert_raises(ArgumentError) do
@default.tc=2
end
assert_raises(Header::WrongRecursiveError) do
@default.recursive=2
end
assert_raises(ArgumentError) do
@default.ra=2
end
assert_raises(ArgumentError) do
@default.cd=2
end
assert_raises(ArgumentError) do
@default.ad=2
end
assert_raises(ArgumentError) do
@default.rCode=46
end
assert_raises(Header::WrongCountError) do
@default.qdCount=100000
end
assert_raises(Header::WrongCountError) do
@default.anCount=100000
end
assert_raises(Header::WrongCountError) do
@default.nsCount=100000
end
assert_raises(Header::WrongCountError) do
@default.arCount=100000
end
end
end
ruby-net-dns-0.8.0/test/names_test.rb 0000664 0000000 0000000 00000000762 12142435533 0017523 0 ustar 00root root 0000000 0000000 require 'test_helper'
require 'net/dns/names'
class NamesTest < Test::Unit::TestCase
include Net::DNS::Names
def test_long_names
assert_nothing_raised do
pack_name('a' * 63)
end
assert_raises ArgumentError do
pack_name('a' * 64)
end
assert_nothing_raised do
pack_name(['a' * 63, 'b' * 63, 'c' * 63, 'd' * 63].join('.'))
end
assert_raises ArgumentError do
pack_name(['a' * 63, 'b' * 63, 'c' * 63, 'd' * 63, 'e'].join('.'))
end
end
end
ruby-net-dns-0.8.0/test/packet_test.rb 0000664 0000000 0000000 00000005211 12142435533 0017661 0 ustar 00root root 0000000 0000000 require 'test_helper'
require 'net/dns/packet'
class PacketTest < Test::Unit::TestCase
def setup
@klass = Net::DNS::Packet
@domain = 'example.com'
end
def test_initialize
@record = @klass.new(@domain, Net::DNS::MX, Net::DNS::HS)
assert_instance_of @klass, @record
assert_instance_of Net::DNS::Header, @record.header
assert_instance_of Array, @record.question
assert_instance_of Net::DNS::Question, @record.question.first
assert_instance_of Array, @record.answer
assert_instance_of Array, @record.authority
assert_instance_of Array, @record.additional
end
def test_initialize_should_set_question
@question = @klass.new(@domain).question.first
assert_equal @domain, @question.qName
assert_equal Net::DNS::RR::Types.new(Net::DNS::A).to_s, @question.qType.to_s
assert_equal Net::DNS::RR::Classes.new(Net::DNS::IN).to_s, @question.qClass.to_s
@question = @klass.new(@domain, Net::DNS::MX, Net::DNS::HS).question.first
assert_equal @domain, @question.qName
assert_equal Net::DNS::RR::Types.new(Net::DNS::MX).to_s, @question.qType.to_s
assert_equal Net::DNS::RR::Classes.new(Net::DNS::HS).to_s, @question.qClass.to_s
end
def test_self_parse
packet = "\337M\201\200\000\001\000\003\000\004\000\004\006google\003com\000\000\001\000\001\300\f\000\001\000\001\000\000\001,\000\004@\351\273c\300\f\000\001\000\001\000\000\001,\000\004H\016\317c\300\f\000\001\000\001\000\000\001,\000\004@\351\247c\300\f\000\002\000\001\000\003\364\200\000\006\003ns1\300\f\300\f\000\002\000\001\000\003\364\200\000\006\003ns2\300\f\300\f\000\002\000\001\000\003\364\200\000\006\003ns3\300\f\300\f\000\002\000\001\000\003\364\200\000\006\003ns4\300\f\300X\000\001\000\001\000\003\307\273\000\004\330\357 \n\300j\000\001\000\001\000\003\307\273\000\004\330\357\"\n\300|\000\001\000\001\000\003\307\273\000\004\330\357$\n\300\216\000\001\000\001\000\003\307\273\000\004\330\357&\n"
@record = @klass.parse(packet)
assert_instance_of @klass, @record
assert_instance_of Net::DNS::Header, @record.header
assert_instance_of Array, @record.question
assert_instance_of Net::DNS::Question, @record.question.first
assert_instance_of Array, @record.answer
assert_instance_of Net::DNS::RR::A, @record.answer.first
assert_instance_of Array, @record.authority
assert_instance_of Net::DNS::RR::NS, @record.authority.first
assert_instance_of Array, @record.additional
assert_instance_of Net::DNS::RR::A, @record.additional.first
end
end
ruby-net-dns-0.8.0/test/question_test.rb 0000664 0000000 0000000 00000005654 12142435533 0020274 0 ustar 00root root 0000000 0000000 require 'test_helper'
require 'net/dns/question'
class QuestionTest < Test::Unit::TestCase
def setup
@domain = 'example.com.'
@type = 'MX'
@cls = 'HS'
@data = "\006google\003com\000\000\001\000\001"
@default = Net::DNS::Question.new(@domain)
@string = Net::DNS::Question.new(@domain,@type,@cls)
@binary = Net::DNS::Question.parse(@data)
@binary2 = Net::DNS::Question.parse(@string.data)
end
def test_simple
assert_equal(@default.qName, @domain)
assert_equal(@default.qType.to_s, "A")
assert_equal(@default.qClass.to_s, "IN")
assert_equal(@string.qName, @domain)
assert_equal(@string.qType.to_s, "MX")
assert_equal(@string.qClass.to_s, "HS")
assert_equal(@binary.qName, "google.com.")
assert_equal(@binary.qType.to_s, "A")
assert_equal(@binary.qClass.to_s, "IN")
assert_equal(@binary2.qName, @domain)
assert_equal(@binary2.qType.to_s, "MX")
assert_equal(@binary2.qClass.to_s, "HS")
end
def test_raise
# assert_raises(Net::DNS::Question::NameInvalid) do
# Net::DNS::Question.new(1)
# end
assert_raises(Net::DNS::Question::NameInvalid) do
Net::DNS::Question.new("test{")
end
assert_raises(ArgumentError) do
Net::DNS::Question.parse(Array.new)
end
assert_raises(ArgumentError) do
Net::DNS::Question.parse("test")
end
end
def test_inspect
assert_equal "google.com. IN A ",
Net::DNS::Question.new("google.com.").inspect
assert_equal "google.com. IN A ",
Net::DNS::Question.new("google.com.", Net::DNS::A).inspect
assert_equal "google.com. IN NS ",
Net::DNS::Question.new("google.com.", Net::DNS::NS).inspect
assert_equal "google.com. IN NS ",
Net::DNS::Question.new("google.com.", Net::DNS::NS).inspect
end
def test_inspect_with_name_longer_than_29_chrs
assert_equal "supercalifragilistichespiralidoso.com IN A ",
Net::DNS::Question.new("supercalifragilistichespiralidoso.com").inspect
end
def test_to_s
assert_equal "google.com. IN A ",
Net::DNS::Question.new("google.com.").to_s
assert_equal "google.com. IN A ",
Net::DNS::Question.new("google.com.", Net::DNS::A).to_s
assert_equal "google.com. IN NS ",
Net::DNS::Question.new("google.com.", Net::DNS::NS).to_s
assert_equal "google.com. IN NS ",
Net::DNS::Question.new("google.com.", Net::DNS::NS).to_s
end
def test_to_s_with_name_longer_than_29_chrs
assert_equal "supercalifragilistichespiralidoso.com IN A ",
Net::DNS::Question.new("supercalifragilistichespiralidoso.com").to_s
end
end
ruby-net-dns-0.8.0/test/resolver/ 0000775 0000000 0000000 00000000000 12142435533 0016670 5 ustar 00root root 0000000 0000000 ruby-net-dns-0.8.0/test/resolver/timeouts_test.rb 0000664 0000000 0000000 00000006122 12142435533 0022126 0 ustar 00root root 0000000 0000000 require 'test_helper'
require 'net/dns/resolver/timeouts'
class DnsTimeoutTest < Test::Unit::TestCase
def setup
@klass = Net::DNS::Resolver::DnsTimeout
end
def test_initialize
timeout = @klass.new(0)
assert_instance_of @klass, timeout
end
def test_initialize_should_set_timeout
assert_equal 0, @klass.new(0).seconds
assert_equal 10, @klass.new(10).seconds
end
def test_initialize_should_set_raise_with_invalid_timeout
assert_raises(ArgumentError) { @klass.new(nil) }
assert_raises(ArgumentError) { @klass.new("") }
assert_raises(ArgumentError) { @klass.new("foo") }
assert_raises(ArgumentError) { @klass.new(-1) }
end
def test_to_s
assert_equal "", @klass.new(0).to_s
assert_equal "1", @klass.new(1).to_s
assert_equal "10", @klass.new(10).to_s
end
def test_timeout_should_raise_localjumperror_without_block
assert_raises(LocalJumpError) { @klass.new(1).timeout }
end
end
class TcpTimeoutTest < Test::Unit::TestCase
def test_initialize
assert_raises(ArgumentError) do
Net::DNS::Resolver::TcpTimeout.new("a")
end
assert_raises(ArgumentError) do
Net::DNS::Resolver::TcpTimeout.new(-1)
end
assert_raises(TimeoutError) do
Net::DNS::Resolver::TcpTimeout.new(0.1).timeout { sleep 2 }
end
end
def test_to_s
assert_equal "infinite", Net::DNS::Resolver::TcpTimeout.new(0).to_s
assert_equal "30", Net::DNS::Resolver::TcpTimeout.new(30).to_s
end
def test_pretty_to_s
assert_equal "30 seconds", Net::DNS::Resolver::TcpTimeout.new(30).pretty_to_s
assert_equal "1 minutes and 30 seconds", Net::DNS::Resolver::TcpTimeout.new(90).pretty_to_s
assert_equal "1 hours, 1 minutes and 30 seconds", Net::DNS::Resolver::TcpTimeout.new(3690).pretty_to_s
end
def test_timeout
assert_equal 2, Net::DNS::Resolver::TcpTimeout.new(1).timeout { 1 + 1 }
end
def test_timeout_should_raise_localjumperror_without_block
assert_raises(LocalJumpError) { Net::DNS::Resolver::TcpTimeout.new(1).timeout }
end
end
class UdpTimeoutTest < Test::Unit::TestCase
def test_initialize
assert_raises(ArgumentError) do
Net::DNS::Resolver::UdpTimeout.new("a")
end
assert_raises(ArgumentError) do
Net::DNS::Resolver::UdpTimeout.new(-1)
end
assert_raises(TimeoutError) do
Net::DNS::Resolver::UdpTimeout.new(0.1).timeout {sleep 2}
end
end
def test_to_s
assert_equal "not defined", Net::DNS::Resolver::UdpTimeout.new(0).to_s
assert_equal "30", Net::DNS::Resolver::UdpTimeout.new(30).to_s
end
def test_pretty_to_s
assert_equal "30 seconds", Net::DNS::Resolver::UdpTimeout.new(30).pretty_to_s
assert_equal "1 minutes and 30 seconds", Net::DNS::Resolver::UdpTimeout.new(90).pretty_to_s
assert_equal "1 hours, 1 minutes and 30 seconds", Net::DNS::Resolver::UdpTimeout.new(3690).pretty_to_s
end
def test_timeout
assert_equal 2, Net::DNS::Resolver::UdpTimeout.new(1).timeout { 1 + 1 }
end
def test_timeout_should_raise_localjumperror_without_block
assert_raises(LocalJumpError) { Net::DNS::Resolver::UdpTimeout.new(1).timeout }
end
end
ruby-net-dns-0.8.0/test/resolver_test.rb 0000664 0000000 0000000 00000010735 12142435533 0020262 0 ustar 00root root 0000000 0000000 require 'test_helper'
require 'net/dns/resolver'
class Net::DNS::Resolver
attr_reader :config
end
class ResolverTest < Test::Unit::TestCase
def test_initialize
assert_nothing_raised { Net::DNS::Resolver.new }
end
def test_initialize_with_config
assert_nothing_raised { Net::DNS::Resolver.new({}) }
end
def test_initialize_with_multi_name_servers
resolver = Net::DNS::Resolver.new({:config_file => 'fixtures/resolv.conf'})
assert_equal ['192.168.1.1', '192.168.1.2', '192.168.1.3', '192.168.1.4'], resolver.nameservers
end
def test_initialize_with_invalid_config_should_raise_argumenterror
assert_raises(ArgumentError) { Net::DNS::Resolver.new("") }
assert_raises(ArgumentError) { Net::DNS::Resolver.new(0) }
assert_raises(ArgumentError) { Net::DNS::Resolver.new(:foo) }
end
def test_query_with_no_nameservers_should_raise_resolvererror
assert_raises(Net::DNS::Resolver::Error) { Net::DNS::Resolver.new(:nameservers => []).query("example.com") }
end
# def test_send_to_ipv6_nameserver_should_not_raise_einval
# assert_nothing_raised { Net::DNS::Resolver.new(:nameservers => ['2001:4860:4860::8888', '2001:4860:4860::8844']).send('example.com')}
# end
# I know private methods are supposed to not be tested directly
# but since this library lacks unit tests, for now let me test them in this way.
def _make_query_packet(*args)
Net::DNS::Resolver.new.send(:make_query_packet, *args)
end
def test_make_query_packet_from_ipaddr
packet = _make_query_packet(IPAddr.new("192.168.1.1"), Net::DNS::A, cls = Net::DNS::IN)
assert_equal "1.1.168.192.in-addr.arpa", packet.question.first.qName
assert_equal Net::DNS::PTR.to_i, packet.question.first.qType.to_i
assert_equal Net::DNS::IN.to_i, packet.question.first.qClass.to_i
end
def test_make_query_packet_from_string_like_ipv4
packet = _make_query_packet("192.168.1.1", Net::DNS::A, cls = Net::DNS::IN)
assert_equal "1.1.168.192.in-addr.arpa", packet.question.first.qName
assert_equal Net::DNS::PTR.to_i, packet.question.first.qType.to_i
assert_equal Net::DNS::IN.to_i, packet.question.first.qClass.to_i
end
def test_make_query_packet_from_string_like_ipv6
packet = _make_query_packet("2001:1ac0::200:0:a5d1:6004:2", Net::DNS::A, cls = Net::DNS::IN)
assert_equal "2.0.0.0.4.0.0.6.1.d.5.a.0.0.0.0.0.0.2.0.0.0.0.0.0.c.a.1.1.0.0.2.ip6.arpa", packet.question.first.qName
assert_equal Net::DNS::PTR.to_i, packet.question.first.qType.to_i
assert_equal Net::DNS::IN.to_i, packet.question.first.qClass.to_i
end
def test_make_query_packet_from_string_like_hostname
packet = _make_query_packet("ns2.google.com", Net::DNS::A, cls = Net::DNS::IN)
assert_equal "ns2.google.com", packet.question.first.qName
assert_equal Net::DNS::A.to_i, packet.question.first.qType.to_i
assert_equal Net::DNS::IN.to_i, packet.question.first.qClass.to_i
end
def test_make_query_packet_from_string_like_hostname_with_number
packet = _make_query_packet("ns.google.com", Net::DNS::A, cls = Net::DNS::IN)
assert_equal "ns.google.com", packet.question.first.qName
assert_equal Net::DNS::A.to_i, packet.question.first.qType.to_i
assert_equal Net::DNS::IN.to_i, packet.question.first.qClass.to_i
end
def test_should_return_state_without_exception
res = Net::DNS::Resolver.new
assert_nothing_raised {res.state}
end
RubyPlatforms = [
["darwin9.0", false], # Mac OS X
["darwin", false], # JRuby on Mac OS X
["linux-gnu", false],
["mingw32", true], # ruby 1.8.6 (2008-03-03 patchlevel 114) [i386-mingw32]
["mswin32", true], # ruby 1.8.6 (2008-03-03 patchlevel 114) [i386-mswin32]
["mswin32", true], # ruby 1.8.6 (2008-04-22 rev 6555) [x86-jruby1.1.1]
]
C = Object.const_get(defined?(RbConfig) ? :RbConfig : :Config)::CONFIG
def test_self_platform_windows_question
RubyPlatforms.each do |platform, is_windows|
assert_equal is_windows,
override_platform(platform) { Net::DNS::Resolver.platform_windows? },
"Expected `#{is_windows}' with platform `#{platform}'"
end
end
private
def override_platform(new_platform, &block)
raise LocalJumpError, "no block given" unless block_given?
old_platform = C["host_os"]
C["host_os"] = new_platform
result = yield
ensure
C["host_os"] = old_platform
result
end
end
ruby-net-dns-0.8.0/test/rr/ 0000775 0000000 0000000 00000000000 12142435533 0015452 5 ustar 00root root 0000000 0000000 ruby-net-dns-0.8.0/test/rr/a_test.rb 0000664 0000000 0000000 00000006330 12142435533 0017260 0 ustar 00root root 0000000 0000000 require 'test_helper'
require 'net/dns/rr'
class RRATest < Test::Unit::TestCase
def setup
@rr_name = "google.com."
@rr_type = "A"
@rr_cls = "IN"
@rr_ttl = 10000
@rr_value = "64.233.187.99"
@rr_address = IPAddr.new(@rr_value)
@rr_output = "google.com. 10000 IN A 64.233.187.99"
@rr = Net::DNS::RR::A.new(:name => @rr_name, :address => @rr_address, :ttl => @rr_ttl)
end
def test_initialize_from_hash
@record = Net::DNS::RR::A.new(:name => @rr_name, :address => @rr_value, :ttl => @rr_ttl)
assert_equal @rr_output, @record.to_s
assert_equal @rr_name, @record.name
assert_equal @rr_type, @record.type
assert_equal @rr_cls, @record.cls
assert_equal @rr_ttl, @record.ttl
assert_equal @rr_address, @record.address
assert_equal @rr_value, @record.value
end
def test_initialize_from_string
@record = Net::DNS::RR::A.new("#{@rr_name} #{@rr_ttl} #{@rr_cls} #{@rr_type} #{@rr_value}")
assert_equal @rr_output, @record.to_s
assert_equal @rr_name, @record.name
assert_equal @rr_type, @record.type
assert_equal @rr_cls, @record.cls
assert_equal @rr_ttl, @record.ttl
assert_equal @rr_address, @record.address
assert_equal @rr_value, @record.value
end
def test_parse
data = "\006google\003com\000\000\001\000\001\000\000'\020\000\004@\351\273c"
@record = Net::DNS::RR.parse(data)
assert_equal @rr_output, @record.to_s
assert_equal @rr_name, @record.name
assert_equal @rr_type, @record.type
assert_equal @rr_cls, @record.cls
assert_equal @rr_ttl, @record.ttl
assert_equal @rr_address, @record.address
assert_equal @rr_value, @record.value
end
InvalidArguments = [
{ :name => "google.com", :address => "255.256" },
{ :name => "google.com" },
Object.new,
Array.new(7),
"10800 IN A",
"google.com. 10800 IN B",
"google.com. 10800 IM A",
]
InvalidArguments.each_with_index do |arguments, index|
define_method "test_initialize_should_raise_with_invalid_arguments_#{index}" do
assert_raises(ArgumentError) { Net::DNS::RR::A.new(arguments) }
end
end
def test_address_getter
assert_equal @rr_address, @rr.address
end
def test_address_setter
assert_raises(ArgumentError) { @rr.address = nil }
expected = IPAddr.new("64.233.187.99")
assert_equal expected, @rr.address = "64.233.187.99"
assert_equal expected, @rr.address
expected = IPAddr.new("64.233.187.90")
assert_equal expected, @rr.address = 1089059674
assert_equal expected, @rr.address
expected = IPAddr.new("64.233.187.80")
assert_equal expected, @rr.address = IPAddr.new("64.233.187.80")
assert_equal expected, @rr.address
end
def test_value
assert_equal @rr_value, @rr.value
end
def test_inspect
assert_equal "google.com. 10000 IN A 64.233.187.99",
@rr.inspect
end
def test_to_s
assert_equal "google.com. 10000 IN A 64.233.187.99",
@rr.to_s
end
def test_to_a
assert_equal ["google.com.", 10000, "IN", "A", "64.233.187.99"],
@rr.to_a
end
end
ruby-net-dns-0.8.0/test/rr/aaaa_test.rb 0000664 0000000 0000000 00000006307 12142435533 0017727 0 ustar 00root root 0000000 0000000 require 'test_helper'
require 'net/dns/rr'
class RRAAAATest < Test::Unit::TestCase
def setup
@rr_name = "www.nic.it."
@rr_type = "AAAA"
@rr_cls = "IN"
@rr_ttl = 60
@rr_value = "2a00:d40:1:1::239"
@rr_address = IPAddr.new(@rr_value)
@rr_output = "www.nic.it. 60 IN AAAA 2a00:d40:1:1::239"
@rr = Net::DNS::RR::AAAA.new(:name => @rr_name, :address => @rr_address, :ttl => @rr_ttl)
end
def test_initialize_from_hash
@record = Net::DNS::RR::AAAA.new(:name => @rr_name, :address => @rr_value, :ttl => @rr_ttl)
assert_equal @rr_output, @record.to_s
assert_equal @rr_name, @record.name
assert_equal @rr_type, @record.type
assert_equal @rr_cls, @record.cls
assert_equal @rr_ttl, @record.ttl
assert_equal @rr_address, @record.address
assert_equal @rr_value, @record.value
end
def test_initialize_from_string
@record = Net::DNS::RR::AAAA.new("#{@rr_name} #{@rr_ttl} #{@rr_cls} #{@rr_type} #{@rr_value}")
assert_equal @rr_output, @record.to_s
assert_equal @rr_name, @record.name
assert_equal @rr_type, @record.type
assert_equal @rr_cls, @record.cls
assert_equal @rr_ttl, @record.ttl
assert_equal @rr_address, @record.address
assert_equal @rr_value, @record.value
end
def test_parse
data = "\003www\003nic\002it\000\000\034\000\001\000\000\000<\000\020*\000\r@\000\001\000\001\000\000\000\000\000\000\0029"
@record = Net::DNS::RR.parse(data)
assert_equal @rr_output, @record.to_s
assert_equal @rr_name, @record.name
assert_equal @rr_type, @record.type
assert_equal @rr_cls, @record.cls
assert_equal @rr_ttl, @record.ttl
assert_equal @rr_address, @record.address
assert_equal @rr_value, @record.value
end
InvalidArguments = [
{ :name => "google.com", :address => "2a00" },
{ :name => "google.com" },
Object.new,
Array.new(7),
"10800 IN AAAA",
# FIXME: "google.com. 10800 IN B",
# FIXME: "google.com. 10800 IM AAAA",
]
InvalidArguments.each_with_index do |arguments, index|
define_method "test_initialize_should_raise_with_invalid_arguments_#{index}" do
assert_raises(ArgumentError) { Net::DNS::RR::AAAA.new(arguments) }
end
end
def test_address_getter
assert_equal @rr_address, @rr.address
end
def test_address_setter
assert_raises(ArgumentError) { @rr.address = nil }
expected = IPAddr.new("2a00:d40:1:1::239")
assert_equal expected, @rr.address = "2a00:d40:1:1::239"
assert_equal expected, @rr.address
expected = IPAddr.new("2a00:d40:1:1::240")
assert_equal expected, @rr.address = IPAddr.new("2a00:d40:1:1::240")
assert_equal expected, @rr.address
end
def test_value
assert_equal @rr_value, @rr.value
end
def test_inspect
assert_equal "www.nic.it. 60 IN AAAA 2a00:d40:1:1::239",
@rr.inspect
end
def test_to_s
assert_equal "www.nic.it. 60 IN AAAA 2a00:d40:1:1::239",
@rr.to_s
end
def test_to_a
assert_equal ["www.nic.it.", 60, "IN", "AAAA", "2a00:d40:1:1::239"],
@rr.to_a
end
end
ruby-net-dns-0.8.0/test/rr/classes_test.rb 0000664 0000000 0000000 00000004235 12142435533 0020477 0 ustar 00root root 0000000 0000000 require 'test_helper'
require 'net/dns/rr'
class RRClassesTest < Test::Unit::TestCase
def setup
@classes = {
}
@regexp_string = "ANY|CH|HS|IN|NONE"
end
StrAndNum = [
['IN' , 1],
['CH' , 3],
['HS' , 4],
['NONE' , 254],
['ANY' , 255],
]
StrAndNum.each do |str, num|
define_method "test_initialize_from_str_#{str}" do
instance = Net::DNS::RR::Classes.new(str)
assert_equal str, instance.to_s
assert_equal num, instance.to_i
end
define_method "test_initialize_from_num_#{num}" do
instance = Net::DNS::RR::Classes.new(num)
assert_equal str, instance.to_s
assert_equal num, instance.to_i
end
end
def test_initialize_should_raise_with_invalid_class
assert_raises(ArgumentError) { Net::DNS::RR::Classes.new(Hash.new) }
end
def test_inspect
assert_equal 1, Net::DNS::RR::Classes.new(1).inspect
assert_equal 1, Net::DNS::RR::Classes.new("IN").inspect
end
def test_to_s
assert_equal "IN", Net::DNS::RR::Classes.new(1).to_s
assert_equal "IN", Net::DNS::RR::Classes.new("IN").to_s
end
def test_to_i
assert_equal 1, Net::DNS::RR::Classes.new(1).to_i
assert_equal 1, Net::DNS::RR::Classes.new("IN").to_i
end
def test_self_default
# Default type should be ANY => 255
instance = Net::DNS::RR::Classes.new(nil)
assert_equal 1, instance.to_i
assert_equal "IN", instance.to_s
# Let's change default behaviour
Net::DNS::RR::Classes.default = "CH"
instance = Net::DNS::RR::Classes.new(nil)
assert_equal 3, instance.to_i
assert_equal "CH", instance.to_s
Net::DNS::RR::Classes.default = "IN"
instance = Net::DNS::RR::Classes.new(nil)
assert_equal 1, instance.to_i
assert_equal "IN", instance.to_s
end
def test_self_valid?
assert Net::DNS::RR::Classes.valid?("IN")
assert Net::DNS::RR::Classes.valid?(1)
assert !Net::DNS::RR::Classes.valid?("Q")
assert !Net::DNS::RR::Classes.valid?(256)
assert_raises(ArgumentError) { Net::DNS::RR::Classes.valid?(Hash.new) }
end
def test_self_regexp
assert_equal @regexp_string, Net::DNS::RR::Classes.regexp
end
end
ruby-net-dns-0.8.0/test/rr/cname_test.rb 0000664 0000000 0000000 00000005477 12142435533 0020136 0 ustar 00root root 0000000 0000000 require 'test_helper'
require 'net/dns/rr'
class RRCNAMETest < Test::Unit::TestCase
def setup
@rr_name = "www.google.com."
@rr_type = "CNAME"
@rr_cls = "IN"
@rr_ttl = 550317
@rr_value = "www.l.google.com."
@rr_cname = @rr_value
@rr_output = "www.google.com. 550317 IN CNAME www.l.google.com."
@rr = Net::DNS::RR::CNAME.new(:name => @rr_name, :cname => @rr_cname, :ttl => @rr_ttl)
end
def test_initialize_from_hash
@record = Net::DNS::RR::CNAME.new(:name => @rr_name, :cname => @rr_value, :ttl => @rr_ttl)
assert_equal @rr_output, @record.to_s
assert_equal @rr_name, @record.name
assert_equal @rr_type, @record.type
assert_equal @rr_cls, @record.cls
assert_equal @rr_ttl, @record.ttl
assert_equal @rr_cname, @record.cname
assert_equal @rr_value, @record.value
end
def test_initialize_from_string
@record = Net::DNS::RR::CNAME.new("#{@rr_name} #{@rr_ttl} #{@rr_cls} #{@rr_type} #{@rr_value}")
assert_equal @rr_output, @record.to_s
assert_equal @rr_name, @record.name
assert_equal @rr_type, @record.type
assert_equal @rr_cls, @record.cls
assert_equal @rr_ttl, @record.ttl
assert_equal @rr_cname, @record.cname
assert_equal @rr_value, @record.value
end
def test_parse
data = "\003www\006google\003com\000\000\005\000\001\000\be\255\000\022\003www\001l\006google\003com\000"
@record = Net::DNS::RR.parse(data)
assert_equal @rr_output, @record.to_s
assert_equal @rr_name, @record.name
assert_equal @rr_type, @record.type
assert_equal @rr_cls, @record.cls
assert_equal @rr_ttl, @record.ttl
assert_equal @rr_cname, @record.cname
assert_equal @rr_value, @record.value
end
InvalidArguments = [
# FIXME: { :name => "google.com", :cname => "foo___bar" },
# FIXME: { :name => "google.com", :cname => "foo$bar" },
{ :name => "google.com" },
Object.new,
Array.new(7),
"10800 IN CNAME",
"google.com. 10800 IN CNAME",
]
InvalidArguments.each_with_index do |arguments, index|
define_method "test_initialize_should_raise_with_invalid_arguments_#{index}" do
assert_raises(ArgumentError) { p Net::DNS::RR::CNAME.new(arguments) }
end
end
def test_cname_getter
assert_equal @rr_cname, @rr.cname
end
def test_value
assert_equal @rr_value, @rr.value
end
def test_inspect
assert_equal "www.google.com. 550317 IN CNAME www.l.google.com.",
@rr.inspect
end
def test_to_s
assert_equal "www.google.com. 550317 IN CNAME www.l.google.com.",
@rr.to_s
end
def test_to_a
assert_equal ["www.google.com.", 550317, "IN", "CNAME", "www.l.google.com."],
@rr.to_a
end
end
ruby-net-dns-0.8.0/test/rr/hinfo_test.rb 0000664 0000000 0000000 00000006605 12142435533 0020150 0 ustar 00root root 0000000 0000000 require 'test_helper'
require 'net/dns/rr'
require 'net/dns/rr/hinfo'
class RRHINFOTest < Test::Unit::TestCase
def setup
@rr_name = ""
@rr_type = "HINFO"
@rr_cls = "IN"
@rr_ttl = nil
@rr_value = %Q{"PC-Intel-700mhz" "Redhat Linux 7.1"}
@rr_output = %Q{ IN HINFO "PC-Intel-700mhz" "Redhat Linux 7.1"}
@rr_cpu = "PC-Intel-700mhz"
@rr_os = "Redhat Linux 7.1"
@rr = Net::DNS::RR::HINFO.new(:name => @rr_name, :cpu => @rr_cpu, :os => @rr_os)
end
def test_initialize_from_hash
@record = Net::DNS::RR::HINFO.new(:name => @rr_name, :cpu => @rr_cpu, :os => @rr_os)
assert_equal @rr_output, @record.to_s
assert_equal @rr_name, @record.name
assert_equal @rr_type, @record.type
assert_equal @rr_cls, @record.cls
assert_equal 10800, @record.ttl
assert_equal @rr_value, @record.value
assert_equal @rr_cpu, @record.cpu
assert_equal @rr_os, @record.os
end
def test_initialize_from_string
@record = Net::DNS::RR::HINFO.new(%Q{#{@rr_name} #{@rr_ttl} #{@rr_cls} #{@rr_type} PC-Intel-700mhz "Redhat Linux 7.1"})
assert_equal @rr_output, @record.to_s
assert_equal @rr_value, @record.value
assert_equal @rr_cpu, @record.cpu
assert_equal @rr_os, @record.os
end
def test_initialize_from_string_without_quotes
@record = Net::DNS::RR::HINFO.new("#{@rr_name} #{@rr_ttl} #{@rr_cls} #{@rr_type} #{@rr_value}")
assert_equal @rr_output, @record.to_s
# FIXME: assert_equal @rr_name, @record.name
assert_equal @rr_type, @record.type
assert_equal @rr_cls, @record.cls
assert_equal 10800, @record.ttl
assert_equal @rr_value, @record.value
assert_equal @rr_cpu, @record.cpu
assert_equal @rr_os, @record.os
end
#Â FIXME: Can't get valid data
# def test_parse
# data = "\002in\000\000\r\000\001\000\000*0\000!\017PC-Intel-700mhz\020Redhat Linux 7.1"
# @record = Net::DNS::RR.parse(data)
# assert_equal @rr_output, @record.to_s
# assert_equal @rr_name, @record.name
# assert_equal @rr_type, @record.type
# assert_equal @rr_cls, @record.cls
# assert_equal @rr_ttl, @record.ttl
# assert_equal @rr_value, @record.value
#
# assert_equal @rr_cpu, @record.cpu
# assert_equal @rr_os, @record.os
# end
InvalidArguments = [
{ :name => "google.com" },
Object.new,
Array.new(7),
"10800 IN HINFO",
"IN HINFO",
]
InvalidArguments.each_with_index do |arguments, index|
define_method "test_initialize_should_raise_with_invalid_arguments_#{index}" do
assert_raises(ArgumentError) { p Net::DNS::RR::HINFO.new(arguments) }
end
end
def test_cpu
assert_equal @rr_cpu, @rr.cpu
end
def test_os
assert_equal @rr_os, @rr.os
end
def test_value
assert_equal %Q{"PC-Intel-700mhz" "Redhat Linux 7.1"}, @rr.value
end
def test_inspect
assert_equal %Q{ IN HINFO "PC-Intel-700mhz" "Redhat Linux 7.1"},
@rr.inspect
end
def test_to_s
assert_equal %Q{ IN HINFO "PC-Intel-700mhz" "Redhat Linux 7.1"},
@rr.to_s
end
def test_to_a
assert_equal [nil, nil, "IN", "HINFO", %Q{"PC-Intel-700mhz" "Redhat Linux 7.1"}],
@rr.to_a
end
end
ruby-net-dns-0.8.0/test/rr/mr_test.rb 0000664 0000000 0000000 00000006652 12142435533 0017465 0 ustar 00root root 0000000 0000000 require 'test_helper'
require 'net/dns/rr'
class RRMRTest < Test::Unit::TestCase
def setup
@klass = Net::DNS::RR::MR
@rr = @klass.new(:name => "eddie.movie.edu.", :newname => "eddie.bornagain.edu.", :ttl => 9000)
@rr_name = "eddie.movie.edu."
@rr_type = "MR"
@rr_cls = "IN"
@rr_ttl = 9000
@rr_newname = "eddie.bornagain.edu."
@rr_value = "eddie.bornagain.edu."
@rr_output = "eddie.movie.edu. 9000 IN MR eddie.bornagain.edu."
end
def test_initialize_from_hash
@record = @klass.new(:name => "eddie.movie.edu.", :newname => "eddie.bornagain.edu.", :ttl => 9000)
assert_equal @rr_output, @record.inspect
assert_equal @rr_name, @record.name
assert_equal @rr_type, @record.type
assert_equal @rr_cls, @record.cls
assert_equal @rr_ttl, @record.ttl
assert_equal @rr_newname, @record.newname
end
def test_initialize_from_string
@record = @klass.new("eddie.movie.edu. 9000 IN MR eddie.bornagain.edu.")
assert_equal @rr_output, @record.inspect
assert_equal @rr_name, @record.name
assert_equal @rr_type, @record.type
assert_equal @rr_cls, @record.cls
assert_equal @rr_ttl, @record.ttl
assert_equal @rr_newname, @record.newname
end
# def test_parse
# data = "\005eddie\005movie\003edu\000\000\t\000\001\000\000#(\000\025\005eddie\tbornagain\003edu\000"
# @record = Net::DNS::RR.parse(data)
# assert_equal @rr_output, @record.inspect
# assert_equal @rr_name, @record.name
# assert_equal @rr_type, @record.type
# assert_equal @rr_cls, @record.cls
# assert_equal @rr_ttl, @record.ttl
# assert_equal @rr_newname, @record.newname
# end
InvalidArguments = [
# FIXME: { :name => "eddie.movie.edu.", :newname => "foo___bar" },
# FIXME: { :name => "eddie.movie.edu.", :newname => "foo$bar" },
# FIXME: { :name => "eddie.movie.edu", :newname => "eddie.newname.edu." },
Object.new,
Array.new(7),
"9000 IN MR",
]
InvalidArguments.each_with_index do |arguments, index|
define_method "test_initialize_should_raise_with_invalid_arguments_#{index}" do
assert_raises(ArgumentError) { @klass.new(arguments) }
end
end
def test_initialize_should_raise_with_missing_newname
error = assert_raises(ArgumentError) { @klass.new(:name => "eddie.movie.edu.") }
assert_match /:newname/, error.message
end
def test_value
@rr = @klass.new(:name => "eddie.movie.edu.", :newname => "eddie.newname.edu.")
assert_equal "eddie.newname.edu.", @rr.value
@rr = @klass.new(:name => "eddie.movie.edu.", :newname => "eddie.othername.edu.")
assert_equal "eddie.othername.edu.", @rr.value
end
def test_newname
@rr = @klass.new(:name => "eddie.movie.edu.", :newname => "eddie.newname.edu.")
assert_equal "eddie.newname.edu.", @rr.newname
@rr = @klass.new(:name => "eddie.movie.edu.", :newname => "eddie.othername.edu.")
assert_equal "eddie.othername.edu.", @rr.newname
end
def test_inspect
assert_equal "eddie.movie.edu. 9000 IN MR eddie.bornagain.edu.",
@rr.inspect
end
def test_to_s
assert_equal "eddie.movie.edu. 9000 IN MR eddie.bornagain.edu.",
@rr.to_s
end
def test_to_a
assert_equal ["eddie.movie.edu.", 9000, "IN", "MR", "eddie.bornagain.edu."],
@rr.to_a
end
end
ruby-net-dns-0.8.0/test/rr/mx_test.rb 0000664 0000000 0000000 00000007467 12142435533 0017500 0 ustar 00root root 0000000 0000000 require 'test_helper'
require 'net/dns/rr'
class RRMXTest < Test::Unit::TestCase
def setup
@rr_name = "example.com."
@rr_type = "MX"
@rr_cls = "IN"
@rr_ttl = 10000
@rr_preference = 10
@rr_exchange = "mail.example.com."
@rr_value = "#{@rr_preference} #{@rr_exchange}"
@rr_output = "example.com. 10000 IN MX 10 mail.example.com."
@rr = Net::DNS::RR::MX.new(:name => "example.com.", :preference => 10, :exchange => "mail.example.com.", :ttl => 10000)
end
def test_initialize_from_hash
@record = Net::DNS::RR::MX.new(:name => "example.com.", :preference => 10, :exchange => "mail.example.com.", :ttl => 10000)
assert_equal @rr_output, @record.to_s
assert_equal @rr_name, @record.name
assert_equal @rr_type, @record.type
assert_equal @rr_cls, @record.cls
assert_equal @rr_ttl, @record.ttl
assert_equal @rr_preference, @record.preference
assert_equal @rr_exchange, @record.exchange
end
def test_initialize_from_string
@record = Net::DNS::RR::MX.new("example.com. 10000 IN MX 10 mail.example.com.")
assert_equal @rr_output, @record.to_s
assert_equal @rr_name, @record.name
assert_equal @rr_type, @record.type
assert_equal @rr_cls, @record.cls
assert_equal @rr_ttl, @record.ttl
assert_equal @rr_preference, @record.preference
assert_equal @rr_exchange, @record.exchange
end
# FIXME: can't get it working with canned data
# def test_parse
# data = "\001\220\006google\003com\004s9b2\005psmtp\003com\000"
# @record = Net::DNS::RR.parse(data)
# assert_equal @rr_output, @record.to_s
# assert_equal @rr_name, @record.name
# assert_equal @rr_type, @record.type
# assert_equal @rr_cls, @record.cls
# assert_equal @rr_ttl, @record.ttl
# assert_equal @rr_preference, @record.preference
# assert_equal @rr_exchange, @record.exchange
# end
InvalidArguments = [
{ :name => "google.com" },
Object.new,
Array.new(7),
"10800 IN NS",
"google.com. 10800 IN NS",
]
InvalidArguments.each_with_index do |arguments, index|
define_method "test_initialize_should_raise_with_invalid_arguments_#{index}" do
assert_raises(ArgumentError) { p Net::DNS::RR::MX.new(arguments) }
end
end
def test_preference
@rr = Net::DNS::RR::MX.new(:name => "example.com.", :preference => 10, :exchange => "mail.example.com.")
assert_equal 10, @rr.preference
@rr = Net::DNS::RR::MX.new(:name => "example.com.", :preference => 100, :exchange => "mail.example.com.")
assert_equal 100, @rr.preference
end
def test_exchange
@rr = Net::DNS::RR::MX.new(:name => "example.com.", :preference => 10, :exchange => "mail.example.com.")
assert_equal "mail.example.com.", @rr.exchange
@rr = Net::DNS::RR::MX.new(:name => "example.com.", :preference => 10, :exchange => "mail2.example.com.")
assert_equal "mail2.example.com.", @rr.exchange
end
def test_value
@rr = Net::DNS::RR::MX.new(:name => "example.com.", :preference => 10, :exchange => "mail.example.com.")
assert_equal "10 mail.example.com.", @rr.value
@rr = Net::DNS::RR::MX.new(:name => "example.com.", :preference => 100, :exchange => "mail2.example.com.")
assert_equal "100 mail2.example.com.", @rr.value
end
def test_inspect
assert_equal "example.com. 10000 IN MX 10 mail.example.com.",
@rr.inspect
end
def test_to_s
assert_equal "example.com. 10000 IN MX 10 mail.example.com.",
@rr.to_s
end
def test_to_a
assert_equal ["example.com.", 10000, "IN", "MX", "10 mail.example.com."],
@rr.to_a
end
end
ruby-net-dns-0.8.0/test/rr/ns_test.rb 0000664 0000000 0000000 00000004713 12142435533 0017463 0 ustar 00root root 0000000 0000000 require 'test_helper'
require 'net/dns/rr'
class RRNSTest < Test::Unit::TestCase
def setup
@rr_name = "google.com."
@rr_type = "NS"
@rr_cls = "IN"
@rr_ttl = 10800
@rr_nsdname = "ns1.google.com."
@rr_output = "google.com. 10800 IN NS ns1.google.com."
@rr = Net::DNS::RR::NS.new(:name => "google.com.", :nsdname => "ns1.google.com.", :ttl => @rr_ttl)
end
def test_initialize_from_hash
@record = Net::DNS::RR::NS.new(:name => "google.com.", :nsdname => "ns1.google.com.")
assert_equal @rr_output, @record.inspect
assert_equal @rr_name, @record.name
assert_equal @rr_type, @record.type
assert_equal @rr_cls, @record.cls
assert_equal @rr_ttl, @record.ttl
assert_equal @rr_nsdname, @record.nsdname
end
def test_initialize_from_string
@record = Net::DNS::RR::NS.new("google.com. 10800 IN NS ns1.google.com.")
assert_equal @rr_output, @record.inspect
assert_equal @rr_name, @record.name
assert_equal @rr_type, @record.type
assert_equal @rr_cls, @record.cls
assert_equal @rr_ttl, @record.ttl
assert_equal @rr_nsdname, @record.nsdname
end
def test_parse
data = "\006google\003com\000\000\002\000\001\000\000*0\000\020\003ns1\006google\003com\000"
@record = Net::DNS::RR.parse(data)
assert_equal @rr_output, @record.inspect
assert_equal @rr_name, @record.name
assert_equal @rr_type, @record.type
assert_equal @rr_cls, @record.cls
assert_equal @rr_ttl, @record.ttl
assert_equal @rr_nsdname, @record.nsdname
end
InvalidArguments = [
{ :name => "google.com", :nsdname => "255.256" },
{ :name => "google.com" },
Object.new,
Array.new(7),
"10800 IN A",
]
InvalidArguments.each_with_index do |arguments, index|
define_method "test_initialize_should_raise_with_invalid_arguments_#{index}" do
assert_raises(ArgumentError) { Net::DNS::RR::NS.new(arguments) }
end
end
def test_value
assert_equal "ns1.google.com.", @rr.value
end
def test_inspect
assert_equal "google.com. 10800 IN NS ns1.google.com.",
@rr.inspect
end
def test_to_s
assert_equal "google.com. 10800 IN NS ns1.google.com.",
@rr.to_s
end
def test_to_a
assert_equal ["google.com.", 10800, "IN", "NS", "ns1.google.com."],
@rr.to_a
end
end
ruby-net-dns-0.8.0/test/rr/types_test.rb 0000664 0000000 0000000 00000003633 12142435533 0020207 0 ustar 00root root 0000000 0000000 require 'test_helper'
require 'net/dns/rr'
class RRTypesTest < Test::Unit::TestCase
def setup
end
def test_default
# Default type should be ANY => 255
instance = Net::DNS::RR::Types.new(nil)
assert_equal("1", instance.to_str)
assert_equal("A", instance.to_s)
# Let's change default behaviour
Net::DNS::RR::Types.default = "A"
instance = Net::DNS::RR::Types.new(nil)
assert_equal("1", instance.to_str)
assert_equal("A", instance.to_s)
Net::DNS::RR::Types.default = "ANY"
instance = Net::DNS::RR::Types.new(nil)
assert_equal("255", instance.to_str)
assert_equal("ANY", instance.to_s)
end
def test_types
Net::DNS::RR::Types::TYPES.each do |key, num|
instance_from_string = Net::DNS::RR::Types.new(key)
instance_from_num = Net::DNS::RR::Types.new(num)
assert_equal(key, instance_from_string.to_s)
assert_equal(num.to_s, instance_from_string.to_str)
assert_equal(key, instance_from_num.to_s)
assert_equal(num.to_s, instance_from_num.to_str)
end
assert_raises(ArgumentError) do
Net::DNS::RR::Types.new(Hash.new)
end
end
def test_regexp
pattern = Net::DNS::RR::Types.regexp
assert_instance_of String, pattern
Net::DNS::RR::Types::TYPES.each do |key, num|
assert_match /\|?#{key}\|?/, pattern
end
end
def test_valid?
assert_equal(true, Net::DNS::RR::Types.valid?("A"))
assert_equal(true, Net::DNS::RR::Types.valid?(1))
assert_equal(false, Net::DNS::RR::Types.valid?("Q"))
assert_equal(false, Net::DNS::RR::Types.valid?(256))
assert_raises(ArgumentError) do
Net::DNS::RR::Types.valid? Hash.new
end
end
def test_to_str
assert_equal("A", Net::DNS::RR::Types.to_str(1))
assert_raises(ArgumentError) do
Net::DNS::RR::Types.to_str(256)
end
assert_raises(ArgumentError) do
Net::DNS::RR::Types.to_str("string")
end
end
end
ruby-net-dns-0.8.0/test/rr_test.rb 0000664 0000000 0000000 00000007613 12142435533 0017045 0 ustar 00root root 0000000 0000000 require 'test_helper'
require 'net/dns/rr'
class RRTest < Test::Unit::TestCase
def setup
@rr_name = "example.com."
@type = "A"
@cls = "IN"
@ttl = 10800
@rdata = "64.233.187.99"
@defaults = Net::DNS::RR.new(:name => @rr_name,
:rdata => @rdata)
@a_hash = Net::DNS::RR.new(:name => @rr_name,
:ttl => @ttl,
:cls => @cls,
:type => @type,
:address => @rdata)
@a_string = Net::DNS::RR::A.new("example.com. 10800 IN A 64.233.187.99")
@str = "example.com. 10800 IN A 64.233.187.99"
@a = Net::DNS::RR.new("foo.example.com. 86400 A 10.1.2.3")
@mx = Net::DNS::RR.new("example.com. 7200 MX 10 mailhost.example.com.")
@cname = Net::DNS::RR.new("www.example.com IN CNAME www1.example.com")
@txt = Net::DNS::RR.new('baz.example.com 3600 HS TXT "text record"')
@a_data = @a.data
@a_binary = Net::DNS::RR.parse(@a_data)
@mx_data = @mx.data
@mx_binary = Net::DNS::RR.parse(@mx_data)
@array = [@rr_name,@ttl,@cls,@type,@rdata]
end
def test_classes
assert_instance_of Net::DNS::RR::A, @a
assert_instance_of Net::DNS::RR::MX, @mx
assert_instance_of Net::DNS::RR::CNAME, @cname
assert_instance_of Net::DNS::RR::TXT, @txt
assert_instance_of Net::DNS::RR::A, @a_binary
assert_instance_of Net::DNS::RR::MX, @mx_binary
end
def test_ttl
assert_equal @a.ttl, 86400
assert_equal @mx.ttl, 7200
assert_equal @cname.ttl, 10800
assert_equal @txt.ttl, 3600
assert_equal @a_binary.ttl, 86400
assert_equal @mx_binary.ttl, 7200
end
def test_types
assert_equal @a.type, "A"
assert_equal @mx.type, "MX"
assert_equal @cname.type, "CNAME"
assert_equal @txt.type, "TXT"
assert_equal @a_binary.type, "A"
assert_equal @mx_binary.type, "MX"
end
def test_cls
assert_equal @a.cls, "IN"
assert_equal @mx.cls, "IN"
assert_equal @cname.cls, "IN"
assert_equal @txt.cls, "HS"
assert_equal @a_binary.cls, "IN"
assert_equal @mx_binary.cls, "IN"
end
def test_name
assert_equal @a.name, "foo.example.com."
assert_equal @mx.name, "example.com."
assert_equal @cname.name, "www.example.com"
assert_equal @txt.name, "baz.example.com"
assert_equal @a_binary.name, "foo.example.com."
assert_equal @mx_binary.name, "example.com."
end
def test_rdata
assert_equal @a.address.to_s, "10.1.2.3"
assert_equal @mx.preference, 10
assert_equal @mx.exchange, "mailhost.example.com."
assert_equal @cname.cname, "www1.example.com"
assert_equal @txt.txt, '"text record"'
assert_equal @a_binary.address.to_s, "10.1.2.3"
assert_equal @mx_binary.preference, 10
assert_equal @mx_binary.exchange, "mailhost.example.com."
end
def test_simple
assert_equal @rr_name, @defaults.name
assert_equal @type, @defaults.type
assert_equal @cls, @defaults.cls
assert_equal @ttl, @defaults.ttl
assert_equal @rdata, @defaults.rdata.to_s
assert_equal(@str,@a_hash.inspect)
assert_equal(@rr_name, @a_hash.name)
assert_equal(@type, @a_hash.type)
assert_equal(@cls, @a_hash.cls)
assert_equal(@ttl, @a_hash.ttl)
assert_equal(@rdata, @a_hash.address.to_s)
assert_equal(@str, @a_string.inspect)
assert_equal(@rr_name, @a_string.name)
assert_equal(@type, @a_string.type)
assert_equal(@cls, @a_string.cls)
assert_equal(@ttl, @a_string.ttl)
assert_equal(@rdata, @a_string.address.to_s)
assert_equal(@a_data, @a_binary.data)
assert_equal(@mx_data, @mx_binary.data)
assert_equal(@str, @a_hash.to_s)
assert_equal(@array, @a_hash.to_a)
end
def test_range
assert_raises(ArgumentError) do
Net::DNS::RR.new("google.com. 10800 IM A")
end
end
end
ruby-net-dns-0.8.0/test/test_helper.rb 0000664 0000000 0000000 00000000125 12142435533 0017670 0 ustar 00root root 0000000 0000000 $:.unshift(File.dirname(__FILE__) + '/../lib')
require 'test/unit'
require 'net/dns'