dnsruby 1.58.0 → 1.59.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/LICENSE +11 -0
- data/RELEASE_NOTES.md +15 -0
- data/Rakefile +2 -1
- data/demo/axfr.rb +84 -85
- data/demo/check_soa.rb +115 -94
- data/demo/check_zone.rb +69 -64
- data/demo/digdlv.rb +22 -24
- data/demo/digroot.rb +23 -19
- data/demo/example_recurse.rb +20 -6
- data/demo/mresolv.rb +26 -14
- data/demo/mx.rb +21 -11
- data/demo/rubydig.rb +34 -25
- data/demo/trace_dns.rb +22 -16
- data/lib/dnsruby/cache.rb +8 -0
- data/lib/dnsruby/config.rb +1 -1
- data/lib/dnsruby/dnssec.rb +6 -2
- data/lib/dnsruby/message/decoder.rb +1 -0
- data/lib/dnsruby/message/question.rb +1 -1
- data/lib/dnsruby/packet_sender.rb +4 -0
- data/lib/dnsruby/recursor.rb +9 -1
- data/lib/dnsruby/resource/OPT.rb +2 -2
- data/lib/dnsruby/resource/RR.rb +4 -4
- data/lib/dnsruby/select_thread.rb +2 -2
- data/lib/dnsruby/single_verifier.rb +24 -4
- data/lib/dnsruby/update.rb +1 -1
- data/lib/dnsruby/validator_thread.rb +2 -1
- data/lib/dnsruby/version.rb +1 -1
- data/test/tc_axfr.rb +1 -1
- data/test/tc_cache.rb +45 -9
- data/test/tc_dns.rb +64 -50
- data/test/tc_message.rb +17 -1
- data/test/tc_res_config.rb +3 -2
- data/test/tc_resolv.rb +1 -1
- data/test/tc_single_resolver.rb +148 -132
- data/test/ts_online.rb +7 -0
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 30959b577be6d8f64a67832ec6418fd157ece057
|
4
|
+
data.tar.gz: 94af23844c0a0f1d53b405b0720c9253364ad890
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2237405083ea6ba078a24a172d681b8fde6f770d61fab1617cf4683f576ade793af97edadabe2e76fd649dc0d1eb868eb8bd931021b151ad64b8d0f3c99fc271
|
7
|
+
data.tar.gz: b7f1a0e23ca45cbe15410bd604754c26688ca835edb39dcc340ac4aece8d76c3e67d6ed06a9c2c3488caf2d56c6a5d526fca80f1c6933b43c4e3f0f1ff7a6bce
|
data/LICENSE
ADDED
@@ -0,0 +1,11 @@
|
|
1
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
2
|
+
# you may not use this file except in compliance with the License.
|
3
|
+
# You may obtain a copy of the License at
|
4
|
+
#
|
5
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
6
|
+
#
|
7
|
+
# Unless required by applicable law or agreed to in writing, software
|
8
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
9
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
10
|
+
# See the License for the specific language governing permissions and
|
11
|
+
# limitations under the License.
|
data/RELEASE_NOTES.md
CHANGED
@@ -1,5 +1,20 @@
|
|
1
1
|
# Release Notes
|
2
2
|
|
3
|
+
## v1.59.0
|
4
|
+
|
5
|
+
* Add LICENSE file
|
6
|
+
* Add Cache max_size (gihub issue 64)
|
7
|
+
* Disable caching for SOA lookups in demo check_soa.rb
|
8
|
+
* Fix for invalid nameserver in config
|
9
|
+
* Fix encoding for OPT data (thanks Craig Despeaux)
|
10
|
+
* Various test system fixes
|
11
|
+
* OPT fixes
|
12
|
+
* DNSSEC verification failure handling wrt lack of DS chain
|
13
|
+
* DNSSEC validation policy name constants
|
14
|
+
* Fix for BOGUS DLV chains
|
15
|
+
* demo upgrades
|
16
|
+
* Resolver hints improvements
|
17
|
+
|
3
18
|
|
4
19
|
## v1.58.0
|
5
20
|
|
data/Rakefile
CHANGED
@@ -29,4 +29,5 @@ create_task(:test, 'test/ts_dnsruby.rb')
|
|
29
29
|
create_task(:test_offline, 'test/ts_offline.rb')
|
30
30
|
create_task(:test_online, 'test/ts_online.rb')
|
31
31
|
create_task(:soak, 'test/tc_soak.rb')
|
32
|
-
|
32
|
+
create_task(:message, 'test/tc_message.rb')
|
33
|
+
create_task(:cache, 'test/tc_cache.rb')
|
data/demo/axfr.rb
CHANGED
@@ -1,6 +1,9 @@
|
|
1
|
+
#! /usr/bin/env ruby
|
2
|
+
|
1
3
|
# --
|
2
4
|
# Copyright 2007 Nominet UK
|
3
5
|
#
|
6
|
+
|
4
7
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
5
8
|
# you may not use this file except in compliance with the License.
|
6
9
|
# You may obtain a copy of the License at
|
@@ -59,9 +62,16 @@
|
|
59
62
|
# Michael Fuhr <mike@fuhr.org>
|
60
63
|
#
|
61
64
|
|
65
|
+
unless (1..2).include?(ARGV.length)
|
66
|
+
puts "Usage: #{$0} [ -fqs ] [ -D directory ] [ @nameserver ] zone"
|
67
|
+
exit(-1)
|
68
|
+
end
|
69
|
+
|
70
|
+
|
62
71
|
require 'getoptLong'
|
63
72
|
require 'dnsruby'
|
64
73
|
|
74
|
+
|
65
75
|
# ------------------------------------------------------------------------------
|
66
76
|
# Read any command-line options and check syntax.
|
67
77
|
# ------------------------------------------------------------------------------
|
@@ -89,110 +99,99 @@ opts.each do |opt, arg|
|
|
89
99
|
end
|
90
100
|
end
|
91
101
|
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
# Get the nameserver (if specified) and set up the zone transfer directory
|
97
|
-
# hierarchy.
|
98
|
-
# ------------------------------------------------------------------------------
|
99
|
-
|
100
|
-
nameserver = (ARGV[0] =~ /^@/) ? ARGV.shift : ""
|
101
|
-
nameserver = nameserver.sub(/^@/, "")
|
102
|
-
res = nil
|
103
|
-
if nameserver
|
104
|
-
res = Dnsruby::Resolver.new(nameserver)
|
105
|
-
else
|
106
|
-
res = Dnsruby::Resolver.new
|
107
|
-
end
|
102
|
+
# ------------------------------------------------------------------------------
|
103
|
+
# Get the nameserver (if specified) and set up the zone transfer directory
|
104
|
+
# hierarchy.
|
105
|
+
# ------------------------------------------------------------------------------
|
108
106
|
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
zonefile = basedir + "/" + zonedir + "/axfr"
|
107
|
+
nameserver = (ARGV[0] =~ /^@/) ? ARGV.shift : ''
|
108
|
+
nameserver = nameserver.sub(/^@/, '')
|
109
|
+
resolver = nameserver ? Dnsruby::Resolver.new(nameserver) : Dnsruby::Resolver.new
|
113
110
|
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
end
|
111
|
+
zone = ARGV.shift
|
112
|
+
basedir = opt_d || File.join((ENV['HOME'] || ''), '.dns-zones')
|
113
|
+
zonedir = zone.split(/\./).reverse.join("/")
|
114
|
+
zonefile = File.join(basedir, zonedir, 'axfr')
|
119
115
|
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
end
|
116
|
+
# Don't worry about the 0777 permissions here - the current umask setting
|
117
|
+
# will be applied.
|
118
|
+
# NOTE: mkdir will raise an error on failure so I don't think 'or' works here.
|
119
|
+
unless FileTest.directory?(basedir)
|
120
|
+
Dir.mkdir(basedir, 0777) or raise RuntimeError, "can't mkdir #{basedir}: #{$!}\n"
|
121
|
+
end
|
127
122
|
|
128
|
-
|
129
|
-
|
130
|
-
|
123
|
+
dir = basedir
|
124
|
+
# NOTE: What are we doing here? Could this be replaced by mkdir_p?
|
125
|
+
zonedir.split('/').each do |subdir|
|
126
|
+
dir += '/' + subdir
|
127
|
+
unless FileTest.directory?(dir)
|
128
|
+
Dir.mkdir(dir, 0777) or raise RuntimeError, "can't mkdir #{dir}: #{$!}\n"
|
129
|
+
end
|
130
|
+
end
|
131
131
|
|
132
|
-
|
132
|
+
# ------------------------------------------------------------------------------
|
133
|
+
# Get the zone.
|
134
|
+
# ------------------------------------------------------------------------------
|
133
135
|
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
136
|
+
if FileTest.exist?(zonefile) && !opt_f
|
137
|
+
zoneref = Marshal.load(File.open(zonefile))
|
138
|
+
if zoneref.nil?
|
139
|
+
raise RuntimeError, "couldn't retrieve zone from #{zonefile}: #{$!}\n"
|
140
|
+
end
|
139
141
|
|
140
|
-
|
141
|
-
|
142
|
-
|
142
|
+
# ----------------------------------------------------------------------
|
143
|
+
# Check the SOA serial number if desired.
|
144
|
+
# ----------------------------------------------------------------------
|
143
145
|
|
144
|
-
|
145
|
-
|
146
|
+
if opt_s
|
147
|
+
serial_file = serial_zone = nil
|
146
148
|
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
end
|
152
|
-
end
|
153
|
-
if serial_file==nil
|
154
|
-
raise RuntimeError, "no SOA in #{zonefile}\n"
|
149
|
+
zoneref.each do |rr|
|
150
|
+
if (rr.type == 'SOA')
|
151
|
+
serial_file = rr.serial
|
152
|
+
break
|
155
153
|
end
|
154
|
+
end
|
155
|
+
if serial_file.nil?
|
156
|
+
raise RuntimeError, "no SOA in #{zonefile}\n"
|
157
|
+
end
|
156
158
|
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
159
|
+
soa = resolver.query(zone, 'SOA')
|
160
|
+
if soa.nil?
|
161
|
+
raise RuntimeError, "couldn't get SOA for #{zone}: " + resolver.errorstring + "\n"
|
162
|
+
end
|
161
163
|
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
end
|
164
|
+
soa.answer.each do |rr|
|
165
|
+
if rr.type == 'SOA'
|
166
|
+
serial_zone = rr.serial
|
167
|
+
break
|
167
168
|
end
|
169
|
+
end
|
168
170
|
|
169
|
-
|
170
|
-
|
171
|
-
end
|
171
|
+
if serial_zone != serial_file
|
172
|
+
opt_f = true
|
172
173
|
end
|
173
|
-
else
|
174
|
-
opt_f = true
|
175
174
|
end
|
175
|
+
else
|
176
|
+
opt_f = true
|
177
|
+
end
|
176
178
|
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
179
|
+
if opt_f
|
180
|
+
print "nameserver = #{nameserver}, zone=#{zone}"
|
181
|
+
zt = Dnsruby::ZoneTransfer.new
|
182
|
+
zt.server = nameserver if nameserver != ''
|
181
183
|
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
end
|
186
|
-
Marshal.dump(zoneref, File.open(zonefile, File::CREAT|File::RDWR))
|
184
|
+
zoneref = zt.transfer(zone)
|
185
|
+
if zoneref.nil?
|
186
|
+
raise RuntimeError, "couldn't transfer zone\n"
|
187
187
|
end
|
188
|
+
Marshal.dump(zoneref, File.open(zonefile, File::CREAT | File::RDWR))
|
189
|
+
end
|
188
190
|
|
189
|
-
|
190
|
-
|
191
|
-
|
191
|
+
# ------------------------------------------------------------------------------
|
192
|
+
# Print the records in the zone.
|
193
|
+
# ------------------------------------------------------------------------------
|
192
194
|
|
193
|
-
|
194
|
-
|
195
|
-
print z.to_s + "\n"
|
196
|
-
end
|
197
|
-
end
|
195
|
+
unless opt_q
|
196
|
+
zoneref.each { |z| puts z }
|
198
197
|
end
|
data/demo/check_soa.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
#! /usr/bin/env ruby
|
2
|
+
|
1
3
|
# --
|
2
4
|
# Copyright 2007 Nominet UK
|
3
5
|
#
|
@@ -35,7 +37,7 @@
|
|
35
37
|
# The original Bourne Shell and C versions were printed in
|
36
38
|
# "DNS and BIND" by Paul Albitz & Cricket Liu.
|
37
39
|
#
|
38
|
-
#
|
40
|
+
# The Perl version was written by Michael Fuhr <mike@fuhr.org>.
|
39
41
|
#
|
40
42
|
# = SEE ALSO
|
41
43
|
#
|
@@ -43,116 +45,135 @@
|
|
43
45
|
|
44
46
|
require 'dnsruby'
|
45
47
|
|
46
|
-
|
47
|
-
|
48
|
-
# ------------------------------------------------------------------------------
|
48
|
+
NO_DOMAIN_SPECIFIED = -1
|
49
|
+
NO_NAMESERVERS = -2
|
49
50
|
|
50
|
-
if ARGV.length ==1
|
51
|
-
domain = ARGV[0]
|
52
51
|
|
53
|
-
|
54
|
-
|
55
|
-
|
52
|
+
def fatal_error(message, exit_code)
|
53
|
+
puts message
|
54
|
+
exit(exit_code)
|
55
|
+
end
|
56
56
|
|
57
|
-
res = Dnsruby::Resolver.new
|
58
57
|
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
begin
|
63
|
-
ns_req = res.query(domain, "NS")
|
64
|
-
rescue Exception => e
|
65
|
-
print "Error : #{e}"
|
66
|
-
return
|
67
|
-
end
|
68
|
-
if (ns_req.header.ancount == 0)
|
69
|
-
print "No nameservers found for #{domain}\n"
|
70
|
-
return
|
71
|
-
end
|
58
|
+
def usage
|
59
|
+
fatal_error("Usage: #{$0} domain", NO_DOMAIN_SPECIFIED)
|
60
|
+
end
|
72
61
|
|
73
|
-
# Send out non-recursive queries
|
74
|
-
res.recurse=(0)
|
75
62
|
|
63
|
+
def create_resolver
|
64
|
+
resolver = Dnsruby::Resolver.new
|
65
|
+
resolver.retry_times = 2
|
66
|
+
resolver.recurse = 0 # Send out non-recursive queries
|
67
|
+
# disable caching otherwise SOA is cached from first nameserver queried
|
68
|
+
resolver.do_caching = false
|
69
|
+
resolver
|
70
|
+
end
|
76
71
|
|
77
|
-
# ------------------------------------------------------------------------------
|
78
|
-
# Check the SOA record on each nameserver.
|
79
|
-
# ------------------------------------------------------------------------------
|
80
72
|
|
81
|
-
|
73
|
+
def get_ns_response(resolver, domain)
|
74
|
+
ns_response = resolver.query(domain, 'NS')
|
75
|
+
if ns_response.header.ancount == 0
|
76
|
+
fatal_error("No nameservers found for #{domain}.", NO_NAMESERVERS)
|
77
|
+
end
|
78
|
+
ns_response
|
79
|
+
end
|
82
80
|
|
83
|
-
# ----------------------------------------------------------------------
|
84
|
-
# Set the resolver to query this nameserver.
|
85
|
-
# ----------------------------------------------------------------------
|
86
|
-
ns = nsrr.domainname
|
87
81
|
|
82
|
+
# Finds all the nameserver domains for the domain.
|
83
|
+
def get_ns_domains(resolver, domain)
|
84
|
+
ns_response = get_ns_response(resolver, domain)
|
85
|
+
ns_answers = ns_response.answer.select { |r| r.type == 'NS'}
|
86
|
+
ns_answers.map(&:domainname)
|
87
|
+
end
|
88
|
+
|
89
|
+
|
90
|
+
def process_ns_domain(resolver, domain, ns_domain)
|
91
|
+
|
92
|
+
a_response = begin
|
88
93
|
# In order to lookup the IP(s) of the nameserver, we need a Resolver
|
89
94
|
# object that is set to our local, recursive nameserver. So we create
|
90
95
|
# a new object just to do that.
|
96
|
+
local_resolver = Dnsruby::Resolver.new
|
91
97
|
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
98
|
+
local_resolver.query(ns_domain, 'A')
|
99
|
+
rescue Exception => e
|
100
|
+
puts "Cannot find address for #{ns_domain}: #{e}"
|
101
|
+
return
|
102
|
+
end
|
103
|
+
|
104
|
+
a_answers = a_response.answer.select {|r| r.type == 'A'}
|
105
|
+
a_answers.each do |a_answer|
|
106
|
+
|
107
|
+
# ----------------------------------------------------------------------
|
108
|
+
# Ask this IP.
|
109
|
+
# ----------------------------------------------------------------------
|
110
|
+
ip_address = a_answer.address
|
111
|
+
resolver.nameserver = ip_address.to_s
|
112
|
+
print "#{ns_domain} (#{ip_address}): "
|
113
|
+
|
114
|
+
# ----------------------------------------------------------------------
|
115
|
+
# Get the SOA record.
|
116
|
+
# ----------------------------------------------------------------------
|
117
|
+
soa_response = begin
|
118
|
+
resolver.query(domain, 'SOA', 'IN')
|
96
119
|
rescue Exception => e
|
97
|
-
|
98
|
-
|
120
|
+
puts "Error : #{e}"
|
121
|
+
return
|
122
|
+
end
|
123
|
+
|
124
|
+
# ----------------------------------------------------------------------
|
125
|
+
# Is this nameserver authoritative for the domain?
|
126
|
+
# ----------------------------------------------------------------------
|
127
|
+
|
128
|
+
unless soa_response.header.aa
|
129
|
+
print "isn't authoritative for #{domain}\n"
|
130
|
+
return
|
131
|
+
end
|
132
|
+
|
133
|
+
# ----------------------------------------------------------------------
|
134
|
+
# We should have received exactly one answer.
|
135
|
+
# ----------------------------------------------------------------------
|
136
|
+
|
137
|
+
unless soa_response.header.ancount == 1
|
138
|
+
puts "expected 1 answer, got #{soa_response.header.ancount}."
|
139
|
+
return
|
99
140
|
end
|
100
141
|
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
print "#{ns} (#{ip}): "
|
110
|
-
|
111
|
-
# ----------------------------------------------------------------------
|
112
|
-
# Get the SOA record.
|
113
|
-
# ----------------------------------------------------------------------
|
114
|
-
soa_req=nil
|
115
|
-
begin
|
116
|
-
soa_req = res.query(domain, 'SOA', 'IN')
|
117
|
-
rescue Exception => e
|
118
|
-
print "Error : #{e}\n"
|
119
|
-
next
|
120
|
-
end
|
121
|
-
|
122
|
-
# ----------------------------------------------------------------------
|
123
|
-
# Is this nameserver authoritative for the domain?
|
124
|
-
# ----------------------------------------------------------------------
|
125
|
-
|
126
|
-
unless (soa_req.header.aa)
|
127
|
-
print "isn't authoritative for #{domain}\n"
|
128
|
-
next
|
129
|
-
end
|
130
|
-
|
131
|
-
# ----------------------------------------------------------------------
|
132
|
-
# We should have received exactly one answer.
|
133
|
-
# ----------------------------------------------------------------------
|
134
|
-
|
135
|
-
unless (soa_req.header.ancount == 1)
|
136
|
-
print "expected 1 answer, got ", soa_req.header.ancount, "\n"
|
137
|
-
next
|
138
|
-
end
|
139
|
-
|
140
|
-
# ----------------------------------------------------------------------
|
141
|
-
# Did we receive an SOA record?
|
142
|
-
# ----------------------------------------------------------------------
|
143
|
-
|
144
|
-
unless ((soa_req.answer)[0].type == "SOA")
|
145
|
-
print "expected SOA, got ", (soa_req.answer)[0].type, "\n"
|
146
|
-
next
|
147
|
-
end
|
148
|
-
|
149
|
-
# ----------------------------------------------------------------------
|
150
|
-
# Print the serial number.
|
151
|
-
# ----------------------------------------------------------------------
|
152
|
-
|
153
|
-
print "has serial number ", (soa_req.answer)[0].serial, "\n"
|
142
|
+
# ----------------------------------------------------------------------
|
143
|
+
# Did we receive an SOA record?
|
144
|
+
# ----------------------------------------------------------------------
|
145
|
+
|
146
|
+
answer_type = soa_response.answer[0].type
|
147
|
+
unless answer_type == 'SOA'
|
148
|
+
puts "expected SOA, got #{answer_type}"
|
149
|
+
return
|
154
150
|
end
|
151
|
+
|
152
|
+
# ----------------------------------------------------------------------
|
153
|
+
# Print the serial number.
|
154
|
+
# ----------------------------------------------------------------------
|
155
|
+
|
156
|
+
puts "has serial number #{soa_response.answer[0].serial}"
|
155
157
|
end
|
156
|
-
else
|
157
|
-
print "Usage: #{$0} domain\n"
|
158
158
|
end
|
159
|
+
|
160
|
+
|
161
|
+
def main
|
162
|
+
|
163
|
+
# Get domain from command line, printing usage and exiting if none provided:
|
164
|
+
domain = ARGV.fetch(0) { usage }
|
165
|
+
|
166
|
+
resolver = create_resolver
|
167
|
+
|
168
|
+
ns_domains = get_ns_domains(resolver, domain)
|
169
|
+
|
170
|
+
# ------------------------------------------------------------------------------
|
171
|
+
# Check the SOA record on each nameserver.
|
172
|
+
# ------------------------------------------------------------------------------
|
173
|
+
ns_domains.each do |ns_domain_name|
|
174
|
+
process_ns_domain(resolver, domain, ns_domain_name)
|
175
|
+
end
|
176
|
+
end
|
177
|
+
|
178
|
+
|
179
|
+
main
|