net-dns2 0.8.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +8 -0
- data/.travis.yml +20 -0
- data/CHANGELOG.md +105 -0
- data/Gemfile +4 -0
- data/README.md +155 -0
- data/Rakefile +94 -0
- data/THANKS.rdoc +24 -0
- data/demo/check_soa.rb +115 -0
- data/demo/threads.rb +22 -0
- data/lib/net/dns.rb +112 -0
- data/lib/net/dns/core_ext.rb +52 -0
- data/lib/net/dns/header.rb +713 -0
- data/lib/net/dns/names.rb +118 -0
- data/lib/net/dns/packet.rb +563 -0
- data/lib/net/dns/question.rb +188 -0
- data/lib/net/dns/resolver.rb +1313 -0
- data/lib/net/dns/resolver/socks.rb +154 -0
- data/lib/net/dns/resolver/timeouts.rb +75 -0
- data/lib/net/dns/rr.rb +366 -0
- data/lib/net/dns/rr/a.rb +124 -0
- data/lib/net/dns/rr/aaaa.rb +103 -0
- data/lib/net/dns/rr/classes.rb +133 -0
- data/lib/net/dns/rr/cname.rb +82 -0
- data/lib/net/dns/rr/hinfo.rb +108 -0
- data/lib/net/dns/rr/mr.rb +79 -0
- data/lib/net/dns/rr/mx.rb +92 -0
- data/lib/net/dns/rr/ns.rb +78 -0
- data/lib/net/dns/rr/null.rb +53 -0
- data/lib/net/dns/rr/ptr.rb +83 -0
- data/lib/net/dns/rr/soa.rb +78 -0
- data/lib/net/dns/rr/srv.rb +45 -0
- data/lib/net/dns/rr/txt.rb +61 -0
- data/lib/net/dns/rr/types.rb +193 -0
- data/lib/net/dns/version.rb +16 -0
- data/net-dns.gemspec +37 -0
- data/test/header_test.rb +167 -0
- data/test/names_test.rb +21 -0
- data/test/packet_test.rb +49 -0
- data/test/question_test.rb +83 -0
- data/test/resolver_test.rb +117 -0
- data/test/rr/a_test.rb +113 -0
- data/test/rr/aaaa_test.rb +109 -0
- data/test/rr/classes_test.rb +85 -0
- data/test/rr/cname_test.rb +97 -0
- data/test/rr/hinfo_test.rb +117 -0
- data/test/rr/mr_test.rb +105 -0
- data/test/rr/mx_test.rb +112 -0
- data/test/rr/ns_test.rb +86 -0
- data/test/rr/types_test.rb +69 -0
- data/test/rr_test.rb +131 -0
- data/test/test_helper.rb +4 -0
- metadata +158 -0
@@ -0,0 +1,79 @@
|
|
1
|
+
module Net # :nodoc:
|
2
|
+
module DNS
|
3
|
+
|
4
|
+
class RR
|
5
|
+
|
6
|
+
#
|
7
|
+
# = Mail Rename Record (MR)
|
8
|
+
#
|
9
|
+
# Class for DNS MR resource records.
|
10
|
+
#
|
11
|
+
class MR < RR
|
12
|
+
|
13
|
+
# Gets the newname value.
|
14
|
+
#
|
15
|
+
# Returns a String.
|
16
|
+
def newname
|
17
|
+
@newname
|
18
|
+
end
|
19
|
+
|
20
|
+
# Gets the standardized value for this record,
|
21
|
+
# represented by the value of <tt>newname</tt>.
|
22
|
+
#
|
23
|
+
# Returns a String.
|
24
|
+
def value
|
25
|
+
newname.to_s
|
26
|
+
end
|
27
|
+
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
def subclass_new_from_hash(options)
|
32
|
+
if options.has_key?(:newname)
|
33
|
+
@newname = check_name(options[:newname])
|
34
|
+
else
|
35
|
+
raise ArgumentError, ":newname field is mandatory"
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def subclass_new_from_string(str)
|
40
|
+
@newname = check_name(str)
|
41
|
+
end
|
42
|
+
|
43
|
+
def subclass_new_from_binary(data, offset)
|
44
|
+
@newname = dn_expand(data,offset)
|
45
|
+
offset
|
46
|
+
end
|
47
|
+
|
48
|
+
|
49
|
+
def set_type
|
50
|
+
@type = Net::DNS::RR::Types.new("MR")
|
51
|
+
end
|
52
|
+
|
53
|
+
def get_inspect
|
54
|
+
value
|
55
|
+
end
|
56
|
+
|
57
|
+
|
58
|
+
def check_name(input)
|
59
|
+
name = input.to_s
|
60
|
+
unless name =~ /(\w\.?)+\s*$/
|
61
|
+
raise ArgumentError, "Invalid Domain Name `#{name}'"
|
62
|
+
end
|
63
|
+
name
|
64
|
+
end
|
65
|
+
|
66
|
+
def build_pack
|
67
|
+
@newname_pack = pack_name(@newname)
|
68
|
+
@rdlength = @newname_pack.size
|
69
|
+
end
|
70
|
+
|
71
|
+
def get_data
|
72
|
+
@newname_pack
|
73
|
+
end
|
74
|
+
|
75
|
+
end
|
76
|
+
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
@@ -0,0 +1,92 @@
|
|
1
|
+
module Net # :nodoc:
|
2
|
+
module DNS
|
3
|
+
class RR
|
4
|
+
|
5
|
+
#
|
6
|
+
# = Mail Exchange Record (MX)
|
7
|
+
#
|
8
|
+
# Class for DNS MX resource records.
|
9
|
+
#
|
10
|
+
# A MX record specifies the name and relative preference of mail servers
|
11
|
+
# (mail exchangers in the DNS jargon) for the zone.
|
12
|
+
# The MX RR is used by SMTP (Mail) Agents to route mail for the domain.
|
13
|
+
#
|
14
|
+
class MX < RR
|
15
|
+
|
16
|
+
# Gets the preference value.
|
17
|
+
#
|
18
|
+
# Returns an Integer.
|
19
|
+
def preference
|
20
|
+
@preference
|
21
|
+
end
|
22
|
+
|
23
|
+
# Gets the exchange value.
|
24
|
+
#
|
25
|
+
# Returns a String.
|
26
|
+
def exchange
|
27
|
+
@exchange
|
28
|
+
end
|
29
|
+
|
30
|
+
# Gets the standardized value for this record,
|
31
|
+
# represented by the value of <tt>preference</tt> and <tt>exchange</tt>.
|
32
|
+
#
|
33
|
+
# Returns a String.
|
34
|
+
def value
|
35
|
+
"#{preference} #{exchange}"
|
36
|
+
end
|
37
|
+
|
38
|
+
|
39
|
+
private
|
40
|
+
|
41
|
+
def subclass_new_from_hash(options)
|
42
|
+
if options.has_key?(:preference) && options.has_key?(:exchange)
|
43
|
+
@preference = options[:preference].to_i
|
44
|
+
@exchange = options[:exchange]
|
45
|
+
else
|
46
|
+
raise ArgumentError, ":preference and :exchange fields are mandatory"
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def subclass_new_from_string(str)
|
51
|
+
@preference, @exchange = check_mx(str)
|
52
|
+
end
|
53
|
+
|
54
|
+
def subclass_new_from_binary(data, offset)
|
55
|
+
@preference = data.unpack("@#{offset} n")[0]
|
56
|
+
offset += 2
|
57
|
+
@exchange, offset = dn_expand(data, offset)
|
58
|
+
offset
|
59
|
+
end
|
60
|
+
|
61
|
+
|
62
|
+
def set_type
|
63
|
+
@type = Net::DNS::RR::Types.new("MX")
|
64
|
+
end
|
65
|
+
|
66
|
+
def get_inspect
|
67
|
+
value
|
68
|
+
end
|
69
|
+
|
70
|
+
|
71
|
+
def check_mx(input)
|
72
|
+
str = input.to_s
|
73
|
+
unless str.strip =~ /^(\d+)\s+(\S+)$/
|
74
|
+
raise ArgumentError, "Invalid MX section `#{str}'"
|
75
|
+
end
|
76
|
+
[$1.to_i, $2]
|
77
|
+
end
|
78
|
+
|
79
|
+
def build_pack
|
80
|
+
@mx_pack = [@preference].pack("n") + pack_name(@exchange)
|
81
|
+
@rdlength = @mx_pack.size
|
82
|
+
end
|
83
|
+
|
84
|
+
def get_data
|
85
|
+
@mx_pack
|
86
|
+
end
|
87
|
+
|
88
|
+
end
|
89
|
+
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
@@ -0,0 +1,78 @@
|
|
1
|
+
module Net # :nodoc:
|
2
|
+
module DNS
|
3
|
+
class RR
|
4
|
+
|
5
|
+
#
|
6
|
+
# = Name Server Record (NS)
|
7
|
+
#
|
8
|
+
# Class for DNS NS resource records.
|
9
|
+
#
|
10
|
+
class NS < RR
|
11
|
+
|
12
|
+
# Gets the name server value.
|
13
|
+
#
|
14
|
+
# Returns a String.
|
15
|
+
def nsdname
|
16
|
+
@nsdname
|
17
|
+
end
|
18
|
+
|
19
|
+
# Gets the standardized value for this record,
|
20
|
+
# represented by the value of <tt>nsdname</tt>.
|
21
|
+
#
|
22
|
+
# Returns a String.
|
23
|
+
def value
|
24
|
+
nsdname.to_s
|
25
|
+
end
|
26
|
+
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
def subclass_new_from_hash(options)
|
31
|
+
if options.has_key?(:nsdname)
|
32
|
+
@nsdname = check_name(options[:nsdname])
|
33
|
+
else
|
34
|
+
raise ArgumentError, ":nsdname field is mandatory"
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def subclass_new_from_string(str)
|
39
|
+
@nsdname = check_name(str)
|
40
|
+
end
|
41
|
+
|
42
|
+
def subclass_new_from_binary(data, offset)
|
43
|
+
@nsdname, offset = dn_expand(data, offset)
|
44
|
+
offset
|
45
|
+
end
|
46
|
+
|
47
|
+
|
48
|
+
def set_type
|
49
|
+
@type = Net::DNS::RR::Types.new("NS")
|
50
|
+
end
|
51
|
+
|
52
|
+
def get_inspect
|
53
|
+
value
|
54
|
+
end
|
55
|
+
|
56
|
+
|
57
|
+
def check_name(input)
|
58
|
+
name = input.to_s
|
59
|
+
unless name =~ /(\w\.?)+\s*$/ and name =~ /[a-zA-Z]/
|
60
|
+
raise ArgumentError, "Invalid Name Server `#{name}'"
|
61
|
+
end
|
62
|
+
name
|
63
|
+
end
|
64
|
+
|
65
|
+
def build_pack
|
66
|
+
@nsdname_pack = pack_name(@nsdname)
|
67
|
+
@rdlength = @nsdname_pack.size
|
68
|
+
end
|
69
|
+
|
70
|
+
def get_data
|
71
|
+
@nsdname_pack
|
72
|
+
end
|
73
|
+
|
74
|
+
end
|
75
|
+
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
module Net # :nodoc:
|
2
|
+
module DNS
|
3
|
+
class RR
|
4
|
+
|
5
|
+
#------------------------------------------------------------
|
6
|
+
# RR type NULL
|
7
|
+
#------------------------------------------------------------
|
8
|
+
class NULL < RR
|
9
|
+
attr_reader :null
|
10
|
+
|
11
|
+
private
|
12
|
+
|
13
|
+
def build_pack
|
14
|
+
@null_pack = @null
|
15
|
+
@rdlength = @null_pack.size
|
16
|
+
end
|
17
|
+
|
18
|
+
def get_data
|
19
|
+
@null_pack
|
20
|
+
end
|
21
|
+
|
22
|
+
def get_inspect
|
23
|
+
"#@null"
|
24
|
+
end
|
25
|
+
|
26
|
+
def subclass_new_from_hash(args)
|
27
|
+
if args.has_key? :null
|
28
|
+
@null = args[:null]
|
29
|
+
else
|
30
|
+
raise ArgumentError, ":null field is mandatory but missing"
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def subclass_new_from_string(str)
|
35
|
+
@null = str.strip
|
36
|
+
end
|
37
|
+
|
38
|
+
def subclass_new_from_binary(data,offset)
|
39
|
+
@null = data[offset..offset+@rdlength]
|
40
|
+
return offset + @rdlength
|
41
|
+
end
|
42
|
+
|
43
|
+
private
|
44
|
+
|
45
|
+
def set_type
|
46
|
+
@type = Net::DNS::RR::Types.new("NULL")
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,83 @@
|
|
1
|
+
module Net
|
2
|
+
module DNS
|
3
|
+
class RR
|
4
|
+
|
5
|
+
#
|
6
|
+
# = Pointer Record (PTR)
|
7
|
+
#
|
8
|
+
# Class for DNS Pointer (PTR) resource records.
|
9
|
+
#
|
10
|
+
# Pointer records are the opposite of A and AAAA RRs
|
11
|
+
# and are used in Reverse Map zone files to map
|
12
|
+
# an IP address (IPv4 or IPv6) to a host name.
|
13
|
+
#
|
14
|
+
class PTR < RR
|
15
|
+
|
16
|
+
# Gets the PTR value.
|
17
|
+
#
|
18
|
+
# Returns a String.
|
19
|
+
def ptrdname
|
20
|
+
@ptrdname.to_s
|
21
|
+
end
|
22
|
+
|
23
|
+
alias_method :ptr, :ptrdname
|
24
|
+
|
25
|
+
# Gets the standardized value for this record,
|
26
|
+
# represented by the value of <tt>ptrdname</tt>.
|
27
|
+
#
|
28
|
+
# Returns a String.
|
29
|
+
def value
|
30
|
+
ptrdname.to_s
|
31
|
+
end
|
32
|
+
|
33
|
+
|
34
|
+
private
|
35
|
+
|
36
|
+
def build_pack
|
37
|
+
@ptrdname_pack = pack_name(@ptrdname)
|
38
|
+
@rdlength = @ptrdname_pack.size
|
39
|
+
end
|
40
|
+
|
41
|
+
def get_data
|
42
|
+
@ptrdname_pack
|
43
|
+
end
|
44
|
+
|
45
|
+
def subclass_new_from_hash(args)
|
46
|
+
if args.has_key?(:ptrdname) or args.has_key?(:ptr)
|
47
|
+
@ptrdname = args[:ptrdname]
|
48
|
+
else
|
49
|
+
raise ArgumentError, ":ptrdname or :ptr field is mandatory"
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def subclass_new_from_string(str)
|
54
|
+
@ptrdname = check_name(str)
|
55
|
+
end
|
56
|
+
|
57
|
+
def subclass_new_from_binary(data, offset)
|
58
|
+
@ptrdname, offset = dn_expand(data, offset)
|
59
|
+
offset
|
60
|
+
end
|
61
|
+
|
62
|
+
private
|
63
|
+
|
64
|
+
def set_type
|
65
|
+
@type = Net::DNS::RR::Types.new("PTR")
|
66
|
+
end
|
67
|
+
|
68
|
+
def get_inspect
|
69
|
+
value
|
70
|
+
end
|
71
|
+
|
72
|
+
|
73
|
+
def check_name(input)
|
74
|
+
IPAddr.new(str)
|
75
|
+
rescue
|
76
|
+
raise ArgumentError, "Invalid PTR Section `#{input}'"
|
77
|
+
end
|
78
|
+
|
79
|
+
end
|
80
|
+
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
@@ -0,0 +1,78 @@
|
|
1
|
+
module Net # :nodoc:
|
2
|
+
module DNS
|
3
|
+
class RR
|
4
|
+
|
5
|
+
#------------------------------------------------------------
|
6
|
+
# RR type SOA
|
7
|
+
#------------------------------------------------------------
|
8
|
+
class SOA < RR
|
9
|
+
attr_reader :mname, :rname, :serial, :refresh, :retry, :expire, :minimum
|
10
|
+
|
11
|
+
private
|
12
|
+
|
13
|
+
def build_pack
|
14
|
+
@soa_pack = pack_name(@mname)
|
15
|
+
@soa_pack += pack_name(@rname)
|
16
|
+
@soa_pack += [@serial,@refresh,@retry,@expire,@minimum].pack("N5")
|
17
|
+
end
|
18
|
+
|
19
|
+
def get_data
|
20
|
+
@soa_pack
|
21
|
+
end
|
22
|
+
|
23
|
+
def get_inspect
|
24
|
+
"#@mname #@rname #@serial #@refresh #@retry #@expire #@minimum"
|
25
|
+
end
|
26
|
+
|
27
|
+
def subclass_new_from_hash(args)
|
28
|
+
if args.has_key? :rdata
|
29
|
+
subclass_new_from_string(args[:rdata])
|
30
|
+
else
|
31
|
+
[:mname,:rname,:serial,:refresh,:retry,:expire,:minimum].each do |key|
|
32
|
+
raise ArgumentError, "Missing field :#{key}" unless args.has_key? key
|
33
|
+
end
|
34
|
+
@mname = args[:mname] if valid? args[:mname]
|
35
|
+
@rname = args[:rname] if valid? args[:rname]
|
36
|
+
@serial = args[:serial] if number? args[:serial]
|
37
|
+
@refresh = args[:refresh] if number? args[:refresh]
|
38
|
+
@retry = args[:retry] if number? args[:retry]
|
39
|
+
@expire = args[:expire] if number? args[:expire]
|
40
|
+
@minimum = args[:minimum] if number? args[:minimum]
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def number?(num)
|
45
|
+
if num.kind_of? Integer and num > 0
|
46
|
+
true
|
47
|
+
else
|
48
|
+
raise ArgumentError, "Wrong format field: #{num} not a number or less than zero"
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def subclass_new_from_string(str)
|
53
|
+
mname,rname,serial,refresh,ret,expire,minimum = str.strip.split(" ")
|
54
|
+
@mname = mname if valid? mname
|
55
|
+
@rname = rname if valid? rname
|
56
|
+
@serial,@refresh,@retry,@expire,@minimum = [serial,refresh,ret,expire,minimum].collect do |i|
|
57
|
+
i.to_i if valid? i.to_i
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def subclass_new_from_binary(data,offset)
|
62
|
+
@mname,offset = dn_expand(data,offset)
|
63
|
+
@rname,offset = dn_expand(data,offset)
|
64
|
+
@serial,@refresh,@retry,@expire,@minimum = data.unpack("@#{offset} N5")
|
65
|
+
return offset + 5*Net::DNS::INT32SZ
|
66
|
+
end
|
67
|
+
|
68
|
+
private
|
69
|
+
|
70
|
+
def set_type
|
71
|
+
@type = Net::DNS::RR::Types.new("SOA")
|
72
|
+
end
|
73
|
+
|
74
|
+
end
|
75
|
+
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|