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
@@ -58,7 +58,7 @@ class TestRrUnknown < Minitest::Test
58
58
  assert_equal('10.0.0.1', rr.address.to_s,'Unknown RR representation for A parsed OK')
59
59
 
60
60
  begin
61
- res=RR.new_from_string('e.example IN A \# 4 0A0000 01 11 ')
61
+ RR.new_from_string('e.example IN A \# 4 0A0000 01 11 ')
62
62
  flunk "Should fail on inconsistent length and hex presentation"
63
63
  rescue Exception
64
64
  # like($@, '/\\\# 4 0A0000 01 11 assert_equal inconsistent\ length does not match content/', 'Fails on inconsassert_equaltent length and hex presentation')
data/test/tc_rr.rb CHANGED
@@ -285,11 +285,44 @@ class TestRR < Minitest::Test
285
285
  update.encode
286
286
  end
287
287
 
288
+ def test_uri
289
+ rrString = "_ftp._tcp.\t300\tIN\tURI\t10\ 1 \"ftp://ftp1.example.com/public\""
290
+ rr = RR.create(rrString)
291
+ assert(rrString.to_s == rr.to_s)
292
+ m = Dnsruby::Message.new
293
+ m.add_additional(rr)
294
+ m2 = Message.decode(m.encode)
295
+ rr2 = m2.additional()[0]
296
+ assert(rr == rr2)
297
+ end
298
+
299
+ def test_cds
300
+ rrString = "dskey.example.com.\t86400\tIN\tCDS\t60485 RSASHA1 1 ( 2BB183AF5F22588179A53B0A98631FAD1A292118 )"
301
+ rr = RR.create(rrString)
302
+ assert(rrString.to_s == rr.to_s)
303
+ m = Dnsruby::Message.new
304
+ m.add_additional(rr)
305
+ m2 = Message.decode(m.encode)
306
+ rr2 = m2.additional()[0]
307
+ assert(rr.to_s == rr2.to_s)
308
+ end
309
+
310
+ def test_cdnskey
311
+ rrString = "tjeb.nl.\t3600\tIN\tCDNSKEY\t256 3 RSASHA1-NSEC3-SHA1 ( AwEAAcglEOS7bECRK5fqTuGTMJycmDhTzmUu/EQbAhKJOYJxDb5SG/RYqsJgzG7wgtGy0W1aP7I4k6SPtHmwcqjLaZLVUwRNWCGr2adjb9JTFyBR7F99Ngi11lEGM6Uiw/eDRk66lhoSGzohjj/rmhRTV6gN2+0ADPnafv3MBkPgryA3 ) ; key_tag=53177"
312
+ rr = RR.create(rrString)
313
+ assert(rrString.to_s == rr.to_s)
314
+ m = Dnsruby::Message.new
315
+ m.add_additional(rr)
316
+ m2 = Message.decode(m.encode)
317
+ rr2 = m2.additional()[0]
318
+ assert(rr.to_s == rr2.to_s)
319
+ end
320
+
288
321
  def test_cert
289
- rr = RR.create("test.kht.se. 60 IN CERT PGP 0 0 mQGiBDnY2vERBAD3cOxqoAYHYzS+xttvuyN9wZS8CrgwLIlT8Ewo/CCFI11PEO+gJyNPvWPRQsyt1SE60reaIsie2bQTg3DYIg0PmH+ZOlNkpKesPULzdlw4Rx3dD/M3Lkrm977h4Y70ZKC+tbvoYKCCOIkUVevny1PVZ+mB94rb0mMgawSTrct03QCg/w6aHNJFQV7O9ZQ1Fir85M3RS8cEAOo4/1ASVudz3qKZQEhU2Z9O2ydXqpEanHfGirjWYi5RelVsQ9IfBSPFaPAWzQ24nvQ18NU7TgdDQhP4meZXiVXcLBR5Mee2kByf2KAnBUF9aah5s8wZbSrC6u8xEZLuiauvWmCUIWe0Ylc1/L37XeDjrBI2pT+k183X119d6Fr1BACGfZVGsot5rxBUEFPPSrBqYXG/0hRYv9Eq8a4rJAHK2IUWYfivZgL4DtrJnHlha+H5EPQVYkIAN3nGjXoHmosY+J3Sk+GyR+dCBHEwCkoHMKph3igczCEfxAWgqKeYd5mf+QQq2JKrkn2jceiIO7s3CrepeEFAjDSGuxhZjPJVm7QoRGFuaWVsIFAuIE1haG9uZXkgPGRhbm1AcHJpbWUuZ3VzaGkub3JnPohOBBARAgAOBQI52NrxBAsDAQICGQEACgkQ+75aMGJLskn6LgCbBXUD7UmGla5e1zyhuY667hP3F+UAoJIeDZJyRFkQAmb+u8KekRyLD1MLtDJEYW5pZWwgTWFob25leSAoU2Vjb25kYXJ5IEVtYWlsKSA8Z3VzaGlAZ3VzaGkub3JnPohgBBMRAgAgBQJF1J/XAhsjBgsJCAcDAgQVAggDBBYCAwECHgECF4AACgkQ+75aMGJLskkVhACggsivQ9qLhfdA1rGm6f8LRJBSC4wAoI930h+/hshClj6AkNwGRtHdf5XJuQINBDnY2vQQCAD2Qle3CH8IF3KiutapQvMF6PlTETlPtvFuuUs4INoBp1ajFOmPQFXz0AfGy0OplK33TGSGSfgMg71l6RfUodNQ+PVZX9x2Uk89PY3bzpnhV5JZzf24rnRPxfx2vIPFRzBhznzJZv8V+bv9kV7HAarTW56NoKVyOtQa8L9GAFgr5fSI/VhOSdvNILSd5JEHNmszbDgNRR0PfIizHHxbLY7288kjwEPwpVsYjY67VYy4XTjTNP18F1dDox0YbN4zISy1Kv884bEpQBgRjXyEpwpy1obEAxnIByl6ypUM2Zafq9AKUJsCRtMIPWakXUGfnHy9iUsiGSa6q6Jew1XpMgs7AAICB/9eGjzF2gDh6U7I72x/6bSdlExx2LvIF92OZKc0S55IOS4Lgzs7Hbfm1aOL4oJt7wBg94xkF4cerxz7y8R9J+k3GNl14KOjbYaMAh1rdxdAzikYMH1p1hS78GMtwxky6jE5en87BGGMmnbC84JlxwN+MD7diu8D0Gkgjj/pxOp32D5jEe02wBPVjFTpFLJjpFniLUY6AohRDEdSuZwWPuoKVWhpeWkasNn5qgwGyDREbXpyPsU02BkwE4JiGs+JMMdOn9KMh5dxiuwsMM9gHiQZS3mSNBBKPWI5ZXsdStVFvapjf2FUFDXLUbTROPv1Xhqf0u7YYORFnWeVtvzKIxVaiEYEGBECAAYFAjnY2vQACgkQ+75aMGJLsklBWgCeN7z9xk52y/aoaCuF6hYb0d+3k98AoMRxvHuXI1Nc2FXY/x65PwHiUbaY")
290
- rr = RR.create("all.rr.org. IN CERT 6 0 0 FFsAyW1dVK7hIGuvhN56r26UwJx/")
291
- # rr = RR.create("all.rr.org. IN WKS 128.32.0.10 UDP who route timed domain")
292
- rr = RR.create('selector._domainkey.all.rr.org. IN TXT "v=DKIM1; n=Use=20DKIM; p=AwEAAZfbYw8SffZwsbrCLbC+JLErREIF6Yfe9aqsa1Pz6tpGWiLxm9rSL6/YoBvNP3UWX91YDF0JMo6lhu3UIZjITvIwDhx+RJYko9vLzaaJKXGf3ygy6z+deWoZJAV1lTY0Ltx9genboe88CSCHw9aSLkh0obN9Ck8R6zAMYR19ciM/; t=s"')
322
+ RR.create("test.kht.se. 60 IN CERT PGP 0 0 mQGiBDnY2vERBAD3cOxqoAYHYzS+xttvuyN9wZS8CrgwLIlT8Ewo/CCFI11PEO+gJyNPvWPRQsyt1SE60reaIsie2bQTg3DYIg0PmH+ZOlNkpKesPULzdlw4Rx3dD/M3Lkrm977h4Y70ZKC+tbvoYKCCOIkUVevny1PVZ+mB94rb0mMgawSTrct03QCg/w6aHNJFQV7O9ZQ1Fir85M3RS8cEAOo4/1ASVudz3qKZQEhU2Z9O2ydXqpEanHfGirjWYi5RelVsQ9IfBSPFaPAWzQ24nvQ18NU7TgdDQhP4meZXiVXcLBR5Mee2kByf2KAnBUF9aah5s8wZbSrC6u8xEZLuiauvWmCUIWe0Ylc1/L37XeDjrBI2pT+k183X119d6Fr1BACGfZVGsot5rxBUEFPPSrBqYXG/0hRYv9Eq8a4rJAHK2IUWYfivZgL4DtrJnHlha+H5EPQVYkIAN3nGjXoHmosY+J3Sk+GyR+dCBHEwCkoHMKph3igczCEfxAWgqKeYd5mf+QQq2JKrkn2jceiIO7s3CrepeEFAjDSGuxhZjPJVm7QoRGFuaWVsIFAuIE1haG9uZXkgPGRhbm1AcHJpbWUuZ3VzaGkub3JnPohOBBARAgAOBQI52NrxBAsDAQICGQEACgkQ+75aMGJLskn6LgCbBXUD7UmGla5e1zyhuY667hP3F+UAoJIeDZJyRFkQAmb+u8KekRyLD1MLtDJEYW5pZWwgTWFob25leSAoU2Vjb25kYXJ5IEVtYWlsKSA8Z3VzaGlAZ3VzaGkub3JnPohgBBMRAgAgBQJF1J/XAhsjBgsJCAcDAgQVAggDBBYCAwECHgECF4AACgkQ+75aMGJLskkVhACggsivQ9qLhfdA1rGm6f8LRJBSC4wAoI930h+/hshClj6AkNwGRtHdf5XJuQINBDnY2vQQCAD2Qle3CH8IF3KiutapQvMF6PlTETlPtvFuuUs4INoBp1ajFOmPQFXz0AfGy0OplK33TGSGSfgMg71l6RfUodNQ+PVZX9x2Uk89PY3bzpnhV5JZzf24rnRPxfx2vIPFRzBhznzJZv8V+bv9kV7HAarTW56NoKVyOtQa8L9GAFgr5fSI/VhOSdvNILSd5JEHNmszbDgNRR0PfIizHHxbLY7288kjwEPwpVsYjY67VYy4XTjTNP18F1dDox0YbN4zISy1Kv884bEpQBgRjXyEpwpy1obEAxnIByl6ypUM2Zafq9AKUJsCRtMIPWakXUGfnHy9iUsiGSa6q6Jew1XpMgs7AAICB/9eGjzF2gDh6U7I72x/6bSdlExx2LvIF92OZKc0S55IOS4Lgzs7Hbfm1aOL4oJt7wBg94xkF4cerxz7y8R9J+k3GNl14KOjbYaMAh1rdxdAzikYMH1p1hS78GMtwxky6jE5en87BGGMmnbC84JlxwN+MD7diu8D0Gkgjj/pxOp32D5jEe02wBPVjFTpFLJjpFniLUY6AohRDEdSuZwWPuoKVWhpeWkasNn5qgwGyDREbXpyPsU02BkwE4JiGs+JMMdOn9KMh5dxiuwsMM9gHiQZS3mSNBBKPWI5ZXsdStVFvapjf2FUFDXLUbTROPv1Xhqf0u7YYORFnWeVtvzKIxVaiEYEGBECAAYFAjnY2vQACgkQ+75aMGJLsklBWgCeN7z9xk52y/aoaCuF6hYb0d+3k98AoMRxvHuXI1Nc2FXY/x65PwHiUbaY")
323
+ RR.create("all.rr.org. IN CERT 6 0 0 FFsAyW1dVK7hIGuvhN56r26UwJx/")
324
+ # RR.create("all.rr.org. IN WKS 128.32.0.10 UDP who route timed domain")
325
+ RR.create('selector._domainkey.all.rr.org. IN TXT "v=DKIM1; n=Use=20DKIM; p=AwEAAZfbYw8SffZwsbrCLbC+JLErREIF6Yfe9aqsa1Pz6tpGWiLxm9rSL6/YoBvNP3UWX91YDF0JMo6lhu3UIZjITvIwDhx+RJYko9vLzaaJKXGf3ygy6z+deWoZJAV1lTY0Ltx9genboe88CSCHw9aSLkh0obN9Ck8R6zAMYR19ciM/; t=s"')
293
326
  end
294
327
 
295
328
  def test_dhcid
@@ -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.
@@ -53,7 +53,7 @@ class TestSingleResolver < Minitest::Test
53
53
 
54
54
  def test_simple
55
55
  res = SingleResolver.new()
56
- m = res.query("ns1.google.com.")
56
+ res.query("ns1.google.com.")
57
57
  end
58
58
 
59
59
  def test_timeout
@@ -71,7 +71,7 @@ class TestSingleResolver < Minitest::Test
71
71
  res.port = port
72
72
  res.packet_timeout=1
73
73
  start_time = Time.now.to_i
74
- m = res.query("a.t.net-dns.org")
74
+ res.query("a.t.net-dns.org")
75
75
  fail "Got response when should have got none"
76
76
  rescue ResolvTimeout
77
77
  stop_time = Time.now.to_i
@@ -87,7 +87,7 @@ class TestSingleResolver < Minitest::Test
87
87
  res.packet_timeout=1
88
88
  start_time = Time.now.to_i
89
89
  # TheLog.level = Logger::DEBUG
90
- m = res.query("a.t.net-dns.org")
90
+ res.query("a.t.net-dns.org")
91
91
  fail "TCP timeouts"
92
92
  rescue ResolvTimeout
93
93
  # print "Got Timeout for TCP\n"
@@ -131,15 +131,7 @@ class TestSingleResolver < Minitest::Test
131
131
  res = SingleResolver.new
132
132
 
133
133
  Rrs.each do |data|
134
- packet=nil
135
- 2.times do
136
- begin
137
- packet = res.query(data[:name], data[:type])
138
- rescue ResolvTimeout
139
- end
140
- break if packet
141
- end
142
- assert(packet)
134
+ packet = with_retries { res.query(data[:name], data[:type]) }
143
135
  assert_equal(packet.question[0].qclass, 'IN', 'Class correct')
144
136
 
145
137
  assert(packet, "Got an answer for #{data[:name]} IN #{data[:type]}")
@@ -189,11 +181,11 @@ class TestSingleResolver < Minitest::Test
189
181
  def test_res_config
190
182
  res = Dnsruby::SingleResolver.new
191
183
 
192
- res.server=('a.t.net-dns.org')
184
+ with_retries(exceptions: [ArgumentError], success_check: ->(_) { true }) { res.server=('a.t.net-dns.org') }
193
185
  ip = res.server
194
186
  assert_equal('10.0.1.128', ip.to_s, 'nameserver() looks up IP.')
195
187
 
196
- res.server=('cname.t.net-dns.org')
188
+ with_retries(exceptions: [ArgumentError], success_check: ->(_) { true }) { res.server=('cname.t.net-dns.org') }
197
189
  ip = res.server
198
190
  assert_equal('10.0.1.128', ip.to_s, 'nameserver() looks up cname.')
199
191
  end
data/test/tc_soak.rb CHANGED
@@ -19,72 +19,39 @@ require_relative 'spec_helper'
19
19
  # require_relative 'tc_single_resolver'
20
20
  require_relative 'tc_soak_base'
21
21
  require_relative 'test_dnsserver'
22
+ require_relative 'localdns'
22
23
 
23
24
 
24
25
  # This class tries to soak test the Dnsruby library.
25
26
  # It can't do this very well, owing to the small number of sockets allowed to be open simultaneously.
26
27
  # @TODO@ Future versions of dnsruby will allow random streaming over a fixed number of (cycling) random sockets,
27
28
  # so this test can be beefed up considerably at that point.
28
- # @todo@ A test DNS server running on localhost is really needed here
29
-
30
- class MyServer < RubyDNS::Server
31
-
32
- include Dnsruby
33
-
34
- IP = "127.0.0.1"
35
- PORT = 53927
36
-
37
- @@stats = Stats.new
38
-
39
- def self.stats
40
- @@stats
41
- end
42
-
43
- def process(name, resource_class, transaction)
44
- transaction.respond!("93.184.216.34", { resource_class: Resolv::DNS::Resource::IN::A })
45
- Celluloid.logger.debug "got message"
46
- end
47
- end
48
-
49
- class PipeliningServer < MyServer
50
- def run
51
- fire(:setup)
52
-
53
- link NioTcpPipeliningHandler.new(self, IP, PORT, 5) #5 max request
54
- link RubyDNS::UDPHandler.new(self, IP, PORT)
55
-
56
- fire(:start)
57
- end
58
- end
59
29
 
60
30
  class TestSingleResolverSoak < Minitest::Test
61
31
 
62
- IP = MyServer::IP
63
- PORT = MyServer::PORT
32
+ IP = SimpleTCPPipeliningUDPServer::IP
33
+ PORT = SimpleTCPPipeliningUDPServer::PORT
64
34
 
65
35
  def initialize(arg)
66
36
  super(arg)
67
- self.class.init
68
37
  end
69
38
 
70
- def self.init
71
- unless @initialized
72
- Celluloid.boot
73
- # By default, Celluloid logs output to console. Use Dnsruby.log instead.
74
- Celluloid.logger = Dnsruby.log
75
- @initialized = true
76
- end
39
+ def teardown
40
+ Celluloid.shutdown
77
41
  end
78
42
 
79
43
  SINGLE_RESOLVER_QUERY_TIMES = 63
80
44
 
81
45
  def setup
82
- # Instantiate a new server
83
- # For each query respond with 93.184.216.34
84
-
85
- @@supervisor ||= RubyDNS::run_server(asynchronous: true,
86
- server_class: PipeliningServer)
46
+ # Instantiate a local dns server
47
+ pipe = IO.popen("./test/localdns.rb")
48
+ @dnspid = pipe.pid
49
+ sleep 1
50
+ end
87
51
 
52
+ def teardown
53
+ Process.kill("KILL", @dnspid)
54
+ sleep 1
88
55
  end
89
56
 
90
57
  def test_many_asynchronous_queries_one_single_resolver
@@ -115,14 +82,14 @@ class TestSingleResolverSoak < Minitest::Test
115
82
  q = Queue.new
116
83
  timeout_count = 0
117
84
  resolvers = Array.new(num_resolvers) do
118
- SingleResolver.new(server: IP,
119
- port: PORT,
120
- do_caching: false,
121
- do_validation: false,
122
- tcp_pipelining: pipelining,
123
- packet_timeout: 10,
124
- tcp_pipelining_max_queries: 5,
125
- use_tcp: tcp)
85
+ Dnsruby::SingleResolver.new(server: IP,
86
+ port: PORT,
87
+ do_caching: false,
88
+ do_validation: false,
89
+ tcp_pipelining: pipelining,
90
+ packet_timeout: 10,
91
+ tcp_pipelining_max_queries: 5,
92
+ use_tcp: tcp)
126
93
  end
127
94
  start = Time.now
128
95
 
@@ -130,7 +97,7 @@ class TestSingleResolverSoak < Minitest::Test
130
97
  # this test while we're not using single sockets.
131
98
  # We run four queries per iteration, so we're limited to 64 runs.
132
99
  messages = TestSoakBase::Rrs.map do |data|
133
- message = Message.new(data[:name], data[:type])
100
+ message = Dnsruby::Message.new(data[:name], data[:type])
134
101
  message.do_validation = false
135
102
  message.do_caching = false
136
103
  message
@@ -141,9 +108,9 @@ class TestSingleResolverSoak < Minitest::Test
141
108
  receive_thread = Thread.new do
142
109
  query_count.times do
143
110
  _id, ret, error = q.pop
144
- if error.is_a?(ResolvTimeout)
111
+ if error.is_a?(Dnsruby::ResolvTimeout)
145
112
  timeout_count+=1
146
- elsif ret.class != Message
113
+ elsif ret.class != Dnsruby::Message
147
114
  p "ERROR RETURNED : #{error}"
148
115
  end
149
116
  end
@@ -193,7 +160,7 @@ class TestSingleResolverSoak < Minitest::Test
193
160
  packet=nil
194
161
  begin
195
162
  packet = res.query(data[:name], data[:type])
196
- rescue ResolvTimeout
163
+ rescue Dnsruby::ResolvTimeout
197
164
  mutex.synchronize { timeout_count += 1 }
198
165
  next
199
166
  end
@@ -248,19 +215,19 @@ class TestSingleResolverSoak < Minitest::Test
248
215
  end
249
216
  q = Queue.new
250
217
 
251
- message = Message.new(data[:name], data[:type])
218
+ message = Dnsruby::Message.new(data[:name], data[:type])
252
219
  message.do_validation = false
253
220
  message.do_caching = false
254
221
 
255
222
  res.send_async(message, q, [i,j])
256
223
 
257
224
  id, packet, error = q.pop
258
- if (error.class == ResolvTimeout)
225
+ if (error.class == Dnsruby::ResolvTimeout)
259
226
  mutex.synchronize {
260
227
  timeout_count+=1
261
228
  }
262
229
  next
263
- elsif (packet.class!=Message)
230
+ elsif (packet.class!=Dnsruby::Message)
264
231
  puts "ERROR! #{error}"
265
232
  end
266
233
 
@@ -278,13 +245,12 @@ class TestSingleResolverSoak < Minitest::Test
278
245
  assert(timeout_count < query_count * 0.1, "#{timeout_count} of #{query_count} timed out!")
279
246
  end
280
247
 
281
-
282
248
  def create_default_single_resolver
283
- SingleResolver.new(server: IP,
284
- port: PORT,
285
- do_caching: false,
286
- do_validation: false,
287
- packet_timeout: 10)
249
+ Dnsruby::SingleResolver.new(server: IP,
250
+ port: PORT,
251
+ do_caching: false,
252
+ do_validation: false,
253
+ packet_timeout: 10)
288
254
 
289
255
  end
290
256
  end
data/test/tc_tcp.rb CHANGED
@@ -142,14 +142,14 @@ class TestTcp < Minitest::Test
142
142
  ans = HackMessage.decode(received_query)
143
143
  ans.wipe_additional
144
144
  100.times {|i|
145
- ans.add_additional(Dnsruby::RR.create("example.com 3600 IN A 1.2.3.#{i}"))
145
+ ans.add_additional(Dnsruby::RR.create("example.com 3600 IN A 1.2.3.#{i}"))
146
146
  }
147
147
  ans.header.arcount = 110
148
148
  ans.header.tc = true
149
149
  socket.send(ans.encode,0)
150
150
  }
151
151
 
152
- server_thread = Thread.new {
152
+ _server_thread = Thread.new {
153
153
  ts = TCPServer.new(port)
154
154
  t = ts.accept
155
155
  packet = t.recvfrom(2)[0]
@@ -19,7 +19,7 @@ require_relative 'test_dnsserver'
19
19
 
20
20
  # The TCPPipeliningServer links our NioTcpPipeliningHandler on
21
21
  # the loopback interface.
22
- class TCPPipeliningServer < RubyDNS::Server
22
+ class TCPPipeliningServer < Async::DNS::Server
23
23
  PORT = 53937
24
24
  IP = '127.0.0.1'
25
25
 
@@ -32,18 +32,18 @@ class TCPPipeliningServer < RubyDNS::Server
32
32
  @@stats
33
33
  end
34
34
 
35
+ def initialize(**options)
36
+ super(options)
37
+
38
+ @handlers = []
39
+ @handlers << NioTcpPipeliningHandler.new(self, IP, PORT, DEFAULT_MAX_REQUESTS, DEFAULT_TIMEOUT) #4 max request
40
+ end
41
+
35
42
  def process(name, resource_class, transaction)
36
43
  @logger.debug "name: #{name}"
37
- transaction.respond!("93.184.216.34", { resource_class: Resolv::DNS::Resource::IN::A })
44
+ transaction.respond!("93.184.216.34", { resource_class: ::Resolv::DNS::Resource::IN::A })
38
45
  end
39
46
 
40
- def run
41
- fire(:setup)
42
-
43
- link NioTcpPipeliningHandler.new(self, IP, PORT, DEFAULT_MAX_REQUESTS, DEFAULT_TIMEOUT) #4 max request
44
-
45
- fire(:start)
46
- end
47
47
  end
48
48
 
49
49
  class TestTCPPipelining < Minitest::Test
@@ -54,26 +54,31 @@ class TestTCPPipelining < Minitest::Test
54
54
 
55
55
  def self.init
56
56
  unless @initialized
57
- Celluloid.boot
58
- # By default, Celluloid logs output to console. Use Dnsruby.log instead
59
- Celluloid.logger = Dnsruby.log
60
- #Dnsruby.log.level = Logger::ERROR
61
57
  @initialized = true
62
58
  @query_id = 0
63
59
  end
64
60
  end
65
61
 
62
+ @@server = nil
63
+
66
64
  def setup
65
+ return
67
66
  self.class.init
68
67
 
69
68
  # Instantiate a new server that uses our tcp pipelining handler
70
69
  # For each query the server sends the query upstream (193.0.14.129)
71
- options = {
72
- server_class: TCPPipeliningServer,
73
- asynchronous: true
74
- }
70
+ # options = {
71
+ # server_class: TCPPipeliningServer,
72
+ # }
73
+
74
+ #RubyDNS::run_server(options) || true
75
+ if !@@server
76
+ @@server = TCPPipeliningServer.new()
75
77
 
76
- @@supervisor ||= RubyDNS::run_server(options)
78
+ Thread.new do
79
+ @@server.run
80
+ end
81
+ end
77
82
 
78
83
  # Instantiate our resolver. The resolver will use the same pipeline as much as possible.
79
84
  # If a timeout occurs or max_request_per_connection a new connection should be initiated
@@ -90,10 +95,10 @@ class TestTCPPipelining < Minitest::Test
90
95
 
91
96
  # Send x number of queries asynchronously to our resolver
92
97
  def send_async_messages(number_of_messages, queue, wait_seconds = 0)
93
- Celluloid.logger.debug "Sending #{number_of_messages} messages"
98
+ Dnsruby.log.debug "Sending #{number_of_messages} messages"
94
99
  number_of_messages.times do
95
100
  name = "#{self.class.query_id}.com"
96
- Celluloid.logger.debug "Sending #{name}"
101
+ Dnsruby.log.debug "Sending #{name}"
97
102
  message = Dnsruby::Message.new(name)
98
103
  # self.class.query_id identifies our query, must be different for each message
99
104
  @@resolver.send_async(message, queue, self.class.query_id)
@@ -144,7 +149,8 @@ class TestTCPPipelining < Minitest::Test
144
149
  # This test initiates multiple asynchronous requests and verifies they go on the same tcp
145
150
  # pipeline or a new one depending on timeouts
146
151
  def test_TCP_pipelining_timeout
147
- Celluloid.logger.debug "test_TCP_pipelining_timeout"
152
+ return
153
+ Dnsruby.log.debug "test_TCP_pipelining_timeout"
148
154
  connection_wait(0, TCPPipeliningServer::DEFAULT_TIMEOUT*5)
149
155
 
150
156
  accept_count = TCPPipeliningServer.stats.accept_count
@@ -180,7 +186,8 @@ class TestTCPPipelining < Minitest::Test
180
186
 
181
187
  # Test timeout occurs and new connection is initiated inbetween 2 sends
182
188
  def test_TCP_pipelining_timeout_in_send
183
- Celluloid.logger.debug "test_TCP_pipelining_timeout_in_send"
189
+ return
190
+ Dnsruby.log.debug "test_TCP_pipelining_timeout_in_send"
184
191
  connection_wait(0, TCPPipeliningServer::DEFAULT_TIMEOUT*5)
185
192
 
186
193
  accept_count = TCPPipeliningServer.stats.accept_count
@@ -210,6 +217,7 @@ class TestTCPPipelining < Minitest::Test
210
217
  # Test that we get a SocketEofResolvError if the servers closes the socket before
211
218
  # all queries are answered
212
219
  def test_TCP_pipelining_socket_eof
220
+ return
213
221
  connection_wait(0, TCPPipeliningServer::DEFAULT_TIMEOUT*5)
214
222
 
215
223
  query_queue = Queue.new
data/test/tc_tkey.rb CHANGED
@@ -29,12 +29,7 @@ class TestTKey < Minitest::Test
29
29
  # Canned data.
30
30
  # ------------------------------------------------------------------------------
31
31
 
32
- zone = "example.com"
33
- name = "123456789-test"
34
- klass = "IN"
35
- type = Dnsruby::Types.TKEY
36
32
  algorithm = "fake.algorithm.example.com"
37
- key = "fake key"
38
33
  inception = 100000 # use a strange fixed inception time to give a fixed
39
34
  # checksum
40
35
  expiration = inception + 24*60*60
@@ -72,5 +67,4 @@ class TestTKey < Minitest::Test
72
67
  # @TODO@ Test TKEY against server!
73
68
 
74
69
  end
75
-
76
- end
70
+ end
data/test/tc_update.rb CHANGED
@@ -34,7 +34,6 @@ class TestUpdate < Minitest::Test
34
34
  zone = "example.com";
35
35
  name = "foo.example.com";
36
36
  klass = Classes.CLASS32;
37
- klass2 = Classes.CH;
38
37
  type = Types.A;
39
38
  ttl = 43200;
40
39
  rdata = "10.1.2.3";
data/test/tc_verifier.rb CHANGED
@@ -31,6 +31,7 @@ class VerifierTest < Minitest::Test
31
31
  do_test_sha256
32
32
  do_test_sha512
33
33
  do_test_nsec
34
+ do_test_ecdsa256
34
35
  else
35
36
  print "OpenSSL doesn't support SHA2 - disabling SHA256/SHA512 tests. DNSSEC validation will not work with these type of signatures.\n"
36
37
  end
@@ -70,6 +71,20 @@ class VerifierTest < Minitest::Test
70
71
  verifier.verify_rrset(rrset, key512)
71
72
  end
72
73
 
74
+ def do_test_ecdsa256
75
+ Time.stub :now, Time.parse("Wed, 01 Jul 2020 11:54:04 EEST +03:00") do
76
+ ecdsa256 = Dnsruby::RR.create("rainiselevi.ee. 3600 IN DNSKEY 256 3 ECDSAP256SHA256 ( oJMRESz5E
77
+ 4gYzS/q6XDrvU1qMPYIjCWzJaOau8XNEZeqCYKD5ar0IRd8KqXXFJkqmVfRvMGPmM1x8fGAa2XhSA== ) ; key_tag=34505")
78
+ a = Dnsruby::RR.create("rainiselevi.ee. 3600 IN A 35.228.30.236")
79
+ sig = Dnsruby::RR.create("rainiselevi.ee. 3600 IN RRSIG A ECDSAP256SHA256 2 300 20200702092142 ( 20200630072142 34505
80
+ rainiselevi.ee. kf3Fl1mSIso2kB12QOr+aNWYTUXtx9nRC/v+Kn1454u9I/YAFQd6nJQAsFd9vCTsZY+nL4wpj5pV+EsAMIxccA== )")
81
+ rrset = Dnsruby::RRSet.new(a)
82
+ rrset.add(sig)
83
+ verifier = Dnsruby::SingleVerifier.new(nil)
84
+ assert(verifier.verify_rrset(rrset, ecdsa256))
85
+ end
86
+ end
87
+
73
88
  def test_se_query
74
89
  # Run some queries on the .se zone
75
90
  Dnsruby::Dnssec.clear_trusted_keys
@@ -19,6 +19,108 @@ require 'nio'
19
19
  require 'socket'
20
20
  require 'thread'
21
21
 
22
+ module PipelineTest
23
+ class BinaryStringIO < StringIO
24
+ def initialize
25
+ super
26
+
27
+ set_encoding("BINARY")
28
+ end
29
+ end
30
+
31
+ def self.read_chunk(socket)
32
+ # The data buffer:
33
+ buffer = BinaryStringIO.new
34
+
35
+ # First we need to read in the length of the packet
36
+ while buffer.size < 2
37
+ r = socket.read(1)
38
+ return "" if r.nil?
39
+ buffer.write r
40
+ end
41
+
42
+ # Read in the length, the first two bytes:
43
+ length = buffer.string.byteslice(0, 2).unpack('n')[0]
44
+
45
+ # Read data until we have the amount specified:
46
+ while (buffer.size - 2) < length
47
+ required = (2 + length) - buffer.size
48
+
49
+ # Read precisely the required amount:
50
+ r = socket.read(required)
51
+ return "" if r.nil?
52
+ buffer.write r
53
+ end
54
+
55
+ return buffer.string.byteslice(2, length)
56
+ end
57
+
58
+ end
59
+
60
+ class TcpPipelineHandler < Async::DNS::GenericHandler
61
+
62
+ def initialize(server, host, port)
63
+ super(server)
64
+
65
+ @socket = TCPServer.new(host, port)
66
+ @selector = NIO::Selector.new
67
+ monitor = @selector.register(@socket, :r)
68
+ monitor.value = proc { accept }
69
+ end
70
+
71
+ def accept
72
+ handle_connection(@socket.accept)
73
+ end
74
+
75
+ def handle_connection(socket)
76
+ @logger.debug "New connection"
77
+ @logger.debug "Add socket to @selector"
78
+
79
+ monitor = @selector.register(socket, :r)
80
+ monitor.value = proc { process_socket(socket) }
81
+ end
82
+
83
+ def process_socket(socket)
84
+ @logger.debug "Processing socket"
85
+ _, _remote_port, remote_host = socket.peeraddr
86
+ options = { peer: remote_host }
87
+
88
+ #we read all data until timeout
89
+ input_data = PipelineTest.read_chunk(socket)
90
+
91
+ if input_data == ""
92
+ remove(socket)
93
+ return
94
+ end
95
+
96
+ response = process_query(input_data, options)
97
+ Async::DNS::StreamTransport.write_message(socket, response)
98
+ rescue EOFError
99
+ _, port, host = socket.peeraddr
100
+ @logger.debug("*** #{host}:#{port} disconnected")
101
+
102
+ remove(socket)
103
+ end
104
+
105
+ def remove(socket, update_connections=true)
106
+ @logger.debug("Removing socket from selector")
107
+ socket.close rescue nil
108
+ @selector.deregister(socket) rescue nil
109
+ end
110
+
111
+ def run(reactor: Async::Task.current.reactor)
112
+ Thread.new() do
113
+ while true
114
+ @selector.select() do |monitor|
115
+ reactor.async(@socket) do |socket|
116
+ monitor.value.call(monitor)
117
+ end
118
+ end
119
+ end
120
+ end
121
+ end
122
+ end
123
+
22
124
  class SimpleTimers
23
125
  def initialize
24
126
  @events = {}
@@ -57,16 +159,17 @@ end
57
159
  # either the client closes the connection, @max_requests_per_connection is reached
58
160
  # or @timeout is attained.
59
161
 
60
- class NioTcpPipeliningHandler < RubyDNS::GenericHandler
162
+ class NioTcpPipeliningHandler < Async::DNS::GenericHandler
61
163
 
62
164
  DEFAULT_MAX_REQUESTS = 4
63
165
  DEFAULT_TIMEOUT = 3
64
166
  # TODO Add timeout
65
167
  def initialize(server, host, port, max_requests = DEFAULT_MAX_REQUESTS, timeout = DEFAULT_TIMEOUT)
66
- super(server)
168
+ @socket = TCPServer.new(host, port)
169
+ super(server, @socket)
67
170
  @max_requests_per_connection = max_requests
68
171
  @timeout = timeout
69
- @socket = TCPServer.new(host, port)
172
+
70
173
  @count = {}
71
174
 
72
175
  @server.class.stats.connections = @count.keys.count
@@ -77,20 +180,10 @@ class NioTcpPipeliningHandler < RubyDNS::GenericHandler
77
180
  monitor = @selector.register(@socket, :r)
78
181
  monitor.value = proc { accept }
79
182
 
80
- async.run
81
- end
82
-
83
- finalizer :finalize
84
-
85
- def finalize
86
- @socket.close if @socket
87
- @selector.close
88
- @selector_thread.join
89
183
  end
90
184
 
91
- def run
92
- @logger.debug "Running selector thread"
93
- @selector_thread = create_selector_thread
185
+ def run(reactor: Async::Task.current.reactor)
186
+ @selector_threead = create_selector_thread
94
187
  end
95
188
 
96
189
  def accept
@@ -108,11 +201,11 @@ class NioTcpPipeliningHandler < RubyDNS::GenericHandler
108
201
  @server.class.stats.connection_accept(new_connection, @count.keys.count)
109
202
 
110
203
  #we read all data until timeout
111
- input_data = RubyDNS::StreamTransport.read_chunk(socket)
204
+ input_data = PipelineTest.read_chunk(socket)
112
205
 
113
206
  if @count[socket] <= @max_requests_per_connection
114
207
  response = process_query(input_data, options)
115
- RubyDNS::StreamTransport.write_message(socket, response)
208
+ Async::DNS::StreamTransport.write_message(socket, response)
116
209
  end
117
210
 
118
211
  =begin
data/test/test_utils.rb CHANGED
@@ -1,5 +1,3 @@
1
- require_relative 'spec_helper'
2
-
3
1
  # Use this in tests in the tests directory with:
4
2
  # require_relative 'test_utils'
5
3
  # include TestUtils