net-dns 0.6.1 → 0.7.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (53) hide show
  1. data/.gitignore +8 -6
  2. data/.travis.yml +14 -0
  3. data/CHANGELOG.md +79 -0
  4. data/Gemfile +4 -0
  5. data/Rakefile +56 -66
  6. data/demo/check_soa.rb +1 -1
  7. data/demo/threads.rb +1 -1
  8. data/lib/net/dns.rb +24 -22
  9. data/lib/net/dns/header.rb +77 -103
  10. data/lib/net/dns/{names/names.rb → names.rb} +19 -20
  11. data/lib/net/dns/packet.rb +231 -256
  12. data/lib/net/dns/question.rb +11 -40
  13. data/lib/net/dns/resolver.rb +248 -250
  14. data/lib/net/dns/resolver/socks.rb +6 -6
  15. data/lib/net/dns/resolver/timeouts.rb +1 -1
  16. data/lib/net/dns/rr.rb +112 -117
  17. data/lib/net/dns/rr/a.rb +98 -89
  18. data/lib/net/dns/rr/aaaa.rb +84 -68
  19. data/lib/net/dns/rr/classes.rb +91 -106
  20. data/lib/net/dns/rr/cname.rb +64 -45
  21. data/lib/net/dns/rr/hinfo.rb +90 -50
  22. data/lib/net/dns/rr/mr.rb +61 -44
  23. data/lib/net/dns/rr/mx.rb +73 -48
  24. data/lib/net/dns/rr/ns.rb +60 -46
  25. data/lib/net/dns/rr/null.rb +11 -12
  26. data/lib/net/dns/rr/ptr.rb +47 -34
  27. data/lib/net/dns/rr/soa.rb +5 -6
  28. data/lib/net/dns/rr/srv.rb +1 -4
  29. data/lib/net/dns/rr/txt.rb +14 -14
  30. data/lib/net/dns/rr/types.rb +13 -13
  31. data/lib/net/dns/version.rb +8 -14
  32. data/net-dns.gemspec +35 -0
  33. data/setup.rb +3 -2
  34. data/test/header_test.rb +18 -18
  35. data/test/names_test.rb +21 -0
  36. data/test/packet_test.rb +38 -31
  37. data/test/question_test.rb +23 -24
  38. data/test/resolver/timeouts_test.rb +13 -13
  39. data/test/resolver_test.rb +28 -20
  40. data/test/rr/a_test.rb +70 -23
  41. data/test/rr/aaaa_test.rb +109 -0
  42. data/test/rr/classes_test.rb +61 -49
  43. data/test/rr/cname_test.rb +97 -0
  44. data/test/rr/hinfo_test.rb +117 -0
  45. data/test/rr/mr_test.rb +105 -0
  46. data/test/rr/mx_test.rb +112 -0
  47. data/test/rr/ns_test.rb +34 -12
  48. data/test/rr/types_test.rb +4 -4
  49. data/test/rr_test.rb +1 -1
  50. metadata +77 -52
  51. data/AUTHORS.rdoc +0 -7
  52. data/CHANGELOG.rdoc +0 -46
  53. data/VERSION.yml +0 -5
@@ -1,10 +1,4 @@
1
- require 'net/dns'
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 Net::DNS::Names
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 NameError < Error
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(name)
195
- name.strip!
168
+ def check_name(input)
169
+ name = input.to_s.strip
196
170
  if name =~ /[^\w\.\-_]/
197
- raise NameError, "Question name #{name.inspect} not valid"
198
- else
199
- name
171
+ raise NameInvalid, "Invalid Question Name `#{name}'"
200
172
  end
201
- rescue
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}\n{e.backtrace}"
182
+ raise ArgumentError, "Invalid data: #{data.inspect}"
212
183
  end
213
184
 
214
185
  end
215
186
 
216
187
  end
217
- end
188
+ end
@@ -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
- alias old_send send
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
- # #=> 5
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
- # #=> 484 bytes
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,&blk)
26
- obj = Net::DNS::Resolver.start(name,type,cls)
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 obj
23
+ yield resolver
29
24
  else
30
- return obj
25
+ resolver
31
26
  end
32
27
  end
33
28
 
34
- module Net # :nodoc:
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
- # Create a new resolver object.
134
- #
135
- # Argument +config+ can either be empty or be an hash with
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, "Argument has to be Hash" unless config.kind_of? Hash
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
- arr = []
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 send() method instead.
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#send
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[:defnames]
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.send(send_packet)
936
+ # packet = res.query(send_packet)
922
937
  #
923
938
  # # Executes the query with a host, type and cls
924
- # packet = res.send("host.example.com")
925
- # packet = res.send("host.example.com", Net::DNS::NS)
926
- # packet = res.send("host.example.com", Net::DNS::NS, Net::DNS::HS)
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.send(ip)
947
+ # packet = res.query(ip)
933
948
  #
934
- # packet = res.send("172.16.100.2")
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 send(argument, type = Net::DNS::A, cls = Net::DNS::IN)
954
+ def query(argument, type = Net::DNS::A, cls = Net::DNS::IN)
940
955
  if @config[:nameservers].size == 0
941
- raise ResolverError, "No nameservers specified!"
956
+ raise Resolver::Error, "No nameservers specified!"
942
957
  end
943
958
 
944
- method = :send_udp
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 = :send_tcp
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 = :send_tcp
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 = :send_tcp
997
+ @logger.warn "AXFR query, switching to TCP"
998
+ method = :query_tcp
984
999
  end
985
1000
  end
986
-
987
- ans = self.old_send(method,packet,packet_data)
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 send(argument,type,cls)
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
- send(name,Net::DNS::AXFR,cls)
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
- # Performs an MX query for the domain name passed as parameter.
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
- send(name, Net::DNS::MX, cls).answer.each do |entry|
1047
+ query(name, Net::DNS::MX, cls).answer.each do |entry|
1035
1048
  arr << entry if entry.type == 'MX'
1036
1049
  end
1037
- return arr.sort_by {|a| a.preference}
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 ::ArgumentError
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 send_tcp(packet, packet_data)
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 send_udp(packet, packet_data)
1185
- socket = UDPSocket.new
1186
- socket.bind(@config[:source_address].to_s,@config[:source_port])
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
- socket.send(packet_data,0,ns.to_s,@config[:port])
1195
- ans = socket.recvfrom(@config[:packet_size])
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