net-dns 0.5.3 → 0.6.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.
- data/.gitignore +6 -0
- data/AUTHORS.rdoc +7 -0
- data/CHANGELOG.rdoc +34 -0
- data/README.rdoc +26 -14
- data/Rakefile +23 -30
- data/{THANKS → THANKS.rdoc} +0 -0
- data/VERSION.yml +3 -2
- data/demo/check_soa.rb +6 -11
- data/lib/net/{dns/dns.rb → dns.rb} +5 -12
- data/lib/net/dns/core_ext.rb +52 -0
- data/lib/net/dns/header.rb +55 -49
- data/lib/net/dns/names/names.rb +20 -10
- data/lib/net/dns/packet.rb +33 -26
- data/lib/net/dns/question.rb +60 -27
- data/lib/net/dns/resolver.rb +101 -156
- data/lib/net/dns/resolver/timeouts.rb +71 -65
- data/lib/net/dns/rr.rb +131 -166
- data/lib/net/dns/rr/a.rb +20 -26
- data/lib/net/dns/rr/aaaa.rb +15 -20
- data/lib/net/dns/rr/classes.rb +1 -1
- data/lib/net/dns/rr/cname.rb +8 -14
- data/lib/net/dns/rr/hinfo.rb +8 -14
- data/lib/net/dns/rr/mr.rb +8 -14
- data/lib/net/dns/rr/mx.rb +11 -18
- data/lib/net/dns/rr/ns.rb +8 -14
- data/lib/net/dns/rr/null.rb +7 -14
- data/lib/net/dns/rr/ptr.rb +9 -15
- data/lib/net/dns/rr/soa.rb +9 -15
- data/lib/net/dns/rr/srv.rb +10 -19
- data/lib/net/dns/rr/txt.rb +9 -20
- data/lib/net/dns/rr/types.rb +51 -58
- data/lib/net/dns/version.rb +22 -0
- data/test/{net/dns/test_header.rb → header_test.rb} +20 -20
- data/test/{net/dns/test_packet.rb → packet_test.rb} +2 -2
- data/test/question_test.rb +84 -0
- data/test/resolver/timeouts_test.rb +109 -0
- data/test/{net/dns/test_resolver.rb → resolver_test.rb} +6 -6
- data/test/rr/a_test.rb +66 -0
- data/test/{net/dns/rr/test_classes.rb → rr/classes_test.rb} +5 -5
- data/test/rr/ns_test.rb +64 -0
- data/test/rr/types_test.rb +69 -0
- data/test/{net/dns/test_rr.rb → rr_test.rb} +10 -12
- data/test/test_helper.rb +4 -0
- metadata +50 -35
- data/AUTHORS +0 -10
- data/CHANGELOG +0 -7
- data/INSTALL +0 -8
- data/net-dns.gemspec +0 -92
- data/test/net/dns/resolver/test_timeouts.rb +0 -59
- data/test/net/dns/rr/test_a.rb +0 -72
- data/test/net/dns/rr/test_ns.rb +0 -66
- data/test/net/dns/rr/test_types.rb +0 -124
- data/test/net/dns/test_question.rb +0 -54
@@ -1,73 +1,79 @@
|
|
1
1
|
require 'timeout'
|
2
2
|
|
3
|
-
module
|
4
|
-
|
5
|
-
|
6
|
-
when 0
|
7
|
-
to_s
|
8
|
-
when 1..59
|
9
|
-
"#{secs} seconds"
|
10
|
-
when 60..3559
|
11
|
-
"#{secs/60} minutes and #{secs%60} seconds"
|
12
|
-
else
|
13
|
-
hours = secs/3600
|
14
|
-
secs -= (hours*3600)
|
15
|
-
"#{hours} hours, #{secs/60} minutes and #{secs%60} seconds"
|
16
|
-
end
|
17
|
-
end
|
18
|
-
end
|
3
|
+
module Net # :nodoc:
|
4
|
+
module DNS
|
5
|
+
class Resolver
|
19
6
|
|
20
|
-
class DnsTimeout
|
7
|
+
class DnsTimeout
|
8
|
+
|
9
|
+
attr_reader :seconds
|
10
|
+
|
11
|
+
|
12
|
+
def initialize(seconds)
|
13
|
+
if seconds.is_a? Numeric and seconds >= 0
|
14
|
+
@seconds = seconds
|
15
|
+
else
|
16
|
+
raise ::ArgumentError, "Invalid value for tcp timeout"
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
# Returns a string representation of the timeout corresponding
|
21
|
+
# to the number of <tt>@seconds</tt>.
|
22
|
+
def to_s
|
23
|
+
if @seconds == 0
|
24
|
+
@output.to_s
|
25
|
+
else
|
26
|
+
@seconds.to_s
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def pretty_to_s
|
31
|
+
transform(@seconds)
|
32
|
+
end
|
33
|
+
|
34
|
+
# Executes the method's block. If the block execution terminates before +sec+
|
35
|
+
# seconds has passed, it returns true. If not, it terminates the execution
|
36
|
+
# and raises Timeout::Error.
|
37
|
+
# If @seconds is 0 or nil, no timeout is set.
|
38
|
+
def timeout(&block)
|
39
|
+
raise LocalJumpError, "no block given" unless block_given?
|
40
|
+
Timeout.timeout(@seconds, &block)
|
41
|
+
end
|
42
|
+
|
43
|
+
|
44
|
+
private
|
45
|
+
|
46
|
+
def transform(secs)
|
47
|
+
case secs
|
48
|
+
when 0
|
49
|
+
to_s
|
50
|
+
when 1..59
|
51
|
+
"#{secs} seconds"
|
52
|
+
when 60..3559
|
53
|
+
"#{secs / 60} minutes and #{secs % 60} seconds"
|
54
|
+
else
|
55
|
+
hours = secs / 3600
|
56
|
+
secs -= (hours * 3600)
|
57
|
+
"#{hours} hours, #{secs / 60} minutes and #{secs % 60} seconds"
|
58
|
+
end
|
59
|
+
end
|
21
60
|
|
22
|
-
include SecondsHandle
|
23
|
-
|
24
|
-
def initialize(seconds)
|
25
|
-
if seconds.is_a? Numeric and seconds >= 0
|
26
|
-
@timeout = seconds
|
27
|
-
else
|
28
|
-
raise DnsTimeoutArgumentError, "Invalid value for tcp timeout"
|
29
|
-
end
|
30
|
-
end
|
31
|
-
|
32
|
-
def to_s
|
33
|
-
if @timeout == 0
|
34
|
-
@output
|
35
|
-
else
|
36
|
-
@timeout.to_s
|
37
|
-
end
|
38
|
-
end
|
39
|
-
|
40
|
-
def pretty_to_s
|
41
|
-
transform(@timeout)
|
42
|
-
end
|
43
|
-
|
44
|
-
def timeout
|
45
|
-
unless block_given?
|
46
|
-
raise DnsTimeoutArgumentError, "Block required but missing"
|
47
|
-
end
|
48
|
-
if @timeout == 0
|
49
|
-
yield
|
50
|
-
else
|
51
|
-
return Timeout.timeout(@timeout) do
|
52
|
-
yield
|
53
61
|
end
|
54
|
-
end
|
55
|
-
end
|
56
|
-
end
|
57
62
|
|
58
|
-
class TcpTimeout < DnsTimeout
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
end
|
63
|
+
class TcpTimeout < DnsTimeout
|
64
|
+
def initialize(seconds)
|
65
|
+
@output = "infinite"
|
66
|
+
super
|
67
|
+
end
|
68
|
+
end
|
64
69
|
|
65
|
-
class UdpTimeout < DnsTimeout
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
end
|
70
|
+
class UdpTimeout < DnsTimeout
|
71
|
+
def initialize(seconds)
|
72
|
+
@output = "not defined"
|
73
|
+
super
|
74
|
+
end
|
75
|
+
end
|
71
76
|
|
72
|
-
|
73
|
-
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
data/lib/net/dns/rr.rb
CHANGED
@@ -1,7 +1,3 @@
|
|
1
|
-
#
|
2
|
-
# $Id: RR.rb,v 1.19 2006/07/28 07:33:36 bluemonk Exp $
|
3
|
-
#
|
4
|
-
|
5
1
|
require 'net/dns/names/names'
|
6
2
|
require 'net/dns/rr/types'
|
7
3
|
require 'net/dns/rr/classes'
|
@@ -14,16 +10,9 @@ end
|
|
14
10
|
module Net # :nodoc:
|
15
11
|
module DNS
|
16
12
|
|
17
|
-
# =Name
|
18
|
-
#
|
19
|
-
# Net::DNS::RR - DNS Resource Record class
|
20
13
|
#
|
21
|
-
# =
|
22
|
-
#
|
23
|
-
# require 'net/dns/rr'
|
14
|
+
# = Net::DNS::RR - DNS Resource Record class
|
24
15
|
#
|
25
|
-
# =Description
|
26
|
-
#
|
27
16
|
# The Net::DNS::RR is the base class for DNS Resource
|
28
17
|
# Record (RR) objects. A RR is a pack of data that represents
|
29
18
|
# resources for a DNS zone. The form in which this data is
|
@@ -50,30 +39,36 @@ module Net # :nodoc:
|
|
50
39
|
# such the ones above, or specifying each field as the pair
|
51
40
|
# of an hash. See the Net::DNS::RR.new method for details.
|
52
41
|
#
|
53
|
-
#
|
42
|
+
# == Error classes
|
54
43
|
#
|
55
44
|
# Some error classes has been defined for the Net::DNS::RR class,
|
56
45
|
# which are listed here to keep a light and browsable main documentation.
|
57
46
|
# We have:
|
58
47
|
#
|
59
|
-
#
|
60
|
-
#
|
61
|
-
#
|
62
|
-
# =Copyright
|
63
|
-
#
|
64
|
-
# Copyright (c) 2006 Marco Ceresa
|
65
|
-
#
|
66
|
-
# All rights reserved. This program is free software; you may redistribute
|
67
|
-
# it and/or modify it under the same terms as Ruby itself.
|
48
|
+
# ArgumentError:: Generic argument error for class Net::DNS::RR
|
49
|
+
# DataError:: Error in parsing binary data, maybe from a malformed packet.
|
68
50
|
#
|
69
51
|
class RR
|
70
52
|
include Net::DNS::Names
|
71
53
|
|
54
|
+
# Argument Error for class Net::DNS::RR.
|
55
|
+
class ArgumentError < ArgumentError
|
56
|
+
end
|
57
|
+
|
58
|
+
# Base error class.
|
59
|
+
class Error < StandardError
|
60
|
+
end
|
61
|
+
|
62
|
+
# Error in parsing binary data, maybe from a malformed packet.
|
63
|
+
class DataError < Error
|
64
|
+
end
|
65
|
+
|
66
|
+
|
72
67
|
# Regexp matching an RR string
|
73
68
|
RR_REGEXP = Regexp.new("^\\s*(\\S+)\\s*(\\d+)?\\s+(" +
|
74
69
|
Net::DNS::RR::Classes.regexp +
|
75
70
|
"|CLASS\\d+)?\\s*(" +
|
76
|
-
Net::DNS::RR::Types.regexp +
|
71
|
+
Net::DNS::RR::Types.regexp +
|
77
72
|
"|TYPE\\d+)?\\s*(.*)$", Regexp::IGNORECASE)
|
78
73
|
|
79
74
|
# Dimension of the sum of class, type, TTL and rdlength fields in a
|
@@ -131,13 +126,13 @@ module Net # :nodoc:
|
|
131
126
|
# for the resource in each subclass.
|
132
127
|
#
|
133
128
|
def initialize(arg)
|
134
|
-
case arg
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
129
|
+
instance = case arg
|
130
|
+
when String
|
131
|
+
new_from_string(arg)
|
132
|
+
when Hash
|
133
|
+
new_from_hash(arg)
|
134
|
+
else
|
135
|
+
raise ArgumentError, "Invalid argument, must be a RR string or an hash of values"
|
141
136
|
end
|
142
137
|
|
143
138
|
if @type.to_s == "ANY"
|
@@ -205,17 +200,16 @@ module Net # :nodoc:
|
|
205
200
|
return str + [type,cls,@ttl,@rdlength].pack("n2 N n") + get_data
|
206
201
|
end
|
207
202
|
|
208
|
-
# Canonical inspect method
|
203
|
+
# Canonical inspect method.
|
209
204
|
#
|
210
205
|
# mx = Net::DNS::RR.new("example.com. 7200 MX 10 mailhost.example.com.")
|
211
|
-
#
|
206
|
+
# #=> example.com. 7200 IN MX 10 mailhost.example.com.
|
212
207
|
#
|
213
208
|
def inspect
|
214
209
|
data = get_inspect
|
215
210
|
# Returns the preformatted string
|
216
211
|
if @name.size < 24
|
217
|
-
[@name, @ttl.to_s, @cls.to_s, @type.to_s,
|
218
|
-
data].pack("A24 A8 A8 A8 A*")
|
212
|
+
[@name, @ttl.to_s, @cls.to_s, @type.to_s, data].pack("A24 A8 A8 A8 A*")
|
219
213
|
else
|
220
214
|
to_a.join(" ")
|
221
215
|
end
|
@@ -225,20 +219,20 @@ module Net # :nodoc:
|
|
225
219
|
#
|
226
220
|
# mx = Net::DNS::RR.new("example.com. 7200 MX 10 mailhost.example.com.")
|
227
221
|
# mx.to_s
|
228
|
-
#
|
222
|
+
# #=> "example.com. 7200 IN MX 10 mailhost.example.com."
|
229
223
|
#
|
230
224
|
def to_s
|
231
|
-
|
225
|
+
inspect.to_s
|
232
226
|
end
|
233
227
|
|
234
228
|
# Returns an array with all the fields for the RR record.
|
235
229
|
#
|
236
230
|
# mx = Net::DNS::RR.new("example.com. 7200 MX 10 mailhost.example.com.")
|
237
231
|
# mx.to_a
|
238
|
-
#
|
232
|
+
# #=> ["example.com.",7200,"IN","MX","10 mailhost.example.com."]
|
239
233
|
#
|
240
234
|
def to_a
|
241
|
-
[@name
|
235
|
+
[@name, @ttl, @cls.to_s, @type.to_s, get_inspect]
|
242
236
|
end
|
243
237
|
|
244
238
|
# Type accessor
|
@@ -252,111 +246,113 @@ module Net # :nodoc:
|
|
252
246
|
end
|
253
247
|
|
254
248
|
private
|
255
|
-
|
256
|
-
#---
|
257
|
-
# New RR with argument in string form
|
258
|
-
#---
|
259
|
-
def new_from_string(rrstring)
|
260
249
|
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
250
|
+
#---
|
251
|
+
# New RR with argument in string form
|
252
|
+
#---
|
253
|
+
def new_from_string(rrstring)
|
265
254
|
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
unless args.has_key? :name
|
297
|
-
raise RRArgumentError, "RR argument error: need at least RR name"
|
255
|
+
unless rrstring =~ RR_REGEXP
|
256
|
+
raise ArgumentError,
|
257
|
+
"Format error for RR string (maybe CLASS and TYPE not valid?)"
|
258
|
+
end
|
259
|
+
|
260
|
+
# Name of RR - mandatory
|
261
|
+
begin
|
262
|
+
@name = $1.downcase
|
263
|
+
rescue NoMethodError
|
264
|
+
raise ArgumentError, "Missing name field in RR string #{rrstring}"
|
265
|
+
end
|
266
|
+
|
267
|
+
# Time to live for RR, default 3 hours
|
268
|
+
@ttl = $2 ? $2.to_i : 10800
|
269
|
+
|
270
|
+
# RR class, default to IN
|
271
|
+
@cls = Net::DNS::RR::Classes.new $3
|
272
|
+
|
273
|
+
# RR type, default to A
|
274
|
+
@type = Net::DNS::RR::Types.new $4
|
275
|
+
|
276
|
+
# All the rest is data
|
277
|
+
@rdata = $5 ? $5.strip : ""
|
278
|
+
|
279
|
+
if self.class == Net::DNS::RR
|
280
|
+
(eval "Net::DNS::RR::#@type").new(rrstring)
|
281
|
+
else
|
282
|
+
subclass_new_from_string(@rdata)
|
283
|
+
self.class
|
284
|
+
end
|
298
285
|
end
|
299
286
|
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
@rdata = args[:rdata] ? args[:rdata].strip : ""
|
306
|
-
@rdlength = args[:rdlength] || @rdata.size
|
287
|
+
def new_from_hash(args)
|
288
|
+
# Name field is mandatory
|
289
|
+
unless args.has_key? :name
|
290
|
+
raise ArgumentError, "RR argument error: need at least RR name"
|
291
|
+
end
|
307
292
|
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
|
293
|
+
@name = args[:name].downcase
|
294
|
+
@ttl = args[:ttl] ? args[:ttl].to_i : 10800 # Default 3 hours
|
295
|
+
@type = Net::DNS::RR::Types.new args[:type]
|
296
|
+
@cls = Net::DNS::RR::Classes.new args[:cls]
|
297
|
+
|
298
|
+
@rdata = args[:rdata] ? args[:rdata].strip : ""
|
299
|
+
@rdlength = args[:rdlength] || @rdata.size
|
300
|
+
|
301
|
+
if self.class == Net::DNS::RR
|
302
|
+
(eval "Net::DNS::RR::#@type").new(args)
|
303
|
+
else
|
304
|
+
hash = args - [:name,:ttl,:type,:cls]
|
305
|
+
if hash.has_key? :rdata
|
306
|
+
subclass_new_from_string(hash[:rdata])
|
307
|
+
else
|
308
|
+
subclass_new_from_hash(hash)
|
309
|
+
end
|
310
|
+
self.class
|
311
|
+
end
|
312
|
+
end # new_from_hash
|
313
|
+
|
314
|
+
def new_from_binary(data,offset)
|
315
|
+
if self.class == Net::DNS::RR
|
316
|
+
temp = dn_expand(data,offset)[1]
|
317
|
+
type = Net::DNS::RR::Types.new data.unpack("@#{temp} n")[0]
|
318
|
+
(eval "Net::DNS::RR::#{type}").parse_packet(data,offset)
|
314
319
|
else
|
315
|
-
|
320
|
+
@name,offset = dn_expand(data,offset)
|
321
|
+
rrtype,cls,@ttl,@rdlength = data.unpack("@#{offset} n2 N n")
|
322
|
+
@type = Net::DNS::RR::Types.new rrtype
|
323
|
+
@cls = Net::DNS::RR::Classes.new cls
|
324
|
+
offset += RRFIXEDSZ
|
325
|
+
offset = subclass_new_from_binary(data,offset)
|
326
|
+
build_pack
|
327
|
+
set_type
|
328
|
+
return [self,offset]
|
316
329
|
end
|
317
|
-
self.class
|
318
330
|
end
|
319
|
-
end # new_from_hash
|
320
331
|
|
321
|
-
|
322
|
-
|
323
|
-
|
324
|
-
|
325
|
-
|
326
|
-
|
327
|
-
|
328
|
-
|
329
|
-
|
330
|
-
|
331
|
-
|
332
|
-
|
333
|
-
|
334
|
-
|
335
|
-
|
332
|
+
# Methods to be overridden by subclasses
|
333
|
+
def subclass_new_from_array(arr)
|
334
|
+
end
|
335
|
+
def subclass_new_from_string(str)
|
336
|
+
end
|
337
|
+
def subclass_new_from_hash(hash)
|
338
|
+
end
|
339
|
+
def subclass_new_from_binary(data,offset)
|
340
|
+
end
|
341
|
+
def build_pack
|
342
|
+
end
|
343
|
+
def get_inspect
|
344
|
+
@rdata
|
345
|
+
end
|
346
|
+
def get_data
|
347
|
+
@rdata
|
336
348
|
end
|
337
|
-
|
338
|
-
|
339
|
-
|
340
|
-
|
341
|
-
|
342
|
-
|
343
|
-
|
344
|
-
def subclass_new_from_string(str)
|
345
|
-
end
|
346
|
-
def subclass_new_from_hash(hash)
|
347
|
-
end
|
348
|
-
def subclass_new_from_binary(data,offset)
|
349
|
-
end
|
350
|
-
def build_pack
|
351
|
-
end
|
352
|
-
def set_type
|
353
|
-
end
|
354
|
-
def get_inspect
|
355
|
-
@rdata
|
356
|
-
end
|
357
|
-
def get_data
|
358
|
-
@rdata
|
359
|
-
end
|
349
|
+
|
350
|
+
def set_type
|
351
|
+
# TODO: Here we should probably
|
352
|
+
# raise NotImplementedError
|
353
|
+
# if we want the method to be implemented in any subclass.
|
354
|
+
end
|
355
|
+
|
360
356
|
|
361
357
|
# NEW new method :)
|
362
358
|
def self.new(*args)
|
@@ -369,38 +365,7 @@ module Net # :nodoc:
|
|
369
365
|
end
|
370
366
|
end
|
371
367
|
|
372
|
-
end # class RR
|
373
|
-
|
374
|
-
end # module DNS
|
375
|
-
end # module Net
|
376
|
-
|
377
|
-
class RRArgumentError < ArgumentError # :nodoc:
|
378
|
-
end
|
379
|
-
class RRDataError < StandardError # :nodoc:
|
380
|
-
end
|
381
|
-
|
382
|
-
module ExtendHash # :nodoc:
|
383
|
-
|
384
|
-
# Performs a sort of group difference
|
385
|
-
# operation on hashes or arrays
|
386
|
-
#
|
387
|
-
# a = {:a=>1,:b=>2,:c=>3}
|
388
|
-
# b = {:a=>1,:b=>2}
|
389
|
-
# c = [:a,:c]
|
390
|
-
# a-b #=> {:c=>3}
|
391
|
-
# a-c #=> {:b=>2}
|
392
|
-
#
|
393
|
-
def -(oth)
|
394
|
-
case oth
|
395
|
-
when Hash
|
396
|
-
delete_if {|k,v| oth.has_key? k}
|
397
|
-
when Array
|
398
|
-
delete_if {|k,v| oth.include? k}
|
399
368
|
end
|
369
|
+
|
400
370
|
end
|
401
|
-
end
|
402
|
-
|
403
|
-
class Hash # :nodoc:
|
404
|
-
include ExtendHash
|
405
|
-
end
|
406
|
-
|
371
|
+
end
|