net-dns 0.8.0 → 0.9.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 +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
|