net-dns 0.6.1 → 0.7.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 +8 -6
- data/.travis.yml +14 -0
- data/CHANGELOG.md +79 -0
- data/Gemfile +4 -0
- data/Rakefile +56 -66
- data/demo/check_soa.rb +1 -1
- data/demo/threads.rb +1 -1
- data/lib/net/dns.rb +24 -22
- data/lib/net/dns/header.rb +77 -103
- data/lib/net/dns/{names/names.rb → names.rb} +19 -20
- data/lib/net/dns/packet.rb +231 -256
- data/lib/net/dns/question.rb +11 -40
- data/lib/net/dns/resolver.rb +248 -250
- data/lib/net/dns/resolver/socks.rb +6 -6
- data/lib/net/dns/resolver/timeouts.rb +1 -1
- data/lib/net/dns/rr.rb +112 -117
- data/lib/net/dns/rr/a.rb +98 -89
- data/lib/net/dns/rr/aaaa.rb +84 -68
- data/lib/net/dns/rr/classes.rb +91 -106
- data/lib/net/dns/rr/cname.rb +64 -45
- data/lib/net/dns/rr/hinfo.rb +90 -50
- data/lib/net/dns/rr/mr.rb +61 -44
- data/lib/net/dns/rr/mx.rb +73 -48
- data/lib/net/dns/rr/ns.rb +60 -46
- data/lib/net/dns/rr/null.rb +11 -12
- data/lib/net/dns/rr/ptr.rb +47 -34
- data/lib/net/dns/rr/soa.rb +5 -6
- data/lib/net/dns/rr/srv.rb +1 -4
- data/lib/net/dns/rr/txt.rb +14 -14
- data/lib/net/dns/rr/types.rb +13 -13
- data/lib/net/dns/version.rb +8 -14
- data/net-dns.gemspec +35 -0
- data/setup.rb +3 -2
- data/test/header_test.rb +18 -18
- data/test/names_test.rb +21 -0
- data/test/packet_test.rb +38 -31
- data/test/question_test.rb +23 -24
- data/test/resolver/timeouts_test.rb +13 -13
- data/test/resolver_test.rb +28 -20
- data/test/rr/a_test.rb +70 -23
- data/test/rr/aaaa_test.rb +109 -0
- data/test/rr/classes_test.rb +61 -49
- data/test/rr/cname_test.rb +97 -0
- data/test/rr/hinfo_test.rb +117 -0
- data/test/rr/mr_test.rb +105 -0
- data/test/rr/mx_test.rb +112 -0
- data/test/rr/ns_test.rb +34 -12
- data/test/rr/types_test.rb +4 -4
- data/test/rr_test.rb +1 -1
- metadata +77 -52
- data/AUTHORS.rdoc +0 -7
- data/CHANGELOG.rdoc +0 -46
- data/VERSION.yml +0 -5
data/lib/net/dns/question.rb
CHANGED
@@ -1,10 +1,4 @@
|
|
1
|
-
|
2
|
-
require 'net/dns/names/names'
|
3
|
-
require 'net/dns/rr/types'
|
4
|
-
require 'net/dns/rr/classes'
|
5
|
-
|
6
|
-
|
7
|
-
module Net # :nodoc:
|
1
|
+
module Net
|
8
2
|
module DNS
|
9
3
|
|
10
4
|
#
|
@@ -40,35 +34,15 @@ module Net # :nodoc:
|
|
40
34
|
# the Perl version of the library, as long as methods name which are
|
41
35
|
# more or less the same.
|
42
36
|
#
|
43
|
-
# =Error classes
|
44
|
-
#
|
45
|
-
# Some error classes has been defined for the Net::DNS::Header class,
|
46
|
-
# which are listed here to keep a light and browsable main documentation.
|
47
|
-
# We have:
|
48
|
-
#
|
49
|
-
# ArgumentError:: Argument Error for class Net::DNS::Question
|
50
|
-
# NameError:: An error in the +name+ part of a Question entry
|
51
|
-
#
|
52
|
-
# =Copyright
|
53
|
-
#
|
54
|
-
# Copyright (c) 2006 Marco Ceresa
|
55
|
-
#
|
56
|
-
# All rights reserved. This program is free software; you may redistribute
|
57
|
-
# it and/or modify it under the same terms as Ruby itself.
|
58
|
-
#
|
59
37
|
class Question
|
60
|
-
include
|
61
|
-
|
62
|
-
# Argument Error for class Net::DNS::Question
|
63
|
-
class ArgumentError < ArgumentError
|
64
|
-
end
|
65
|
-
|
38
|
+
include Names
|
39
|
+
|
66
40
|
# Base error class.
|
67
41
|
class Error < StandardError
|
68
42
|
end
|
69
43
|
|
70
44
|
# An error in the +name+ part of a Question entry
|
71
|
-
class
|
45
|
+
class NameInvalid < Error
|
72
46
|
end
|
73
47
|
|
74
48
|
# +name+ part of a Question entry
|
@@ -191,27 +165,24 @@ module Net # :nodoc:
|
|
191
165
|
result
|
192
166
|
end
|
193
167
|
|
194
|
-
def check_name(
|
195
|
-
name.strip
|
168
|
+
def check_name(input)
|
169
|
+
name = input.to_s.strip
|
196
170
|
if name =~ /[^\w\.\-_]/
|
197
|
-
raise
|
198
|
-
else
|
199
|
-
name
|
171
|
+
raise NameInvalid, "Invalid Question Name `#{name}'"
|
200
172
|
end
|
201
|
-
|
202
|
-
raise NameError, "Question name #{name.inspect} not valid"
|
173
|
+
name
|
203
174
|
end
|
204
175
|
|
205
176
|
def new_from_binary(data)
|
206
|
-
str,type,cls = data.unpack("a#{data.size-4}nn")
|
177
|
+
str,type,cls = data.unpack("a#{data.size - 4}nn")
|
207
178
|
@qName = build_qName(str)
|
208
179
|
@qType = Net::DNS::RR::Types.new type
|
209
180
|
@qClass = Net::DNS::RR::Classes.new cls
|
210
181
|
rescue StandardError => e
|
211
|
-
raise ArgumentError, "Invalid data: #{data.inspect}
|
182
|
+
raise ArgumentError, "Invalid data: #{data.inspect}"
|
212
183
|
end
|
213
184
|
|
214
185
|
end
|
215
186
|
|
216
187
|
end
|
217
|
-
end
|
188
|
+
end
|
data/lib/net/dns/resolver.rb
CHANGED
@@ -1,57 +1,52 @@
|
|
1
1
|
require 'rbconfig'
|
2
2
|
require 'socket'
|
3
3
|
require 'timeout'
|
4
|
-
require 'ipaddr'
|
5
|
-
require 'logger'
|
6
4
|
require 'net/dns/packet'
|
7
5
|
require 'net/dns/resolver/timeouts'
|
8
6
|
|
9
|
-
|
10
|
-
|
7
|
+
# Resolver helper method.
|
11
8
|
#
|
12
|
-
# = Resolver helper method
|
13
|
-
#
|
14
9
|
# Calling the resolver directly:
|
15
|
-
#
|
10
|
+
#
|
16
11
|
# require 'net/dns/resolver'
|
17
12
|
# puts Resolver("www.google.com").answer.size
|
18
|
-
#
|
13
|
+
# # => 5
|
19
14
|
#
|
20
15
|
# An optional block can be passed yielding the Net::DNS::Packet object.
|
21
16
|
#
|
22
|
-
# Resolver("www.google.com") {|packet| puts packet.size + " bytes"}
|
23
|
-
#
|
17
|
+
# Resolver("www.google.com") { |packet| puts packet.size + " bytes" }
|
18
|
+
# # => 484 bytes
|
24
19
|
#
|
25
|
-
def Resolver(name,type=Net::DNS::A,cls=Net::DNS::IN
|
26
|
-
|
20
|
+
def Resolver(name, type = Net::DNS::A, cls = Net::DNS::IN, &block)
|
21
|
+
resolver = Net::DNS::Resolver.start(name, type, cls)
|
27
22
|
if block_given?
|
28
|
-
yield
|
23
|
+
yield resolver
|
29
24
|
else
|
30
|
-
|
25
|
+
resolver
|
31
26
|
end
|
32
27
|
end
|
33
28
|
|
34
|
-
module Net
|
35
|
-
module DNS
|
36
|
-
|
29
|
+
module Net
|
30
|
+
module DNS
|
31
|
+
|
37
32
|
include Logger::Severity
|
38
33
|
|
39
34
|
# = Net::DNS::Resolver - DNS resolver class
|
40
35
|
#
|
41
36
|
# The Net::DNS::Resolver class implements a complete DNS resolver written
|
42
|
-
# in pure Ruby, without a single C line of code. It has all of the
|
43
|
-
# tipical properties of an evoluted resolver, and a bit of OO which
|
44
|
-
# comes from having used Ruby.
|
45
|
-
#
|
46
|
-
# This project started as a porting of the Net::DNS Perl module,
|
37
|
+
# in pure Ruby, without a single C line of code. It has all of the
|
38
|
+
# tipical properties of an evoluted resolver, and a bit of OO which
|
39
|
+
# comes from having used Ruby.
|
40
|
+
#
|
41
|
+
# This project started as a porting of the Net::DNS Perl module,
|
47
42
|
# written by Martin Fuhr, but turned out (in the last months) to be
|
48
43
|
# an almost complete rewriting. Well, maybe some of the features of
|
49
44
|
# the Perl version are still missing, but guys, at least this is
|
50
|
-
# readable code!
|
45
|
+
# readable code!
|
51
46
|
#
|
52
47
|
# == Environment
|
53
48
|
#
|
54
|
-
# The Following Environment variables can also be used to configure
|
49
|
+
# The Following Environment variables can also be used to configure
|
55
50
|
# the resolver:
|
56
51
|
#
|
57
52
|
# * +RES_NAMESERVERS+: A space-separated list of nameservers to query.
|
@@ -63,7 +58,7 @@ module Net # :nodoc:
|
|
63
58
|
# # C Shell
|
64
59
|
# % setenv RES_NAMESERVERS "192.168.1.1 192.168.2.2 192.168.3.3"
|
65
60
|
#
|
66
|
-
# * +RES_SEARCHLIST+: A space-separated list of domains to put in the
|
61
|
+
# * +RES_SEARCHLIST+: A space-separated list of domains to put in the
|
67
62
|
# search list.
|
68
63
|
#
|
69
64
|
# # Bourne Shell
|
@@ -72,7 +67,7 @@ module Net # :nodoc:
|
|
72
67
|
#
|
73
68
|
# # C Shell
|
74
69
|
# % setenv RES_SEARCHLIST "example.com sub1.example.com sub2.example.com"
|
75
|
-
#
|
70
|
+
#
|
76
71
|
# * +LOCALDOMAIN+: The default domain.
|
77
72
|
#
|
78
73
|
# # Bourne Shell
|
@@ -82,7 +77,7 @@ module Net # :nodoc:
|
|
82
77
|
# # C Shell
|
83
78
|
# % setenv LOCALDOMAIN example.com
|
84
79
|
#
|
85
|
-
# * +RES_OPTIONS+: A space-separated list of resolver options to set.
|
80
|
+
# * +RES_OPTIONS+: A space-separated list of resolver options to set.
|
86
81
|
# Options that take values are specified as option:value.
|
87
82
|
#
|
88
83
|
# # Bourne Shell
|
@@ -91,23 +86,18 @@ module Net # :nodoc:
|
|
91
86
|
#
|
92
87
|
# # C Shell
|
93
88
|
# % setenv RES_OPTIONS "retrans:3 retry:2 debug"
|
94
|
-
#
|
89
|
+
#
|
95
90
|
class Resolver
|
96
|
-
|
97
|
-
# Argument Error for class Net::DNS::Resolver.
|
98
|
-
class ArgumentError < ArgumentError
|
99
|
-
end
|
100
|
-
|
91
|
+
|
101
92
|
class Error < StandardError
|
102
93
|
end
|
103
|
-
|
94
|
+
|
104
95
|
class NoResponseError < Error
|
105
96
|
end
|
106
|
-
|
107
|
-
|
97
|
+
|
108
98
|
# An hash with the defaults values of almost all the
|
109
99
|
# configuration parameters of a resolver object. See
|
110
|
-
# the description for each parameter to have an
|
100
|
+
# the description for each parameter to have an
|
111
101
|
# explanation of its usage.
|
112
102
|
Defaults = {
|
113
103
|
:config_file => "/etc/resolv.conf",
|
@@ -118,6 +108,7 @@ module Net # :nodoc:
|
|
118
108
|
:domain => "",
|
119
109
|
:source_port => 0,
|
120
110
|
:source_address => IPAddr.new("0.0.0.0"),
|
111
|
+
:source_address_inet6 => IPAddr.new('::'),
|
121
112
|
:retry_interval => 5,
|
122
113
|
:retry_number => 4,
|
123
114
|
:recursive => true,
|
@@ -129,10 +120,36 @@ module Net # :nodoc:
|
|
129
120
|
:tcp_timeout => TcpTimeout.new(5),
|
130
121
|
:udp_timeout => UdpTimeout.new(5),
|
131
122
|
}
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
123
|
+
|
124
|
+
|
125
|
+
class << self
|
126
|
+
|
127
|
+
C = Object.const_get(defined?(RbConfig) ? :RbConfig : :Config)::CONFIG
|
128
|
+
|
129
|
+
# Quick resolver method. Bypass the configuration using
|
130
|
+
# the defaults.
|
131
|
+
#
|
132
|
+
# Net::DNS::Resolver.start "www.google.com"
|
133
|
+
#
|
134
|
+
def start(*params)
|
135
|
+
new.search(*params)
|
136
|
+
end
|
137
|
+
|
138
|
+
# Returns true if running on a Windows platform.
|
139
|
+
#
|
140
|
+
# Note. This method doesn't rely on the RUBY_PLATFORM constant
|
141
|
+
# because the comparison will fail when running on JRuby.
|
142
|
+
# On JRuby RUBY_PLATFORM == 'java'.
|
143
|
+
def platform_windows?
|
144
|
+
!!(C["host_os"] =~ /msdos|mswin|djgpp|mingw/i)
|
145
|
+
end
|
146
|
+
|
147
|
+
end
|
148
|
+
|
149
|
+
|
150
|
+
# Creates a new resolver object.
|
151
|
+
#
|
152
|
+
# Argument +config+ can either be empty or be an hash with
|
136
153
|
# some configuration parameters. To know what each parameter
|
137
154
|
# do, look at the description of each.
|
138
155
|
# Some example:
|
@@ -142,17 +159,17 @@ module Net # :nodoc:
|
|
142
159
|
#
|
143
160
|
# # Specify a configuration file
|
144
161
|
# res = Net::DNS::Resolver.new(:config_file => '/my/dns.conf')
|
145
|
-
#
|
162
|
+
#
|
146
163
|
# # Set some option
|
147
164
|
# res = Net::DNS::Resolver.new(:nameservers => "172.16.1.1",
|
148
165
|
# :recursive => false,
|
149
166
|
# :retry => 10)
|
150
167
|
#
|
151
168
|
# == Config file
|
152
|
-
#
|
169
|
+
#
|
153
170
|
# Net::DNS::Resolver uses a config file to read the usual
|
154
171
|
# values a resolver needs, such as nameserver list and
|
155
|
-
# domain names. On UNIX systems the defaults are read from the
|
172
|
+
# domain names. On UNIX systems the defaults are read from the
|
156
173
|
# following files, in the order indicated:
|
157
174
|
#
|
158
175
|
# * /etc/resolv.conf
|
@@ -165,32 +182,32 @@ module Net # :nodoc:
|
|
165
182
|
# * search: a space-separated list of domains to put in the search list.
|
166
183
|
# * nameserver: a space-separated list of nameservers to query.
|
167
184
|
#
|
168
|
-
# Files except for /etc/resolv.conf must be owned by the effective userid
|
169
|
-
# running the program or they won't be read. In addition, several environment
|
170
|
-
# variables can also contain configuration information; see Environment
|
185
|
+
# Files except for /etc/resolv.conf must be owned by the effective userid
|
186
|
+
# running the program or they won't be read. In addition, several environment
|
187
|
+
# variables can also contain configuration information; see Environment
|
171
188
|
# in the main description for Resolver class.
|
172
|
-
#
|
173
|
-
# On Windows Systems, an attempt is made to determine the system defaults
|
174
|
-
# using the registry. This is still a work in progress; systems with many
|
189
|
+
#
|
190
|
+
# On Windows Systems, an attempt is made to determine the system defaults
|
191
|
+
# using the registry. This is still a work in progress; systems with many
|
175
192
|
# dynamically configured network interfaces may confuse Net::DNS.
|
176
193
|
#
|
177
|
-
# You can include a configuration file of your own when creating a resolver
|
194
|
+
# You can include a configuration file of your own when creating a resolver
|
178
195
|
# object:
|
179
196
|
#
|
180
197
|
# # Use my own configuration file
|
181
198
|
# my $res = Net::DNS::Resolver->new(config_file => '/my/dns.conf');
|
182
199
|
#
|
183
|
-
# This is supported on both UNIX and Windows. Values pulled from a custom
|
184
|
-
# configuration file override the the system's defaults, but can still be
|
200
|
+
# This is supported on both UNIX and Windows. Values pulled from a custom
|
201
|
+
# configuration file override the the system's defaults, but can still be
|
185
202
|
# overridden by the other arguments to Resolver::new.
|
186
203
|
#
|
187
|
-
# Explicit arguments to Resolver::new override both the system's defaults
|
204
|
+
# Explicit arguments to Resolver::new override both the system's defaults
|
188
205
|
# and the values of the custom configuration file, if any.
|
189
206
|
#
|
190
207
|
# == Parameters
|
191
|
-
#
|
208
|
+
#
|
192
209
|
# The following arguments to Resolver::new are supported:
|
193
|
-
#
|
210
|
+
#
|
194
211
|
# * nameservers: an array reference of nameservers to query.
|
195
212
|
# * searchlist: an array reference of domains.
|
196
213
|
# * recurse
|
@@ -212,16 +229,17 @@ module Net # :nodoc:
|
|
212
229
|
# * persistent_udp
|
213
230
|
# * dnssec
|
214
231
|
#
|
215
|
-
# For more information on any of these options, please consult the
|
232
|
+
# For more information on any of these options, please consult the
|
216
233
|
# method of the same name.
|
217
234
|
#
|
218
235
|
# == Disclaimer
|
219
|
-
#
|
220
|
-
# Part of the above documentation is taken from the one in the
|
236
|
+
#
|
237
|
+
# Part of the above documentation is taken from the one in the
|
221
238
|
# Net::DNS::Resolver Perl module.
|
222
239
|
#
|
223
240
|
def initialize(config = {})
|
224
|
-
raise ArgumentError, "
|
241
|
+
raise ArgumentError, "Expected `config' to be a Hash" unless config.is_a?(Hash)
|
242
|
+
|
225
243
|
# config.downcase_keys!
|
226
244
|
@config = Defaults.merge config
|
227
245
|
@raw = false
|
@@ -229,7 +247,7 @@ module Net # :nodoc:
|
|
229
247
|
# New logger facility
|
230
248
|
@logger = Logger.new(@config[:log_file])
|
231
249
|
@logger.level = $DEBUG ? Logger::DEBUG : Logger::WARN
|
232
|
-
|
250
|
+
|
233
251
|
#------------------------------------------------------------
|
234
252
|
# Resolver configuration will be set in order from:
|
235
253
|
# 1) initialize arguments
|
@@ -238,18 +256,18 @@ module Net # :nodoc:
|
|
238
256
|
# 4) defaults (and /etc/resolv.conf for config)
|
239
257
|
#------------------------------------------------------------
|
240
258
|
|
241
|
-
|
242
|
-
|
259
|
+
|
260
|
+
|
243
261
|
#------------------------------------------------------------
|
244
262
|
# Parsing config file
|
245
263
|
#------------------------------------------------------------
|
246
264
|
parse_config_file
|
247
|
-
|
265
|
+
|
248
266
|
#------------------------------------------------------------
|
249
267
|
# Parsing ENV variables
|
250
268
|
#------------------------------------------------------------
|
251
269
|
parse_environment_variables
|
252
|
-
|
270
|
+
|
253
271
|
#------------------------------------------------------------
|
254
272
|
# Parsing arguments
|
255
273
|
#------------------------------------------------------------
|
@@ -262,7 +280,7 @@ module Net # :nodoc:
|
|
262
280
|
end
|
263
281
|
end
|
264
282
|
end
|
265
|
-
|
283
|
+
|
266
284
|
# Get the resolver search list, returned as an array of entries.
|
267
285
|
#
|
268
286
|
# res.searchlist
|
@@ -272,7 +290,7 @@ module Net # :nodoc:
|
|
272
290
|
@config[:searchlist].inspect
|
273
291
|
end
|
274
292
|
|
275
|
-
# Set the resolver searchlist.
|
293
|
+
# Set the resolver searchlist.
|
276
294
|
# +arg+ can be a single string or an array of strings.
|
277
295
|
#
|
278
296
|
# res.searchstring = "example.com"
|
@@ -293,24 +311,21 @@ module Net # :nodoc:
|
|
293
311
|
@logger.info "Searchlist changed to value #{@config[:searchlist].inspect}"
|
294
312
|
when Array
|
295
313
|
@config[:searchlist] = arg if arg.all? {|x| valid? x}
|
296
|
-
@logger.info "Searchlist changed to value #{@config[:searchlist].inspect}"
|
314
|
+
@logger.info "Searchlist changed to value #{@config[:searchlist].inspect}"
|
297
315
|
else
|
298
316
|
raise ArgumentError, "Wrong argument format, neither String nor Array"
|
299
317
|
end
|
300
318
|
end
|
301
|
-
|
319
|
+
|
302
320
|
# Get the list of resolver nameservers, in a dotted decimal format-
|
303
321
|
#
|
304
322
|
# res.nameservers
|
305
323
|
# #=> ["192.168.0.1","192.168.0.2"]
|
306
324
|
#
|
307
325
|
def nameservers
|
308
|
-
|
309
|
-
@config[:nameservers].each do |x|
|
310
|
-
arr << x.to_s
|
311
|
-
end
|
312
|
-
arr
|
326
|
+
@config[:nameservers].map(&:to_s)
|
313
327
|
end
|
328
|
+
|
314
329
|
alias_method :nameserver, :nameservers
|
315
330
|
|
316
331
|
# Set the list of resolver nameservers.
|
@@ -338,7 +353,7 @@ module Net # :nodoc:
|
|
338
353
|
end
|
339
354
|
when IPAddr
|
340
355
|
@config[:nameservers] = [arg]
|
341
|
-
@logger.info "Nameservers list changed to value #{@config[:nameservers].inspect}"
|
356
|
+
@logger.info "Nameservers list changed to value #{@config[:nameservers].inspect}"
|
342
357
|
when Array
|
343
358
|
@config[:nameservers] = []
|
344
359
|
arg.each do |x|
|
@@ -356,13 +371,13 @@ module Net # :nodoc:
|
|
356
371
|
raise ArgumentError, "Wrong argument format"
|
357
372
|
end
|
358
373
|
end
|
359
|
-
@logger.info "Nameservers list changed to value #{@config[:nameservers].inspect}"
|
374
|
+
@logger.info "Nameservers list changed to value #{@config[:nameservers].inspect}"
|
360
375
|
else
|
361
376
|
raise ArgumentError, "Wrong argument format, neither String, Array nor IPAddr"
|
362
377
|
end
|
363
378
|
end
|
364
379
|
alias_method("nameserver=","nameservers=")
|
365
|
-
|
380
|
+
|
366
381
|
# Return a string with the default domain.
|
367
382
|
def domain
|
368
383
|
@config[:domain].inspect
|
@@ -372,7 +387,7 @@ module Net # :nodoc:
|
|
372
387
|
def domain=(name)
|
373
388
|
@config[:domain] = name if valid? name
|
374
389
|
end
|
375
|
-
|
390
|
+
|
376
391
|
# Return the defined size of the packet.
|
377
392
|
def packet_size
|
378
393
|
@config[:packet_size]
|
@@ -386,8 +401,8 @@ module Net # :nodoc:
|
|
386
401
|
@config[:port]
|
387
402
|
end
|
388
403
|
|
389
|
-
# Set the port number to which the resolver sends queries. This can be useful
|
390
|
-
# for testing a nameserver running on a non-standard port.
|
404
|
+
# Set the port number to which the resolver sends queries. This can be useful
|
405
|
+
# for testing a nameserver running on a non-standard port.
|
391
406
|
#
|
392
407
|
# res.port = 10053
|
393
408
|
#
|
@@ -396,7 +411,7 @@ module Net # :nodoc:
|
|
396
411
|
def port=(num)
|
397
412
|
if (0..65535).include? num
|
398
413
|
@config[:port] = num
|
399
|
-
@logger.info "Port number changed to #{num}"
|
414
|
+
@logger.info "Port number changed to #{num}"
|
400
415
|
else
|
401
416
|
raise ArgumentError, "Wrong port number #{num}"
|
402
417
|
end
|
@@ -415,8 +430,8 @@ module Net # :nodoc:
|
|
415
430
|
#
|
416
431
|
# res.source_port = 40000
|
417
432
|
#
|
418
|
-
# Note that if you want to set a port you need root priviledges, as
|
419
|
-
# raw sockets will be used to generate packets. The class will then
|
433
|
+
# Note that if you want to set a port you need root priviledges, as
|
434
|
+
# raw sockets will be used to generate packets. The class will then
|
420
435
|
# generate the exception ResolverPermissionError if you're not root.
|
421
436
|
#
|
422
437
|
# The default is 0, which means that the port will be chosen by the
|
@@ -426,14 +441,14 @@ module Net # :nodoc:
|
|
426
441
|
unless root?
|
427
442
|
raise ResolverPermissionError, "Are you root?"
|
428
443
|
end
|
429
|
-
if (0..65535).include?(num)
|
444
|
+
if (0..65535).include?(num)
|
430
445
|
@config[:source_port] = num
|
431
446
|
else
|
432
447
|
raise ArgumentError, "Wrong port number #{num}"
|
433
448
|
end
|
434
449
|
end
|
435
|
-
alias srcport= source_port=
|
436
|
-
|
450
|
+
alias srcport= source_port=
|
451
|
+
|
437
452
|
# Get the local address from which the resolver sends queries
|
438
453
|
#
|
439
454
|
# puts "Sending queries using source address #{res.source_address}"
|
@@ -441,7 +456,7 @@ module Net # :nodoc:
|
|
441
456
|
def source_address
|
442
457
|
@config[:source_address].to_s
|
443
458
|
end
|
444
|
-
alias srcaddr source_address
|
459
|
+
alias srcaddr source_address
|
445
460
|
|
446
461
|
# Set the local source address from which the resolver sends its queries.
|
447
462
|
#
|
@@ -452,16 +467,16 @@ module Net # :nodoc:
|
|
452
467
|
# or an instance of IPAddr class.
|
453
468
|
#
|
454
469
|
# Normally this can be used to force queries out a specific interface
|
455
|
-
# on a multi-homed host. In this case, you should of course need to
|
470
|
+
# on a multi-homed host. In this case, you should of course need to
|
456
471
|
# know the addresses of the interfaces.
|
457
472
|
#
|
458
473
|
# Another way to use this option is for some kind of spoofing attacks
|
459
|
-
# towards weak nameservers, to probe the security of your network.
|
460
|
-
# This includes specifing ranged attacks such as DoS and others. For
|
474
|
+
# towards weak nameservers, to probe the security of your network.
|
475
|
+
# This includes specifing ranged attacks such as DoS and others. For
|
461
476
|
# a paper on DNS security, checks http://www.marcoceresa.com/security/
|
462
477
|
#
|
463
|
-
# Note that if you want to set a non-binded source address you need
|
464
|
-
# root priviledges, as raw sockets will be used to generate packets.
|
478
|
+
# Note that if you want to set a non-binded source address you need
|
479
|
+
# root priviledges, as raw sockets will be used to generate packets.
|
465
480
|
# The class will then generate an exception if you're not root.
|
466
481
|
#
|
467
482
|
# The default is 0.0.0.0, meaning any local address (chosen on routing needs).
|
@@ -489,37 +504,37 @@ module Net # :nodoc:
|
|
489
504
|
ensure
|
490
505
|
a.close
|
491
506
|
end
|
492
|
-
|
507
|
+
|
493
508
|
case addr
|
494
509
|
when String
|
495
510
|
@config[:source_address] = IPAddr.new(string)
|
496
511
|
@logger.info "Using new source address: #{@config[:source_address]}"
|
497
512
|
when IPAddr
|
498
513
|
@config[:source_address] = addr
|
499
|
-
@logger.info "Using new source address: #{@config[:source_address]}"
|
514
|
+
@logger.info "Using new source address: #{@config[:source_address]}"
|
500
515
|
else
|
501
516
|
raise ArgumentError, "Unknown dest_address format"
|
502
517
|
end
|
503
518
|
end
|
504
|
-
alias srcaddr= source_address=
|
505
|
-
|
506
|
-
# Return the retrasmission interval (in seconds) the resolvers has
|
519
|
+
alias srcaddr= source_address=
|
520
|
+
|
521
|
+
# Return the retrasmission interval (in seconds) the resolvers has
|
507
522
|
# been set on.
|
508
523
|
def retry_interval
|
509
524
|
@config[:retry_interval]
|
510
525
|
end
|
511
|
-
alias retrans retry_interval
|
526
|
+
alias retrans retry_interval
|
512
527
|
|
513
528
|
# Set the retrasmission interval in seconds. Default 5 seconds.
|
514
529
|
def retry_interval=(num)
|
515
530
|
if num > 0
|
516
531
|
@config[:retry_interval] = num
|
517
|
-
@logger.info "Retransmission interval changed to #{num} seconds"
|
532
|
+
@logger.info "Retransmission interval changed to #{num} seconds"
|
518
533
|
else
|
519
534
|
raise ArgumentError, "Interval must be positive"
|
520
535
|
end
|
521
536
|
end
|
522
|
-
alias retrans= retry_interval=
|
537
|
+
alias retrans= retry_interval=
|
523
538
|
|
524
539
|
# The number of times the resolver will try a query.
|
525
540
|
#
|
@@ -538,10 +553,10 @@ module Net # :nodoc:
|
|
538
553
|
else
|
539
554
|
raise ArgumentError, "Retry value must be a positive integer"
|
540
555
|
end
|
541
|
-
end
|
542
|
-
alias_method('retry=', 'retry_number=')
|
556
|
+
end
|
557
|
+
alias_method('retry=', 'retry_number=')
|
543
558
|
|
544
|
-
# This method will return true if the resolver is configured to
|
559
|
+
# This method will return true if the resolver is configured to
|
545
560
|
# perform recursive queries.
|
546
561
|
#
|
547
562
|
# print "The resolver will perform a "
|
@@ -551,8 +566,8 @@ module Net # :nodoc:
|
|
551
566
|
def recursive?
|
552
567
|
@config[:recursive]
|
553
568
|
end
|
554
|
-
alias_method :recurse, :recursive?
|
555
|
-
alias_method :recursive, :recursive?
|
569
|
+
alias_method :recurse, :recursive?
|
570
|
+
alias_method :recursive, :recursive?
|
556
571
|
|
557
572
|
# Sets whether or not the resolver should perform recursive
|
558
573
|
# queries. Default is true.
|
@@ -568,8 +583,8 @@ module Net # :nodoc:
|
|
568
583
|
raise ArgumentError, "Argument must be boolean"
|
569
584
|
end
|
570
585
|
end
|
571
|
-
alias_method :recurse=, :recursive=
|
572
|
-
|
586
|
+
alias_method :recurse=, :recursive=
|
587
|
+
|
573
588
|
# Return a string representing the resolver state, suitable
|
574
589
|
# for printing on the screen.
|
575
590
|
#
|
@@ -577,7 +592,7 @@ module Net # :nodoc:
|
|
577
592
|
# puts res.state
|
578
593
|
#
|
579
594
|
def state
|
580
|
-
str = ";; RESOLVER state:\n;; "
|
595
|
+
str = ";; RESOLVER state:\n;; "
|
581
596
|
i = 1
|
582
597
|
@config.each do |key,val|
|
583
598
|
if key == :log_file or key == :config_file
|
@@ -590,17 +605,17 @@ module Net # :nodoc:
|
|
590
605
|
end
|
591
606
|
str
|
592
607
|
end
|
593
|
-
alias print state
|
594
|
-
alias inspect state
|
595
|
-
|
608
|
+
alias print state
|
609
|
+
alias inspect state
|
610
|
+
|
596
611
|
# Checks whether the +defname+ flag has been activate.
|
597
612
|
def defname?
|
598
613
|
@config[:defname]
|
599
614
|
end
|
600
|
-
alias defname defname?
|
615
|
+
alias defname defname?
|
601
616
|
|
602
|
-
# Set the flag +defname+ in a boolean state. if +defname+ is true,
|
603
|
-
# calls to Resolver#query will append the default domain to names
|
617
|
+
# Set the flag +defname+ in a boolean state. if +defname+ is true,
|
618
|
+
# calls to Resolver#query will append the default domain to names
|
604
619
|
# that contain no dots.
|
605
620
|
# Example:
|
606
621
|
#
|
@@ -615,7 +630,7 @@ module Net # :nodoc:
|
|
615
630
|
case bool
|
616
631
|
when TrueClass,FalseClass
|
617
632
|
@config[:defname] = bool
|
618
|
-
@logger.info("Defname state changed to #{bool}")
|
633
|
+
@logger.info("Defname state changed to #{bool}")
|
619
634
|
else
|
620
635
|
raise ArgumentError, "Argument must be boolean"
|
621
636
|
end
|
@@ -625,8 +640,8 @@ module Net # :nodoc:
|
|
625
640
|
def dns_search
|
626
641
|
@config[:dns_search]
|
627
642
|
end
|
628
|
-
alias_method :dnsrch, :dns_search
|
629
|
-
|
643
|
+
alias_method :dnsrch, :dns_search
|
644
|
+
|
630
645
|
# Set the flag +dns_search+ in a boolean state. If +dns_search+
|
631
646
|
# is true, when using the Resolver#search method will be applied
|
632
647
|
# the search list. Default is true.
|
@@ -634,23 +649,23 @@ module Net # :nodoc:
|
|
634
649
|
case bool
|
635
650
|
when TrueClass,FalseClass
|
636
651
|
@config[:dns_search] = bool
|
637
|
-
@logger.info("DNS search state changed to #{bool}")
|
652
|
+
@logger.info("DNS search state changed to #{bool}")
|
638
653
|
else
|
639
654
|
raise ArgumentError, "Argument must be boolean"
|
640
655
|
end
|
641
656
|
end
|
642
657
|
alias_method("dnsrch=","dns_search=")
|
643
|
-
|
658
|
+
|
644
659
|
# Get the state of the use_tcp flag.
|
645
660
|
#
|
646
661
|
def use_tcp?
|
647
662
|
@config[:use_tcp]
|
648
663
|
end
|
649
|
-
alias_method :usevc, :use_tcp?
|
650
|
-
alias_method :use_tcp, :use_tcp?
|
664
|
+
alias_method :usevc, :use_tcp?
|
665
|
+
alias_method :use_tcp, :use_tcp?
|
651
666
|
|
652
|
-
# If +use_tcp+ is true, the resolver will perform all queries
|
653
|
-
# using TCP virtual circuits instead of UDP datagrams, which
|
667
|
+
# If +use_tcp+ is true, the resolver will perform all queries
|
668
|
+
# using TCP virtual circuits instead of UDP datagrams, which
|
654
669
|
# is the default for the DNS protocol.
|
655
670
|
#
|
656
671
|
# res.use_tcp = true
|
@@ -663,12 +678,12 @@ module Net # :nodoc:
|
|
663
678
|
case bool
|
664
679
|
when TrueClass,FalseClass
|
665
680
|
@config[:use_tcp] = bool
|
666
|
-
@logger.info("Use tcp flag changed to #{bool}")
|
681
|
+
@logger.info("Use tcp flag changed to #{bool}")
|
667
682
|
else
|
668
683
|
raise ArgumentError, "Argument must be boolean"
|
669
684
|
end
|
670
685
|
end
|
671
|
-
alias usevc= use_tcp=
|
686
|
+
alias usevc= use_tcp=
|
672
687
|
|
673
688
|
def ignore_truncated?
|
674
689
|
@config[:ignore_truncated]
|
@@ -679,20 +694,20 @@ module Net # :nodoc:
|
|
679
694
|
case bool
|
680
695
|
when TrueClass,FalseClass
|
681
696
|
@config[:ignore_truncated] = bool
|
682
|
-
@logger.info("Ignore truncated flag changed to #{bool}")
|
697
|
+
@logger.info("Ignore truncated flag changed to #{bool}")
|
683
698
|
else
|
684
699
|
raise ArgumentError, "Argument must be boolean"
|
685
700
|
end
|
686
701
|
end
|
687
|
-
|
688
|
-
# Return an object representing the value of the stored TCP
|
702
|
+
|
703
|
+
# Return an object representing the value of the stored TCP
|
689
704
|
# timeout the resolver will use in is queries. This object
|
690
705
|
# is an instance of the class +TcpTimeout+, and two methods
|
691
706
|
# are available for printing informations: TcpTimeout#to_s
|
692
707
|
# and TcpTimeout#pretty_to_s.
|
693
708
|
#
|
694
709
|
# Here's some example:
|
695
|
-
#
|
710
|
+
#
|
696
711
|
# puts "Timeout of #{res.tcp_timeout} seconds" # implicit to_s
|
697
712
|
# #=> Timeout of 150 seconds
|
698
713
|
#
|
@@ -715,17 +730,17 @@ module Net # :nodoc:
|
|
715
730
|
#
|
716
731
|
def tcp_timeout=(secs)
|
717
732
|
@config[:tcp_timeout] = TcpTimeout.new(secs)
|
718
|
-
@logger.info("New TCP timeout value: #{@config[:tcp_timeout]} seconds")
|
733
|
+
@logger.info("New TCP timeout value: #{@config[:tcp_timeout]} seconds")
|
719
734
|
end
|
720
735
|
|
721
|
-
# Return an object representing the value of the stored UDP
|
736
|
+
# Return an object representing the value of the stored UDP
|
722
737
|
# timeout the resolver will use in is queries. This object
|
723
738
|
# is an instance of the class +UdpTimeout+, and two methods
|
724
739
|
# are available for printing information: UdpTimeout#to_s
|
725
740
|
# and UdpTimeout#pretty_to_s.
|
726
741
|
#
|
727
742
|
# Here's some example:
|
728
|
-
#
|
743
|
+
#
|
729
744
|
# puts "Timeout of #{res.udp_timeout} seconds" # implicit to_s
|
730
745
|
# #=> Timeout of 150 seconds
|
731
746
|
#
|
@@ -741,9 +756,9 @@ module Net # :nodoc:
|
|
741
756
|
|
742
757
|
# Set the value of UDP timeout for resolver queries that
|
743
758
|
# will be performed using UDP. A value of 0 means that
|
744
|
-
# the timeout will not be used, and the resolver will use
|
759
|
+
# the timeout will not be used, and the resolver will use
|
745
760
|
# only +retry_number+ and +retry_interval+ parameters.
|
746
|
-
#
|
761
|
+
#
|
747
762
|
# Default is 5 seconds.
|
748
763
|
#
|
749
764
|
# The value is stored internally as a +UdpTimeout+ object, see
|
@@ -751,7 +766,7 @@ module Net # :nodoc:
|
|
751
766
|
#
|
752
767
|
def udp_timeout=(secs)
|
753
768
|
@config[:udp_timeout] = UdpTimeout.new(secs)
|
754
|
-
@logger.info("New UDP timeout value: #{@config[:udp_timeout]} seconds")
|
769
|
+
@logger.info("New UDP timeout value: #{@config[:udp_timeout]} seconds")
|
755
770
|
end
|
756
771
|
|
757
772
|
# Set a new log file for the logger facility of the resolver
|
@@ -768,11 +783,11 @@ module Net # :nodoc:
|
|
768
783
|
@logger = Logger.new(@config[:log_file])
|
769
784
|
@logger.level = $DEBUG ? Logger::DEBUG : Logger::WARN
|
770
785
|
end
|
771
|
-
|
786
|
+
|
772
787
|
# This one permits to have a personal logger facility to handle
|
773
788
|
# resolver messages, instead of new built-in one, which is set up
|
774
789
|
# for a +$stdout+ (or +$stderr+) use.
|
775
|
-
#
|
790
|
+
#
|
776
791
|
# If you want your own logging facility you can create a new instance
|
777
792
|
# of the +Logger+ class:
|
778
793
|
#
|
@@ -798,12 +813,12 @@ module Net # :nodoc:
|
|
798
813
|
# Set the log level for the built-in logging facility.
|
799
814
|
#
|
800
815
|
# The log level can be one of the following:
|
801
|
-
#
|
802
|
-
# - +Net::DNS::DEBUG+
|
803
|
-
# - +Net::DNS::INFO+
|
804
|
-
# - +Net::DNS::WARN+
|
805
|
-
# - +Net::DNS::ERROR+
|
806
|
-
# - +Net::DNS::FATAL+
|
816
|
+
#
|
817
|
+
# - +Net::DNS::DEBUG+
|
818
|
+
# - +Net::DNS::INFO+
|
819
|
+
# - +Net::DNS::WARN+
|
820
|
+
# - +Net::DNS::ERROR+
|
821
|
+
# - +Net::DNS::FATAL+
|
807
822
|
#
|
808
823
|
# Note that if the global variable $DEBUG is set (like when the
|
809
824
|
# -d switch is used at the command line) the logger level is
|
@@ -815,12 +830,12 @@ module Net # :nodoc:
|
|
815
830
|
def log_level=(level)
|
816
831
|
@logger.level = level
|
817
832
|
end
|
818
|
-
|
819
|
-
# Performs a DNS query for the given name, applying the searchlist if
|
833
|
+
|
834
|
+
# Performs a DNS query for the given name, applying the searchlist if
|
820
835
|
# appropriate. The search algorithm is as follows:
|
821
836
|
#
|
822
837
|
# 1. If the name contains at least one dot, try it as is.
|
823
|
-
# 2. If the name doesn't end in a dot then append each item in the search
|
838
|
+
# 2. If the name doesn't end in a dot then append each item in the search
|
824
839
|
# list to the name. This is only done if +dns_search+ is true.
|
825
840
|
# 3. If the name doesn't contain any dots, try it as is.
|
826
841
|
#
|
@@ -831,7 +846,7 @@ module Net # :nodoc:
|
|
831
846
|
# packet = res.search('example.com', Net::DNS::MX)
|
832
847
|
# packet = res.search('user.passwd.example.com', Net::DNS::TXT, Net::DNS::HS)
|
833
848
|
#
|
834
|
-
# If the name is an IP address (Ipv4 or IPv6), in the form of a string
|
849
|
+
# If the name is an IP address (Ipv4 or IPv6), in the form of a string
|
835
850
|
# or a +IPAddr+ object, then an appropriate PTR query will be performed:
|
836
851
|
#
|
837
852
|
# ip = IPAddr.new("172.16.100.2")
|
@@ -839,19 +854,19 @@ module Net # :nodoc:
|
|
839
854
|
# packet = res.search("192.168.10.254")
|
840
855
|
#
|
841
856
|
# Returns a Net::DNS::Packet object. If you need to examine the response packet
|
842
|
-
# whether it contains any answers or not, use the
|
857
|
+
# whether it contains any answers or not, use the Resolver#query method instead.
|
843
858
|
#
|
844
859
|
def search(name,type=Net::DNS::A,cls=Net::DNS::IN)
|
845
860
|
|
846
861
|
return query(name,type,cls) if name.class == IPAddr
|
847
862
|
|
848
|
-
# If the name contains at least one dot then try it as is first.
|
863
|
+
# If the name contains at least one dot then try it as is first.
|
849
864
|
if name.include? "."
|
850
865
|
@logger.debug "Search(#{name},#{Net::DNS::RR::Types.new(type)},#{Net::DNS::RR::Classes.new(cls)})"
|
851
866
|
ans = query(name,type,cls)
|
852
867
|
return ans if ans.header.anCount > 0
|
853
868
|
end
|
854
|
-
|
869
|
+
|
855
870
|
# If the name doesn't end in a dot then apply the search list.
|
856
871
|
if name !~ /\.$/ and @config[:dns_search]
|
857
872
|
@config[:searchlist].each do |domain|
|
@@ -865,15 +880,15 @@ module Net # :nodoc:
|
|
865
880
|
# Finally, if the name has no dots then try it as is.
|
866
881
|
@logger.debug "Search(#{name},#{Net::DNS::RR::Types.new(type)},#{Net::DNS::RR::Classes.new(cls)})"
|
867
882
|
query(name+".",type,cls)
|
868
|
-
|
883
|
+
|
869
884
|
end
|
870
|
-
|
871
|
-
# Performs a DNS query for the given name; the search list
|
872
|
-
# is not applied. If the name doesn't contain any dots and
|
885
|
+
|
886
|
+
# Performs a DNS query for the given name; the search list
|
887
|
+
# is not applied. If the name doesn't contain any dots and
|
873
888
|
# +defname+ is true then the default domain will be appended.
|
874
889
|
#
|
875
|
-
# The record type and class can be omitted; they default to +A+
|
876
|
-
# and +IN+. If the name looks like an IP address (IPv4 or IPv6),
|
890
|
+
# The record type and class can be omitted; they default to +A+
|
891
|
+
# and +IN+. If the name looks like an IP address (IPv4 or IPv6),
|
877
892
|
# then an appropriate PTR query will be performed.
|
878
893
|
#
|
879
894
|
# packet = res.query('mailhost')
|
@@ -881,67 +896,67 @@ module Net # :nodoc:
|
|
881
896
|
# packet = res.query('example.com', Net::DNS::MX)
|
882
897
|
# packet = res.query('user.passwd.example.com', Net::DNS::TXT, Net::DNS::HS)
|
883
898
|
#
|
884
|
-
# If the name is an IP address (Ipv4 or IPv6), in the form of a string
|
899
|
+
# If the name is an IP address (Ipv4 or IPv6), in the form of a string
|
885
900
|
# or a +IPAddr+ object, then an appropriate PTR query will be performed:
|
886
901
|
#
|
887
902
|
# ip = IPAddr.new("172.16.100.2")
|
888
903
|
# packet = res.query(ip)
|
889
904
|
# packet = res.query("192.168.10.254")
|
890
905
|
#
|
891
|
-
# Returns a Net::DNS::Packet object. If you need to examine the response
|
892
|
-
# packet whether it contains any answers or not, use the Resolver#
|
906
|
+
# Returns a Net::DNS::Packet object. If you need to examine the response
|
907
|
+
# packet whether it contains any answers or not, use the Resolver#query
|
893
908
|
# method instead.
|
894
909
|
#
|
895
910
|
def query(name,type=Net::DNS::A,cls=Net::DNS::IN)
|
896
911
|
|
897
912
|
return send(name,type,cls) if name.class == IPAddr
|
898
913
|
|
899
|
-
# If the name doesn't contain any dots then append the default domain.
|
900
|
-
if name !~ /\./ and name !~ /:/ and @config[:
|
914
|
+
# If the name doesn't contain any dots then append the default domain.
|
915
|
+
if name !~ /\./ and name !~ /:/ and @config[:defname]
|
901
916
|
name += "." + @config[:domain]
|
902
917
|
end
|
903
|
-
|
918
|
+
|
904
919
|
@logger.debug "Query(#{name},#{Net::DNS::RR::Types.new(type)},#{Net::DNS::RR::Classes.new(cls)})"
|
905
|
-
|
920
|
+
|
906
921
|
send(name,type,cls)
|
907
|
-
|
922
|
+
|
908
923
|
end
|
909
|
-
|
910
|
-
# Performs a DNS query for the given name. Neither the
|
924
|
+
|
925
|
+
# Performs a DNS query for the given name. Neither the
|
911
926
|
# searchlist nor the default domain will be appended.
|
912
927
|
#
|
913
|
-
# The argument list can be either a Net::DNS::Packet object
|
914
|
-
# or a name string plus optional type and class, which if
|
915
|
-
# omitted default to +A+ and +IN+.
|
928
|
+
# The argument list can be either a Net::DNS::Packet object
|
929
|
+
# or a name string plus optional type and class, which if
|
930
|
+
# omitted default to +A+ and +IN+.
|
916
931
|
#
|
917
932
|
# Returns a Net::DNS::Packet object.
|
918
933
|
#
|
919
934
|
# # Executes the query with a +Packet+ object
|
920
935
|
# send_packet = Net::DNS::Packet.new("host.example.com", Net::DNS::NS, Net::DNS::HS)
|
921
|
-
# packet = res.
|
936
|
+
# packet = res.query(send_packet)
|
922
937
|
#
|
923
938
|
# # Executes the query with a host, type and cls
|
924
|
-
# packet = res.
|
925
|
-
# packet = res.
|
926
|
-
# packet = res.
|
939
|
+
# packet = res.query("host.example.com")
|
940
|
+
# packet = res.query("host.example.com", Net::DNS::NS)
|
941
|
+
# packet = res.query("host.example.com", Net::DNS::NS, Net::DNS::HS)
|
927
942
|
#
|
928
|
-
# If the name is an IP address (Ipv4 or IPv6), in the form of a string
|
943
|
+
# If the name is an IP address (Ipv4 or IPv6), in the form of a string
|
929
944
|
# or a IPAddr object, then an appropriate PTR query will be performed:
|
930
945
|
#
|
931
946
|
# ip = IPAddr.new("172.16.100.2")
|
932
|
-
# packet = res.
|
947
|
+
# packet = res.query(ip)
|
933
948
|
#
|
934
|
-
# packet = res.
|
949
|
+
# packet = res.query("172.16.100.2")
|
935
950
|
#
|
936
|
-
# Use +packet.header.ancount+ or +packet.answer+ to find out if there
|
951
|
+
# Use +packet.header.ancount+ or +packet.answer+ to find out if there
|
937
952
|
# were any records in the answer section.
|
938
953
|
#
|
939
|
-
def
|
954
|
+
def query(argument, type = Net::DNS::A, cls = Net::DNS::IN)
|
940
955
|
if @config[:nameservers].size == 0
|
941
|
-
raise
|
956
|
+
raise Resolver::Error, "No nameservers specified!"
|
942
957
|
end
|
943
958
|
|
944
|
-
method = :
|
959
|
+
method = :query_udp
|
945
960
|
packet = if argument.kind_of? Net::DNS::Packet
|
946
961
|
argument
|
947
962
|
else
|
@@ -959,33 +974,33 @@ module Net # :nodoc:
|
|
959
974
|
@logger.info "Sending #{packet_size} bytes using TCP over RAW socket"
|
960
975
|
method = :send_raw_tcp
|
961
976
|
else
|
962
|
-
@logger.info "Sending #{packet_size} bytes using TCP"
|
963
|
-
method = :
|
977
|
+
@logger.info "Sending #{packet_size} bytes using TCP"
|
978
|
+
method = :query_tcp
|
964
979
|
end
|
965
980
|
else # Packet size is inside the boundaries
|
966
981
|
if @raw # Use raw sockets?
|
967
|
-
@logger.info "Sending #{packet_size} bytes using UDP over RAW socket"
|
982
|
+
@logger.info "Sending #{packet_size} bytes using UDP over RAW socket"
|
968
983
|
method = :send_raw_udp
|
969
984
|
elsif use_tcp? # User requested TCP
|
970
|
-
@logger.info "Sending #{packet_size} bytes using TCP"
|
971
|
-
method = :
|
985
|
+
@logger.info "Sending #{packet_size} bytes using TCP"
|
986
|
+
method = :query_tcp
|
972
987
|
else # Finally use UDP
|
973
|
-
@logger.info "Sending #{packet_size} bytes using UDP"
|
988
|
+
@logger.info "Sending #{packet_size} bytes using UDP"
|
974
989
|
end
|
975
990
|
end
|
976
991
|
|
977
|
-
if type == Net::DNS::AXFR
|
992
|
+
if type == Net::DNS::AXFR
|
978
993
|
if @raw
|
979
994
|
@logger.warn "AXFR query, switching to TCP over RAW socket"
|
980
995
|
method = :send_raw_tcp
|
981
996
|
else
|
982
|
-
@logger.warn "AXFR query, switching to TCP"
|
983
|
-
method = :
|
997
|
+
@logger.warn "AXFR query, switching to TCP"
|
998
|
+
method = :query_tcp
|
984
999
|
end
|
985
1000
|
end
|
986
|
-
|
987
|
-
ans = self.
|
988
|
-
|
1001
|
+
|
1002
|
+
ans = self.send(method, packet, packet_data)
|
1003
|
+
|
989
1004
|
unless ans
|
990
1005
|
message = "No response from nameservers list"
|
991
1006
|
@logger.fatal(message)
|
@@ -994,12 +1009,12 @@ module Net # :nodoc:
|
|
994
1009
|
|
995
1010
|
@logger.info "Received #{ans[0].size} bytes from #{ans[1][2]+":"+ans[1][1].to_s}"
|
996
1011
|
response = Net::DNS::Packet.parse(ans[0],ans[1])
|
997
|
-
|
1012
|
+
|
998
1013
|
if response.header.truncated? and not ignore_truncated?
|
999
1014
|
@logger.warn "Packet truncated, retrying using TCP"
|
1000
1015
|
self.use_tcp = true
|
1001
1016
|
begin
|
1002
|
-
return
|
1017
|
+
return query(argument,type,cls)
|
1003
1018
|
ensure
|
1004
1019
|
self.use_tcp = false
|
1005
1020
|
end
|
@@ -1008,52 +1023,41 @@ module Net # :nodoc:
|
|
1008
1023
|
return response
|
1009
1024
|
end
|
1010
1025
|
|
1011
|
-
#
|
1012
1026
|
# Performs a zone transfer for the zone passed as a parameter.
|
1013
1027
|
#
|
1014
1028
|
# It is actually only a wrapper to a send with type set as Net::DNS::AXFR,
|
1015
1029
|
# since it is using the same infrastucture.
|
1016
1030
|
#
|
1017
|
-
def axfr(name,cls=Net::DNS::IN)
|
1031
|
+
def axfr(name, cls = Net::DNS::IN)
|
1018
1032
|
@logger.info "Requested AXFR transfer, zone #{name} class #{cls}"
|
1019
|
-
|
1033
|
+
query(name, Net::DNS::AXFR, cls)
|
1020
1034
|
end
|
1021
1035
|
|
1036
|
+
# Performs an MX query for the domain name passed as parameter.
|
1022
1037
|
#
|
1023
|
-
#
|
1024
|
-
#
|
1025
|
-
# It actually uses the same methods a normal Resolver query would
|
1026
|
-
# use, but automatically sort the results based on preferences
|
1038
|
+
# It actually uses the same methods a normal Resolver query would
|
1039
|
+
# use, but automatically sort the results based on preferences
|
1027
1040
|
# and returns an ordered array.
|
1028
1041
|
#
|
1029
1042
|
# res = Net::DNS::Resolver.new
|
1030
1043
|
# res.mx("google.com")
|
1031
1044
|
#
|
1032
|
-
def mx(name,cls=Net::DNS::IN)
|
1045
|
+
def mx(name, cls = Net::DNS::IN)
|
1033
1046
|
arr = []
|
1034
|
-
|
1047
|
+
query(name, Net::DNS::MX, cls).answer.each do |entry|
|
1035
1048
|
arr << entry if entry.type == 'MX'
|
1036
1049
|
end
|
1037
|
-
|
1038
|
-
end
|
1039
|
-
|
1040
|
-
# Quick resolver method. Bypass the configuration using
|
1041
|
-
# the defaults.
|
1042
|
-
#
|
1043
|
-
# Net::DNS::Resolver.start "www.google.com"
|
1044
|
-
#
|
1045
|
-
def self.start(*params)
|
1046
|
-
self.new.search(*params)
|
1050
|
+
arr.sort_by { |a| a.preference }
|
1047
1051
|
end
|
1048
1052
|
|
1049
1053
|
private
|
1050
|
-
|
1054
|
+
|
1051
1055
|
# Parses a configuration file specified as the argument.
|
1052
1056
|
def parse_config_file
|
1053
1057
|
if self.class.platform_windows?
|
1054
1058
|
require 'win32/resolv'
|
1055
1059
|
arr = Win32::Resolv.get_resolv_info
|
1056
|
-
self.domain = arr[0]
|
1060
|
+
self.domain = arr[0].to_s
|
1057
1061
|
self.nameservers = arr[1]
|
1058
1062
|
else
|
1059
1063
|
IO.foreach(@config[:config_file]) do |line|
|
@@ -1070,7 +1074,7 @@ module Net # :nodoc:
|
|
1070
1074
|
end
|
1071
1075
|
end
|
1072
1076
|
end
|
1073
|
-
|
1077
|
+
|
1074
1078
|
# Parses environment variables.
|
1075
1079
|
def parse_environment_variables
|
1076
1080
|
if ENV['RES_NAMESERVERS']
|
@@ -1114,7 +1118,7 @@ module Net # :nodoc:
|
|
1114
1118
|
begin
|
1115
1119
|
name = IPAddr.new(string.chomp(".")).reverse
|
1116
1120
|
type = Net::DNS::PTR
|
1117
|
-
rescue
|
1121
|
+
rescue ArgumentError
|
1118
1122
|
name = string if valid? string
|
1119
1123
|
end
|
1120
1124
|
else
|
@@ -1127,34 +1131,34 @@ module Net # :nodoc:
|
|
1127
1131
|
if packet.query?
|
1128
1132
|
packet.header.recursive = @config[:recursive] ? 1 : 0
|
1129
1133
|
end
|
1130
|
-
|
1134
|
+
|
1131
1135
|
# DNSSEC and TSIG stuff to be inserted here
|
1132
|
-
|
1136
|
+
|
1133
1137
|
packet
|
1134
1138
|
end
|
1135
1139
|
|
1136
|
-
def
|
1140
|
+
def query_tcp(packet, packet_data)
|
1137
1141
|
|
1138
1142
|
ans = nil
|
1139
1143
|
length = [packet_data.size].pack("n")
|
1140
|
-
|
1144
|
+
|
1141
1145
|
@config[:nameservers].each do |ns|
|
1142
1146
|
begin
|
1143
1147
|
buffer = ""
|
1144
1148
|
socket = Socket.new(Socket::AF_INET,Socket::SOCK_STREAM,0)
|
1145
1149
|
socket.bind(Socket.pack_sockaddr_in(@config[:source_port],@config[:source_address].to_s))
|
1146
|
-
|
1150
|
+
|
1147
1151
|
sockaddr = Socket.pack_sockaddr_in(@config[:port],ns.to_s)
|
1148
|
-
|
1152
|
+
|
1149
1153
|
@config[:tcp_timeout].timeout do
|
1150
|
-
socket.connect(sockaddr)
|
1154
|
+
socket.connect(sockaddr)
|
1151
1155
|
@logger.info "Contacting nameserver #{ns} port #{@config[:port]}"
|
1152
1156
|
socket.write(length+packet_data)
|
1153
1157
|
ans = socket.recv(Net::DNS::INT16SZ)
|
1154
1158
|
len = ans.unpack("n")[0]
|
1155
1159
|
|
1156
1160
|
@logger.info "Receiving #{len} bytes..."
|
1157
|
-
|
1161
|
+
|
1158
1162
|
if len == 0
|
1159
1163
|
@logger.warn "Receiving 0 lenght packet from nameserver #{ns}, trying next."
|
1160
1164
|
next
|
@@ -1165,7 +1169,7 @@ module Net # :nodoc:
|
|
1165
1169
|
temp,from = socket.recvfrom(left)
|
1166
1170
|
buffer += temp
|
1167
1171
|
end
|
1168
|
-
|
1172
|
+
|
1169
1173
|
unless buffer.size == len
|
1170
1174
|
@logger.warn "Malformed packet from nameserver #{ns}, trying next."
|
1171
1175
|
next
|
@@ -1173,26 +1177,33 @@ module Net # :nodoc:
|
|
1173
1177
|
end
|
1174
1178
|
return [buffer,["",@config[:port],ns.to_s,ns.to_s]]
|
1175
1179
|
rescue TimeoutError
|
1176
|
-
@logger.warn "Nameserver #{ns} not responding within TCP timeout, trying next one"
|
1180
|
+
@logger.warn "Nameserver #{ns} not responding within TCP timeout, trying next one"
|
1177
1181
|
next
|
1178
1182
|
ensure
|
1179
|
-
socket.close
|
1183
|
+
socket.close
|
1180
1184
|
end
|
1181
1185
|
end
|
1182
1186
|
end
|
1183
|
-
|
1184
|
-
def
|
1185
|
-
|
1186
|
-
|
1187
|
-
|
1187
|
+
|
1188
|
+
def query_udp(packet, packet_data)
|
1189
|
+
socket4 = UDPSocket.new
|
1190
|
+
socket4.bind(@config[:source_address].to_s,@config[:source_port])
|
1191
|
+
socket6 = UDPSocket.new(Socket::AF_INET6)
|
1192
|
+
socket6.bind(@config[:source_address_inet6].to_s,@config[:source_port])
|
1193
|
+
|
1188
1194
|
ans = nil
|
1189
1195
|
response = ""
|
1190
1196
|
@config[:nameservers].each do |ns|
|
1191
1197
|
begin
|
1192
1198
|
@config[:udp_timeout].timeout do
|
1193
|
-
@logger.info "Contacting nameserver #{ns} port #{@config[:port]}"
|
1194
|
-
|
1195
|
-
|
1199
|
+
@logger.info "Contacting nameserver #{ns} port #{@config[:port]}"
|
1200
|
+
ans = if ns.ipv6?
|
1201
|
+
socket6.send(packet_data, 0, ns.to_s, @config[:port])
|
1202
|
+
socket6.recvfrom(@config[:packet_size])
|
1203
|
+
else
|
1204
|
+
socket4.send(packet_data, 0, ns.to_s, @config[:port])
|
1205
|
+
socket4.recvfrom(@config[:packet_size])
|
1206
|
+
end
|
1196
1207
|
end
|
1197
1208
|
break if ans
|
1198
1209
|
rescue TimeoutError
|
@@ -1203,6 +1214,7 @@ module Net # :nodoc:
|
|
1203
1214
|
ans
|
1204
1215
|
end
|
1205
1216
|
|
1217
|
+
# FIXME: a ? method should never raise.
|
1206
1218
|
def valid?(name)
|
1207
1219
|
if name =~ /[^-\w\.]/
|
1208
1220
|
raise ArgumentError, "Invalid domain name #{name}"
|
@@ -1211,20 +1223,6 @@ module Net # :nodoc:
|
|
1211
1223
|
end
|
1212
1224
|
end
|
1213
1225
|
|
1214
|
-
|
1215
|
-
class << self
|
1216
|
-
|
1217
|
-
# Returns true if running on a Windows platform.
|
1218
|
-
#
|
1219
|
-
# Note. This method doesn't rely on the RUBY_PLATFORM constant
|
1220
|
-
# because the comparison will fail when running on JRuby.
|
1221
|
-
# On JRuby RUBY_PLATFORM == 'java'.
|
1222
|
-
def platform_windows?
|
1223
|
-
!!(Config::CONFIG["host_os"] =~ /msdos|mswin|djgpp|mingw/i)
|
1224
|
-
end
|
1225
|
-
|
1226
|
-
end
|
1227
|
-
|
1228
1226
|
end
|
1229
1227
|
end
|
1230
1228
|
end
|