net-dns 0.8.0 → 0.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +6 -14
- data/.gitignore +1 -1
- data/.rspec +1 -0
- data/.rubocop.yml +3 -0
- data/.rubocop_defaults.yml +364 -0
- data/.rubocop_todo.yml +207 -0
- data/.travis.yml +9 -16
- data/CHANGELOG.md +12 -1
- data/Gemfile +6 -2
- data/LICENSE.txt +56 -0
- data/README.md +94 -77
- data/Rakefile +23 -56
- data/bin/console +14 -0
- data/demo/check_soa.rb +27 -38
- data/demo/threads.rb +3 -7
- data/lib/net/dns.rb +4 -11
- data/lib/net/dns/core_ext.rb +8 -15
- data/lib/net/dns/header.rb +58 -66
- data/lib/net/dns/names.rb +25 -23
- data/lib/net/dns/packet.rb +136 -139
- data/lib/net/dns/question.rb +36 -39
- data/lib/net/dns/resolver.rb +103 -113
- data/lib/net/dns/resolver/socks.rb +45 -51
- data/lib/net/dns/resolver/timeouts.rb +17 -26
- data/lib/net/dns/rr.rb +107 -117
- data/lib/net/dns/rr/a.rb +46 -55
- data/lib/net/dns/rr/aaaa.rb +40 -49
- data/lib/net/dns/rr/classes.rb +26 -29
- data/lib/net/dns/rr/cname.rb +33 -41
- data/lib/net/dns/rr/hinfo.rb +44 -56
- data/lib/net/dns/rr/mr.rb +33 -42
- data/lib/net/dns/rr/mx.rb +37 -47
- data/lib/net/dns/rr/ns.rb +33 -41
- data/lib/net/dns/rr/null.rb +8 -11
- data/lib/net/dns/rr/ptr.rb +14 -20
- data/lib/net/dns/rr/soa.rb +27 -30
- data/lib/net/dns/rr/srv.rb +13 -17
- data/lib/net/dns/rr/txt.rb +8 -11
- data/lib/net/dns/rr/types.rb +97 -99
- data/lib/net/dns/version.rb +5 -13
- data/net-dns.gemspec +17 -29
- data/{fixtures → spec/fixtures}/resolv.conf +0 -0
- data/spec/spec_helper.rb +14 -0
- data/spec/unit/resolver/dns_timeout_spec.rb +36 -0
- data/spec/unit/resolver/tcp_timeout_spec.rb +46 -0
- data/spec/unit/resolver/udp_timeout_spec.rb +46 -0
- data/test/test_helper.rb +12 -3
- data/test/{header_test.rb → unit/header_test.rb} +43 -46
- data/test/{names_test.rb → unit/names_test.rb} +1 -1
- data/test/{packet_test.rb → unit/packet_test.rb} +3 -5
- data/test/{question_test.rb → unit/question_test.rb} +3 -5
- data/test/{resolver_test.rb → unit/resolver_test.rb} +10 -13
- data/test/{rr → unit/rr}/a_test.rb +10 -17
- data/test/{rr → unit/rr}/aaaa_test.rb +7 -14
- data/test/{rr → unit/rr}/classes_test.rb +14 -16
- data/test/{rr → unit/rr}/cname_test.rb +7 -14
- data/test/{rr → unit/rr}/hinfo_test.rb +16 -22
- data/test/{rr → unit/rr}/mr_test.rb +12 -18
- data/test/{rr → unit/rr}/mx_test.rb +18 -24
- data/test/{rr → unit/rr}/ns_test.rb +10 -16
- data/test/{rr → unit/rr}/types_test.rb +10 -8
- data/test/{rr_test.rb → unit/rr_test.rb} +33 -37
- metadata +77 -49
- data/test/resolver/timeouts_test.rb +0 -109
data/lib/net/dns/rr/a.rb
CHANGED
@@ -1,7 +1,6 @@
|
|
1
1
|
module Net
|
2
2
|
module DNS
|
3
3
|
class RR
|
4
|
-
|
5
4
|
#
|
6
5
|
# = IPv4 Address Record (A)
|
7
6
|
#
|
@@ -23,13 +22,10 @@ module Net
|
|
23
22
|
# without any embedded space (e.g. "10.2.0.52" or "192.0.5.6").
|
24
23
|
#
|
25
24
|
class A < RR
|
26
|
-
|
27
25
|
# Gets the current IPv4 address for this record.
|
28
26
|
#
|
29
27
|
# Returns an instance of IPAddr.
|
30
|
-
|
31
|
-
@address
|
32
|
-
end
|
28
|
+
attr_reader :address
|
33
29
|
|
34
30
|
# Assigns a new IPv4 address to this record, which can be in the
|
35
31
|
# form of a <tt>String</tt> or an <tt>IPAddr</tt> object.
|
@@ -54,71 +50,66 @@ module Net
|
|
54
50
|
address.to_s
|
55
51
|
end
|
56
52
|
|
57
|
-
|
58
53
|
private
|
59
54
|
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
end
|
55
|
+
def subclass_new_from_hash(options)
|
56
|
+
if options.key?(:address)
|
57
|
+
@address = check_address(options[:address])
|
58
|
+
elsif options.key?(:rdata)
|
59
|
+
@address = check_address(options[:rdata])
|
60
|
+
else
|
61
|
+
raise ArgumentError, ":address or :rdata field is mandatory"
|
68
62
|
end
|
63
|
+
end
|
69
64
|
|
70
|
-
|
71
|
-
|
72
|
-
|
65
|
+
def subclass_new_from_string(str)
|
66
|
+
@address = check_address(str)
|
67
|
+
end
|
73
68
|
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
69
|
+
def subclass_new_from_binary(data, offset)
|
70
|
+
a, b, c, d = data.unpack("@#{offset} CCCC")
|
71
|
+
@address = IPAddr.new("#{a}.#{b}.#{c}.#{d}")
|
72
|
+
offset + 4
|
73
|
+
end
|
79
74
|
|
75
|
+
def set_type
|
76
|
+
@type = Net::DNS::RR::Types.new("A")
|
77
|
+
end
|
80
78
|
|
81
|
-
|
82
|
-
|
83
|
-
|
79
|
+
def get_inspect
|
80
|
+
value
|
81
|
+
end
|
84
82
|
|
85
|
-
|
86
|
-
|
83
|
+
def check_address(input)
|
84
|
+
address = case input
|
85
|
+
when IPAddr
|
86
|
+
input
|
87
|
+
when Integer # Address in numeric form
|
88
|
+
tmp = [(input >> 24), (input >> 16) & 0xFF, (input >> 8) & 0xFF, input & 0xFF]
|
89
|
+
tmp = tmp.collect(&:to_s).join(".")
|
90
|
+
IPAddr.new(tmp)
|
91
|
+
when String
|
92
|
+
IPAddr.new(input)
|
93
|
+
else
|
94
|
+
raise ArgumentError, "Invalid IP address `#{input}'"
|
87
95
|
end
|
88
96
|
|
89
|
-
|
90
|
-
|
91
|
-
address = case input
|
92
|
-
when IPAddr
|
93
|
-
input
|
94
|
-
when Integer # Address in numeric form
|
95
|
-
tmp = [(input >> 24), (input >> 16) & 0xFF, (input >> 8) & 0xFF, input & 0xFF]
|
96
|
-
tmp = tmp.collect { |x| x.to_s }.join(".")
|
97
|
-
IPAddr.new(tmp)
|
98
|
-
when String
|
99
|
-
IPAddr.new(input)
|
100
|
-
else
|
101
|
-
raise ArgumentError, "Invalid IP address `#{input}'"
|
102
|
-
end
|
103
|
-
|
104
|
-
if !address.ipv4?
|
105
|
-
raise(ArgumentError, "Must specify an IPv4 address")
|
106
|
-
end
|
107
|
-
|
108
|
-
address
|
97
|
+
unless address.ipv4?
|
98
|
+
raise(ArgumentError, "Must specify an IPv4 address")
|
109
99
|
end
|
110
100
|
|
111
|
-
|
112
|
-
|
113
|
-
@rdlength = @address_pack.size
|
114
|
-
end
|
101
|
+
address
|
102
|
+
end
|
115
103
|
|
116
|
-
|
117
|
-
|
118
|
-
|
104
|
+
def build_pack
|
105
|
+
@address_pack = @address.hton
|
106
|
+
@rdlength = @address_pack.size
|
107
|
+
end
|
119
108
|
|
109
|
+
def get_data
|
110
|
+
@address_pack
|
111
|
+
end
|
120
112
|
end
|
121
|
-
|
122
113
|
end
|
123
114
|
end
|
124
115
|
end
|
data/lib/net/dns/rr/aaaa.rb
CHANGED
@@ -1,20 +1,16 @@
|
|
1
1
|
module Net
|
2
2
|
module DNS
|
3
3
|
class RR
|
4
|
-
|
5
4
|
#
|
6
5
|
# = IPv6 Address Record (AAAA)
|
7
6
|
#
|
8
7
|
# Class for DNS IPv6 Address (AAAA) resource records.
|
9
8
|
#
|
10
9
|
class AAAA < RR
|
11
|
-
|
12
10
|
# Gets the current IPv6 address for this record.
|
13
11
|
#
|
14
12
|
# Returns an instance of IPAddr.
|
15
|
-
|
16
|
-
@address
|
17
|
-
end
|
13
|
+
attr_reader :address
|
18
14
|
|
19
15
|
# Assigns a new IPv6 address to this record, which can be in the
|
20
16
|
# form of a <tt>String</tt> or an <tt>IPAddr</tt> object.
|
@@ -39,65 +35,60 @@ module Net
|
|
39
35
|
address.to_s
|
40
36
|
end
|
41
37
|
|
42
|
-
|
43
38
|
private
|
44
39
|
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
end
|
40
|
+
def subclass_new_from_hash(options)
|
41
|
+
if options.key?(:address)
|
42
|
+
@address = check_address(options[:address])
|
43
|
+
else
|
44
|
+
raise ArgumentError, ":address field is mandatory"
|
51
45
|
end
|
46
|
+
end
|
52
47
|
|
53
|
-
|
54
|
-
|
55
|
-
|
48
|
+
def subclass_new_from_string(str)
|
49
|
+
@address = check_address(str)
|
50
|
+
end
|
56
51
|
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
52
|
+
def subclass_new_from_binary(data, offset)
|
53
|
+
tokens = data.unpack("@#{offset} n8")
|
54
|
+
@address = IPAddr.new(format("%x:%x:%x:%x:%x:%x:%x:%x", *tokens))
|
55
|
+
offset + 16
|
56
|
+
end
|
62
57
|
|
58
|
+
def set_type
|
59
|
+
@type = Net::DNS::RR::Types.new("AAAA")
|
60
|
+
end
|
63
61
|
|
64
|
-
|
65
|
-
|
66
|
-
|
62
|
+
def get_inspect
|
63
|
+
value
|
64
|
+
end
|
67
65
|
|
68
|
-
|
69
|
-
|
66
|
+
def check_address(input)
|
67
|
+
address = case input
|
68
|
+
when IPAddr
|
69
|
+
input
|
70
|
+
when String
|
71
|
+
IPAddr.new(input)
|
72
|
+
else
|
73
|
+
raise ArgumentError, "Invalid IP address `#{input}'"
|
70
74
|
end
|
71
75
|
|
72
|
-
|
73
|
-
|
74
|
-
address = case input
|
75
|
-
when IPAddr
|
76
|
-
input
|
77
|
-
when String
|
78
|
-
IPAddr.new(input)
|
79
|
-
else
|
80
|
-
raise ArgumentError, "Invalid IP address `#{input}'"
|
81
|
-
end
|
82
|
-
|
83
|
-
if !address.ipv6?
|
84
|
-
raise(ArgumentError, "Must specify an IPv6 address")
|
85
|
-
end
|
86
|
-
|
87
|
-
address
|
76
|
+
unless address.ipv6?
|
77
|
+
raise(ArgumentError, "Must specify an IPv6 address")
|
88
78
|
end
|
89
79
|
|
90
|
-
|
91
|
-
|
92
|
-
@rdlength = @address_pack.size
|
93
|
-
end
|
80
|
+
address
|
81
|
+
end
|
94
82
|
|
95
|
-
|
96
|
-
|
97
|
-
|
83
|
+
def build_pack
|
84
|
+
@address_pack = @address.hton
|
85
|
+
@rdlength = @address_pack.size
|
86
|
+
end
|
98
87
|
|
88
|
+
def get_data
|
89
|
+
@address_pack
|
90
|
+
end
|
99
91
|
end
|
100
|
-
|
101
92
|
end
|
102
93
|
end
|
103
94
|
end
|
data/lib/net/dns/rr/classes.rb
CHANGED
@@ -1,8 +1,6 @@
|
|
1
1
|
module Net
|
2
2
|
module DNS
|
3
|
-
|
4
3
|
class RR
|
5
|
-
|
6
4
|
#
|
7
5
|
# = Net::DNS::Classes
|
8
6
|
#
|
@@ -10,32 +8,30 @@ module Net
|
|
10
8
|
# class field in a DNS packet.
|
11
9
|
#
|
12
10
|
class Classes
|
13
|
-
|
14
11
|
# Hash with the values of each RR class stored with the
|
15
12
|
# respective id number.
|
16
13
|
CLASSES = {
|
17
|
-
'IN'
|
18
|
-
'CH'
|
19
|
-
'HS'
|
20
|
-
'NONE'
|
21
|
-
'ANY'
|
22
|
-
}
|
14
|
+
'IN' => 1, # RFC 1035
|
15
|
+
'CH' => 3, # RFC 1035
|
16
|
+
'HS' => 4, # RFC 1035
|
17
|
+
'NONE' => 254, # RFC 2136
|
18
|
+
'ANY' => 255, # RFC 1035
|
19
|
+
}.freeze
|
23
20
|
|
24
21
|
# The default value when class is nil in Resource Records
|
25
22
|
@@default = CLASSES["IN"]
|
26
23
|
|
27
|
-
|
28
24
|
# Creates a new object representing an RR class. Performs some
|
29
25
|
# checks on the argument validity too. Il +cls+ is +nil+, the
|
30
26
|
# default value is +ANY+ or the one set with Classes.default=
|
31
27
|
def initialize(cls)
|
32
28
|
case cls
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
29
|
+
when String
|
30
|
+
initialize_from_str(cls)
|
31
|
+
when Integer
|
32
|
+
initialize_from_num(cls)
|
33
|
+
when nil
|
34
|
+
initialize_from_num(@@default)
|
39
35
|
end
|
40
36
|
|
41
37
|
if @str.nil? || @num.nil?
|
@@ -64,7 +60,9 @@ module Net
|
|
64
60
|
@num.to_i
|
65
61
|
end
|
66
62
|
|
67
|
-
|
63
|
+
def self.default
|
64
|
+
@@default
|
65
|
+
end
|
68
66
|
|
69
67
|
# Be able to control the default class to assign when
|
70
68
|
# cls argument is +nil+. Default to +IN+
|
@@ -96,12 +94,12 @@ module Net
|
|
96
94
|
#
|
97
95
|
def self.valid?(cls)
|
98
96
|
case cls
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
97
|
+
when String
|
98
|
+
CLASSES.key?(cls)
|
99
|
+
when Integer
|
100
|
+
CLASSES.invert.key?(cls)
|
101
|
+
else
|
102
|
+
raise ArgumentError, "Wrong cls class: #{cls.class}"
|
105
103
|
end
|
106
104
|
end
|
107
105
|
|
@@ -111,23 +109,22 @@ module Net
|
|
111
109
|
CLASSES.keys.sort.join("|")
|
112
110
|
end
|
113
111
|
|
114
|
-
|
115
|
-
private
|
112
|
+
private
|
116
113
|
|
117
114
|
# Initialize a new instance from a Class name.
|
118
115
|
def initialize_from_str(str)
|
119
116
|
key = str.to_s.upcase
|
120
|
-
@num
|
117
|
+
@num = CLASSES[key]
|
118
|
+
@str = key
|
121
119
|
end
|
122
120
|
|
123
121
|
# Initialize a new instance from the Class value.
|
124
122
|
def initialize_from_num(num)
|
125
123
|
key = num.to_i
|
126
|
-
@num
|
124
|
+
@num = key
|
125
|
+
@str = CLASSES.invert[key]
|
127
126
|
end
|
128
|
-
|
129
127
|
end
|
130
|
-
|
131
128
|
end
|
132
129
|
end
|
133
130
|
end
|
data/lib/net/dns/rr/cname.rb
CHANGED
@@ -1,7 +1,6 @@
|
|
1
1
|
module Net # :nodoc:
|
2
2
|
module DNS
|
3
3
|
class RR
|
4
|
-
|
5
4
|
#
|
6
5
|
# = Canonical Name Record (CNAME)
|
7
6
|
#
|
@@ -12,13 +11,10 @@ module Net # :nodoc:
|
|
12
11
|
# Canonical means expected or real name.
|
13
12
|
#
|
14
13
|
class CNAME < RR
|
15
|
-
|
16
14
|
# Gets the canonical name value.
|
17
15
|
#
|
18
16
|
# Returns a String.
|
19
|
-
|
20
|
-
@cname
|
21
|
-
end
|
17
|
+
attr_reader :cname
|
22
18
|
|
23
19
|
# Gets the standardized value for this record,
|
24
20
|
# represented by the value of <tt>cname</tt>.
|
@@ -28,55 +24,51 @@ module Net # :nodoc:
|
|
28
24
|
cname.to_s
|
29
25
|
end
|
30
26
|
|
31
|
-
|
32
27
|
private
|
33
28
|
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
end
|
40
|
-
end
|
41
|
-
|
42
|
-
def subclass_new_from_string(str)
|
43
|
-
@cname = check_name(str)
|
44
|
-
end
|
45
|
-
|
46
|
-
def subclass_new_from_binary(data, offset)
|
47
|
-
@cname, offset = dn_expand(data, offset)
|
48
|
-
offset
|
29
|
+
def subclass_new_from_hash(options)
|
30
|
+
if options.key?(:cname)
|
31
|
+
@cname = check_name(options[:cname])
|
32
|
+
else
|
33
|
+
raise ArgumentError, ":cname field is mandatory"
|
49
34
|
end
|
35
|
+
end
|
50
36
|
|
37
|
+
def subclass_new_from_string(str)
|
38
|
+
@cname = check_name(str)
|
39
|
+
end
|
51
40
|
|
52
|
-
|
53
|
-
|
54
|
-
|
41
|
+
def subclass_new_from_binary(data, offset)
|
42
|
+
@cname, offset = dn_expand(data, offset)
|
43
|
+
offset
|
44
|
+
end
|
55
45
|
|
56
|
-
|
57
|
-
|
58
|
-
|
46
|
+
def set_type
|
47
|
+
@type = Net::DNS::RR::Types.new("CNAME")
|
48
|
+
end
|
59
49
|
|
50
|
+
def get_inspect
|
51
|
+
value
|
52
|
+
end
|
60
53
|
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
end
|
66
|
-
name
|
54
|
+
def check_name(input)
|
55
|
+
name = input.to_s
|
56
|
+
unless name =~ /(\w\.?)+\s*$/ && name =~ /[a-zA-Z]/
|
57
|
+
raise ArgumentError, "Invalid Canonical Name `#{name}'"
|
67
58
|
end
|
68
59
|
|
69
|
-
|
70
|
-
|
71
|
-
@rdlength = @cname_pack.size
|
72
|
-
end
|
60
|
+
name
|
61
|
+
end
|
73
62
|
|
74
|
-
|
75
|
-
|
76
|
-
|
63
|
+
def build_pack
|
64
|
+
@cname_pack = pack_name(@cname)
|
65
|
+
@rdlength = @cname_pack.size
|
66
|
+
end
|
77
67
|
|
68
|
+
def get_data
|
69
|
+
@cname_pack
|
70
|
+
end
|
78
71
|
end
|
79
|
-
|
80
72
|
end
|
81
73
|
end
|
82
74
|
end
|