dnsruby 1.70.0 → 1.74.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.
Files changed (52) hide show
  1. checksums.yaml +4 -4
  2. data/.github/FUNDING.yml +3 -0
  3. data/.github/dependabot.yml +11 -0
  4. data/.github/workflows/ci.yml +10 -7
  5. data/RELEASE_NOTES.md +50 -0
  6. data/cache_delay.rb +20 -0
  7. data/demo/rubydig.rb +2 -0
  8. data/dnsruby.gemspec +10 -8
  9. data/fd.ruby +33 -0
  10. data/lib/dnsruby/bit_mapping.rb +2 -2
  11. data/lib/dnsruby/cache.rb +0 -2
  12. data/lib/dnsruby/code_mappers.rb +3 -2
  13. data/lib/dnsruby/config.rb +2 -5
  14. data/lib/dnsruby/hosts.rb +0 -7
  15. data/lib/dnsruby/ipv6.rb +5 -5
  16. data/lib/dnsruby/message/encoder.rb +1 -1
  17. data/lib/dnsruby/message/message.rb +2 -2
  18. data/lib/dnsruby/packet_sender.rb +19 -4
  19. data/lib/dnsruby/recursor.rb +7 -6
  20. data/lib/dnsruby/resolver.rb +40 -17
  21. data/lib/dnsruby/resource/CAA.rb +5 -2
  22. data/lib/dnsruby/resource/DNSKEY.rb +15 -8
  23. data/lib/dnsruby/resource/GPOS.rb +1 -1
  24. data/lib/dnsruby/resource/IN.rb +2 -2
  25. data/lib/dnsruby/resource/NSEC.rb +2 -2
  26. data/lib/dnsruby/resource/NXT.rb +1 -1
  27. data/lib/dnsruby/resource/OPT.rb +2 -3
  28. data/lib/dnsruby/resource/TXT.rb +1 -1
  29. data/lib/dnsruby/select_thread.rb +43 -27
  30. data/lib/dnsruby/single_verifier.rb +1 -1
  31. data/lib/dnsruby/version.rb +1 -1
  32. data/test/spec_helper.rb +22 -3
  33. data/test/tc_caa.rb +13 -0
  34. data/test/tc_dns.rb +13 -13
  35. data/test/tc_ecdsa.rb +27 -0
  36. data/test/tc_escapedchars.rb +8 -9
  37. data/test/tc_gpos.rb +1 -1
  38. data/test/tc_hs.rb +0 -5
  39. data/test/tc_message.rb +2 -2
  40. data/test/tc_name.rb +2 -2
  41. data/test/tc_nxt.rb +0 -1
  42. data/test/tc_recur.rb +4 -7
  43. data/test/tc_res_config.rb +29 -0
  44. data/test/tc_resolv.rb +11 -4
  45. data/test/tc_resolver.rb +93 -3
  46. data/test/tc_rr-unknown.rb +1 -1
  47. data/test/tc_rr.rb +4 -4
  48. data/test/tc_single_resolver.rb +9 -17
  49. data/test/tc_tcp_pipelining.rb +3 -3
  50. data/test/tc_tkey.rb +1 -7
  51. data/test/tc_update.rb +0 -1
  52. metadata +60 -9
@@ -152,7 +152,7 @@ module Dnsruby
152
152
  end
153
153
 
154
154
  def self.encode_types(nsec)
155
- output = ''
155
+ output = +''
156
156
  # types represents all 65536 possible RR types.
157
157
  # Split up types into sets of 256 different types.
158
158
  type_codes = []
@@ -171,7 +171,7 @@ module Dnsruby
171
171
 
172
172
  unless types_to_go.empty?
173
173
  # Then create the bitmap for them
174
- bitmap = ''
174
+ bitmap = +''
175
175
  # keep on adding them until there's none left
176
176
  pos = 0
177
177
  bitmap_pos = 0
@@ -95,7 +95,7 @@ class NXT < RR
95
95
  next_domain = Name.create(next_domain) if next_domain.is_a?(String)
96
96
  types = TypeBitmap.from_type_codes(types) if types.is_a?(Array)
97
97
 
98
- binary_string = ''.force_encoding('ASCII-8BIT')
98
+ binary_string = ''.b
99
99
  binary_string << next_domain.canonical
100
100
  binary_string << BitMapping.reverse_binary_string_bits(types.to_binary_string)
101
101
  binary_string
@@ -227,13 +227,12 @@ module Dnsruby
227
227
  if @options
228
228
  @options.each do |opt|
229
229
  if opt.code == EDNS_SUBNET_OPTION
230
- ret = ret + "CLIENT-SUBNET: #{get_client_subnet(opt)}"
230
+ ret = ret + "CLIENT-SUBNET: #{get_client_subnet(opt)}\n"
231
231
  else
232
- ret = ret + " " + opt.to_s
232
+ ret = ret + "OPT=#{opt.code}: #{opt.data}\n"
233
233
  end
234
234
  end
235
235
  end
236
- ret = ret + "\n"
237
236
  return ret
238
237
  end
239
238
 
@@ -63,7 +63,7 @@ module Dnsruby
63
63
  unquoted = false
64
64
  seen_strings = false
65
65
  pos = 0
66
- input.sub!(/^\s*\(\s*/, "")
66
+ input = input.sub(/^\s*\(\s*/, "")
67
67
  input.sub!(/\s*\)\s*$/, "")
68
68
  input.each_char {|c|
69
69
  if (((c == "'") || (c == '"')) && (!in_escaped) && (!unquoted))
@@ -138,6 +138,10 @@ module Dnsruby
138
138
  @@sockets << query_settings.socket
139
139
  @@socket_is_persistent[query_settings.socket] = query_settings.is_persistent_socket
140
140
  }
141
+ wake_up_select_thread
142
+ end
143
+
144
+ def wake_up_select_thread
141
145
  begin
142
146
  @@wakeup_sockets[0].send("wakeup!", 0)
143
147
  rescue Exception
@@ -224,17 +228,20 @@ module Dnsruby
224
228
  if (unused_loop_count > 10 && @@query_hash.empty? && @@observers.empty?)
225
229
  Dnsruby.log.debug("Try stop select loop")
226
230
 
231
+ # We leave the @@wakeup_sockets here, but remove everything else
227
232
  non_persistent_sockets = @@sockets.select { |s| ! @@socket_is_persistent[s] }
228
233
  non_persistent_sockets.each do |socket|
229
- socket.close rescue nil
230
- @@sockets.delete(socket)
234
+ if socket != @@wakeup_sockets[1]
235
+ socket.close rescue nil
236
+ @@sockets.delete(socket)
237
+ end
231
238
  end
232
239
 
233
- Dnsruby.log.debug("Deleted #{non_persistent_sockets.size} non-persistent sockets," +
234
- " #{@@sockets.count} persistent sockets remain.")
240
+ Dnsruby.log.debug("Deleted #{non_persistent_sockets.size - 1} non-persistent sockets," +
241
+ " #{@@sockets.count - 1} persistent sockets remain.")
235
242
  @@socket_hash.clear
236
243
 
237
- if @@sockets.empty?
244
+ if @@sockets.size == 1
238
245
  Dnsruby.log.debug("Stopping select loop")
239
246
  return
240
247
  end
@@ -247,10 +254,11 @@ module Dnsruby
247
254
  # Removes closed sockets from @@sockets, and returns an array containing 1
248
255
  # exception for each closed socket contained in @@socket_hash.
249
256
  def clean_up_closed_sockets
257
+ exceptions = []
250
258
  @@mutex.synchronize do
251
259
  closed_sockets_in_hash = @@sockets.select(&:closed?).select { |s| @@socket_hash[s] }
252
260
  @@sockets.delete_if { | socket | socket.closed? }
253
- closed_sockets_in_hash.each_with_object([]) do |socket, exceptions|
261
+ closed_sockets_in_hash.each_with_object([]) do |socket, exception|
254
262
  @@socket_hash[socket].each do | client_id |
255
263
  exceptions << [SocketEofResolvError.new("TCP socket closed before all answers received"), socket, client_id]
256
264
  end
@@ -368,21 +376,28 @@ module Dnsruby
368
376
  end
369
377
 
370
378
  def remove_id(id)
371
-
372
379
  @@mutex.synchronize do
373
- socket = @@query_hash[id].socket
374
- @@timeouts.delete(id)
375
- @@query_hash.delete(id)
376
- @@socket_hash[socket].delete(id)
377
-
378
- decrement_remaining_queries(socket) if persistent?(socket)
379
-
380
- if !persistent?(socket) || max_attained?(socket)
381
- @@sockets.delete(socket)
382
- @@socket_hash.delete(socket)
383
- Dnsruby.log.debug("Closing socket #{socket}")
384
- socket.close rescue nil
385
- end
380
+ remove_id_from_mutex_synchronized_block(id)
381
+ end
382
+ end
383
+
384
+ # THIS MUST BE CALLED FROM INSIDE A @@mutex SYNCHRONISED BLOCK!
385
+ def remove_id_from_mutex_synchronized_block(id)
386
+ socket = @@query_hash[id].socket
387
+ @@timeouts.delete(id)
388
+ @@query_hash.delete(id)
389
+ @@socket_hash[socket].delete(id)
390
+
391
+ decrement_remaining_queries(socket) if persistent?(socket)
392
+
393
+ if !persistent?(socket) || max_attained?(socket)
394
+ @@sockets.delete(socket)
395
+ @@socket_hash.delete(socket)
396
+ @@socket_remaining_queries.delete(socket)
397
+ @@socket_is_persistent.delete(socket)
398
+ @@tcp_buffers.delete(socket)
399
+ Dnsruby.log.debug("Closing socket #{socket}")
400
+ socket.close rescue nil
386
401
  end
387
402
  end
388
403
 
@@ -414,12 +429,12 @@ module Dnsruby
414
429
  # Keep buffer for all TCP sockets, and return
415
430
  # to select after reading available data. Once all data has been received,
416
431
  # then process message.
417
- buf=""
432
+ buf = +""
418
433
  expected_length = 0
419
434
  @@mutex.synchronize {
420
435
  buf, expected_length = @@tcp_buffers[socket]
421
436
  if (!buf)
422
- buf = ""
437
+ buf = +""
423
438
  expected_length = 2
424
439
  @@tcp_buffers[socket]=[buf, expected_length]
425
440
  end
@@ -443,7 +458,7 @@ module Dnsruby
443
458
 
444
459
  return false
445
460
  end
446
- buf << input
461
+ buf << input if input
447
462
  rescue
448
463
  # Oh well - better luck next time!
449
464
  return false
@@ -455,7 +470,7 @@ module Dnsruby
455
470
  # We just read the data_length field. Now we need to start reading that many bytes.
456
471
  @@mutex.synchronize {
457
472
  answersize = buf.unpack('n')[0]
458
- @@tcp_buffers[socket] = ["", answersize]
473
+ @@tcp_buffers[socket] = [+"", answersize]
459
474
  }
460
475
  return tcp_read(socket)
461
476
  else
@@ -546,12 +561,10 @@ module Dnsruby
546
561
  query_header_id = @@query_hash[id].query.header.id
547
562
  if (query_header_id == e.partial_message.header.id)
548
563
  # process the response
549
- client_queue = nil
550
- res = nil
551
- query=nil
552
564
  client_queue = @@query_hash[id].client_queue
553
565
  res = @@query_hash[id].single_resolver
554
566
  query = @@query_hash[id].query
567
+ remove_id_from_mutex_synchronized_block(id)
555
568
 
556
569
  # NOW RESEND OVER TCP!
557
570
  Thread.new {
@@ -641,6 +654,7 @@ module Dnsruby
641
654
  do_select
642
655
  }
643
656
  end
657
+ wake_up_select_thread
644
658
  end
645
659
 
646
660
  def push_response_to_select(client_id, client_queue, msg, query, res)
@@ -661,6 +675,7 @@ module Dnsruby
661
675
  do_select
662
676
  }
663
677
  end
678
+ wake_up_select_thread
664
679
  end
665
680
 
666
681
  def push_validation_response_to_select(client_id, client_queue, msg, err, query, res)
@@ -677,6 +692,7 @@ module Dnsruby
677
692
  do_select
678
693
  }
679
694
  end
695
+ wake_up_select_thread
680
696
  end
681
697
 
682
698
  def send_queued_exceptions
@@ -773,7 +773,7 @@ module Dnsruby
773
773
  }.to_s # @TODO@ worry about wildcards here?
774
774
  rec.ttl = old_ttl
775
775
  if (RUBY_VERSION >= "1.9")
776
- data.force_encoding("ASCII-8BIT")
776
+ data.force_encoding(Encoding::BINARY)
777
777
  end
778
778
  sig_data += data
779
779
  end
@@ -1,3 +1,3 @@
1
1
  module Dnsruby
2
- VERSION = '1.70.0'
2
+ VERSION = '1.74.0'
3
3
  end
data/test/spec_helper.rb CHANGED
@@ -5,8 +5,12 @@ if Warning.respond_to?(:[]=)
5
5
  end
6
6
 
7
7
  if ENV['RUN_EXTRA_TASK'] == 'TRUE'
8
- require 'coveralls'
9
- Coveralls.wear!
8
+ unless "test".frozen?
9
+ # Coverall setup term-ansi-color which isn't yet frozen string literal compatible
10
+ # Ref: https://github.com/flori/term-ansicolor/pull/38
11
+ require 'coveralls'
12
+ Coveralls.wear!
13
+ end
10
14
 
11
15
  require 'simplecov'
12
16
 
@@ -22,7 +26,7 @@ require 'minitest'
22
26
  require 'minitest/autorun'
23
27
  require 'minitest/display'
24
28
 
25
- MiniTest::Display.options = {
29
+ Minitest::Display.options = {
26
30
  suite_names: true,
27
31
  color: true,
28
32
  print: {
@@ -39,3 +43,18 @@ MiniTest::Display.options = {
39
43
  require_relative '../lib/dnsruby'
40
44
  require_relative 'test_utils'
41
45
  end.()
46
+
47
+ def with_retries(max_attempts: 5, exceptions: [Dnsruby::ServFail, Dnsruby::ResolvTimeout], success_check: ->(result) { result }, &block)
48
+ attempts = 0
49
+ while attempts < max_attempts
50
+ begin
51
+ result = block.call
52
+ return result if success_check.call(result) # e.g., for nil-check: ->(r) { r }
53
+ rescue *exceptions => e
54
+ puts "Retry #{attempts + 1}/#{max_attempts}: #{e.class} - #{e.message}" if ENV['DEBUG_TESTS']
55
+ end
56
+ sleep(1)
57
+ attempts += 1
58
+ end
59
+ raise Minitest::Assertion, "Failed after #{max_attempts} retries"
60
+ end
data/test/tc_caa.rb CHANGED
@@ -25,6 +25,8 @@ class TestCAA < Minitest::Test
25
25
  {'foo.com. IN CAA 0 issue "ca.example.net"' => [0, 'issue', 'ca.example.net'],
26
26
  'foo.com. IN CAA 1 issue "ca.example.net"' => [1, 'issue', 'ca.example.net'],
27
27
  'foo.com. IN CAA 0 issuewild "ca.example.net"' => [0, 'issuewild', 'ca.example.net'],
28
+ 'foo.com. IN CAA 0 issuemail "ca.example.net"' => [0, 'issuemail', 'ca.example.net'],
29
+ 'foo.com. IN CAA 0 issuevmc "ca.example.net"' => [0, 'issuevmc', 'ca.example.net'],
28
30
  'foo.com. IN CAA 0 iodef "mailto:security@example.com"' => [0, 'iodef', 'mailto:security@example.com'],
29
31
  'foo.com. IN CAA 0 issue "ca.example.net; account=230123"' => [0, 'issue', 'ca.example.net; account=230123']
30
32
  }.each do |text, data|
@@ -44,5 +46,16 @@ class TestCAA < Minitest::Test
44
46
  end
45
47
  end
46
48
 
49
+ def test_caa_error
50
+ {
51
+ 'foo.com. IN CAA 0 ca.example.net "issue"' => [0, 'ca.example.net', 'issue'],
52
+ 'foo.com. IN CAA 0 Issue "ca.example.net"' => [0, 'Issue', 'ca.example.net']
53
+ }.each do |text, data|
54
+ assert_raises DecodeError do
55
+ RR.create(text)
56
+ end
57
+ end
58
+ end
59
+
47
60
  end
48
61
 
data/test/tc_dns.rb CHANGED
@@ -25,7 +25,7 @@ class TestDNS < Minitest::Test
25
25
  end
26
26
 
27
27
  def test_ipv4_address
28
- Dnsruby::DNS.open { |dns| dns.getnames(Dnsruby::IPv4.create("221.186.184.68")) }
28
+ Dnsruby::DNS.open { |dns| dns.getnames(Dnsruby::IPv4.create("8.8.8.8")) }
29
29
  end
30
30
 
31
31
  # def test_resolv_rb_api
@@ -167,9 +167,9 @@ class TestDNS < Minitest::Test
167
167
  end # test_online
168
168
 
169
169
  def test_search_query_reverse
170
- #
170
+ #
171
171
  # test that getname() DTRT with reverse lookups
172
- #
172
+ #
173
173
  tests = [
174
174
  {
175
175
  :ip => '198.41.0.4',
@@ -183,7 +183,7 @@ class TestDNS < Minitest::Test
183
183
 
184
184
  res = DNS.new
185
185
  tests.each do |test|
186
- name = res.getname(test[:ip])
186
+ name = with_retries { res.getname(test[:ip]) }
187
187
 
188
188
  assert_instance_of(Name,name)
189
189
 
@@ -235,7 +235,7 @@ class TestDNS < Minitest::Test
235
235
  res.config.apply_search_list=true
236
236
  end
237
237
 
238
- ans, query = res.send_query(test[:name])
238
+ ans, _ = res.send_query(test[:name])
239
239
 
240
240
  assert_instance_of(Message, ans)
241
241
 
@@ -249,14 +249,14 @@ class TestDNS < Minitest::Test
249
249
  end
250
250
  end
251
251
 
252
- def test_port
253
- d = DNS.new({:port => 5353})
254
- assert(d.to_s.include?"5353")
255
- end
252
+ def test_port
253
+ d = DNS.new({:port => 5353})
254
+ assert(d.to_s.include?"5353")
255
+ end
256
256
 
257
- def test_port_nil
258
- d = DNS.new({:port => nil})
259
- assert(d.to_s.include? Dnsruby::Config::DEFAULT_PORT.to_s)
260
- end
257
+ def test_port_nil
258
+ d = DNS.new({:port => nil})
259
+ assert(d.to_s.include? Dnsruby::Config::DEFAULT_PORT.to_s)
260
+ end
261
261
 
262
262
  end
data/test/tc_ecdsa.rb ADDED
@@ -0,0 +1,27 @@
1
+ require_relative 'spec_helper'
2
+
3
+ Dnsruby::TheLog.level = Logger::DEBUG
4
+
5
+ class VerifierTest < Minitest::Test
6
+
7
+ def test_ecdsa
8
+ inner_resolver = Dnsruby::Resolver.new
9
+ inner_resolver.do_validation = true
10
+ inner_resolver.dnssec = true
11
+ resolver = Dnsruby::Recursor.new(inner_resolver)
12
+ resolver.dnssec = true
13
+
14
+ # Dnsruby::TheLog.level=Logger::DEBUG
15
+
16
+ name = 'carlgo11.com'
17
+ type = 'A'
18
+ klass = 'IN'
19
+
20
+ begin
21
+ answer = resolver.query(name, type, klass)
22
+ print answer
23
+ rescue Exception => e
24
+ fatal_error("query failed: #{e}")
25
+ end
26
+ end
27
+ end
@@ -350,7 +350,7 @@ d0
350
350
  packet = Message.decode(packetdata)
351
351
  assert_equal( '\\\\e.eg.secret-wg.org',(packet.answer)[0].name.to_s,"Correctly dealt escaped backslash from wireformat \\\..eg.secret-wg.org")
352
352
 
353
- testrr=RR.create(
353
+ RR.create(
354
354
  :name => '\\e.eg.secret-wg.org',
355
355
  :type => 'TXT',
356
356
  :txtdata => '"WildCard Match"',
@@ -360,7 +360,6 @@ d0
360
360
 
361
361
 
362
362
 
363
- klass = "IN"
364
363
  ttl = 43200
365
364
  name = 'def0au&lt.example.com'
366
365
 
@@ -471,17 +470,17 @@ d0
471
470
  type = data[:type]
472
471
  # foreach my $meth (keys %{$data}) {
473
472
  (data.keys.each do |meth|
474
- if (meth == :type)
475
- assert_equal(Types.new(data[meth]).to_s, rr.send(meth).to_s, "#{type} - #meth() correct")
476
- else
477
- assert_equal(data[meth].to_s, rr.send(meth).to_s, "#{type} - #meth() correct")
478
- end
473
+ if (meth == :type)
474
+ assert_equal(Types.new(data[meth]).to_s, rr.send(meth).to_s, "#{type} - #meth() correct")
475
+ else
476
+ assert_equal(data[meth].to_s, rr.send(meth).to_s, "#{type} - #meth() correct")
477
+ end
479
478
  end)
480
479
 
481
480
  rr2 = RR.new_from_string(rr.to_s)
482
481
  assert_equal(rr.to_s, rr2.to_s, "#{type} - Parsing from string works")
483
- end
482
+ end
484
483
 
485
484
  Name::Label.set_max_length(Name::Label::MaxLabelLength)
486
- end
487
485
  end
486
+ end
data/test/tc_gpos.rb CHANGED
@@ -93,7 +93,7 @@ class TestGPOS < Minitest::Test
93
93
  response_binary = "E0\x84\x80\x00\x01\x00\x01\x00\x01\x00\x01\x01a\adnsruby\x03com\x00\x00\e\x00\x01\xC0\f\x00\e\x00\x01\x00\x00*0\x00\x0F\x0410.0\x0420.0\x0430.0\xC0\x0E\x00\x02\x00\x01\x00\x00*0\x00\x06\x03ns1\xC0\x0E\xC0F\x00\x01\x00\x01\x00\x00*0\x00\x04\x7F\x00\x00\x01"
94
94
  message_object = Message.decode(response_binary)
95
95
  reconstructed_binary = message_object.encode
96
- assert_equal response_binary.force_encoding('ASCII-8BIT'), reconstructed_binary
96
+ assert_equal response_binary.b, reconstructed_binary
97
97
  end
98
98
  end
99
99
 
data/test/tc_hs.rb CHANGED
@@ -2,11 +2,6 @@ require_relative 'spec_helper'
2
2
 
3
3
  class TestDNS < Minitest::Test
4
4
 
5
- def setup
6
- Dnsruby::Config.reset
7
- end
8
-
9
-
10
5
  # Illustrates that when a message whose class is 'HS' is sent to
11
6
  # a DNS server that does not support the HS class, using send_plain_message,
12
7
  # the response returns with an rcode of NOTIMP and a Dnsruby::NotImp error.
data/test/tc_message.rb CHANGED
@@ -49,7 +49,7 @@ class TestMessage < Minitest::Test
49
49
  def test_rd_flag_displayed_when_true
50
50
  message = sample_message
51
51
  message.header.instance_variable_set(:@rd, true)
52
- assert /;; flags(.+)rd/.match(message.to_s), message
52
+ assert(/;; flags(.+)rd/.match(message.to_s), message)
53
53
  end
54
54
 
55
55
  def test_header_line_contains_opcode_and_status_and_id
@@ -86,7 +86,7 @@ class TestMessage < Minitest::Test
86
86
  end
87
87
 
88
88
  def test_equals
89
- response_as_string = "\x10\a\x81\x90\x00\x01\x00\x04\x00\x00\x00\x06\x03cnn\x03com\x00\x00\x02\x00\x01\xC0\f\x00\x02\x00\x01\x00\x01QC\x00\x14\x03ns3\ntimewarner\x03net\x00\xC0\f\x00\x02\x00\x01\x00\x01QC\x00\x11\x03ns2\x03p42\x06dynect\xC04\xC0\f\x00\x02\x00\x01\x00\x01QC\x00\x06\x03ns1\xC0)\xC0\f\x00\x02\x00\x01\x00\x01QC\x00\x06\x03ns1\xC0I\xC0%\x00\x01\x00\x01\x00\x001\xA2\x00\x04\xC7\aD\xEE\xC0E\x00\x01\x00\x01\x00\x00\xB1\x0E\x00\x04\xCC\r\xFA*\xC0b\x00\x01\x00\x01\x00\x009`\x00\x04\xCCJl\xEE\xC0t\x00\x01\x00\x01\x00\x00\xBDg\x00\x04\xD0NF*\xC0t\x00\x1C\x00\x01\x00\x00\x00\xBB\x00\x10 \x01\x05\x00\x00\x90\x00\x01\x00\x00\x00\x00\x00\x00\x00B\x00\x00)\x0F\xA0\x00\x00\x80\x00\x00\x00".force_encoding("ASCII-8BIT")
89
+ response_as_string = "\x10\a\x81\x90\x00\x01\x00\x04\x00\x00\x00\x06\x03cnn\x03com\x00\x00\x02\x00\x01\xC0\f\x00\x02\x00\x01\x00\x01QC\x00\x14\x03ns3\ntimewarner\x03net\x00\xC0\f\x00\x02\x00\x01\x00\x01QC\x00\x11\x03ns2\x03p42\x06dynect\xC04\xC0\f\x00\x02\x00\x01\x00\x01QC\x00\x06\x03ns1\xC0)\xC0\f\x00\x02\x00\x01\x00\x01QC\x00\x06\x03ns1\xC0I\xC0%\x00\x01\x00\x01\x00\x001\xA2\x00\x04\xC7\aD\xEE\xC0E\x00\x01\x00\x01\x00\x00\xB1\x0E\x00\x04\xCC\r\xFA*\xC0b\x00\x01\x00\x01\x00\x009`\x00\x04\xCCJl\xEE\xC0t\x00\x01\x00\x01\x00\x00\xBDg\x00\x04\xD0NF*\xC0t\x00\x1C\x00\x01\x00\x00\x00\xBB\x00\x10 \x01\x05\x00\x00\x90\x00\x01\x00\x00\x00\x00\x00\x00\x00B\x00\x00)\x0F\xA0\x00\x00\x80\x00\x00\x00".b
90
90
  message = Message.decode(response_as_string)
91
91
  assert(message == message, message.to_s)
92
92
  end
data/test/tc_name.rb CHANGED
@@ -24,7 +24,7 @@ class TestName < Minitest::Test
24
24
  Name::Label.set_max_length(Name::Label::MaxLabelLength) # Other tests may have changed this
25
25
  # Test max label length = 63
26
26
  begin
27
- name = Name.create("a.b.12345678901234567890123456789012345678901234567890123456789012345.com")
27
+ Name.create("a.b.12345678901234567890123456789012345678901234567890123456789012345.com")
28
28
  assert(false, "Label of more than max=63 allowed")
29
29
  rescue ResolvError
30
30
  end
@@ -33,7 +33,7 @@ class TestName < Minitest::Test
33
33
  def test_name_length
34
34
  # Test max name length=255
35
35
  begin
36
- name = Name.create("1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123.com")
36
+ Name.create("1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123.com")
37
37
  assert(false, "Name of length > 255 allowed")
38
38
  rescue ResolvError
39
39
  end
data/test/tc_nxt.rb CHANGED
@@ -60,7 +60,6 @@ class TestNXT < Minitest::Test
60
60
  def test_binary_string_to_codes
61
61
  test_type_codes_as_code_array = [1, 6, 28, 100]
62
62
  test_type_codes_as_name_array = %w(A SOA AAAA UINFO)
63
- test_type_codes_as_number = 1267650600228229401496971640898 # (2 ** 1) + (2 ** 6) + (2 ** 28) + (2 ** 100)
64
63
  test_type_codes_as_binary_string = "\x10\x0\x0\x0\x0\x0\x0\x0\x0\x10\x0\x0\x42"
65
64
  assert_equal(test_type_codes_as_code_array, RR::NXT::NxtTypes.binary_string_to_codes(test_type_codes_as_binary_string))
66
65
  assert_equal(test_type_codes_as_name_array, RR::NXT::NxtTypes.binary_string_to_names(test_type_codes_as_binary_string))
data/test/tc_recur.rb CHANGED
@@ -1,12 +1,12 @@
1
1
  # --
2
2
  # Copyright 2007 Nominet UK
3
- #
3
+ #
4
4
  # Licensed under the Apache License, Version 2.0 (the "License");
5
5
  # you may not use this file except in compliance with the License.
6
6
  # You may obtain a copy of the License at
7
- #
7
+ #
8
8
  # http://www.apache.org/licenses/LICENSE-2.0
9
- #
9
+ #
10
10
  # Unless required by applicable law or agreed to in writing, software
11
11
  # distributed under the License is distributed on an "AS IS" BASIS,
12
12
  # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -20,10 +20,7 @@ class TestRecur < Minitest::Test
20
20
  def test_recur
21
21
  Dnsruby::PacketSender.clear_caches
22
22
  r = Dnsruby::Recursor.new
23
- # Dnsruby::TheLog.level = Logger::DEBUG
24
- ret = r.query("uk", Dnsruby::Types.DNSKEY)
25
- # print ret
26
- assert ret, "Query result was nil."
23
+ ret = with_retries(max_attempts: 10, exceptions: [Dnsruby::ResolvError]) { r.query("uk", Dnsruby::Types.DNSKEY) }
27
24
  assert ret.answer.length > 0, "Answer length should > 0, but was #{ret.answer.length}."
28
25
  # ret = r.query_dorecursion("aaa.bigzone.uk-dnssec.nic.uk", Dnsruby::Types.DNSKEY)
29
26
  # ret = r.query_dorecursion("uk-dnssec.nic.uk", Dnsruby::Types.DNSKEY)
@@ -92,4 +92,33 @@ class TestResolverConfig < Minitest::Test
92
92
  end;
93
93
  end
94
94
 
95
+ def test_bad_ns
96
+ begin
97
+ res = Dnsruby::Resolver.new(:nameserver => ["ns32.domiancontrol.com."])
98
+ res.query("example.com")
99
+ assert(false, "Should not query with bad nameserver")
100
+ rescue Exception => e
101
+ # OK
102
+ end
103
+ end
104
+
105
+ def test_bad_ns_post_init
106
+ begin
107
+ resolver = Dnsruby::Resolver.new(recurse: false, do_caching: false, retry_times: 2)
108
+ resolver.nameserver = ["ns32.domiancontrol.com."]
109
+ assert(false, "Should not allow bad nameserver")
110
+ resolver.query("example.com")
111
+ rescue ArgumentError
112
+ end
113
+ end
114
+
115
+ def test_one_good_ns_rest_bad
116
+ begin
117
+ resolver = Dnsruby::Resolver.new(recurse: false, do_caching: false, retry_times: 2)
118
+ resolver.nameserver = ["ns32.domiancontrol.com.", "1.1.1.1"]
119
+ resolver.query("example.com")
120
+ rescue ArgumentError
121
+ assert(false, "Should allow one good nameserver")
122
+ end
123
+ end
95
124
  end
data/test/tc_resolv.rb CHANGED
@@ -51,19 +51,26 @@ class TestResolv < Minitest::Test
51
51
  end
52
52
  end
53
53
 
54
-
55
54
  def test_resolv_address_to_name
56
55
 
57
- assert_equal(SHORT_ABSOLUTE_NAME, Dnsruby::Resolv.getname(IPV4_ADDR).to_s(true))
56
+ name = with_retries { Dnsruby::Resolv.getname(IPV4_ADDR) }
57
+ assert_equal(SHORT_ABSOLUTE_NAME, name.to_s(true))
58
58
 
59
59
  assert_raises(Dnsruby::ResolvError) do
60
60
  Dnsruby::Resolv.getname(SHORT_ABSOLUTE_NAME)
61
61
  end
62
62
 
63
- names = Dnsruby::Resolv.getnames(IPV4_ADDR)
63
+ names = with_retries { Dnsruby::Resolv.getnames(IPV4_ADDR) }
64
64
  assert_equal(1, names.size)
65
65
  assert_equal(SHORT_ABSOLUTE_NAME, names.first.to_s(true))
66
- Dnsruby::Resolv.each_name(IPV4_ADDR) { |name| assert_equal(SHORT_ABSOLUTE_NAME, name.to_s(true))}
66
+
67
+ found_names = with_retries(success_check: ->(_) { true }) do
68
+ names = []
69
+ Dnsruby::Resolv.each_name(IPV4_ADDR) { |name| names << name }
70
+ names
71
+ end
72
+
73
+ assert_equal(SHORT_ABSOLUTE_NAME, found_names.first.to_s(true))
67
74
  end
68
75
 
69
76
  def test_resolv_address_to_address