net-dns 0.8.0 → 0.20.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +6 -14
- data/.rspec +1 -0
- data/.travis.yml +9 -16
- data/CHANGELOG.md +37 -13
- data/LICENSE.txt +56 -0
- data/README.md +94 -77
- data/demo/check_soa.rb +27 -38
- data/demo/threads.rb +3 -7
- data/lib/net/dns/header.rb +86 -110
- data/lib/net/dns/names.rb +31 -31
- data/lib/net/dns/packet.rb +148 -158
- data/lib/net/dns/question.rb +41 -42
- data/lib/net/dns/resolver/socks.rb +47 -55
- data/lib/net/dns/resolver/timeouts.rb +19 -30
- data/lib/net/dns/resolver.rb +151 -176
- data/lib/net/dns/rr/a.rb +45 -55
- data/lib/net/dns/rr/aaaa.rb +39 -50
- data/lib/net/dns/rr/classes.rb +32 -37
- data/lib/net/dns/rr/cname.rb +31 -41
- data/lib/net/dns/rr/hinfo.rb +40 -56
- data/lib/net/dns/rr/mr.rb +31 -42
- data/lib/net/dns/rr/mx.rb +35 -47
- data/lib/net/dns/rr/ns.rb +31 -41
- data/lib/net/dns/rr/null.rb +10 -15
- data/lib/net/dns/rr/ptr.rb +16 -24
- data/lib/net/dns/rr/soa.rb +36 -35
- data/lib/net/dns/rr/srv.rb +18 -19
- data/lib/net/dns/rr/txt.rb +11 -16
- data/lib/net/dns/rr/types.rb +118 -109
- data/lib/net/dns/rr.rb +107 -117
- data/lib/net/dns/version.rb +5 -13
- data/lib/net/dns.rb +6 -11
- metadata +18 -83
- data/.gitignore +0 -8
- data/Gemfile +0 -4
- data/Rakefile +0 -71
- data/fixtures/resolv.conf +0 -4
- data/lib/net/dns/core_ext.rb +0 -52
- data/net-dns.gemspec +0 -35
- data/test/header_test.rb +0 -167
- data/test/names_test.rb +0 -21
- data/test/packet_test.rb +0 -49
- data/test/question_test.rb +0 -83
- data/test/resolver/timeouts_test.rb +0 -109
- data/test/resolver_test.rb +0 -117
- data/test/rr/a_test.rb +0 -113
- data/test/rr/aaaa_test.rb +0 -109
- data/test/rr/classes_test.rb +0 -85
- data/test/rr/cname_test.rb +0 -97
- data/test/rr/hinfo_test.rb +0 -117
- data/test/rr/mr_test.rb +0 -105
- data/test/rr/mx_test.rb +0 -112
- data/test/rr/ns_test.rb +0 -86
- data/test/rr/types_test.rb +0 -69
- data/test/rr_test.rb +0 -131
- data/test/test_helper.rb +0 -4
data/lib/net/dns/resolver.rb
CHANGED
@@ -16,7 +16,7 @@ require 'net/dns/resolver/timeouts'
|
|
16
16
|
# Resolver("www.google.com") { |packet| puts packet.size + " bytes" }
|
17
17
|
# # => 484 bytes
|
18
18
|
#
|
19
|
-
def Resolver(name, type = Net::DNS::A, cls = Net::DNS::IN
|
19
|
+
def Resolver(name, type = Net::DNS::A, cls = Net::DNS::IN)
|
20
20
|
resolver = Net::DNS::Resolver.start(name, type, cls)
|
21
21
|
if block_given?
|
22
22
|
yield resolver
|
@@ -27,7 +27,6 @@ end
|
|
27
27
|
|
28
28
|
module Net
|
29
29
|
module DNS
|
30
|
-
|
31
30
|
include Logger::Severity
|
32
31
|
|
33
32
|
# = Net::DNS::Resolver - DNS resolver class
|
@@ -87,7 +86,6 @@ module Net
|
|
87
86
|
# % setenv RES_OPTIONS "retrans:3 retry:2 debug"
|
88
87
|
#
|
89
88
|
class Resolver
|
90
|
-
|
91
89
|
class Error < StandardError
|
92
90
|
end
|
93
91
|
|
@@ -99,30 +97,28 @@ module Net
|
|
99
97
|
# the description for each parameter to have an
|
100
98
|
# explanation of its usage.
|
101
99
|
Defaults = {
|
102
|
-
:
|
103
|
-
:
|
104
|
-
:
|
105
|
-
:
|
106
|
-
:
|
107
|
-
:
|
108
|
-
:
|
109
|
-
:
|
110
|
-
:
|
111
|
-
:
|
112
|
-
:
|
113
|
-
:
|
114
|
-
:
|
115
|
-
:
|
116
|
-
:
|
117
|
-
:
|
118
|
-
:
|
119
|
-
:
|
120
|
-
:
|
121
|
-
}
|
122
|
-
|
100
|
+
config_file: "/etc/resolv.conf",
|
101
|
+
log_file: $stdout,
|
102
|
+
port: 53,
|
103
|
+
searchlist: [],
|
104
|
+
nameservers: [IPAddr.new("127.0.0.1")],
|
105
|
+
domain: "",
|
106
|
+
source_port: 0,
|
107
|
+
source_address: IPAddr.new("0.0.0.0"),
|
108
|
+
source_address_inet6: IPAddr.new('::'),
|
109
|
+
retry_interval: 5,
|
110
|
+
retry_number: 4,
|
111
|
+
recursive: true,
|
112
|
+
defname: true,
|
113
|
+
dns_search: true,
|
114
|
+
use_tcp: false,
|
115
|
+
ignore_truncated: false,
|
116
|
+
packet_size: 512,
|
117
|
+
tcp_timeout: TcpTimeout.new(5),
|
118
|
+
udp_timeout: UdpTimeout.new(5),
|
119
|
+
}.freeze
|
123
120
|
|
124
121
|
class << self
|
125
|
-
|
126
122
|
C = Object.const_get(defined?(RbConfig) ? :RbConfig : :Config)::CONFIG
|
127
123
|
|
128
124
|
# Quick resolver method. Bypass the configuration using
|
@@ -142,10 +138,8 @@ module Net
|
|
142
138
|
def platform_windows?
|
143
139
|
!!(C["host_os"] =~ /msdos|mswin|djgpp|mingw/i)
|
144
140
|
end
|
145
|
-
|
146
141
|
end
|
147
142
|
|
148
|
-
|
149
143
|
# Creates a new resolver object.
|
150
144
|
#
|
151
145
|
# Argument +config+ can either be empty or be an hash with
|
@@ -237,9 +231,9 @@ module Net
|
|
237
231
|
# Net::DNS::Resolver Perl module.
|
238
232
|
#
|
239
233
|
def initialize(config = {})
|
240
|
-
|
234
|
+
config.is_a?(Hash) or
|
235
|
+
raise(ArgumentError, "Expected `config' to be a Hash")
|
241
236
|
|
242
|
-
# config.downcase_keys!
|
243
237
|
@config = Defaults.merge config
|
244
238
|
@raw = false
|
245
239
|
|
@@ -255,8 +249,6 @@ module Net
|
|
255
249
|
# 4) defaults (and /etc/resolv.conf for config)
|
256
250
|
#------------------------------------------------------------
|
257
251
|
|
258
|
-
|
259
|
-
|
260
252
|
#------------------------------------------------------------
|
261
253
|
# Parsing config file
|
262
254
|
#------------------------------------------------------------
|
@@ -270,10 +262,11 @@ module Net
|
|
270
262
|
#------------------------------------------------------------
|
271
263
|
# Parsing arguments
|
272
264
|
#------------------------------------------------------------
|
273
|
-
config.each do |key,val|
|
274
|
-
next if key == :log_file
|
265
|
+
config.each do |key, val|
|
266
|
+
next if (key == :log_file) || (key == :config_file)
|
267
|
+
|
275
268
|
begin
|
276
|
-
eval "self.#{key
|
269
|
+
eval "self.#{key} = val"
|
277
270
|
rescue NoMethodError
|
278
271
|
raise ArgumentError, "Option #{key} not valid"
|
279
272
|
end
|
@@ -309,7 +302,7 @@ module Net
|
|
309
302
|
@config[:searchlist] = [arg] if valid? arg
|
310
303
|
@logger.info "Searchlist changed to value #{@config[:searchlist].inspect}"
|
311
304
|
when Array
|
312
|
-
@config[:searchlist] = arg if arg.all? {|x| valid? x}
|
305
|
+
@config[:searchlist] = arg if arg.all? { |x| valid? x }
|
313
306
|
@logger.info "Searchlist changed to value #{@config[:searchlist].inspect}"
|
314
307
|
else
|
315
308
|
raise ArgumentError, "Wrong argument format, neither String nor Array"
|
@@ -325,7 +318,7 @@ module Net
|
|
325
318
|
@config[:nameservers].map(&:to_s)
|
326
319
|
end
|
327
320
|
|
328
|
-
|
321
|
+
alias nameserver nameservers
|
329
322
|
|
330
323
|
# Set the list of resolver nameservers.
|
331
324
|
# +arg+ can be a single ip address or an array of addresses.
|
@@ -356,26 +349,27 @@ module Net
|
|
356
349
|
when Array
|
357
350
|
@config[:nameservers] = []
|
358
351
|
arg.each do |x|
|
359
|
-
|
360
|
-
|
361
|
-
|
362
|
-
|
363
|
-
|
364
|
-
|
365
|
-
|
366
|
-
|
367
|
-
|
368
|
-
|
369
|
-
|
370
|
-
|
371
|
-
|
352
|
+
val = case x
|
353
|
+
when String
|
354
|
+
begin
|
355
|
+
IPAddr.new(x)
|
356
|
+
rescue ArgumentError
|
357
|
+
nameservers_from_name(arg)
|
358
|
+
return
|
359
|
+
end
|
360
|
+
when IPAddr
|
361
|
+
x
|
362
|
+
else
|
363
|
+
raise ArgumentError, "Wrong argument format"
|
364
|
+
end
|
365
|
+
@config[:nameservers] << val
|
372
366
|
end
|
373
367
|
@logger.info "Nameservers list changed to value #{@config[:nameservers].inspect}"
|
374
368
|
else
|
375
369
|
raise ArgumentError, "Wrong argument format, neither String, Array nor IPAddr"
|
376
370
|
end
|
377
371
|
end
|
378
|
-
alias_method("nameserver=","nameservers=")
|
372
|
+
alias_method("nameserver=", "nameservers=")
|
379
373
|
|
380
374
|
# Return a string with the default domain.
|
381
375
|
def domain
|
@@ -408,12 +402,11 @@ module Net
|
|
408
402
|
# The default is port 53.
|
409
403
|
#
|
410
404
|
def port=(num)
|
411
|
-
|
412
|
-
|
413
|
-
|
414
|
-
|
415
|
-
|
416
|
-
end
|
405
|
+
(0..65_535).cover?(num) or
|
406
|
+
raise(ArgumentError, "Wrong port number #{num}")
|
407
|
+
|
408
|
+
@config[:port] = num
|
409
|
+
@logger.info "Port number changed to #{num}"
|
417
410
|
end
|
418
411
|
|
419
412
|
# Get the value of the source port number.
|
@@ -437,14 +430,12 @@ module Net
|
|
437
430
|
# underlaying layers.
|
438
431
|
#
|
439
432
|
def source_port=(num)
|
440
|
-
|
441
|
-
|
442
|
-
|
443
|
-
|
444
|
-
|
445
|
-
|
446
|
-
raise ArgumentError, "Wrong port number #{num}"
|
447
|
-
end
|
433
|
+
root? or
|
434
|
+
raise(ResolverPermissionError, "Are you root?")
|
435
|
+
(0..65_535).cover?(num) or
|
436
|
+
raise(ArgumentError, "Wrong port number #{num}")
|
437
|
+
|
438
|
+
@config[:source_port] = num
|
448
439
|
end
|
449
440
|
alias srcport= source_port=
|
450
441
|
|
@@ -462,7 +453,7 @@ module Net
|
|
462
453
|
def source_address_inet6
|
463
454
|
@config[:source_address_inet6].to_s
|
464
455
|
end
|
465
|
-
|
456
|
+
|
466
457
|
# Set the local source address from which the resolver sends its queries.
|
467
458
|
#
|
468
459
|
# res.source_address = "172.16.100.1"
|
@@ -487,14 +478,13 @@ module Net
|
|
487
478
|
# The default is 0.0.0.0, meaning any local address (chosen on routing needs).
|
488
479
|
#
|
489
480
|
def source_address=(addr)
|
490
|
-
|
491
|
-
|
492
|
-
end
|
481
|
+
addr.respond_to?(:to_s) or
|
482
|
+
raise(ArgumentError, "Wrong address argument #{addr}")
|
493
483
|
|
494
484
|
begin
|
495
|
-
port = rand(
|
496
|
-
@logger.
|
497
|
-
a = TCPServer.new(addr.to_s,port)
|
485
|
+
port = rand(1024..65_023)
|
486
|
+
@logger.info "Try to determine state of source address #{addr} with port #{port}"
|
487
|
+
a = TCPServer.new(addr.to_s, port)
|
498
488
|
rescue SystemCallError => e
|
499
489
|
case e.errno
|
500
490
|
when 98 # Port already in use!
|
@@ -532,12 +522,11 @@ module Net
|
|
532
522
|
|
533
523
|
# Set the retrasmission interval in seconds. Default 5 seconds.
|
534
524
|
def retry_interval=(num)
|
535
|
-
|
536
|
-
|
537
|
-
|
538
|
-
|
539
|
-
|
540
|
-
end
|
525
|
+
num.positive? or
|
526
|
+
raise(ArgumentError, "Interval must be positive")
|
527
|
+
|
528
|
+
@config[:retry_interval] = num
|
529
|
+
@logger.info "Retransmission interval changed to #{num} seconds"
|
541
530
|
end
|
542
531
|
alias retrans= retry_interval=
|
543
532
|
|
@@ -552,12 +541,11 @@ module Net
|
|
552
541
|
# Set the number of times the resolver will try a query.
|
553
542
|
# Default 4 times.
|
554
543
|
def retry_number=(num)
|
555
|
-
|
556
|
-
|
557
|
-
|
558
|
-
|
559
|
-
|
560
|
-
end
|
544
|
+
(num.is_a?(Integer) && (num > 0)) or
|
545
|
+
raise(ArgumentError, "Retry value must be a positive integer")
|
546
|
+
|
547
|
+
@config[:retry_number] = num
|
548
|
+
@logger.info "Retrasmissions number changed to #{num}"
|
561
549
|
end
|
562
550
|
alias_method('retry=', 'retry_number=')
|
563
551
|
|
@@ -571,8 +559,8 @@ module Net
|
|
571
559
|
def recursive?
|
572
560
|
@config[:recursive]
|
573
561
|
end
|
574
|
-
|
575
|
-
|
562
|
+
alias recurse recursive?
|
563
|
+
alias recursive recursive?
|
576
564
|
|
577
565
|
# Sets whether or not the resolver should perform recursive
|
578
566
|
# queries. Default is true.
|
@@ -581,14 +569,14 @@ module Net
|
|
581
569
|
#
|
582
570
|
def recursive=(bool)
|
583
571
|
case bool
|
584
|
-
when TrueClass,FalseClass
|
572
|
+
when TrueClass, FalseClass
|
585
573
|
@config[:recursive] = bool
|
586
574
|
@logger.info("Recursive state changed to #{bool}")
|
587
575
|
else
|
588
576
|
raise ArgumentError, "Argument must be boolean"
|
589
577
|
end
|
590
578
|
end
|
591
|
-
|
579
|
+
alias recurse= recursive=
|
592
580
|
|
593
581
|
# Return a string representing the resolver state, suitable
|
594
582
|
# for printing on the screen.
|
@@ -599,13 +587,13 @@ module Net
|
|
599
587
|
def state
|
600
588
|
str = ";; RESOLVER state:\n;; "
|
601
589
|
i = 1
|
602
|
-
@config.each do |key,val|
|
603
|
-
if key == :log_file
|
604
|
-
|
590
|
+
@config.each do |key, val|
|
591
|
+
str << if (key == :log_file) || (key == :config_file)
|
592
|
+
"#{key}: #{val} \t"
|
605
593
|
else
|
606
|
-
|
594
|
+
"#{key}: #{eval(key.to_s)} \t"
|
607
595
|
end
|
608
|
-
str << "\n;; " if i
|
596
|
+
str << "\n;; " if i.even?
|
609
597
|
i += 1
|
610
598
|
end
|
611
599
|
str
|
@@ -633,7 +621,7 @@ module Net
|
|
633
621
|
#
|
634
622
|
def defname=(bool)
|
635
623
|
case bool
|
636
|
-
when TrueClass,FalseClass
|
624
|
+
when TrueClass, FalseClass
|
637
625
|
@config[:defname] = bool
|
638
626
|
@logger.info("Defname state changed to #{bool}")
|
639
627
|
else
|
@@ -645,29 +633,29 @@ module Net
|
|
645
633
|
def dns_search
|
646
634
|
@config[:dns_search]
|
647
635
|
end
|
648
|
-
|
636
|
+
alias dnsrch dns_search
|
649
637
|
|
650
638
|
# Set the flag +dns_search+ in a boolean state. If +dns_search+
|
651
639
|
# is true, when using the Resolver#search method will be applied
|
652
640
|
# the search list. Default is true.
|
653
641
|
def dns_search=(bool)
|
654
642
|
case bool
|
655
|
-
when TrueClass,FalseClass
|
643
|
+
when TrueClass, FalseClass
|
656
644
|
@config[:dns_search] = bool
|
657
645
|
@logger.info("DNS search state changed to #{bool}")
|
658
646
|
else
|
659
647
|
raise ArgumentError, "Argument must be boolean"
|
660
648
|
end
|
661
649
|
end
|
662
|
-
alias_method("dnsrch=","dns_search=")
|
650
|
+
alias_method("dnsrch=", "dns_search=")
|
663
651
|
|
664
652
|
# Get the state of the use_tcp flag.
|
665
653
|
#
|
666
654
|
def use_tcp?
|
667
655
|
@config[:use_tcp]
|
668
656
|
end
|
669
|
-
|
670
|
-
|
657
|
+
alias usevc use_tcp?
|
658
|
+
alias use_tcp use_tcp?
|
671
659
|
|
672
660
|
# If +use_tcp+ is true, the resolver will perform all queries
|
673
661
|
# using TCP virtual circuits instead of UDP datagrams, which
|
@@ -681,7 +669,7 @@ module Net
|
|
681
669
|
#
|
682
670
|
def use_tcp=(bool)
|
683
671
|
case bool
|
684
|
-
when TrueClass,FalseClass
|
672
|
+
when TrueClass, FalseClass
|
685
673
|
@config[:use_tcp] = bool
|
686
674
|
@logger.info("Use tcp flag changed to #{bool}")
|
687
675
|
else
|
@@ -693,11 +681,11 @@ module Net
|
|
693
681
|
def ignore_truncated?
|
694
682
|
@config[:ignore_truncated]
|
695
683
|
end
|
696
|
-
|
684
|
+
alias ignore_truncated ignore_truncated?
|
697
685
|
|
698
686
|
def ignore_truncated=(bool)
|
699
687
|
case bool
|
700
|
-
when TrueClass,FalseClass
|
688
|
+
when TrueClass, FalseClass
|
701
689
|
@config[:ignore_truncated] = bool
|
702
690
|
@logger.info("Ignore truncated flag changed to #{bool}")
|
703
691
|
else
|
@@ -783,7 +771,6 @@ module Net
|
|
783
771
|
# the old one, which will then be impossibile to recover.
|
784
772
|
#
|
785
773
|
def log_file=(log)
|
786
|
-
@logger.close
|
787
774
|
@config[:log_file] = log
|
788
775
|
@logger = Logger.new(@config[:log_file])
|
789
776
|
@logger.level = $DEBUG ? Logger::DEBUG : Logger::WARN
|
@@ -807,12 +794,10 @@ module Net
|
|
807
794
|
# Note that this will destroy the precedent logger.
|
808
795
|
#
|
809
796
|
def logger=(logger)
|
810
|
-
|
811
|
-
|
812
|
-
|
813
|
-
|
814
|
-
raise ArgumentError, "Argument must be an instance of Logger class"
|
815
|
-
end
|
797
|
+
logger.is_a?(Logger) or
|
798
|
+
raise(ArgumentError, "Argument must be an instance of Logger class")
|
799
|
+
|
800
|
+
@logger = logger
|
816
801
|
end
|
817
802
|
|
818
803
|
# Set the log level for the built-in logging facility.
|
@@ -861,31 +846,29 @@ module Net
|
|
861
846
|
# Returns a Net::DNS::Packet object. If you need to examine the response packet
|
862
847
|
# whether it contains any answers or not, use the Resolver#query method instead.
|
863
848
|
#
|
864
|
-
def search(name,type=Net::DNS::A,cls=Net::DNS::IN)
|
865
|
-
|
866
|
-
return query(name,type,cls) if name.class == IPAddr
|
849
|
+
def search(name, type = Net::DNS::A, cls = Net::DNS::IN)
|
850
|
+
return query(name, type, cls) if name.class == IPAddr
|
867
851
|
|
868
852
|
# If the name contains at least one dot then try it as is first.
|
869
853
|
if name.include? "."
|
870
854
|
@logger.debug "Search(#{name},#{Net::DNS::RR::Types.new(type)},#{Net::DNS::RR::Classes.new(cls)})"
|
871
|
-
ans = query(name,type,cls)
|
855
|
+
ans = query(name, type, cls)
|
872
856
|
return ans if ans.header.anCount > 0
|
873
857
|
end
|
874
858
|
|
875
859
|
# If the name doesn't end in a dot then apply the search list.
|
876
|
-
if name !~ /\.$/
|
860
|
+
if name !~ /\.$/ && @config[:dns_search]
|
877
861
|
@config[:searchlist].each do |domain|
|
878
862
|
newname = name + "." + domain
|
879
863
|
@logger.debug "Search(#{newname},#{Net::DNS::RR::Types.new(type)},#{Net::DNS::RR::Classes.new(cls)})"
|
880
|
-
ans = query(newname,type,cls)
|
864
|
+
ans = query(newname, type, cls)
|
881
865
|
return ans if ans.header.anCount > 0
|
882
866
|
end
|
883
867
|
end
|
884
868
|
|
885
869
|
# Finally, if the name has no dots then try it as is.
|
886
870
|
@logger.debug "Search(#{name},#{Net::DNS::RR::Types.new(type)},#{Net::DNS::RR::Classes.new(cls)})"
|
887
|
-
query(name+".",type,cls)
|
888
|
-
|
871
|
+
query(name + ".", type, cls)
|
889
872
|
end
|
890
873
|
|
891
874
|
# Performs a DNS query for the given name; the search list
|
@@ -912,19 +895,17 @@ module Net
|
|
912
895
|
# packet whether it contains any answers or not, use the Resolver#query
|
913
896
|
# method instead.
|
914
897
|
#
|
915
|
-
def query(name,type=Net::DNS::A,cls=Net::DNS::IN)
|
916
|
-
|
917
|
-
return send(name,type,cls) if name.class == IPAddr
|
898
|
+
def query(name, type = Net::DNS::A, cls = Net::DNS::IN)
|
899
|
+
return send(name, type, cls) if name.class == IPAddr
|
918
900
|
|
919
901
|
# If the name doesn't contain any dots then append the default domain.
|
920
|
-
if name !~ /\./
|
902
|
+
if name !~ /\./ && name !~ /:/ && @config[:defname]
|
921
903
|
name += "." + @config[:domain]
|
922
904
|
end
|
923
905
|
|
924
906
|
@logger.debug "Query(#{name},#{Net::DNS::RR::Types.new(type)},#{Net::DNS::RR::Classes.new(cls)})"
|
925
907
|
|
926
|
-
send(name,type,cls)
|
927
|
-
|
908
|
+
send(name, type, cls)
|
928
909
|
end
|
929
910
|
|
930
911
|
# Performs a DNS query for the given name. Neither the
|
@@ -950,19 +931,18 @@ module Net
|
|
950
931
|
#
|
951
932
|
# ip = IPAddr.new("172.16.100.2")
|
952
933
|
# packet = res.query(ip)
|
953
|
-
#
|
934
|
+
#
|
954
935
|
# packet = res.query("172.16.100.2")
|
955
936
|
#
|
956
937
|
# Use +packet.header.ancount+ or +packet.answer+ to find out if there
|
957
938
|
# were any records in the answer section.
|
958
939
|
#
|
959
940
|
def query(argument, type = Net::DNS::A, cls = Net::DNS::IN)
|
960
|
-
|
961
|
-
|
962
|
-
end
|
941
|
+
!@config[:nameservers].empty? or
|
942
|
+
raise(Resolver::Error, "No nameservers specified!")
|
963
943
|
|
964
944
|
method = :query_udp
|
965
|
-
packet = if argument.
|
945
|
+
packet = if argument.is_a? Net::DNS::Packet
|
966
946
|
argument
|
967
947
|
else
|
968
948
|
make_query_packet(argument, type, cls)
|
@@ -996,15 +976,15 @@ module Net
|
|
996
976
|
|
997
977
|
if type == Net::DNS::AXFR
|
998
978
|
if @raw
|
999
|
-
@logger.
|
979
|
+
@logger.info "AXFR query, switching to TCP over RAW socket"
|
1000
980
|
method = :send_raw_tcp
|
1001
981
|
else
|
1002
|
-
@logger.
|
982
|
+
@logger.info "AXFR query, switching to TCP"
|
1003
983
|
method = :query_tcp
|
1004
984
|
end
|
1005
985
|
end
|
1006
986
|
|
1007
|
-
ans =
|
987
|
+
ans = send(method, packet, packet_data)
|
1008
988
|
|
1009
989
|
unless ans
|
1010
990
|
message = "No response from nameservers list"
|
@@ -1012,20 +992,20 @@ module Net
|
|
1012
992
|
raise NoResponseError, message
|
1013
993
|
end
|
1014
994
|
|
1015
|
-
@logger.info "Received #{ans[0].size} bytes from #{ans[1][2]+
|
1016
|
-
response = Net::DNS::Packet.parse(ans[0],ans[1])
|
995
|
+
@logger.info "Received #{ans[0].size} bytes from #{ans[1][2] + ':' + ans[1][1].to_s}"
|
996
|
+
response = Net::DNS::Packet.parse(ans[0], ans[1])
|
1017
997
|
|
1018
|
-
if response.header.truncated?
|
998
|
+
if response.header.truncated? && !ignore_truncated?
|
1019
999
|
@logger.warn "Packet truncated, retrying using TCP"
|
1020
1000
|
self.use_tcp = true
|
1021
1001
|
begin
|
1022
|
-
return query(argument,type,cls)
|
1002
|
+
return query(argument, type, cls)
|
1023
1003
|
ensure
|
1024
1004
|
self.use_tcp = false
|
1025
1005
|
end
|
1026
1006
|
end
|
1027
1007
|
|
1028
|
-
|
1008
|
+
response
|
1029
1009
|
end
|
1030
1010
|
|
1031
1011
|
# Performs a zone transfer for the zone passed as a parameter.
|
@@ -1052,7 +1032,7 @@ module Net
|
|
1052
1032
|
query(name, Net::DNS::MX, cls).answer.each do |entry|
|
1053
1033
|
arr << entry if entry.type == 'MX'
|
1054
1034
|
end
|
1055
|
-
arr.sort_by
|
1035
|
+
arr.sort_by(&:preference)
|
1056
1036
|
end
|
1057
1037
|
|
1058
1038
|
private
|
@@ -1062,20 +1042,21 @@ module Net
|
|
1062
1042
|
if self.class.platform_windows?
|
1063
1043
|
require 'win32/resolv'
|
1064
1044
|
arr = Win32::Resolv.get_resolv_info
|
1065
|
-
self.domain = arr[0]
|
1045
|
+
self.domain = arr[0][0]
|
1066
1046
|
self.nameservers = arr[1]
|
1067
1047
|
else
|
1068
1048
|
nameservers = []
|
1069
1049
|
IO.foreach(@config[:config_file]) do |line|
|
1070
|
-
line.gsub!(/\s*[;#].*/,"")
|
1050
|
+
line.gsub!(/\s*[;#].*/, "")
|
1071
1051
|
next unless line =~ /\S/
|
1052
|
+
|
1072
1053
|
case line
|
1073
1054
|
when /^\s*domain\s+(\S+)/
|
1074
|
-
self.domain =
|
1055
|
+
self.domain = Regexp.last_match(1)
|
1075
1056
|
when /^\s*search\s+(.*)/
|
1076
|
-
self.searchlist =
|
1057
|
+
self.searchlist = Regexp.last_match(1).split(" ")
|
1077
1058
|
when /^\s*nameserver\s+(.*)/
|
1078
|
-
nameservers <<
|
1059
|
+
nameservers << Regexp.last_match(1).split(" ")
|
1079
1060
|
end
|
1080
1061
|
end
|
1081
1062
|
self.nameservers = nameservers.flatten
|
@@ -1093,14 +1074,14 @@ module Net
|
|
1093
1074
|
if ENV['LOCALDOMAIN']
|
1094
1075
|
self.domain = ENV['LOCALDOMAIN']
|
1095
1076
|
end
|
1096
|
-
|
1097
|
-
|
1098
|
-
|
1099
|
-
|
1100
|
-
|
1101
|
-
|
1102
|
-
|
1103
|
-
|
1077
|
+
return unless ENV['RES_OPTIONS']
|
1078
|
+
|
1079
|
+
ENV['RES_OPTIONS'].split(" ").each do |opt|
|
1080
|
+
name, val = opt.split(":")
|
1081
|
+
begin
|
1082
|
+
eval("self.#{name} = #{val}")
|
1083
|
+
rescue NoMethodError
|
1084
|
+
raise ArgumentError, "Invalid ENV option #{name}"
|
1104
1085
|
end
|
1105
1086
|
end
|
1106
1087
|
end
|
@@ -1144,36 +1125,34 @@ module Net
|
|
1144
1125
|
packet
|
1145
1126
|
end
|
1146
1127
|
|
1147
|
-
def query_tcp(
|
1148
|
-
|
1128
|
+
def query_tcp(_packet, packet_data)
|
1149
1129
|
ans = nil
|
1150
1130
|
length = [packet_data.size].pack("n")
|
1151
1131
|
|
1152
1132
|
@config[:nameservers].each do |ns|
|
1153
|
-
begin
|
1154
1133
|
buffer = ""
|
1155
|
-
socket = Socket.new(Socket::AF_INET,Socket::SOCK_STREAM,0)
|
1156
|
-
socket.bind(Socket.pack_sockaddr_in(@config[:source_port]
|
1134
|
+
socket = Socket.new(Socket::AF_INET, Socket::SOCK_STREAM, 0)
|
1135
|
+
socket.bind(Socket.pack_sockaddr_in(@config[:source_port], @config[:source_address].to_s))
|
1157
1136
|
|
1158
|
-
sockaddr = Socket.pack_sockaddr_in(@config[:port],ns.to_s)
|
1137
|
+
sockaddr = Socket.pack_sockaddr_in(@config[:port], ns.to_s)
|
1159
1138
|
|
1160
1139
|
@config[:tcp_timeout].timeout do
|
1161
1140
|
socket.connect(sockaddr)
|
1162
1141
|
@logger.info "Contacting nameserver #{ns} port #{@config[:port]}"
|
1163
|
-
socket.write(length+packet_data)
|
1142
|
+
socket.write(length + packet_data)
|
1164
1143
|
ans = socket.recv(Net::DNS::INT16SZ)
|
1165
|
-
len = ans.
|
1144
|
+
len = ans.unpack1("n")
|
1166
1145
|
|
1167
1146
|
@logger.info "Receiving #{len} bytes..."
|
1168
1147
|
|
1169
1148
|
if len == 0
|
1170
|
-
@logger.warn "Receiving 0
|
1149
|
+
@logger.warn "Receiving 0 length packet from nameserver #{ns}, trying next."
|
1171
1150
|
next
|
1172
1151
|
end
|
1173
1152
|
|
1174
|
-
while
|
1153
|
+
while buffer.size < len
|
1175
1154
|
left = len - buffer.size
|
1176
|
-
temp,from = socket.recvfrom(left)
|
1155
|
+
temp, from = socket.recvfrom(left)
|
1177
1156
|
buffer += temp
|
1178
1157
|
end
|
1179
1158
|
|
@@ -1182,26 +1161,25 @@ module Net
|
|
1182
1161
|
next
|
1183
1162
|
end
|
1184
1163
|
end
|
1185
|
-
return [buffer,[""
|
1186
|
-
|
1164
|
+
return [buffer, ["", @config[:port], ns.to_s, ns.to_s]]
|
1165
|
+
rescue Timeout::Error
|
1187
1166
|
@logger.warn "Nameserver #{ns} not responding within TCP timeout, trying next one"
|
1188
1167
|
next
|
1189
|
-
|
1168
|
+
ensure
|
1190
1169
|
socket.close
|
1191
|
-
end
|
1192
1170
|
end
|
1171
|
+
ans
|
1193
1172
|
end
|
1194
1173
|
|
1195
|
-
def query_udp(
|
1174
|
+
def query_udp(_packet, packet_data)
|
1196
1175
|
socket4 = UDPSocket.new
|
1197
|
-
socket4.bind(@config[:source_address].to_s
|
1176
|
+
socket4.bind(@config[:source_address].to_s, @config[:source_port])
|
1198
1177
|
socket6 = UDPSocket.new(Socket::AF_INET6)
|
1199
|
-
socket6.bind(@config[:source_address_inet6].to_s
|
1178
|
+
socket6.bind(@config[:source_address_inet6].to_s, @config[:source_port])
|
1200
1179
|
|
1201
1180
|
ans = nil
|
1202
1181
|
response = ""
|
1203
1182
|
@config[:nameservers].each do |ns|
|
1204
|
-
begin
|
1205
1183
|
@config[:udp_timeout].timeout do
|
1206
1184
|
@logger.info "Contacting nameserver #{ns} port #{@config[:port]}"
|
1207
1185
|
ans = if ns.ipv6?
|
@@ -1213,23 +1191,20 @@ module Net
|
|
1213
1191
|
end
|
1214
1192
|
end
|
1215
1193
|
break if ans
|
1216
|
-
|
1194
|
+
rescue Timeout::Error
|
1217
1195
|
@logger.warn "Nameserver #{ns} not responding within UDP timeout, trying next one"
|
1218
1196
|
next
|
1219
|
-
end
|
1220
1197
|
end
|
1221
1198
|
ans
|
1222
1199
|
end
|
1223
1200
|
|
1224
1201
|
# FIXME: a ? method should never raise.
|
1225
1202
|
def valid?(name)
|
1226
|
-
|
1227
|
-
|
1228
|
-
else
|
1229
|
-
true
|
1230
|
-
end
|
1231
|
-
end
|
1203
|
+
name !~ /[^-\w\.\*]/ or
|
1204
|
+
raise(ArgumentError, "Invalid domain name #{name}")
|
1232
1205
|
|
1206
|
+
true
|
1207
|
+
end
|
1233
1208
|
end
|
1234
1209
|
end
|
1235
1210
|
end
|