net-dns 0.8.0 → 0.9.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +6 -14
- data/.gitignore +1 -1
- data/.rspec +1 -0
- data/.rubocop.yml +3 -0
- data/.rubocop_defaults.yml +364 -0
- data/.rubocop_todo.yml +207 -0
- data/.travis.yml +9 -16
- data/CHANGELOG.md +12 -1
- data/Gemfile +6 -2
- data/LICENSE.txt +56 -0
- data/README.md +94 -77
- data/Rakefile +23 -56
- data/bin/console +14 -0
- data/demo/check_soa.rb +27 -38
- data/demo/threads.rb +3 -7
- data/lib/net/dns.rb +4 -11
- data/lib/net/dns/core_ext.rb +8 -15
- data/lib/net/dns/header.rb +58 -66
- data/lib/net/dns/names.rb +25 -23
- data/lib/net/dns/packet.rb +136 -139
- data/lib/net/dns/question.rb +36 -39
- data/lib/net/dns/resolver.rb +103 -113
- data/lib/net/dns/resolver/socks.rb +45 -51
- data/lib/net/dns/resolver/timeouts.rb +17 -26
- data/lib/net/dns/rr.rb +107 -117
- data/lib/net/dns/rr/a.rb +46 -55
- data/lib/net/dns/rr/aaaa.rb +40 -49
- data/lib/net/dns/rr/classes.rb +26 -29
- data/lib/net/dns/rr/cname.rb +33 -41
- data/lib/net/dns/rr/hinfo.rb +44 -56
- data/lib/net/dns/rr/mr.rb +33 -42
- data/lib/net/dns/rr/mx.rb +37 -47
- data/lib/net/dns/rr/ns.rb +33 -41
- data/lib/net/dns/rr/null.rb +8 -11
- data/lib/net/dns/rr/ptr.rb +14 -20
- data/lib/net/dns/rr/soa.rb +27 -30
- data/lib/net/dns/rr/srv.rb +13 -17
- data/lib/net/dns/rr/txt.rb +8 -11
- data/lib/net/dns/rr/types.rb +97 -99
- data/lib/net/dns/version.rb +5 -13
- data/net-dns.gemspec +17 -29
- data/{fixtures → spec/fixtures}/resolv.conf +0 -0
- data/spec/spec_helper.rb +14 -0
- data/spec/unit/resolver/dns_timeout_spec.rb +36 -0
- data/spec/unit/resolver/tcp_timeout_spec.rb +46 -0
- data/spec/unit/resolver/udp_timeout_spec.rb +46 -0
- data/test/test_helper.rb +12 -3
- data/test/{header_test.rb → unit/header_test.rb} +43 -46
- data/test/{names_test.rb → unit/names_test.rb} +1 -1
- data/test/{packet_test.rb → unit/packet_test.rb} +3 -5
- data/test/{question_test.rb → unit/question_test.rb} +3 -5
- data/test/{resolver_test.rb → unit/resolver_test.rb} +10 -13
- data/test/{rr → unit/rr}/a_test.rb +10 -17
- data/test/{rr → unit/rr}/aaaa_test.rb +7 -14
- data/test/{rr → unit/rr}/classes_test.rb +14 -16
- data/test/{rr → unit/rr}/cname_test.rb +7 -14
- data/test/{rr → unit/rr}/hinfo_test.rb +16 -22
- data/test/{rr → unit/rr}/mr_test.rb +12 -18
- data/test/{rr → unit/rr}/mx_test.rb +18 -24
- data/test/{rr → unit/rr}/ns_test.rb +10 -16
- data/test/{rr → unit/rr}/types_test.rb +10 -8
- data/test/{rr_test.rb → unit/rr_test.rb} +33 -37
- metadata +77 -49
- data/test/resolver/timeouts_test.rb +0 -109
data/lib/net/dns/question.rb
CHANGED
@@ -1,20 +1,19 @@
|
|
1
1
|
module Net
|
2
|
-
module DNS
|
3
|
-
|
2
|
+
module DNS
|
4
3
|
#
|
5
4
|
# =Name
|
6
5
|
#
|
7
6
|
# Net::DNS::Question - DNS packet question class
|
8
7
|
#
|
9
8
|
# =Synopsis
|
10
|
-
#
|
9
|
+
#
|
11
10
|
# require 'net/dns/question'
|
12
11
|
#
|
13
12
|
# =Description
|
14
13
|
#
|
15
14
|
# This class represent the Question portion of a DNS packet. The number
|
16
15
|
# of question entries is stored in the +qdCount+ variable of an Header
|
17
|
-
# object.
|
16
|
+
# object.
|
18
17
|
#
|
19
18
|
# A new object can be created passing the name of the query and the type
|
20
19
|
# of answer desired, plus an optional argument containing the class:
|
@@ -26,13 +25,13 @@ module Net
|
|
26
25
|
# packet, as when an answer is received.
|
27
26
|
# To obtain the binary data from a question object you can use
|
28
27
|
# the method Question#data:
|
29
|
-
#
|
28
|
+
#
|
30
29
|
# question.data
|
31
30
|
# #=> "\006google\003com\000\000\001\000\001"
|
32
31
|
#
|
33
32
|
# A lot of methods were written to keep a compatibility layer with
|
34
33
|
# the Perl version of the library, as long as methods name which are
|
35
|
-
# more or less the same.
|
34
|
+
# more or less the same.
|
36
35
|
#
|
37
36
|
class Question
|
38
37
|
include Names
|
@@ -40,18 +39,18 @@ module Net
|
|
40
39
|
# Base error class.
|
41
40
|
class Error < StandardError
|
42
41
|
end
|
43
|
-
|
42
|
+
|
44
43
|
# An error in the +name+ part of a Question entry
|
45
44
|
class NameInvalid < Error
|
46
45
|
end
|
47
|
-
|
46
|
+
|
48
47
|
# +name+ part of a Question entry
|
49
|
-
attr_reader :qName
|
48
|
+
attr_reader :qName
|
50
49
|
# +type+ part of a Question entry
|
51
|
-
attr_reader :qType
|
50
|
+
attr_reader :qType
|
52
51
|
# +class+ part of a Question entry
|
53
|
-
attr_reader :qClass
|
54
|
-
|
52
|
+
attr_reader :qClass
|
53
|
+
|
55
54
|
# Creates a new Net::DNS::Question object:
|
56
55
|
#
|
57
56
|
# question = Net::DNS::Question.new("example.com")
|
@@ -60,8 +59,8 @@ module Net
|
|
60
59
|
# #=> "example.com MX IN"
|
61
60
|
# question = Net::DNS::Question.new("example.com", Net::DNS::TXT, Net::DNS::HS)
|
62
61
|
# #=> "example.com TXT HS"
|
63
|
-
|
64
|
-
# If not specified, +type+ and +cls+ arguments defaults
|
62
|
+
|
63
|
+
# If not specified, +type+ and +cls+ arguments defaults
|
65
64
|
# to Net::DNS::A and Net::DNS::IN respectively.
|
66
65
|
#
|
67
66
|
def initialize(name, type = Net::DNS::A, cls = Net::DNS::IN)
|
@@ -83,18 +82,18 @@ module Net
|
|
83
82
|
o.send(:new_from_binary, arg.to_s)
|
84
83
|
o
|
85
84
|
end
|
86
|
-
|
85
|
+
|
87
86
|
# Outputs binary data from a Question object
|
88
87
|
#
|
89
88
|
# question.data
|
90
89
|
# #=> "\006google\003com\000\000\001\000\001"
|
91
90
|
#
|
92
91
|
def data
|
93
|
-
[pack_name(@qName)
|
92
|
+
[pack_name(@qName), @qType.to_i, @qClass.to_i].pack("a*nn")
|
94
93
|
end
|
95
|
-
|
94
|
+
|
96
95
|
# Return the binary data of the objects, plus an offset
|
97
|
-
# and an Hash with references to compressed names. For use in
|
96
|
+
# and an Hash with references to compressed names. For use in
|
98
97
|
# Net::DNS::Packet compressed packet creation.
|
99
98
|
def comp_data
|
100
99
|
arr = @qName.split(".")
|
@@ -103,20 +102,19 @@ module Net
|
|
103
102
|
names = {}
|
104
103
|
offset = Net::DNS::HFIXEDSZ
|
105
104
|
arr.size.times do |i|
|
106
|
-
x = i+1
|
105
|
+
x = i + 1
|
107
106
|
elem = arr[-x]
|
108
107
|
len = elem.size
|
109
|
-
string = (
|
108
|
+
string = (string.reverse + [len, elem].pack("Ca*").reverse).reverse
|
110
109
|
names[string] = offset
|
111
110
|
offset += len
|
112
111
|
end
|
113
112
|
offset += 2 * Net::DNS::INT16SZ
|
114
113
|
str += "\000"
|
115
|
-
[[str
|
114
|
+
[[str, @qType.to_i, @qClass.to_i].pack("a*nn"), offset, names]
|
116
115
|
end
|
117
|
-
|
118
|
-
|
119
|
-
#
|
116
|
+
|
117
|
+
#
|
120
118
|
# call-seq:
|
121
119
|
# question.inspect -> string
|
122
120
|
#
|
@@ -126,15 +124,15 @@ module Net
|
|
126
124
|
# q.inspect # => "google.com. IN A "
|
127
125
|
#
|
128
126
|
def inspect
|
129
|
-
if @qName.size > 29
|
130
|
-
|
127
|
+
len = if @qName.size > 29
|
128
|
+
@qName.size + 1
|
131
129
|
else
|
132
|
-
|
130
|
+
29
|
133
131
|
end
|
134
132
|
[@qName, @qClass.to_s, @qType.to_s].pack("A#{len} A8 A8")
|
135
133
|
end
|
136
|
-
|
137
|
-
#
|
134
|
+
|
135
|
+
#
|
138
136
|
# call-seq:
|
139
137
|
# question.to_s -> string
|
140
138
|
#
|
@@ -145,44 +143,43 @@ module Net
|
|
145
143
|
# q.inspect # => "google.com. IN A "
|
146
144
|
#
|
147
145
|
def to_s
|
148
|
-
|
146
|
+
inspect.to_s
|
149
147
|
end
|
150
|
-
|
151
|
-
|
148
|
+
|
152
149
|
private
|
153
|
-
|
150
|
+
|
154
151
|
def build_qName(str)
|
155
152
|
result = ""
|
156
153
|
offset = 0
|
157
154
|
loop do
|
158
155
|
len = str.unpack("@#{offset} C")[0]
|
159
156
|
break if len == 0
|
157
|
+
|
160
158
|
offset += 1
|
161
|
-
result += str[offset..offset+len-1]
|
159
|
+
result += str[offset..offset + len - 1]
|
162
160
|
result += "."
|
163
161
|
offset += len
|
164
162
|
end
|
165
163
|
result
|
166
164
|
end
|
167
|
-
|
165
|
+
|
168
166
|
def check_name(input)
|
169
167
|
name = input.to_s.strip
|
170
168
|
if name =~ /[^\w\.\-_]/
|
171
169
|
raise NameInvalid, "Invalid Question Name `#{name}'"
|
172
170
|
end
|
171
|
+
|
173
172
|
name
|
174
173
|
end
|
175
|
-
|
174
|
+
|
176
175
|
def new_from_binary(data)
|
177
|
-
str,type,cls = data.unpack("a#{data.size - 4}nn")
|
176
|
+
str, type, cls = data.unpack("a#{data.size - 4}nn")
|
178
177
|
@qName = build_qName(str)
|
179
178
|
@qType = Net::DNS::RR::Types.new type
|
180
179
|
@qClass = Net::DNS::RR::Classes.new cls
|
181
180
|
rescue StandardError => e
|
182
181
|
raise ArgumentError, "Invalid data: #{data.inspect}"
|
183
182
|
end
|
184
|
-
|
185
183
|
end
|
186
|
-
|
187
184
|
end
|
188
185
|
end
|
data/lib/net/dns/resolver.rb
CHANGED
@@ -27,7 +27,6 @@ end
|
|
27
27
|
|
28
28
|
module Net
|
29
29
|
module DNS
|
30
|
-
|
31
30
|
include Logger::Severity
|
32
31
|
|
33
32
|
# = Net::DNS::Resolver - DNS resolver class
|
@@ -87,7 +86,6 @@ module Net
|
|
87
86
|
# % setenv RES_OPTIONS "retrans:3 retry:2 debug"
|
88
87
|
#
|
89
88
|
class Resolver
|
90
|
-
|
91
89
|
class Error < StandardError
|
92
90
|
end
|
93
91
|
|
@@ -99,30 +97,28 @@ module Net
|
|
99
97
|
# the description for each parameter to have an
|
100
98
|
# explanation of its usage.
|
101
99
|
Defaults = {
|
102
|
-
:
|
103
|
-
:
|
104
|
-
:
|
105
|
-
:
|
106
|
-
:
|
107
|
-
:
|
108
|
-
:
|
109
|
-
:
|
110
|
-
:
|
111
|
-
:
|
112
|
-
:
|
113
|
-
:
|
114
|
-
:
|
115
|
-
:
|
116
|
-
:
|
117
|
-
:
|
118
|
-
:
|
119
|
-
:
|
120
|
-
:
|
121
|
-
}
|
122
|
-
|
100
|
+
config_file: "/etc/resolv.conf",
|
101
|
+
log_file: $stdout,
|
102
|
+
port: 53,
|
103
|
+
searchlist: [],
|
104
|
+
nameservers: [IPAddr.new("127.0.0.1")],
|
105
|
+
domain: "",
|
106
|
+
source_port: 0,
|
107
|
+
source_address: IPAddr.new("0.0.0.0"),
|
108
|
+
source_address_inet6: IPAddr.new('::'),
|
109
|
+
retry_interval: 5,
|
110
|
+
retry_number: 4,
|
111
|
+
recursive: true,
|
112
|
+
defname: true,
|
113
|
+
dns_search: true,
|
114
|
+
use_tcp: false,
|
115
|
+
ignore_truncated: false,
|
116
|
+
packet_size: 512,
|
117
|
+
tcp_timeout: TcpTimeout.new(5),
|
118
|
+
udp_timeout: UdpTimeout.new(5),
|
119
|
+
}.freeze
|
123
120
|
|
124
121
|
class << self
|
125
|
-
|
126
122
|
C = Object.const_get(defined?(RbConfig) ? :RbConfig : :Config)::CONFIG
|
127
123
|
|
128
124
|
# Quick resolver method. Bypass the configuration using
|
@@ -142,10 +138,8 @@ module Net
|
|
142
138
|
def platform_windows?
|
143
139
|
!!(C["host_os"] =~ /msdos|mswin|djgpp|mingw/i)
|
144
140
|
end
|
145
|
-
|
146
141
|
end
|
147
142
|
|
148
|
-
|
149
143
|
# Creates a new resolver object.
|
150
144
|
#
|
151
145
|
# Argument +config+ can either be empty or be an hash with
|
@@ -255,8 +249,6 @@ module Net
|
|
255
249
|
# 4) defaults (and /etc/resolv.conf for config)
|
256
250
|
#------------------------------------------------------------
|
257
251
|
|
258
|
-
|
259
|
-
|
260
252
|
#------------------------------------------------------------
|
261
253
|
# Parsing config file
|
262
254
|
#------------------------------------------------------------
|
@@ -270,10 +262,11 @@ module Net
|
|
270
262
|
#------------------------------------------------------------
|
271
263
|
# Parsing arguments
|
272
264
|
#------------------------------------------------------------
|
273
|
-
config.each do |key,val|
|
274
|
-
next if key == :log_file
|
265
|
+
config.each do |key, val|
|
266
|
+
next if (key == :log_file) || (key == :config_file)
|
267
|
+
|
275
268
|
begin
|
276
|
-
eval "self.#{key
|
269
|
+
eval "self.#{key} = val"
|
277
270
|
rescue NoMethodError
|
278
271
|
raise ArgumentError, "Option #{key} not valid"
|
279
272
|
end
|
@@ -309,7 +302,7 @@ module Net
|
|
309
302
|
@config[:searchlist] = [arg] if valid? arg
|
310
303
|
@logger.info "Searchlist changed to value #{@config[:searchlist].inspect}"
|
311
304
|
when Array
|
312
|
-
@config[:searchlist] = arg if arg.all? {|x| valid? x}
|
305
|
+
@config[:searchlist] = arg if arg.all? { |x| valid? x }
|
313
306
|
@logger.info "Searchlist changed to value #{@config[:searchlist].inspect}"
|
314
307
|
else
|
315
308
|
raise ArgumentError, "Wrong argument format, neither String nor Array"
|
@@ -325,7 +318,7 @@ module Net
|
|
325
318
|
@config[:nameservers].map(&:to_s)
|
326
319
|
end
|
327
320
|
|
328
|
-
|
321
|
+
alias nameserver nameservers
|
329
322
|
|
330
323
|
# Set the list of resolver nameservers.
|
331
324
|
# +arg+ can be a single ip address or an array of addresses.
|
@@ -356,26 +349,27 @@ module Net
|
|
356
349
|
when Array
|
357
350
|
@config[:nameservers] = []
|
358
351
|
arg.each do |x|
|
359
|
-
|
360
|
-
|
361
|
-
|
362
|
-
|
363
|
-
|
364
|
-
|
365
|
-
|
366
|
-
|
367
|
-
|
368
|
-
|
369
|
-
|
370
|
-
|
371
|
-
|
352
|
+
val = case x
|
353
|
+
when String
|
354
|
+
begin
|
355
|
+
IPAddr.new(x)
|
356
|
+
rescue ArgumentError
|
357
|
+
nameservers_from_name(arg)
|
358
|
+
return
|
359
|
+
end
|
360
|
+
when IPAddr
|
361
|
+
x
|
362
|
+
else
|
363
|
+
raise ArgumentError, "Wrong argument format"
|
364
|
+
end
|
365
|
+
@config[:nameservers] << val
|
372
366
|
end
|
373
367
|
@logger.info "Nameservers list changed to value #{@config[:nameservers].inspect}"
|
374
368
|
else
|
375
369
|
raise ArgumentError, "Wrong argument format, neither String, Array nor IPAddr"
|
376
370
|
end
|
377
371
|
end
|
378
|
-
alias_method("nameserver=","nameservers=")
|
372
|
+
alias_method("nameserver=", "nameservers=")
|
379
373
|
|
380
374
|
# Return a string with the default domain.
|
381
375
|
def domain
|
@@ -408,7 +402,7 @@ module Net
|
|
408
402
|
# The default is port 53.
|
409
403
|
#
|
410
404
|
def port=(num)
|
411
|
-
if (0..
|
405
|
+
if (0..65_535).cover? num
|
412
406
|
@config[:port] = num
|
413
407
|
@logger.info "Port number changed to #{num}"
|
414
408
|
else
|
@@ -440,7 +434,8 @@ module Net
|
|
440
434
|
unless root?
|
441
435
|
raise ResolverPermissionError, "Are you root?"
|
442
436
|
end
|
443
|
-
|
437
|
+
|
438
|
+
if (0..65_535).cover?(num)
|
444
439
|
@config[:source_port] = num
|
445
440
|
else
|
446
441
|
raise ArgumentError, "Wrong port number #{num}"
|
@@ -462,7 +457,7 @@ module Net
|
|
462
457
|
def source_address_inet6
|
463
458
|
@config[:source_address_inet6].to_s
|
464
459
|
end
|
465
|
-
|
460
|
+
|
466
461
|
# Set the local source address from which the resolver sends its queries.
|
467
462
|
#
|
468
463
|
# res.source_address = "172.16.100.1"
|
@@ -492,9 +487,9 @@ module Net
|
|
492
487
|
end
|
493
488
|
|
494
489
|
begin
|
495
|
-
port = rand(
|
490
|
+
port = rand(1024..65_023)
|
496
491
|
@logger.warn "Try to determine state of source address #{addr} with port #{port}"
|
497
|
-
a = TCPServer.new(addr.to_s,port)
|
492
|
+
a = TCPServer.new(addr.to_s, port)
|
498
493
|
rescue SystemCallError => e
|
499
494
|
case e.errno
|
500
495
|
when 98 # Port already in use!
|
@@ -552,7 +547,7 @@ module Net
|
|
552
547
|
# Set the number of times the resolver will try a query.
|
553
548
|
# Default 4 times.
|
554
549
|
def retry_number=(num)
|
555
|
-
if num.
|
550
|
+
if num.is_a?(Integer) && (num > 0)
|
556
551
|
@config[:retry_number] = num
|
557
552
|
@logger.info "Retrasmissions number changed to #{num}"
|
558
553
|
else
|
@@ -571,8 +566,8 @@ module Net
|
|
571
566
|
def recursive?
|
572
567
|
@config[:recursive]
|
573
568
|
end
|
574
|
-
|
575
|
-
|
569
|
+
alias recurse recursive?
|
570
|
+
alias recursive recursive?
|
576
571
|
|
577
572
|
# Sets whether or not the resolver should perform recursive
|
578
573
|
# queries. Default is true.
|
@@ -581,14 +576,14 @@ module Net
|
|
581
576
|
#
|
582
577
|
def recursive=(bool)
|
583
578
|
case bool
|
584
|
-
when TrueClass,FalseClass
|
579
|
+
when TrueClass, FalseClass
|
585
580
|
@config[:recursive] = bool
|
586
581
|
@logger.info("Recursive state changed to #{bool}")
|
587
582
|
else
|
588
583
|
raise ArgumentError, "Argument must be boolean"
|
589
584
|
end
|
590
585
|
end
|
591
|
-
|
586
|
+
alias recurse= recursive=
|
592
587
|
|
593
588
|
# Return a string representing the resolver state, suitable
|
594
589
|
# for printing on the screen.
|
@@ -599,13 +594,13 @@ module Net
|
|
599
594
|
def state
|
600
595
|
str = ";; RESOLVER state:\n;; "
|
601
596
|
i = 1
|
602
|
-
@config.each do |key,val|
|
603
|
-
if key == :log_file
|
604
|
-
|
597
|
+
@config.each do |key, val|
|
598
|
+
str << if (key == :log_file) || (key == :config_file)
|
599
|
+
"#{key}: #{val} \t"
|
605
600
|
else
|
606
|
-
|
601
|
+
"#{key}: #{eval(key.to_s)} \t"
|
607
602
|
end
|
608
|
-
str << "\n;; " if i
|
603
|
+
str << "\n;; " if i.even?
|
609
604
|
i += 1
|
610
605
|
end
|
611
606
|
str
|
@@ -633,7 +628,7 @@ module Net
|
|
633
628
|
#
|
634
629
|
def defname=(bool)
|
635
630
|
case bool
|
636
|
-
when TrueClass,FalseClass
|
631
|
+
when TrueClass, FalseClass
|
637
632
|
@config[:defname] = bool
|
638
633
|
@logger.info("Defname state changed to #{bool}")
|
639
634
|
else
|
@@ -645,29 +640,29 @@ module Net
|
|
645
640
|
def dns_search
|
646
641
|
@config[:dns_search]
|
647
642
|
end
|
648
|
-
|
643
|
+
alias dnsrch dns_search
|
649
644
|
|
650
645
|
# Set the flag +dns_search+ in a boolean state. If +dns_search+
|
651
646
|
# is true, when using the Resolver#search method will be applied
|
652
647
|
# the search list. Default is true.
|
653
648
|
def dns_search=(bool)
|
654
649
|
case bool
|
655
|
-
when TrueClass,FalseClass
|
650
|
+
when TrueClass, FalseClass
|
656
651
|
@config[:dns_search] = bool
|
657
652
|
@logger.info("DNS search state changed to #{bool}")
|
658
653
|
else
|
659
654
|
raise ArgumentError, "Argument must be boolean"
|
660
655
|
end
|
661
656
|
end
|
662
|
-
alias_method("dnsrch=","dns_search=")
|
657
|
+
alias_method("dnsrch=", "dns_search=")
|
663
658
|
|
664
659
|
# Get the state of the use_tcp flag.
|
665
660
|
#
|
666
661
|
def use_tcp?
|
667
662
|
@config[:use_tcp]
|
668
663
|
end
|
669
|
-
|
670
|
-
|
664
|
+
alias usevc use_tcp?
|
665
|
+
alias use_tcp use_tcp?
|
671
666
|
|
672
667
|
# If +use_tcp+ is true, the resolver will perform all queries
|
673
668
|
# using TCP virtual circuits instead of UDP datagrams, which
|
@@ -681,7 +676,7 @@ module Net
|
|
681
676
|
#
|
682
677
|
def use_tcp=(bool)
|
683
678
|
case bool
|
684
|
-
when TrueClass,FalseClass
|
679
|
+
when TrueClass, FalseClass
|
685
680
|
@config[:use_tcp] = bool
|
686
681
|
@logger.info("Use tcp flag changed to #{bool}")
|
687
682
|
else
|
@@ -693,11 +688,11 @@ module Net
|
|
693
688
|
def ignore_truncated?
|
694
689
|
@config[:ignore_truncated]
|
695
690
|
end
|
696
|
-
|
691
|
+
alias ignore_truncated ignore_truncated?
|
697
692
|
|
698
693
|
def ignore_truncated=(bool)
|
699
694
|
case bool
|
700
|
-
when TrueClass,FalseClass
|
695
|
+
when TrueClass, FalseClass
|
701
696
|
@config[:ignore_truncated] = bool
|
702
697
|
@logger.info("Ignore truncated flag changed to #{bool}")
|
703
698
|
else
|
@@ -807,7 +802,7 @@ module Net
|
|
807
802
|
# Note that this will destroy the precedent logger.
|
808
803
|
#
|
809
804
|
def logger=(logger)
|
810
|
-
if logger.
|
805
|
+
if logger.is_a? Logger
|
811
806
|
@logger.close
|
812
807
|
@logger = logger
|
813
808
|
else
|
@@ -861,31 +856,29 @@ module Net
|
|
861
856
|
# Returns a Net::DNS::Packet object. If you need to examine the response packet
|
862
857
|
# whether it contains any answers or not, use the Resolver#query method instead.
|
863
858
|
#
|
864
|
-
def search(name,type=Net::DNS::A,cls=Net::DNS::IN)
|
865
|
-
|
866
|
-
return query(name,type,cls) if name.class == IPAddr
|
859
|
+
def search(name, type = Net::DNS::A, cls = Net::DNS::IN)
|
860
|
+
return query(name, type, cls) if name.class == IPAddr
|
867
861
|
|
868
862
|
# If the name contains at least one dot then try it as is first.
|
869
863
|
if name.include? "."
|
870
864
|
@logger.debug "Search(#{name},#{Net::DNS::RR::Types.new(type)},#{Net::DNS::RR::Classes.new(cls)})"
|
871
|
-
ans = query(name,type,cls)
|
865
|
+
ans = query(name, type, cls)
|
872
866
|
return ans if ans.header.anCount > 0
|
873
867
|
end
|
874
868
|
|
875
869
|
# If the name doesn't end in a dot then apply the search list.
|
876
|
-
if name !~ /\.$/
|
870
|
+
if name !~ /\.$/ && @config[:dns_search]
|
877
871
|
@config[:searchlist].each do |domain|
|
878
872
|
newname = name + "." + domain
|
879
873
|
@logger.debug "Search(#{newname},#{Net::DNS::RR::Types.new(type)},#{Net::DNS::RR::Classes.new(cls)})"
|
880
|
-
ans = query(newname,type,cls)
|
874
|
+
ans = query(newname, type, cls)
|
881
875
|
return ans if ans.header.anCount > 0
|
882
876
|
end
|
883
877
|
end
|
884
878
|
|
885
879
|
# Finally, if the name has no dots then try it as is.
|
886
880
|
@logger.debug "Search(#{name},#{Net::DNS::RR::Types.new(type)},#{Net::DNS::RR::Classes.new(cls)})"
|
887
|
-
query(name+".",type,cls)
|
888
|
-
|
881
|
+
query(name + ".", type, cls)
|
889
882
|
end
|
890
883
|
|
891
884
|
# Performs a DNS query for the given name; the search list
|
@@ -912,19 +905,17 @@ module Net
|
|
912
905
|
# packet whether it contains any answers or not, use the Resolver#query
|
913
906
|
# method instead.
|
914
907
|
#
|
915
|
-
def query(name,type=Net::DNS::A,cls=Net::DNS::IN)
|
916
|
-
|
917
|
-
return send(name,type,cls) if name.class == IPAddr
|
908
|
+
def query(name, type = Net::DNS::A, cls = Net::DNS::IN)
|
909
|
+
return send(name, type, cls) if name.class == IPAddr
|
918
910
|
|
919
911
|
# If the name doesn't contain any dots then append the default domain.
|
920
|
-
if name !~ /\./
|
912
|
+
if name !~ /\./ && name !~ /:/ && @config[:defname]
|
921
913
|
name += "." + @config[:domain]
|
922
914
|
end
|
923
915
|
|
924
916
|
@logger.debug "Query(#{name},#{Net::DNS::RR::Types.new(type)},#{Net::DNS::RR::Classes.new(cls)})"
|
925
917
|
|
926
|
-
send(name,type,cls)
|
927
|
-
|
918
|
+
send(name, type, cls)
|
928
919
|
end
|
929
920
|
|
930
921
|
# Performs a DNS query for the given name. Neither the
|
@@ -950,19 +941,19 @@ module Net
|
|
950
941
|
#
|
951
942
|
# ip = IPAddr.new("172.16.100.2")
|
952
943
|
# packet = res.query(ip)
|
953
|
-
#
|
944
|
+
#
|
954
945
|
# packet = res.query("172.16.100.2")
|
955
946
|
#
|
956
947
|
# Use +packet.header.ancount+ or +packet.answer+ to find out if there
|
957
948
|
# were any records in the answer section.
|
958
949
|
#
|
959
950
|
def query(argument, type = Net::DNS::A, cls = Net::DNS::IN)
|
960
|
-
if @config[:nameservers].
|
951
|
+
if @config[:nameservers].empty?
|
961
952
|
raise Resolver::Error, "No nameservers specified!"
|
962
953
|
end
|
963
954
|
|
964
955
|
method = :query_udp
|
965
|
-
packet = if argument.
|
956
|
+
packet = if argument.is_a? Net::DNS::Packet
|
966
957
|
argument
|
967
958
|
else
|
968
959
|
make_query_packet(argument, type, cls)
|
@@ -1004,7 +995,7 @@ module Net
|
|
1004
995
|
end
|
1005
996
|
end
|
1006
997
|
|
1007
|
-
ans =
|
998
|
+
ans = send(method, packet, packet_data)
|
1008
999
|
|
1009
1000
|
unless ans
|
1010
1001
|
message = "No response from nameservers list"
|
@@ -1012,20 +1003,20 @@ module Net
|
|
1012
1003
|
raise NoResponseError, message
|
1013
1004
|
end
|
1014
1005
|
|
1015
|
-
@logger.info "Received #{ans[0].size} bytes from #{ans[1][2]+
|
1016
|
-
response = Net::DNS::Packet.parse(ans[0],ans[1])
|
1006
|
+
@logger.info "Received #{ans[0].size} bytes from #{ans[1][2] + ':' + ans[1][1].to_s}"
|
1007
|
+
response = Net::DNS::Packet.parse(ans[0], ans[1])
|
1017
1008
|
|
1018
|
-
if response.header.truncated?
|
1009
|
+
if response.header.truncated? && !ignore_truncated?
|
1019
1010
|
@logger.warn "Packet truncated, retrying using TCP"
|
1020
1011
|
self.use_tcp = true
|
1021
1012
|
begin
|
1022
|
-
return query(argument,type,cls)
|
1013
|
+
return query(argument, type, cls)
|
1023
1014
|
ensure
|
1024
1015
|
self.use_tcp = false
|
1025
1016
|
end
|
1026
1017
|
end
|
1027
1018
|
|
1028
|
-
|
1019
|
+
response
|
1029
1020
|
end
|
1030
1021
|
|
1031
1022
|
# Performs a zone transfer for the zone passed as a parameter.
|
@@ -1052,7 +1043,7 @@ module Net
|
|
1052
1043
|
query(name, Net::DNS::MX, cls).answer.each do |entry|
|
1053
1044
|
arr << entry if entry.type == 'MX'
|
1054
1045
|
end
|
1055
|
-
arr.sort_by
|
1046
|
+
arr.sort_by(&:preference)
|
1056
1047
|
end
|
1057
1048
|
|
1058
1049
|
private
|
@@ -1062,20 +1053,21 @@ module Net
|
|
1062
1053
|
if self.class.platform_windows?
|
1063
1054
|
require 'win32/resolv'
|
1064
1055
|
arr = Win32::Resolv.get_resolv_info
|
1065
|
-
self.domain = arr[0]
|
1056
|
+
self.domain = arr[0][0]
|
1066
1057
|
self.nameservers = arr[1]
|
1067
1058
|
else
|
1068
1059
|
nameservers = []
|
1069
1060
|
IO.foreach(@config[:config_file]) do |line|
|
1070
|
-
line.gsub!(/\s*[;#].*/,"")
|
1061
|
+
line.gsub!(/\s*[;#].*/, "")
|
1071
1062
|
next unless line =~ /\S/
|
1063
|
+
|
1072
1064
|
case line
|
1073
1065
|
when /^\s*domain\s+(\S+)/
|
1074
|
-
self.domain =
|
1066
|
+
self.domain = Regexp.last_match(1)
|
1075
1067
|
when /^\s*search\s+(.*)/
|
1076
|
-
self.searchlist =
|
1068
|
+
self.searchlist = Regexp.last_match(1).split(" ")
|
1077
1069
|
when /^\s*nameserver\s+(.*)/
|
1078
|
-
nameservers <<
|
1070
|
+
nameservers << Regexp.last_match(1).split(" ")
|
1079
1071
|
end
|
1080
1072
|
end
|
1081
1073
|
self.nameservers = nameservers.flatten
|
@@ -1095,7 +1087,7 @@ module Net
|
|
1095
1087
|
end
|
1096
1088
|
if ENV['RES_OPTIONS']
|
1097
1089
|
ENV['RES_OPTIONS'].split(" ").each do |opt|
|
1098
|
-
name,val = opt.split(":")
|
1090
|
+
name, val = opt.split(":")
|
1099
1091
|
begin
|
1100
1092
|
eval("self.#{name} = #{val}")
|
1101
1093
|
rescue NoMethodError
|
@@ -1145,22 +1137,21 @@ module Net
|
|
1145
1137
|
end
|
1146
1138
|
|
1147
1139
|
def query_tcp(packet, packet_data)
|
1148
|
-
|
1149
1140
|
ans = nil
|
1150
1141
|
length = [packet_data.size].pack("n")
|
1151
1142
|
|
1152
1143
|
@config[:nameservers].each do |ns|
|
1153
1144
|
begin
|
1154
1145
|
buffer = ""
|
1155
|
-
socket = Socket.new(Socket::AF_INET,Socket::SOCK_STREAM,0)
|
1156
|
-
socket.bind(Socket.pack_sockaddr_in(@config[:source_port]
|
1146
|
+
socket = Socket.new(Socket::AF_INET, Socket::SOCK_STREAM, 0)
|
1147
|
+
socket.bind(Socket.pack_sockaddr_in(@config[:source_port], @config[:source_address].to_s))
|
1157
1148
|
|
1158
|
-
sockaddr = Socket.pack_sockaddr_in(@config[:port],ns.to_s)
|
1149
|
+
sockaddr = Socket.pack_sockaddr_in(@config[:port], ns.to_s)
|
1159
1150
|
|
1160
1151
|
@config[:tcp_timeout].timeout do
|
1161
1152
|
socket.connect(sockaddr)
|
1162
1153
|
@logger.info "Contacting nameserver #{ns} port #{@config[:port]}"
|
1163
|
-
socket.write(length+packet_data)
|
1154
|
+
socket.write(length + packet_data)
|
1164
1155
|
ans = socket.recv(Net::DNS::INT16SZ)
|
1165
1156
|
len = ans.unpack("n")[0]
|
1166
1157
|
|
@@ -1171,9 +1162,9 @@ module Net
|
|
1171
1162
|
next
|
1172
1163
|
end
|
1173
1164
|
|
1174
|
-
while
|
1165
|
+
while buffer.size < len
|
1175
1166
|
left = len - buffer.size
|
1176
|
-
temp,from = socket.recvfrom(left)
|
1167
|
+
temp, from = socket.recvfrom(left)
|
1177
1168
|
buffer += temp
|
1178
1169
|
end
|
1179
1170
|
|
@@ -1182,7 +1173,7 @@ module Net
|
|
1182
1173
|
next
|
1183
1174
|
end
|
1184
1175
|
end
|
1185
|
-
return [buffer,[""
|
1176
|
+
return [buffer, ["", @config[:port], ns.to_s, ns.to_s]]
|
1186
1177
|
rescue TimeoutError
|
1187
1178
|
@logger.warn "Nameserver #{ns} not responding within TCP timeout, trying next one"
|
1188
1179
|
next
|
@@ -1194,9 +1185,9 @@ module Net
|
|
1194
1185
|
|
1195
1186
|
def query_udp(packet, packet_data)
|
1196
1187
|
socket4 = UDPSocket.new
|
1197
|
-
socket4.bind(@config[:source_address].to_s
|
1188
|
+
socket4.bind(@config[:source_address].to_s, @config[:source_port])
|
1198
1189
|
socket6 = UDPSocket.new(Socket::AF_INET6)
|
1199
|
-
socket6.bind(@config[:source_address_inet6].to_s
|
1190
|
+
socket6.bind(@config[:source_address_inet6].to_s, @config[:source_port])
|
1200
1191
|
|
1201
1192
|
ans = nil
|
1202
1193
|
response = ""
|
@@ -1229,7 +1220,6 @@ module Net
|
|
1229
1220
|
true
|
1230
1221
|
end
|
1231
1222
|
end
|
1232
|
-
|
1233
1223
|
end
|
1234
1224
|
end
|
1235
1225
|
end
|