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.
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