dnsruby 1.60.2 → 1.73.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 (79) hide show
  1. checksums.yaml +5 -5
  2. data/.github/FUNDING.yml +3 -0
  3. data/.github/dependabot.yml +11 -0
  4. data/.github/workflows/ci.yml +26 -0
  5. data/.yardopts +7 -0
  6. data/README.md +8 -5
  7. data/RELEASE_NOTES.md +105 -0
  8. data/Rakefile +1 -0
  9. data/demo/digdlv.rb +1 -0
  10. data/demo/digroot.rb +2 -0
  11. data/dnsruby.gemspec +22 -14
  12. data/lib/dnsruby/DNS.rb +1 -1
  13. data/lib/dnsruby/bit_mapping.rb +2 -2
  14. data/lib/dnsruby/code_mappers.rb +6 -2
  15. data/lib/dnsruby/config.rb +29 -15
  16. data/lib/dnsruby/dnssec.rb +4 -1
  17. data/lib/dnsruby/hosts.rb +1 -4
  18. data/lib/dnsruby/ipv6.rb +5 -5
  19. data/lib/dnsruby/message/encoder.rb +5 -5
  20. data/lib/dnsruby/message/header.rb +15 -18
  21. data/lib/dnsruby/message/message.rb +2 -2
  22. data/lib/dnsruby/name.rb +19 -3
  23. data/lib/dnsruby/packet_sender.rb +25 -17
  24. data/lib/dnsruby/recursor.rb +17 -7
  25. data/lib/dnsruby/resolver.rb +43 -26
  26. data/lib/dnsruby/resource/CAA.rb +5 -2
  27. data/lib/dnsruby/resource/CDNSKEY.rb +17 -0
  28. data/lib/dnsruby/resource/CDS.rb +35 -0
  29. data/lib/dnsruby/resource/DNSKEY.rb +53 -13
  30. data/lib/dnsruby/resource/DS.rb +2 -5
  31. data/lib/dnsruby/resource/GPOS.rb +1 -1
  32. data/lib/dnsruby/resource/IN.rb +4 -1
  33. data/lib/dnsruby/resource/NSEC.rb +2 -2
  34. data/lib/dnsruby/resource/NSEC3PARAM.rb +1 -1
  35. data/lib/dnsruby/resource/NXT.rb +1 -1
  36. data/lib/dnsruby/resource/RR.rb +1 -1
  37. data/lib/dnsruby/resource/TLSA.rb +3 -3
  38. data/lib/dnsruby/resource/TXT.rb +12 -2
  39. data/lib/dnsruby/resource/URI.rb +57 -0
  40. data/lib/dnsruby/resource/generic.rb +3 -0
  41. data/lib/dnsruby/select_thread.rb +36 -28
  42. data/lib/dnsruby/single_verifier.rb +29 -8
  43. data/lib/dnsruby/validator_thread.rb +4 -4
  44. data/lib/dnsruby/version.rb +1 -1
  45. data/lib/dnsruby/zone_reader.rb +2 -2
  46. data/lib/dnsruby/zone_transfer.rb +5 -2
  47. data/lib/dnsruby.rb +4 -4
  48. data/test/localdns.rb +29 -0
  49. data/test/spec_helper.rb +34 -9
  50. data/test/tc_caa.rb +12 -1
  51. data/test/tc_dns.rb +15 -5
  52. data/test/tc_dnskey.rb +29 -0
  53. data/test/tc_ecdsa.rb +27 -0
  54. data/test/tc_encoding.rb +31 -0
  55. data/test/tc_escapedchars.rb +8 -9
  56. data/test/tc_gpos.rb +1 -1
  57. data/test/tc_hs.rb +4 -8
  58. data/test/tc_long_labels.rb +46 -0
  59. data/test/tc_message.rb +2 -2
  60. data/test/tc_name.rb +21 -2
  61. data/test/tc_nxt.rb +0 -1
  62. data/test/tc_recur.rb +4 -7
  63. data/test/tc_resolv.rb +14 -6
  64. data/test/tc_resolver.rb +114 -11
  65. data/test/tc_rr-opt.rb +8 -5
  66. data/test/tc_rr-txt.rb +7 -1
  67. data/test/tc_rr-unknown.rb +1 -1
  68. data/test/tc_rr.rb +37 -4
  69. data/test/tc_single_resolver.rb +9 -17
  70. data/test/tc_soak.rb +33 -67
  71. data/test/tc_tcp.rb +2 -2
  72. data/test/tc_tcp_pipelining.rb +30 -22
  73. data/test/tc_tkey.rb +1 -7
  74. data/test/tc_update.rb +0 -1
  75. data/test/tc_verifier.rb +15 -0
  76. data/test/test_dnsserver.rb +110 -17
  77. data/test/test_utils.rb +0 -2
  78. metadata +83 -46
  79. data/.travis.yml +0 -14
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
 
@@ -247,6 +247,16 @@ class TestDNS < Minitest::Test
247
247
  assert_equal(a[0].name.to_s, 'a.t.net-dns.org',"Correct name (with persistent socket and #{method})")
248
248
  # assert_equal(a[0].name.to_s, 'a.t.dnsruby.validation-test-servers.nominet.org.uk',"Correct name (with persistent socket and #{method})")
249
249
  end
250
+ end
250
251
 
252
+ def test_port
253
+ d = DNS.new({:port => 5353})
254
+ assert(d.to_s.include?"5353")
251
255
  end
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
261
+
252
262
  end
data/test/tc_dnskey.rb CHANGED
@@ -85,4 +85,33 @@ class DnskeyTest < Minitest::Test
85
85
  dnskey.protocol=3
86
86
 
87
87
  end
88
+
89
+ def test_ecdsa_integrity
90
+ ecdsa_256_pub = 'example.com. 3600 IN DNSKEY 256 3 13 ( oJMRESz5E4gYzS/q6XD' +
91
+ 'rvU1qMPYIjCWzJaOau8XNEZeqCYKD5ar0IRd8KqXXFJkqmVfRvMGPmM1x8fGAa2XhSA== )'
92
+
93
+ dnskey = Dnsruby::RR.create(ecdsa_256_pub)
94
+ assert_equal(3, dnskey.protocol)
95
+ assert_equal(256, dnskey.flags)
96
+ assert_equal(Dnsruby::Algorithms::ECDSAP256SHA256, dnskey.algorithm)
97
+ assert_equal(Dnsruby::RR::DNSKEY::ZONE_KEY, dnskey.flags & Dnsruby::RR::DNSKEY::ZONE_KEY)
98
+ assert_equal(0, dnskey.flags & Dnsruby::RR::DNSKEY::SEP_KEY)
99
+
100
+ dnskey2 = Dnsruby::RR.create(dnskey.to_s)
101
+ assert(dnskey2.to_s == dnskey.to_s, "#{dnskey} not equal to \n#{dnskey2}")
102
+
103
+ ecdsa_384_pub = 'example.com. 3600 IN DNSKEY 256 3 14 ( Bl2HDw98sGin4lNlx7n' +
104
+ 'QX3w98jx6UhAgC73Jq+6LFlD12gnVTMHecM8Z GoTFSh+mV+qEPFZ5s3NbC4qvwUW0kkPb+0ip' +
105
+ 'CuLRwZYhYKk7D+RDb+fX XozI9hhZrsXBcEhss )'
106
+
107
+ dnskey = Dnsruby::RR.create(ecdsa_384_pub)
108
+ assert_equal(3, dnskey.protocol)
109
+ assert_equal(256, dnskey.flags)
110
+ assert_equal(Dnsruby::Algorithms::ECDSAP384SHA384, dnskey.algorithm)
111
+ assert_equal(Dnsruby::RR::DNSKEY::ZONE_KEY, dnskey.flags & Dnsruby::RR::DNSKEY::ZONE_KEY)
112
+ assert_equal(0, dnskey.flags & Dnsruby::RR::DNSKEY::SEP_KEY)
113
+
114
+ dnskey2 = Dnsruby::RR.create(dnskey.to_s)
115
+ assert(dnskey2.to_s == dnskey.to_s, "#{dnskey} not equal to \n#{dnskey2}")
116
+ end
88
117
  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
@@ -0,0 +1,31 @@
1
+ require_relative 'spec_helper'
2
+
3
+ require 'socket'
4
+
5
+ # @TODO@ We also need a test server so we can control behaviour of server to test
6
+ # different aspects of retry strategy.
7
+ # Of course, with Ruby's limit of 256 open sockets per process, we'd need to run
8
+ # the server in a different Ruby process.
9
+
10
+ class TestEncoding < Minitest::Test
11
+
12
+ include Dnsruby
13
+
14
+ Thread::abort_on_exception = true
15
+
16
+ Dnsruby::TheLog.level = Logger::DEBUG
17
+
18
+
19
+ def test_cdnskey
20
+ rrString = "tjeb.nl.\t3600\tIN\tCDNSKEY\t256 3 RSASHA1-NSEC3-SHA1 ( AwEAAcglEOS7bECRK5fqTuGTMJycmDhTzmUu/EQbAhKJOYJxDb5SG/RYqsJgzG7wgtGy0W1aP7I4k6SPtHmwcqjLaZLVUwRNWCGr2adjb9JTFyBR7F99Ngi11lEGM6Uiw/eDRk66lhoSGzohjj/rmhRTV6gN2+0ADPnafv3MBkPgryA3 ) ; key_tag=53177"
21
+ rr = RR.create(rrString)
22
+ puts rr
23
+ puts rrString
24
+ assert(rrString.to_s == rr.to_s)
25
+ m = Dnsruby::Message.new
26
+ m.add_additional(rr)
27
+ m2 = Message.decode(m.encode)
28
+ rr2 = m2.additional()[0]
29
+ assert(rr.to_s == rr2.to_s)
30
+ end
31
+ 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,21 +2,17 @@ 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.
13
8
  def test_hs_class_returns_notimp_code_and_error
14
9
  resolver_host = 'a.gtld-servers.net'
15
- resolver = Resolver.new(resolver_host)
16
- message = Message.new('test.com', 'A', 'HS')
10
+ resolver = Dnsruby::Resolver.new(resolver_host)
11
+ resolver.query_timeout = 20
12
+ message = Dnsruby::Message.new('test.com', 'A', 'HS')
17
13
  response, error = resolver.send_plain_message(message)
18
14
 
19
- assert_equal(RCode::NOTIMP, response.rcode)
15
+ assert_equal(Dnsruby::RCode::NOTIMP, response.rcode)
20
16
  assert_equal(Dnsruby::NotImp, error.class)
21
17
  end
22
18
 
@@ -0,0 +1,46 @@
1
+ require_relative 'spec_helper'
2
+
3
+ include Dnsruby
4
+ class TestPacket < Minitest::Test
5
+ def test_labels
6
+ wirePacket = %w{0
7
+ 68 5b 35 91 3a f7 00 0f 94 22 d9 51 08 00 45 00 05 12 71 65 40 00 3d 06 46 1f 2e e3 90 33
8
+ c0 a8 01 a3 00 35 e3 cf 94 d5 49 0a 88 da e7 1e 80 18 00 1d 6f 52 00 00 01 01 08 0a 8e 3a
9
+ a6 b1 1f 4d ce 28 c5 b1 c0 0c 00 0c 00 01 00 00 0b 49 00 12 0f 69 6d 70 72 6f 76 65 61 6e
10
+ 61 6c 79 73 69 73 c0 65 c0 0c 00 0c 00 01 00 00 0b 49 00 0e 0b 77 69 6e 64 6f 77 73 72 75
11
+ 62 79 d3 12 c0 0c 00 0c 00 01 00 00 0b 49 00 15 12 6d 69 63 72 6f 73 6f 66 74 66 6f 72 65
12
+ 66 72 6f 6e 74 d3 bd c0 0c 00 0c 00 01 00 00 0b 49 00 11 09 6d 69 63 72 6f 73 6f 66 74 02
13
+ 63 6f 02 6d 7a 00 c0 0c 00 0c 00 01 00 00 0b 49 00 12 09 77 69 6e 64 6f 77 73 78 70 03 6f
14
+ 72 67 02 70 65 00 c0 0c 00 0c 00 01 00 00 0b 49 00 16 0f 65 75 67 72 61 6e 74 73 61 64 76
15
+ 69 73 6f 72 03 63 6f 6d ca 49 c0 0c 00 0c 00 01 00 00 0b 49 00 14 11 64 65 66 79 61 6c 6c
16
+ 63 68 61 6c 6c 65 6e 67 65 73 c5 97 c0 0c 00 0c 00 01 00 00 0b 49 00 18 15 63 6f 6e 73 6f
17
+ 6c 69 64 61 74 65 64 6d 65 73 73 65 6e 67 65 72 c0 65 c0 0c 00 0c 00 01 00 00 0b 49 00 19
18
+ 16 72 65 74 61 69 6c 65 78 65 63 75 74 69 76 65 73 65 6d 69 6e 61 72 c0 a7 c0 0c 00 0c 00
19
+ 01 00 00 0b 49 00 0e 0b 63 74 72 6f 70 65 6e 6f 72 6d 65 c0 65 c0 0c 00 0c 00 01 00 00 0b
20
+ 49 00 0e 0b 77 69 6e 64 6f 77 73 32 30 30 30 cc 6f c0 0c 00 0c 00 01 00 00 0b 49 00 1a 17
21
+ 77 69 6e 64 6f 77 73 6d 6f 62 69 6c 65 63 6f 6d 6d 6d 75 6e 69 74 79 c0 41 c0 0c 00 0c 00
22
+ 01 00 00 0b 49 00 11 0e 72 69 73 65 6f 66 70 65 72 61 74 68 69 61 c0 41 c0 0c 00 0c 00 01
23
+ 00 00 0b 49 00 11 0e 72 65 6e 63 6f 6e 74 72 65 73 2d 33 36 30 c0 41 c0 0c 00 0c 00 01 00
24
+ 00 0b 49 00 11 0e 66 75 74 75 72 65 70 6f 73 74 6d 61 69 6c c0 41 c0 0c 00 0c 00 01 00 00
25
+ 0b 49 00 10 0d 72 65 73 70 6f 6e 73 65 70 6f 69 6e 74 cc 4d c0 0c 00 0c 00 01 00 00 0b 49
26
+ 00 10 0d 74 61 76 75 74 61 74 72 6f 6e 63 68 65 c0 a7 c0 0c 00 0c 00 01 00 00 0b 49 00 09
27
+ 06 66 6c 65 78 67 6f df 34 c0 0c 00 0c 00 01 00 00 0b 49 00 0e 09 77 69 6e 64 6f 77 73 78
28
+ 70 02 73 68 00 c0 0c 00 0c 00 01 00 00 0b 49 00 16 13 73 6d 61 72 74 70 68 6f 6e 65 63 6f
29
+ 6d 6d 75 6e 69 74 79 c0 a7 c0 0c 00 0c 00 01 00 00 0b 49 00 12 0f 63 65 6e 74 72 65 64 65
30
+ 73 75 73 61 67 65 73 c0 65 c0 0c 00 0c 00 01 00 00 0b 49 00 0c 09 77 69 6e 64 6f 77 73 6e
31
+ 74 fc 07 c0 0c 00 0c 00 01 00 00 0b 49 00 19 16 6c 65 73 2d 64 6f 69 67 74 73 2d 64 61 6e
32
+ 73 2d 6c 65 2d 6e 65 7a c0 a7 c0 0c 00 0c 00 01 00 00 0b 49 00 13 10 74 65 63 68 6e 65 74
33
+ 63 68 61 6c 6c 65 6e 67 65 c0 65 c0 0c 00 0c 00 01 00 00 0b 49 00 15 12 6d 69 63 72 6f 73 6f 66 74 66 6f 72 65 66 72 6f 6e 74 c0 41 c0 0c 00 0c 00 01 00 00 0b 49 00 10 0d 6c 65 73 62 6f 6e 73 6f 75 74 69 6c 73 c0 41 c0 0c 00 0c 00 01 00 00 0b 49 00 0d 0a 77 69 6e 74 65 72 6e 61 6c 73 c3 d6 c0 0c 00 0c 00 01 00 00 0b 49 00 23 0e 64 65 73 69 67 6e 65 64 66 6f 72 62 69 67 02 64 65 0e 64 65 73 69 67 6e 65 64 66 6f 72 62 69 67 c2 b2 c0 0c 00 0c 00 01 00 00 0b 49 00 13 10 77 69 6e 64 6f 77 73 76 69 73 74 61 62 6c 6f 67 c9 42 c0 0c 00 0c 00 01 00 00 0b 49 00 12 09 77 69 6e 64 6f 77 73 6e 74 03 6f 72 67 02 66 6a 00 c0 0c 00 0c 00 01 00 00 0b 49 00 0c 09 77 69 6e 64 6f 77 73 6e 74 c1 b6 c0 0c 00 0c 00 01 00 00 0b 49 00 0f 0c 6f 66 66 69 63 65 73 79 73 74 65 6d c2 18 c0 0c 00 0c 00 01 00 00 0b 49 00 0f 0c 74 72 65 79 72 65 73 65 61 72 63 68 c0 41 c0 0c 00 0c 00 01 00 00 0b 49 00 09 06 63 70 61 6e 64 6c c0 65 c0 0c 00 0c 00 01 00 00 0b 49 00 16 13 6f 66 66 72 65 2d 65 62 6c 6f 75 69 73 73 61 6e 74 65 73 c0 41 c0 0c 00 0c 00 01 00 00 0b 49 00 0d 0a 63 6f 68 6f 77 69 6e 65 72 79 c0 41 c0 0c 00 0c 00 01 00 00 0b 49 00 13 10 74 6f 64 6f 73 6c 6f 65 6e 74 69 65 6e 64 65 6e c0 41 c0 0c 00 0c 00 01 00 00 0b 49 00 0f 09 77 69 6e 64 6f 77 73 78 70 02 63 6f f1 03 c0 0c 00 0c 00 01 00 00 0b 49 00 0b 08 74 65 63 68 65 64 30 36 c0 65 c0 0c 00 0c 00 01 00 00 0b 49 00 09 06 66 6c 65 78 67 6f dd 7f c0 0c 00 0c 00 01 00 00 0b 49 00 0c 09 66 6f 72 65 66 72 6f 6e 74 cb 21 c0 0c 00 0c 00 01 00 00 0b 49 00 14 11 64 65 66 79 61 6c 6c 63 68 61 6c 6c 65 6e 67 65 73 cb 44 00 00 29 05 78 00 00 80 00 00 00
34
+ }
35
+ wirePacket.map!{|e| e.hex}
36
+ packetdata = wirePacket.pack('c*')
37
+
38
+ packet = Message.decode(packetdata)
39
+ assert(packet, 'new data returned something'); #28
40
+ end
41
+
42
+ def test_live
43
+ resolver = Dnsruby::Resolver.new
44
+ query = resolver.query('207.46.197.32', 'PTR', 'IN')
45
+ end
46
+ end
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
@@ -80,4 +80,23 @@ class TestName < Minitest::Test
80
80
  n2 = Name.create("nall.all.")
81
81
  assert(n1 == n2, n1.to_s)
82
82
  end
83
+
84
+ def test_punycode
85
+ [
86
+ [
87
+ "møllerriis.com",
88
+ "xn--mllerriis-l8a.com"
89
+ ],
90
+ [
91
+ "フガフガ。hogehoge.エグザンプル.JP",
92
+ "xn--mcka5jb.hogehoge.xn--ickqs6k2dyb.jp"
93
+ ],
94
+ [
95
+ "フガ#フガ。hogehoge.エグザンプル.JP",
96
+ "xn--#-yeub5nc.hogehoge.xn--ickqs6k2dyb.jp"
97
+ ]
98
+ ].each do |tc|
99
+ assert_equal(Dnsruby::Name.create(tc[0]).to_s, tc[1])
100
+ end
101
+ end
83
102
  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)
data/test/tc_resolv.rb CHANGED
@@ -20,6 +20,7 @@ require_relative '../lib/dnsruby/resolv'
20
20
  class TestResolv < Minitest::Test
21
21
 
22
22
  RELATIVE_NAME = 'google-public-dns-a.google.com'
23
+ SHORT_ABSOLUTE_NAME = 'dns.google.'
23
24
  ABSOLUTE_NAME = RELATIVE_NAME + '.'
24
25
  IPV4_ADDR = '8.8.8.8'
25
26
  IPV6_ADDR = '2001:4860:4860::8888'
@@ -50,19 +51,26 @@ class TestResolv < Minitest::Test
50
51
  end
51
52
  end
52
53
 
53
-
54
54
  def test_resolv_address_to_name
55
55
 
56
- assert_equal(RELATIVE_NAME, Dnsruby::Resolv.getname(IPV4_ADDR).to_s)
56
+ name = with_retries { Dnsruby::Resolv.getname(IPV4_ADDR) }
57
+ assert_equal(SHORT_ABSOLUTE_NAME, name.to_s(true))
57
58
 
58
59
  assert_raises(Dnsruby::ResolvError) do
59
- Dnsruby::Resolv.getname(RELATIVE_NAME)
60
+ Dnsruby::Resolv.getname(SHORT_ABSOLUTE_NAME)
60
61
  end
61
62
 
62
- names = Dnsruby::Resolv.getnames(IPV4_ADDR)
63
+ names = with_retries { Dnsruby::Resolv.getnames(IPV4_ADDR) }
63
64
  assert_equal(1, names.size)
64
- assert_equal(RELATIVE_NAME, names.first.to_s)
65
- Dnsruby::Resolv.each_name(IPV4_ADDR) { |name| assert_equal(RELATIVE_NAME, name.to_s)}
65
+ assert_equal(SHORT_ABSOLUTE_NAME, names.first.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))
66
74
  end
67
75
 
68
76
  def test_resolv_address_to_address
data/test/tc_resolver.rb CHANGED
@@ -73,14 +73,26 @@ class TestResolver < Minitest::Test
73
73
  end
74
74
 
75
75
  def test_send_plain_message
76
- resolver = Resolver.new
77
- response, error = resolver.send_plain_message(Message.new("cnn.com"))
76
+ resolver = Resolver.new('1.1.1.1')
77
+
78
+ response, error = with_retries(success_check: ->((res, err)) { err.nil? || ! [Dnsruby::ServFail, Dnsruby::ResolvTimeout].include?(err.class) }) do
79
+ res, err = resolver.send_plain_message(Message.new("example.com", Types.A))
80
+ raise err if [Dnsruby::ServFail, Dnsruby::ResolvTimeout].include?(err.class)
81
+ [res, err]
82
+ end
83
+
78
84
  assert_nil_error(error)
79
85
  assert_valid_response(response)
80
86
 
81
87
  m = Message.new(BAD_DOMAIN_NAME)
82
88
  m.header.rd = true
83
- response, error = resolver.send_plain_message(m)
89
+
90
+ response, error = with_retries(success_check: ->((res, err)) { err.class == Dnsruby::NXDomain || ! [Dnsruby::ServFail, Dnsruby::ResolvTimeout].include?(err.class) }) do
91
+ res, err = resolver.send_plain_message(m)
92
+ raise err if [Dnsruby::ServFail, Dnsruby::ResolvTimeout].include?(err.class)
93
+ [res, err]
94
+ end
95
+
84
96
  assert_valid_response(response)
85
97
  assert_error_is_exception(error, NXDomain)
86
98
  end
@@ -132,13 +144,13 @@ class TestResolver < Minitest::Test
132
144
  r = Resolver.new
133
145
  q=Queue.new
134
146
  r.send_async(m,q,q)
135
- id,ret, error=q.pop
147
+ _id, ret, _error=q.pop
136
148
  assert(ret.kind_of?(Message))
137
149
  no_pointer=true
138
150
  ret.each_answer do |answer|
139
151
  if (answer.type==Types.PTR)
140
152
  no_pointer=false
141
- assert(answer.domainname.to_s=~/google-public-dns/)
153
+ assert(answer.domainname.to_s=~/google/)
142
154
  end
143
155
  end
144
156
  assert(!no_pointer)
@@ -171,7 +183,7 @@ class TestResolver < Minitest::Test
171
183
  # test timeout behaviour for different retry, retrans, total timeout etc.
172
184
  # Problem here is that many sockets will be created for queries which time out.
173
185
  # Run a query which will not respond, and check that the timeout works
174
- if (!RUBY_PLATFORM=~/darwin/)
186
+ if (RUBY_PLATFORM !~ /darwin/)
175
187
  start=stop=0
176
188
  retry_times = 3
177
189
  retry_delay=1
@@ -185,14 +197,14 @@ class TestResolver < Minitest::Test
185
197
  res.retry_times=retry_times
186
198
  res.retry_delay=retry_delay
187
199
  start=Time.now
188
- m = res.send_message(Message.new("a.t.dnsruby.validation-test-servers.nominet.org.uk", Types.A))
200
+ res.send_message(Message.new("a.t.dnsruby.validation-test-servers.nominet.org.uk", Types.A))
189
201
  fail
190
202
  rescue ResolvTimeout
191
203
  stop=Time.now
192
204
  time = stop-start
193
205
  assert(time <= expected * 1.3 && time >= expected * 0.9, "Wrong time take, expected #{expected}, took #{time}")
194
206
  end
195
- end
207
+ end
196
208
  end
197
209
 
198
210
  def test_packet_timeout
@@ -209,7 +221,7 @@ class TestResolver < Minitest::Test
209
221
  # Work out what time should be, then time it to check
210
222
  expected = query_timeout
211
223
  start=Time.now
212
- m = res.send_message(Message.new("a.t.dnsruby.validation-test-servers.nominet.org.uk", Types.A))
224
+ res.send_message(Message.new("a.t.dnsruby.validation-test-servers.nominet.org.uk", Types.A))
213
225
  fail
214
226
  rescue Dnsruby::ResolvTimeout
215
227
  stop=Time.now
@@ -227,7 +239,7 @@ class TestResolver < Minitest::Test
227
239
  res.query_timeout=expected
228
240
  q = Queue.new
229
241
  start = Time.now
230
- m = res.send_async(Message.new("a.t.dnsruby.validation-test-servers.nominet.org.uk", Types.A), q, q)
242
+ res.send_async(Message.new("a.t.dnsruby.validation-test-servers.nominet.org.uk", Types.A), q, q)
231
243
  id,ret,err = q.pop
232
244
  stop = Time.now
233
245
  assert(id=q)
@@ -284,8 +296,73 @@ class TestResolver < Minitest::Test
284
296
  def test_eventtype_api
285
297
  # @TODO@ TEST THE Resolver::EventType interface!
286
298
  end
287
- end
288
299
 
300
+ def capture_sent_message(res, domain, pre_opt=nil)
301
+ q = Queue.new
302
+ res.send_async(Dnsruby::Message.new("test.invalid"), q)
303
+ q.pop
304
+ resolver_ruby = res.instance_variable_get("@resolver_ruby")
305
+ class << resolver_ruby
306
+ attr_accessor :message
307
+ alias_method :original_send_async, :send_async
308
+ def send_async(msg, client_queue, client_query_id=nil)
309
+ @message = msg
310
+ original_send_async(msg, client_queue, client_query_id)
311
+ end
312
+ end
313
+ msg = Dnsruby::Message.new(domain)
314
+ msg.add_additional(pre_opt) if pre_opt
315
+ res.send_async(msg, q)
316
+ _id, _response, _error = q.pop
317
+ resolver_ruby.message
318
+ end
319
+
320
+ def test_custom_udp_size
321
+ [false, true].each do |dnssec_setting|
322
+ [512, 513].each do |udp_size_setting|
323
+ res = Dnsruby::Resolver.new(:udp_size => udp_size_setting, :dnssec => dnssec_setting)
324
+ sent_msg = capture_sent_message(res, "example.com")
325
+
326
+ # The OPT RR is only present if the udp_size is > 512
327
+ opt = sent_msg.get_opt
328
+ if dnssec_setting
329
+ # DNSSEC overrides udp_size to 4096
330
+ assert(opt)
331
+ assert_equal(4096, opt.klass.code)
332
+ else
333
+ if udp_size_setting <= 512
334
+ assert_nil(opt)
335
+ else
336
+ assert(opt)
337
+ assert_equal(udp_size_setting, opt.klass.code)
338
+ end
339
+ end
340
+ if opt
341
+ assert_equal(0, opt.version)
342
+ assert_equal(0, opt.flags)
343
+ end
344
+ end
345
+ end
346
+ end
347
+
348
+ def test_no_duplicate_opt_when_pre_existing
349
+ [false, true].each do |dnssec_setting|
350
+ [512, 513].each do |udp_size_setting|
351
+ res = Dnsruby::Resolver.new(:udp_size => udp_size_setting, :dnssec => dnssec_setting)
352
+ pre_size = dnssec_setting ? 4096 : 1024
353
+ pre_opt = Dnsruby::RR::OPT.new(pre_size)
354
+ sent_msg = capture_sent_message(res, "example.com", pre_opt)
355
+
356
+ opt = sent_msg.get_opt
357
+ assert(opt)
358
+ assert_equal(1, sent_msg.additional.length) # No duplicate added
359
+ assert_equal(pre_size, opt.klass.code) # Original payload size unchanged
360
+ assert_equal(0, opt.version)
361
+ assert_equal(0, opt.flags) # Flags unchanged (code doesn't modify existing OPT)
362
+ end
363
+ end
364
+ end
365
+ end
289
366
 
290
367
  # Tests to see that query_raw handles send_plain_message's return values correctly.
291
368
  class TestRawQuery < Minitest::Test
@@ -374,5 +451,31 @@ class TestRawQuery < Minitest::Test
374
451
  assert_equal KEY, options[:key]
375
452
  assert_equal ALGO, options[:algorithm]
376
453
  end
454
+
455
+ def test_threads
456
+ resolver = Dnsruby::Resolver.new(nameserver: ["8.8.8.8", "8.8.4.4"])
457
+ resolver.query("google.com", "MX")
458
+ resolver.query("google.com", "MX")
459
+ resolver.query("google.com", "MX")
460
+ begin
461
+ resolver.query("googlöe.com", "MX")
462
+ rescue Dnsruby::ResolvError
463
+ # fine
464
+ end
465
+ resolver.query("google.com", "MX")
466
+ resolver.query("google.com", "MX")
467
+ begin
468
+ resolver.query("googlöe.com", "MX")
469
+ rescue Dnsruby::ResolvError
470
+ # fine
471
+ end
472
+ begin
473
+ resolver.query("googlöe.com", "MX")
474
+ rescue Dnsruby::ResolvError
475
+ # fine
476
+ end
477
+ # Dnsruby::Cache.delete("googlöe.com", "MX")
478
+
479
+ end
377
480
  end
378
481
 
data/test/tc_rr-opt.rb CHANGED
@@ -28,26 +28,29 @@ class TestRrOpt < Minitest::Test
28
28
  # This works only with send_plain_message, not send_message, query, etc.
29
29
  def test_plain_respects_bufsize
30
30
 
31
- resolver = Resolver.new('a.gtld-servers.net')
31
+ resolver = Resolver.new('a.gtld-servers.net')
32
+ resolver.query_timeout=20
32
33
 
33
34
  run_test = ->(bufsize) do
34
35
 
36
+
35
37
  create_test_query = ->(bufsize) do
36
- message = Message.new('com', Types.ANY, Classes.IN)
38
+ message = Message.new('com', Types.RRSIG, Classes.IN)
37
39
  message.add_additional(RR::OPT.new(bufsize))
38
40
  message
39
41
  end
40
42
 
41
43
  query = create_test_query.(bufsize)
42
44
  response, _error = resolver.send_plain_message(query)
43
- # puts "\nBufsize is #{bufsize}, binary message size is #{response.encode.size}"
45
+ if (_error != nil) then
46
+ print "Error at #{bufsize} : #{_error}"
47
+ end
48
+ # puts "\nBufsize is #{bufsize}, binary message size is #{response.encode.size}"
44
49
  assert_equal(true, response.header.tc)
45
50
  assert(response.encode.size <= bufsize)
46
51
  end
47
52
 
48
- run_test.(512)
49
53
  run_test.(612)
50
- run_test.(4096)
51
54
  end
52
55
 
53
56
 
data/test/tc_rr-txt.rb CHANGED
@@ -143,7 +143,13 @@ class TestRrTest < Minitest::Test
143
143
 
144
144
  r1 = RR.create("auto._domainkey.cacert.org. 43200 IN TXT \"v=DKIM1\;g=*\;k=rsa\;p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDDNFxiNr+NHJwih3OPhGr4iwLE+BBDu72YrMSzUnU1FF50CW7iOtuhg796UZ6xrZ5VuhAix6YmmzcvF2UxYzoD/XpfZ4MzBu0ND4/nkt9/YOTyIBzwQqn9uMNve0Y76Zsel89dIJtOI+y+lfnFExV0jKwe53gzmxMVpMSSCcZPGwIDAQAB\" ; ----- DKIM auto for cacert.org")
145
145
  r2 = RR.create("auto._domainkey.cacert.org. 43200 IN TXT \"v=DKIM1;g=*;k=rsa;p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDDNFxiNr+NHJwih3OPhGr4iwLE+BBDu72YrMSzUnU1FF50CW7iOtuhg796UZ6xrZ5VuhAix6YmmzcvF2UxYzoD/XpfZ4MzBu0ND4/nkt9/YOTyIBzwQqn9uMNve0Y76Zsel89dIJtOI+y+lfnFExV0jKwe53gzmxMVpMSSCcZPGwIDAQAB\"")
146
- assert(r1.to_s == r2.to_s)
146
+ assert_equal(r1.to_s, r2.to_s)
147
+ end
148
+
149
+ def test_quote_and_unquoted
150
+ t = Dnsruby::RR::TXT.parse '"a" b'
151
+ assert_equal("a", t[0])
152
+ assert_equal("b", t[1])
147
153
  end
148
154
 
149
155
  end