redns 0.1.17 → 0.2.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 +7 -0
- data/.travis.yml +8 -0
- data/Gemfile +8 -0
- data/LICENSE.txt +20 -0
- data/README.md +31 -0
- data/Rakefile +2 -13
- data/VERSION +1 -1
- data/bin/redig +20 -13
- data/lib/redns.rb +32 -32
- data/lib/redns/address.rb +19 -19
- data/lib/redns/connection.rb +16 -16
- data/lib/redns/fragment.rb +5 -5
- data/lib/redns/message.rb +127 -127
- data/lib/redns/name.rb +35 -33
- data/lib/redns/question.rb +27 -27
- data/lib/redns/record/mx.rb +19 -19
- data/lib/redns/record/null.rb +27 -27
- data/lib/redns/record/soa.rb +49 -49
- data/lib/redns/resolver.rb +264 -262
- data/lib/redns/resource.rb +61 -61
- data/lib/redns/support.rb +41 -41
- data/redns.gemspec +26 -15
- data/test/test_redns_connection.rb +18 -6
- data/test/test_redns_fragment.rb +7 -7
- data/test/test_redns_message.rb +40 -40
- data/test/test_redns_name.rb +1 -1
- data/test/test_redns_question.rb +2 -2
- data/test/test_redns_resolver.rb +125 -119
- data/test/test_redns_resource.rb +32 -32
- metadata +43 -13
- data/README.rdoc +0 -17
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: d2bafcebc9a854b66739ac0f38dd909dd56ec4ef
|
4
|
+
data.tar.gz: e3da07761ddd463efaecdbf544d28ef4a8fa7bbd
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 51dc9b6de6d62d44cad19112d858a98ad14cc8457213841665c5526da4d6e5eac7045d9c20f0750d8f3622d412e77d4c0f8ec39f013ee4eb160ebacb33d48d2a
|
7
|
+
data.tar.gz: 617feea176a9adf4f3e7895bc0f46da460850654ccaa598e26aa168dea00acfa262490f9cee88d62af526b747dafbcbd96f67e588dc2e723ccc4efbc6d476ace
|
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2005-2016 Scott Tadman
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
# redns
|
2
|
+
|
3
|
+
Reactor-Ready DNS Library
|
4
|
+
|
5
|
+
This library includes native Ruby encoder/decoder classes for typical
|
6
|
+
DNS records that are specified in RFC1035.
|
7
|
+
|
8
|
+
In addition, RFC2671 extension mechanisms are also supported.
|
9
|
+
|
10
|
+
## Installation
|
11
|
+
|
12
|
+
To install as a dependency, add to your `Gemfile`:
|
13
|
+
|
14
|
+
gem 'redns'
|
15
|
+
|
16
|
+
Then `bundle install` should pick up any dependencies.
|
17
|
+
|
18
|
+
## Usage
|
19
|
+
|
20
|
+
|
21
|
+
|
22
|
+
## References
|
23
|
+
|
24
|
+
* [RFC1035](http://www.faqs.org/rfcs/rfc1035.html) - Domain names - implementation and specification
|
25
|
+
* [RFC2671](http://www.faqs.org/rfcs/rfc2671.html) - Extension Mechanisms for DNS (EDNS0)
|
26
|
+
|
27
|
+
## Copyright
|
28
|
+
|
29
|
+
(C) 2005-2017 Scott Tadman
|
30
|
+
|
31
|
+
See [LICENSE](LICENSE.txt) for more details.
|
data/Rakefile
CHANGED
@@ -19,22 +19,11 @@ rescue LoadError
|
|
19
19
|
end
|
20
20
|
|
21
21
|
require 'rake/testtask'
|
22
|
+
|
22
23
|
Rake::TestTask.new(:test) do |test|
|
23
24
|
test.libs << 'lib' << 'test'
|
24
25
|
test.pattern = 'test/**/test_*.rb'
|
25
26
|
test.verbose = true
|
26
27
|
end
|
27
28
|
|
28
|
-
task :
|
29
|
-
|
30
|
-
task :default => :test
|
31
|
-
|
32
|
-
require 'rake/rdoctask'
|
33
|
-
Rake::RDocTask.new do |rdoc|
|
34
|
-
version = File.exist?('VERSION') ? File.read('VERSION') : ""
|
35
|
-
|
36
|
-
rdoc.rdoc_dir = 'rdoc'
|
37
|
-
rdoc.title = "redns #{version}"
|
38
|
-
rdoc.rdoc_files.include('README*')
|
39
|
-
rdoc.rdoc_files.include('lib/**/*.rb')
|
40
|
-
end
|
29
|
+
task default: :test
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.2.0
|
data/bin/redig
CHANGED
@@ -4,12 +4,13 @@ $LOAD_PATH << File.expand_path(File.join('..','lib'), File.dirname(__FILE__))
|
|
4
4
|
|
5
5
|
require 'optparse'
|
6
6
|
|
7
|
+
require 'eventmachine'
|
7
8
|
require 'redns'
|
8
9
|
|
9
10
|
# == Main ===================================================================
|
10
11
|
|
11
12
|
options = {
|
12
|
-
:
|
13
|
+
query_type: :any,
|
13
14
|
}
|
14
15
|
|
15
16
|
op = OptionParser.new do |op|
|
@@ -30,20 +31,26 @@ queries = op.parse(*ARGV).select do |query|
|
|
30
31
|
end
|
31
32
|
end
|
32
33
|
|
33
|
-
|
34
|
-
|
35
|
-
|
34
|
+
EventMachine.run do
|
35
|
+
resolver = ReDNS::Connection.instance do |c|
|
36
|
+
if (options[:nameservers])
|
37
|
+
c.nameservers = options[:nameservers]
|
38
|
+
end
|
39
|
+
|
40
|
+
c.timeout = 2
|
36
41
|
end
|
37
|
-
end
|
38
42
|
|
39
|
-
queries.each do |query|
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
43
|
+
queries.each do |query|
|
44
|
+
resolver.resolve(query, options[:query_type]) do |results|
|
45
|
+
if (results)
|
46
|
+
results.each do |result|
|
47
|
+
puts result.to_s
|
48
|
+
end
|
49
|
+
else
|
50
|
+
puts "No results"
|
51
|
+
end
|
52
|
+
|
53
|
+
EventMachine.stop_event_loop
|
45
54
|
end
|
46
|
-
else
|
47
|
-
puts "No results"
|
48
55
|
end
|
49
56
|
end
|
data/lib/redns.rb
CHANGED
@@ -4,26 +4,26 @@ module ReDNS
|
|
4
4
|
# RFC1035 Resource Record Type Constants
|
5
5
|
|
6
6
|
RR_TYPE = {
|
7
|
-
:
|
8
|
-
:
|
9
|
-
:
|
10
|
-
:
|
11
|
-
:
|
12
|
-
:
|
13
|
-
:
|
14
|
-
:
|
15
|
-
:
|
16
|
-
:
|
17
|
-
:
|
18
|
-
:
|
19
|
-
:
|
20
|
-
:
|
21
|
-
:
|
22
|
-
:
|
23
|
-
:
|
24
|
-
:
|
25
|
-
:
|
26
|
-
:
|
7
|
+
a: 1,
|
8
|
+
ns: 2,
|
9
|
+
md: 3,
|
10
|
+
mf: 4,
|
11
|
+
cname: 5,
|
12
|
+
soa: 6,
|
13
|
+
mb: 7,
|
14
|
+
mg: 8,
|
15
|
+
mr: 9,
|
16
|
+
null: 10,
|
17
|
+
wks: 11,
|
18
|
+
ptr: 12,
|
19
|
+
hinfo: 13,
|
20
|
+
minfo: 14,
|
21
|
+
mx: 15,
|
22
|
+
txt: 16,
|
23
|
+
axfr: 252,
|
24
|
+
mailb: 253,
|
25
|
+
maila: 254,
|
26
|
+
any: 255
|
27
27
|
}.freeze
|
28
28
|
|
29
29
|
RR_TYPE_LABEL = RR_TYPE.invert.freeze
|
@@ -34,28 +34,28 @@ module ReDNS
|
|
34
34
|
# context. This library is entirely IN(internet)-bound.
|
35
35
|
|
36
36
|
RR_CLASS = {
|
37
|
-
:
|
37
|
+
in: 1
|
38
38
|
}.freeze
|
39
39
|
|
40
40
|
RR_CLASS_LABEL = RR_CLASS.invert.freeze
|
41
41
|
|
42
42
|
OPCODE = {
|
43
|
-
:
|
44
|
-
:
|
45
|
-
:
|
46
|
-
:
|
43
|
+
query: 0,
|
44
|
+
iquery: 1,
|
45
|
+
status: 2,
|
46
|
+
unknown: 15
|
47
47
|
}.freeze
|
48
48
|
|
49
49
|
OPCODE_LABEL = OPCODE.invert.freeze
|
50
50
|
|
51
51
|
RCODE = {
|
52
|
-
:
|
53
|
-
:
|
54
|
-
:
|
55
|
-
:
|
56
|
-
:
|
57
|
-
:
|
58
|
-
:
|
52
|
+
noerror: 0,
|
53
|
+
format_error: 1,
|
54
|
+
server_failure: 2,
|
55
|
+
name_error: 3,
|
56
|
+
not_implemented: 4,
|
57
|
+
refused: 5,
|
58
|
+
unknown: 15
|
59
59
|
}.freeze
|
60
60
|
|
61
61
|
RCODE_LABEL = RCODE.invert.freeze
|
data/lib/redns/address.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
class ReDNS::Address < ReDNS::Fragment
|
2
2
|
# == Attributes ===========================================================
|
3
3
|
|
4
|
-
attribute :address, :
|
4
|
+
attribute :address, default: '0.0.0.0'
|
5
5
|
|
6
6
|
# == Class Methods ========================================================
|
7
7
|
|
@@ -14,7 +14,7 @@ class ReDNS::Address < ReDNS::Fragment
|
|
14
14
|
# method, not intercepted and treated as an actual String
|
15
15
|
super(contents)
|
16
16
|
when String
|
17
|
-
super(:
|
17
|
+
super(address: contents)
|
18
18
|
else
|
19
19
|
super(contents)
|
20
20
|
end
|
@@ -24,21 +24,21 @@ class ReDNS::Address < ReDNS::Fragment
|
|
24
24
|
self.address == '0.0.0.0'
|
25
25
|
end
|
26
26
|
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
27
|
+
def to_s
|
28
|
+
self.address
|
29
|
+
end
|
30
|
+
|
31
|
+
def to_a
|
32
|
+
[ to_s ]
|
33
|
+
end
|
34
|
+
|
35
|
+
def serialize(buffer = ReDNS::Buffer.new)
|
36
|
+
buffer.append(inet_aton(self.address))
|
37
|
+
buffer
|
38
|
+
end
|
39
|
+
|
40
|
+
def deserialize(buffer)
|
41
|
+
self.address = inet_ntoa(buffer).encode('UTF-8')
|
42
|
+
self
|
43
|
+
end
|
44
44
|
end
|
data/lib/redns/connection.rb
CHANGED
@@ -3,13 +3,13 @@ require 'socket'
|
|
3
3
|
class ReDNS::Connection < EventMachine::Connection
|
4
4
|
# == Constants ============================================================
|
5
5
|
|
6
|
-
|
7
|
-
|
6
|
+
TIMEOUT_DEFAULT = 5.0
|
7
|
+
ATTEMPTS_DEFAULT = 5
|
8
8
|
SEQUENCE_LIMIT = 0x10000
|
9
9
|
|
10
10
|
# == Properties ===========================================================
|
11
11
|
|
12
|
-
|
12
|
+
attr_reader :timeout, :attempts
|
13
13
|
|
14
14
|
# == Extensions ===========================================================
|
15
15
|
|
@@ -37,14 +37,14 @@ class ReDNS::Connection < EventMachine::Connection
|
|
37
37
|
# If the supplied value is zero or nil, will revert to the default.
|
38
38
|
def timeout=(value)
|
39
39
|
@timeout = value.to_i
|
40
|
-
@timeout =
|
40
|
+
@timeout = TIMEOUT_DEFAULT if (@timeout == 0)
|
41
41
|
end
|
42
42
|
|
43
43
|
# Sets the current retry attempts parameter to the supplied value.
|
44
44
|
# If the supplied value is zero or nil, will revert to the default.
|
45
45
|
def attempts=(value)
|
46
46
|
@attempts = value.to_i
|
47
|
-
@attempts =
|
47
|
+
@attempts = ATTEMPTS_DEFAULT if (@attempts == 0)
|
48
48
|
end
|
49
49
|
|
50
50
|
# Returns the configured list of nameservers as an Array. If not configured
|
@@ -62,7 +62,7 @@ class ReDNS::Connection < EventMachine::Connection
|
|
62
62
|
@nameservers = nil if (list.empty?)
|
63
63
|
end
|
64
64
|
|
65
|
-
# Picks a random nameserver from the configured list
|
65
|
+
# Picks a random nameserver from the configured list.
|
66
66
|
def random_nameserver
|
67
67
|
nameservers[rand(nameservers.length)]
|
68
68
|
end
|
@@ -93,13 +93,13 @@ class ReDNS::Connection < EventMachine::Connection
|
|
93
93
|
|
94
94
|
if (result > 0)
|
95
95
|
@callback[@sequence] = {
|
96
|
-
:
|
97
|
-
:
|
98
|
-
:
|
99
|
-
:
|
100
|
-
:
|
101
|
-
:
|
102
|
-
:
|
96
|
+
serialized_message: serialized_message,
|
97
|
+
type: type,
|
98
|
+
filter_by_type: (type == :any || !filter) ? false : type,
|
99
|
+
nameserver: target_nameserver,
|
100
|
+
attempts: self.attempts - 1,
|
101
|
+
callback: callback,
|
102
|
+
at: Time.now
|
103
103
|
}
|
104
104
|
else
|
105
105
|
callback.call(nil)
|
@@ -118,8 +118,8 @@ class ReDNS::Connection < EventMachine::Connection
|
|
118
118
|
# Callback tracking is done by matching response IDs in a lookup table
|
119
119
|
@callback = { }
|
120
120
|
|
121
|
-
@timeout ||=
|
122
|
-
@attempts ||=
|
121
|
+
@timeout ||= TIMEOUT_DEFAULT
|
122
|
+
@attempts ||= ATTEMPTS_DEFAULT
|
123
123
|
|
124
124
|
EventMachine.add_periodic_timer(1) do
|
125
125
|
check_for_timeouts!
|
@@ -155,7 +155,7 @@ protected
|
|
155
155
|
# Checks all pending queries for timeouts and triggers callbacks or retries
|
156
156
|
# if necessary.
|
157
157
|
def check_for_timeouts!
|
158
|
-
timeout_at = Time.now - (@timeout ||
|
158
|
+
timeout_at = Time.now - (@timeout || TIMEOUT_DEFAULT)
|
159
159
|
|
160
160
|
@callback.keys.each do |k|
|
161
161
|
if (params = @callback[k])
|
data/lib/redns/fragment.rb
CHANGED
@@ -76,10 +76,10 @@ class ReDNS::Fragment
|
|
76
76
|
|
77
77
|
# == Instance Methods =====================================================
|
78
78
|
|
79
|
-
|
80
|
-
|
79
|
+
def initialize(contents = nil)
|
80
|
+
@attributes = { }
|
81
81
|
|
82
|
-
|
82
|
+
case (contents)
|
83
83
|
when Hash
|
84
84
|
assign(contents)
|
85
85
|
when ReDNS::Buffer
|
@@ -94,8 +94,8 @@ class ReDNS::Fragment
|
|
94
94
|
end
|
95
95
|
|
96
96
|
yield(self) if (block_given?)
|
97
|
-
|
98
|
-
|
97
|
+
end
|
98
|
+
|
99
99
|
protected
|
100
100
|
def assign(attributes)
|
101
101
|
attributes.each do |k, v|
|
data/lib/redns/message.rb
CHANGED
@@ -5,26 +5,26 @@ class ReDNS::Message < ReDNS::Fragment
|
|
5
5
|
|
6
6
|
# == Attributes ===========================================================
|
7
7
|
|
8
|
-
|
8
|
+
attribute :random_id, default: lambda { rand(0x10000) }
|
9
9
|
|
10
|
-
attribute :id, :
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
10
|
+
attribute :id, convert: lambda { |v| v.to_i % 0x10000 }, default: 1
|
11
|
+
attribute :query, boolean: true, default: true
|
12
|
+
attribute :opcode, default: :query
|
13
|
+
attribute :authorative, boolean: true, default: false
|
14
|
+
attribute :truncated, boolean: true, default: false
|
15
|
+
attribute :recursion_desired, boolean: true, default: true
|
16
|
+
attribute :recursion_available, boolean: true, default: false
|
17
|
+
attribute :response_code, default: :noerror
|
18
|
+
|
19
|
+
attribute :questions_count, convert: :to_i, default: 0
|
20
|
+
attribute :answers_count, convert: :to_i, default: 0
|
21
|
+
attribute :nameservers_count, convert: :to_i, default: 0
|
22
|
+
attribute :additional_records_count, convert: :to_i, default: 0
|
23
|
+
|
24
|
+
attribute :questions, default: lambda { [ ] }
|
25
|
+
attribute :answers, default: lambda { [ ] }
|
26
|
+
attribute :nameservers, default: lambda { [ ] }
|
27
|
+
attribute :additional_records, default: lambda { [ ] }
|
28
28
|
|
29
29
|
# == Class Methods ========================================================
|
30
30
|
|
@@ -42,10 +42,10 @@ class ReDNS::Message < ReDNS::Fragment
|
|
42
42
|
end
|
43
43
|
|
44
44
|
message = new(
|
45
|
-
:
|
45
|
+
questions: [
|
46
46
|
ReDNS::Question.new(
|
47
|
-
:
|
48
|
-
:
|
47
|
+
name: name,
|
48
|
+
qtype: qtype
|
49
49
|
)
|
50
50
|
]
|
51
51
|
)
|
@@ -57,78 +57,78 @@ class ReDNS::Message < ReDNS::Fragment
|
|
57
57
|
|
58
58
|
# == Instance Methods =====================================================
|
59
59
|
|
60
|
-
|
61
|
-
|
62
|
-
|
60
|
+
def increment_id!
|
61
|
+
self.id = (self.id + 1) % 0x10000
|
62
|
+
end
|
63
63
|
|
64
64
|
# Returns true if this is a response type message, false otherwise, as is
|
65
65
|
# the case with query messages.
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
66
|
+
def response?
|
67
|
+
!self.query?
|
68
|
+
end
|
69
|
+
|
70
|
+
# Returns a string representation of the message in a format similar to what
|
71
|
+
# the dig shell utility produces.
|
72
|
+
def to_s
|
73
|
+
flags = [ ]
|
74
|
+
flags << 'qr' if (response?)
|
75
|
+
flags << 'aa' if (authorative?)
|
76
|
+
flags << 'tc' if (truncated?)
|
77
|
+
flags << 'rd' if (recursion_desired?)
|
78
|
+
flags << 'ra' if (recursion_available?)
|
79
|
+
|
80
|
+
";; HEADER:\n;; opcode: #{opcode.to_s.upcase} status: #{response_code.to_s.upcase} id: #{id} \n" +
|
81
|
+
";; flags: #{flags.join(' ')}; QUERY: #{questions.length}, ANSWER: #{answers.length}, AUTHORITY: #{nameservers.length}, ADDITIONAL: #{additional_records.length}" +
|
82
|
+
"\n" +
|
83
|
+
";; QUESTION SECTION:\n" +
|
84
|
+
questions.collect(&:to_s).join("\n") + "\n" +
|
85
|
+
";; ANSWER SECTION:\n" +
|
86
|
+
answers.collect(&:to_s).join("\n") + "\n" +
|
87
|
+
";; NAMESERVER SECTION:\n" +
|
88
|
+
nameservers.collect(&:to_s).join("\n") + "\n" +
|
89
|
+
";; ADDITIONAL SECTION:\n" +
|
90
|
+
additional_records.collect(&:to_s).join("\n") + "\n"
|
91
|
+
end
|
92
|
+
|
93
|
+
# Returns the length of the encoded DNS request.
|
94
|
+
def length
|
95
|
+
to_dns.length
|
96
|
+
end
|
97
|
+
|
98
|
+
# Returns true if the questions, answers, nameservers and additional records
|
99
|
+
# are all empty, false otherwise.
|
100
|
+
def empty?
|
101
|
+
questions.empty? and
|
102
|
+
answers.empty? and
|
103
|
+
nameservers.empty? and
|
104
|
+
additional_records.empty?
|
105
|
+
end
|
106
|
+
|
107
|
+
# Returns a YAML serialized version of the message.
|
108
|
+
def to_yaml
|
109
|
+
@attributes.to_yaml
|
110
|
+
end
|
111
111
|
|
112
112
|
# Serializes the message into a supplied buffer, or allocates a new one to
|
113
113
|
# store it. Returns the buffer used.
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
114
|
+
def serialize(buffer = ReDNS::Buffer.new)
|
115
|
+
buffer.pack(
|
116
|
+
'nnnnnn',
|
117
|
+
self.id,
|
118
|
+
(
|
119
|
+
(self.query? ? 0 : 0x8000) |
|
120
|
+
(ReDNS::OPCODE[self.opcode] || ReDNS::OPCODE[:unknown]) << 12 |
|
121
|
+
(self.authorative? ? 0x0400 : 0) |
|
122
|
+
(self.truncated? ? 0x0200 : 0) |
|
123
|
+
(self.recursion_desired? ? 0x0100 : 0) |
|
124
|
+
(self.recursion_available? ? 0x0080 : 0) |
|
125
|
+
(ReDNS::RCODE[self.response_code] || ReDNS::RCODE[:noerror])
|
126
|
+
),
|
127
|
+
self.questions.length,
|
128
|
+
self.answers.length,
|
129
|
+
self.nameservers.length,
|
130
|
+
self.additional_records.length
|
131
|
+
)
|
132
132
|
|
133
133
|
[ :questions, :answers, :nameservers, :additional_records ].each do |section|
|
134
134
|
@attributes[section] and @attributes[section].each do |part|
|
@@ -137,50 +137,50 @@ class ReDNS::Message < ReDNS::Fragment
|
|
137
137
|
end
|
138
138
|
|
139
139
|
buffer
|
140
|
-
|
140
|
+
end
|
141
141
|
|
142
142
|
# Extracts a message from the supplied buffer. Will return the message if
|
143
143
|
# successful, nil if an error occurred or no suitable data cound be found
|
144
144
|
# in the buffer.
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
145
|
+
def deserialize(buffer)
|
146
|
+
return unless (buffer)
|
147
|
+
|
148
|
+
data = buffer.unpack("nnnnnn")
|
149
|
+
|
150
|
+
# Abandon efforts to decode if insufficient data is available.
|
151
|
+
return if (data.length < 6)
|
152
|
+
|
153
|
+
self.id = data.shift
|
154
154
|
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
155
|
+
flags = data.shift
|
156
|
+
self.query = (flags & 0x8000 == 0)
|
157
|
+
self.opcode = ReDNS::OPCODE_LABEL[(flags & 0x7800) >> 12]
|
158
|
+
self.authorative = (flags & 0x0400 != 0)
|
159
|
+
self.truncated = (flags & 0x0200 != 0)
|
160
|
+
self.recursion_desired = (flags & 0x0100 != 0)
|
161
|
+
self.recursion_available = (flags & 0x0080 != 0)
|
162
|
+
self.response_code = ReDNS::RCODE_LABEL[flags & 0x000F]
|
163
|
+
|
164
|
+
SECTIONS.each do |section|
|
165
|
+
@attributes[:"#{section}_count"] = data.shift
|
166
|
+
end
|
167
|
+
|
168
|
+
SECTIONS.each do |section|
|
169
|
+
collection = @attributes[section] = [ ]
|
170
|
+
|
171
|
+
decode_class =
|
172
|
+
case (section)
|
173
|
+
when :questions
|
174
|
+
ReDNS::Question
|
175
|
+
else
|
176
|
+
ReDNS::Resource
|
177
177
|
end
|
178
178
|
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
179
|
+
@attributes[:"#{section}_count"].times do
|
180
|
+
collection << decode_class.new(buffer)
|
181
|
+
end
|
182
|
+
end
|
183
|
+
|
184
|
+
self
|
185
|
+
end
|
186
186
|
end
|