net-dns 0.8.0 → 0.20.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|