redns 0.1.12 → 0.1.13

Sign up to get free protection for your applications and to get access to all the features.
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.1.12
1
+ 0.1.13
@@ -4,6 +4,7 @@ class ReDNS::Connection < EventMachine::Connection
4
4
  # == Constants ============================================================
5
5
 
6
6
  DEFAULT_TIMEOUT = 5
7
+ SEQUENCE_LIMIT = 0x10000
7
8
 
8
9
  # == Properties ===========================================================
9
10
 
@@ -15,6 +16,8 @@ class ReDNS::Connection < EventMachine::Connection
15
16
 
16
17
  # == Class Methods ========================================================
17
18
 
19
+ # Returns a new instance of a reactor-bound resolver. If a block is given,
20
+ # the instance is supplied for customization purposes.
18
21
  def self.instance
19
22
  connection = EventMachine.open_datagram_socket(
20
23
  ReDNS::Support.bind_all_addr,
@@ -32,7 +35,7 @@ class ReDNS::Connection < EventMachine::Connection
32
35
  def post_init
33
36
  # Sequence numbers do not have to be cryptographically secure, but having
34
37
  # a healthy amount of randomness is a good thing.
35
- @sequence = (rand(0x10000) ^ (object_id ^ (Time.now.to_f * 100000).to_i)) % 0x10000
38
+ @sequence = (rand(SEQUENCE_LIMIT) ^ (object_id ^ (Time.now.to_f * SEQUENCE_LIMIT).to_i)) % SEQUENCE_LIMIT
36
39
 
37
40
  # Callback tracking is done by matching response IDs in a lookup table
38
41
  @callback = { }
@@ -97,6 +100,7 @@ class ReDNS::Connection < EventMachine::Connection
97
100
  end
98
101
 
99
102
  @sequence += 1
103
+ @sequence %= SEQUENCE_LIMIT
100
104
  end
101
105
 
102
106
  def unbind
data/lib/redns/message.rb CHANGED
@@ -1,7 +1,7 @@
1
1
  class ReDNS::Message < ReDNS::Fragment
2
2
  # == Constants ============================================================
3
3
 
4
- SECTIONS = [ :questions, :answers, :nameservers, :additional_records ]
4
+ SECTIONS = [ :questions, :answers, :nameservers, :additional_records ].freeze
5
5
 
6
6
  # == Attributes ===========================================================
7
7
 
@@ -28,6 +28,9 @@ class ReDNS::Message < ReDNS::Fragment
28
28
 
29
29
  # == Class Methods ========================================================
30
30
 
31
+ # Constructs a question that asks for more information about a given
32
+ # resource with an optional query type specified. Query type defaults to
33
+ # :ptr for dotted-quad IP addresses, :a otherwise.
31
34
  def self.question(name, qtype = nil)
32
35
  if (!qtype)
33
36
  if (ReDNS::Support.is_ip?(name))
@@ -55,13 +58,17 @@ class ReDNS::Message < ReDNS::Fragment
55
58
  # == Instance Methods =====================================================
56
59
 
57
60
  def increment_id!
58
- self.id += 1
61
+ self.id = (self.id + 1) % 0x10000
59
62
  end
60
63
 
64
+ # Returns true if this is a response type message, false otherwise, as is
65
+ # the case with query messages.
61
66
  def response?
62
67
  !self.query?
63
68
  end
64
69
 
70
+ # Returns a string representation of the message in a format similar to what
71
+ # the dig shell utility produces.
65
72
  def to_s
66
73
  flags = [ ]
67
74
  flags << 'qr' if (response?)
@@ -83,10 +90,13 @@ class ReDNS::Message < ReDNS::Fragment
83
90
  additional_records.collect(&:to_s).join("\n") + "\n"
84
91
  end
85
92
 
93
+ # Returns the length of the encoded DNS request.
86
94
  def length
87
95
  to_dns.length
88
96
  end
89
97
 
98
+ # Returns true if the questions, answers, nameservers and additional records
99
+ # are all empty, false otherwise.
90
100
  def empty?
91
101
  questions.empty? and
92
102
  answers.empty? and
@@ -94,10 +104,13 @@ class ReDNS::Message < ReDNS::Fragment
94
104
  additional_records.empty?
95
105
  end
96
106
 
107
+ # Returns a YAML serialized version of the message.
97
108
  def to_yaml
98
109
  @attributes.to_yaml
99
110
  end
100
111
 
112
+ # Serializes the message into a supplied buffer, or allocates a new one to
113
+ # store it. Returns the buffer used.
101
114
  def serialize(buffer = ReDNS::Buffer.new)
102
115
  buffer.pack(
103
116
  'nnnnnn',
@@ -126,11 +139,17 @@ class ReDNS::Message < ReDNS::Fragment
126
139
  buffer
127
140
  end
128
141
 
142
+ # Extracts a message from the supplied buffer. Will return the message if
143
+ # successful, nil if an error occurred or no suitable data cound be found
144
+ # in the buffer.
129
145
  def deserialize(buffer)
130
146
  return unless (buffer)
131
147
 
132
148
  data = buffer.unpack("nnnnnn")
133
149
 
150
+ # Abandon efforts to decode if insufficient data is available.
151
+ return if (data.length < 6)
152
+
134
153
  self.id = data.shift
135
154
 
136
155
  flags = data.shift
data/lib/redns/name.rb CHANGED
@@ -1,4 +1,8 @@
1
1
  class ReDNS::Name < ReDNS::Fragment
2
+ # == Constants ============================================================
3
+
4
+ POINTER_CHAIN_LIMIT = 64
5
+
2
6
  # == Attributes ===========================================================
3
7
 
4
8
  attribute :name, :default => '.'
@@ -52,6 +56,7 @@ class ReDNS::Name < ReDNS::Fragment
52
56
  self.name = ''
53
57
 
54
58
  return_to_offset = nil
59
+ pointer_count = 0
55
60
 
56
61
  while (c = buffer.unpack('C')[0])
57
62
  if (c & 0xC0 == 0xC0)
@@ -59,11 +64,25 @@ class ReDNS::Name < ReDNS::Fragment
59
64
  # point and read from there, but preserve the position where the
60
65
  # pointer was found to leave the buffer in that final state.
61
66
 
62
- pointer = (c & 0x3F << 8) | buffer.unpack('C')[0]
67
+ if (additional_offset = buffer.unpack('C')[0])
68
+ pointer = (c & 0x3F << 8) | additional_offset
63
69
 
64
- return_to_offset ||= buffer.offset
65
- buffer.rewind
66
- buffer.advance(pointer)
70
+ return_to_offset ||= buffer.offset
71
+ buffer.rewind
72
+ buffer.advance(pointer)
73
+
74
+ pointer_count += 1
75
+
76
+ if (pointer_count > POINTER_CHAIN_LIMIT)
77
+ # Encountered too many pointers, probably a sign of a circular
78
+ # reference or a badly constructed response. Ignore.
79
+ break
80
+ end
81
+ else
82
+ # The buffer may have prematurely run dry, in which case the only
83
+ # option left is to abandon further processing.
84
+ break
85
+ end
67
86
  elsif (c == 0)
68
87
  break
69
88
  else
@@ -24,9 +24,9 @@ class ReDNS::Record::Null < ReDNS::Fragment
24
24
  end
25
25
 
26
26
  def deserialize(buffer)
27
- content_length = buffer.unpack('C')[0]
28
-
29
- self.contents = buffer.read(content_length)
27
+ if (content_length = buffer.unpack('C')[0])
28
+ self.contents = buffer.read(content_length)
29
+ end
30
30
 
31
31
  self
32
32
  end
@@ -71,7 +71,7 @@ class ReDNS::Resource < ReDNS::Fragment
71
71
  when :soa
72
72
  self.rdata = ReDNS::Record::SOA.new(buffer)
73
73
  when :txt, :null
74
- self.rdata = ReDNS::Record::Null.new(buffer.slice(rdata_length))
74
+ self.rdata = (rdata_length and ReDNS::Record::Null.new(buffer.slice(rdata_length)))
75
75
  when :mx
76
76
  self.rdata = ReDNS::Record::MX.new(buffer)
77
77
  else
data/redns.gemspec CHANGED
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{redns}
8
- s.version = "0.1.12"
8
+ s.version = "0.1.13"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["tadman"]
12
- s.date = %q{2011-05-16}
12
+ s.date = %q{2011-06-17}
13
13
  s.description = %q{ReDNS is a pure Ruby DNS library with drivers for reactor-model engines such as EventMachine}
14
14
  s.email = %q{github@tadman.ca}
15
15
  s.extra_rdoc_files = [
@@ -51,7 +51,7 @@ Gem::Specification.new do |s|
51
51
  ]
52
52
  s.homepage = %q{http://github.com/tadman/redns}
53
53
  s.require_paths = ["lib"]
54
- s.rubygems_version = %q{1.6.0}
54
+ s.rubygems_version = %q{1.5.3}
55
55
  s.summary = %q{Ruby Reactor-Ready DNS Library}
56
56
  s.test_files = [
57
57
  "test/helper.rb",
data/test/test_redns.rb CHANGED
@@ -1,4 +1,7 @@
1
1
  require File.expand_path('helper', File.dirname(__FILE__))
2
2
 
3
3
  class TestRedns < Test::Unit::TestCase
4
+ def test_module_loaded
5
+ assert ReDNS
6
+ end
4
7
  end
@@ -58,10 +58,10 @@ class TestReDNSConnection < Test::Unit::TestCase
58
58
  end
59
59
  end
60
60
 
61
- assert_equal %w[ 192.0.32.10 ], address
62
- assert_equal %w[ www.example.com. ], reverse
63
- assert_equal %w[ a.iana-servers.net. b.iana-servers.net. ], nameservers.sort
64
- assert_equal %w[ 74.207.228.18 ], cname
61
+ assert_equal %w[ 192.0.43.10 ], address.collect { |a| a.rdata.to_s }
62
+ assert_equal %w[ www.example.com. ], reverse.collect { |a| a.rdata.to_s }
63
+ assert_equal %w[ a.iana-servers.net. b.iana-servers.net. ], nameservers.collect { |a| a.rdata.to_s }.sort
64
+ assert_equal %w[ 74.207.228.18 ], cname.collect { |a| a.rdata.to_s }
65
65
 
66
66
  end
67
67
 
@@ -86,7 +86,7 @@ class TestReDNSName < Test::Unit::TestCase
86
86
  example_buffer = ReDNS::Buffer.new(
87
87
  [
88
88
  3, ?c, ?o, ?m,
89
- 192, 6,
89
+ 0xC0, 6,
90
90
  3, ?n, ?e, ?t,
91
91
  0,
92
92
  7, ?e, ?x, ?a, ?m, ?p, ?l, ?e,
@@ -105,4 +105,17 @@ class TestReDNSName < Test::Unit::TestCase
105
105
 
106
106
  assert_equal 0, example_buffer.length
107
107
  end
108
+
109
+ def test_circular_pointer
110
+ example_buffer = ReDNS::Buffer.new(
111
+ [
112
+ 3, ?c, ?o, ?m,
113
+ 0xC0, 0
114
+ ].collect(&:chr).join
115
+ )
116
+
117
+ name = ReDNS::Name.new(example_buffer)
118
+
119
+ assert_equal 'com.' * (ReDNS::Name::POINTER_CHAIN_LIMIT + 1), name.to_s
120
+ end
108
121
  end
@@ -25,7 +25,7 @@ class TestReReDNSResolver < Test::Unit::TestCase
25
25
  assert_equal 1, r.size
26
26
 
27
27
  assert_equal :a, r[0].rtype
28
- assert_equal '192.0.32.10', r[0].rdata.to_s
28
+ assert_equal '192.0.43.10', r[0].rdata.to_s
29
29
  end
30
30
 
31
31
  def test_simple_reverse_query
@@ -63,7 +63,7 @@ class TestReReDNSResolver < Test::Unit::TestCase
63
63
  assert_equal 1, r.questions.size
64
64
  assert_equal 1, r.answers.size
65
65
 
66
- assert_equal '192.0.32.10', r.answers[0].rdata.to_s
66
+ assert_equal '192.0.43.10', r.answers[0].rdata.to_s
67
67
  end
68
68
 
69
69
  def test_ns_query
@@ -87,12 +87,12 @@ class TestReReDNSResolver < Test::Unit::TestCase
87
87
 
88
88
  def test_bulk_query
89
89
  addrs = %w[
90
- 192.0.32.1
91
- 192.0.32.2
92
- 192.0.32.3
93
- 192.0.32.4
94
- 192.0.32.5
95
90
  192.0.32.10
91
+ 192.0.32.12
92
+ 192.0.32.13
93
+ 192.0.32.14
94
+ 192.0.32.15
95
+ 192.0.32.16
96
96
  ].collect do |i|
97
97
  ReDNS::Support.addr_to_arpa(i)
98
98
  end
@@ -110,12 +110,12 @@ class TestReReDNSResolver < Test::Unit::TestCase
110
110
  assert rlist[addrs[0]]
111
111
 
112
112
  expected = %w[
113
- 32-1.lax.icann.org.
114
- 32-2.lax.icann.org.
115
- 32-3.lax.icann.org.
116
- 32-4.lax.icann.org.
117
- 32-5.lax.icann.org.
118
113
  www.example.com.
114
+ redirects.iana.org.
115
+ tools.iana.org.
116
+ nomcom.icann.org.
117
+ confirm.icann.org.
118
+ dnscert.com.
119
119
  ]
120
120
 
121
121
  answers = addrs.collect do |a|
@@ -126,13 +126,13 @@ class TestReReDNSResolver < Test::Unit::TestCase
126
126
  end
127
127
 
128
128
  def test_reverse_addresses
129
- addrs = %w[
130
- 192.0.32.1
131
- 192.0.32.2
132
- 192.0.32.3
133
- 192.0.32.4
134
- 192.0.32.5
129
+ addrs = %w[
135
130
  192.0.32.10
131
+ 192.0.32.12
132
+ 192.0.32.13
133
+ 192.0.32.14
134
+ 192.0.32.15
135
+ 192.0.32.16
136
136
  ]
137
137
 
138
138
  res = ReDNS::Resolver.new
@@ -144,12 +144,12 @@ class TestReReDNSResolver < Test::Unit::TestCase
144
144
  assert_equal addrs.length, rlist.length
145
145
 
146
146
  expected = %w[
147
- 32-1.lax.icann.org.
148
- 32-2.lax.icann.org.
149
- 32-3.lax.icann.org.
150
- 32-4.lax.icann.org.
151
- 32-5.lax.icann.org.
152
147
  www.example.com.
148
+ redirects.iana.org.
149
+ tools.iana.org.
150
+ nomcom.icann.org.
151
+ confirm.icann.org.
152
+ dnscert.com.
153
153
  ]
154
154
 
155
155
  answers = addrs.collect do |a|
metadata CHANGED
@@ -2,7 +2,7 @@
2
2
  name: redns
3
3
  version: !ruby/object:Gem::Version
4
4
  prerelease:
5
- version: 0.1.12
5
+ version: 0.1.13
6
6
  platform: ruby
7
7
  authors:
8
8
  - tadman
@@ -10,7 +10,7 @@ autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
12
 
13
- date: 2011-05-16 00:00:00 -04:00
13
+ date: 2011-06-17 00:00:00 -04:00
14
14
  default_executable:
15
15
  dependencies: []
16
16
 
@@ -79,7 +79,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
79
79
  requirements: []
80
80
 
81
81
  rubyforge_project:
82
- rubygems_version: 1.6.0
82
+ rubygems_version: 1.5.3
83
83
  signing_key:
84
84
  specification_version: 3
85
85
  summary: Ruby Reactor-Ready DNS Library