pNet-DNS 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README +68 -0
- data/lib/Net/DNS.rb +879 -0
- data/lib/Net/DNS/Header.rb +303 -0
- data/lib/Net/DNS/Nameserver.rb +601 -0
- data/lib/Net/DNS/Packet.rb +851 -0
- data/lib/Net/DNS/Question.rb +117 -0
- data/lib/Net/DNS/RR.rb +630 -0
- data/lib/Net/DNS/RR/A.rb +103 -0
- data/lib/Net/DNS/RR/AAAA.rb +147 -0
- data/lib/Net/DNS/RR/AFSDB.rb +114 -0
- data/lib/Net/DNS/RR/CERT.rb +191 -0
- data/lib/Net/DNS/RR/CNAME.rb +89 -0
- data/lib/Net/DNS/RR/DNAME.rb +84 -0
- data/lib/Net/DNS/RR/EID.rb +70 -0
- data/lib/Net/DNS/RR/HINFO.rb +108 -0
- data/lib/Net/DNS/RR/ISDN.rb +118 -0
- data/lib/Net/DNS/RR/LOC.rb +341 -0
- data/lib/Net/DNS/RR/MB.rb +92 -0
- data/lib/Net/DNS/RR/MG.rb +96 -0
- data/lib/Net/DNS/RR/MINFO.rb +109 -0
- data/lib/Net/DNS/RR/MR.rb +92 -0
- data/lib/Net/DNS/RR/MX.rb +124 -0
- data/lib/Net/DNS/RR/NAPTR.rb +182 -0
- data/lib/Net/DNS/RR/NIMLOC.rb +70 -0
- data/lib/Net/DNS/RR/NS.rb +100 -0
- data/lib/Net/DNS/RR/NSAP.rb +273 -0
- data/lib/Net/DNS/RR/NULL.rb +68 -0
- data/lib/Net/DNS/RR/OPT.rb +251 -0
- data/lib/Net/DNS/RR/PTR.rb +93 -0
- data/lib/Net/DNS/RR/PX.rb +131 -0
- data/lib/Net/DNS/RR/RP.rb +108 -0
- data/lib/Net/DNS/RR/RT.rb +115 -0
- data/lib/Net/DNS/RR/SOA.rb +195 -0
- data/lib/Net/DNS/RR/SPF.rb +46 -0
- data/lib/Net/DNS/RR/SRV.rb +153 -0
- data/lib/Net/DNS/RR/SSHFP.rb +190 -0
- data/lib/Net/DNS/RR/TKEY.rb +219 -0
- data/lib/Net/DNS/RR/TSIG.rb +358 -0
- data/lib/Net/DNS/RR/TXT.rb +162 -0
- data/lib/Net/DNS/RR/UNKNOWN.rb +76 -0
- data/lib/Net/DNS/RR/X25.rb +90 -0
- data/lib/Net/DNS/Resolver.rb +2090 -0
- data/lib/Net/DNS/Resolver/Recurse.rb +478 -0
- data/lib/Net/DNS/Update.rb +189 -0
- data/test/custom.txt +4 -0
- data/test/resolv.conf +4 -0
- data/test/tc_escapedchars.rb +498 -0
- data/test/tc_header.rb +91 -0
- data/test/tc_inet6.rb +169 -0
- data/test/tc_misc.rb +137 -0
- data/test/tc_online.rb +236 -0
- data/test/tc_packet.rb +174 -0
- data/test/tc_packet_unique_push.rb +126 -0
- data/test/tc_question.rb +49 -0
- data/test/tc_recurse.rb +69 -0
- data/test/tc_res_env.rb +59 -0
- data/test/tc_res_file.rb +55 -0
- data/test/tc_res_opt.rb +135 -0
- data/test/tc_resolver.rb +102 -0
- data/test/tc_rr-opt.rb +40 -0
- data/test/tc_rr-rrsort.rb +116 -0
- data/test/tc_rr-txt.rb +138 -0
- data/test/tc_rr-unknown.rb +95 -0
- data/test/tc_rr.rb +246 -0
- data/test/tc_tcp.rb +34 -0
- data/test/tc_tkey.rb +115 -0
- data/test/tc_update.rb +226 -0
- data/test/ts_netdns.rb +17 -0
- data/test/ts_offline.rb +32 -0
- data/test/ts_online.rb +33 -0
- metadata +119 -0
@@ -0,0 +1,478 @@
|
|
1
|
+
# The contents of this file are subject to the Mozilla
|
2
|
+
# Public Licence Version 1.1 (the "Licence"); you may
|
3
|
+
# not use this file except in compliance with the
|
4
|
+
# Licence. You may obtain a copy of the Licence at
|
5
|
+
# http://www.mozilla.org/MPL
|
6
|
+
# Software distributed under the Licence is distributed
|
7
|
+
# on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND,
|
8
|
+
# either express or implied. See the Licence of the
|
9
|
+
# specific language governing rights and limitations
|
10
|
+
# under the Licence.
|
11
|
+
# The Original Code is pNet::DNS.
|
12
|
+
# The Initial Developer of the Original Code is
|
13
|
+
# Nominet UK (www.nominet.org.uk). Portions created by
|
14
|
+
# Nominet UK are Copyright (c) Nominet UK 2006.
|
15
|
+
# All rights reserved.
|
16
|
+
module Net
|
17
|
+
module DNS
|
18
|
+
class Resolver
|
19
|
+
#= NAME
|
20
|
+
#
|
21
|
+
#Net::DNS::Resolver::Recurse - Perform recursive dns lookups
|
22
|
+
#
|
23
|
+
#= SYNOPSIS
|
24
|
+
#
|
25
|
+
# require 'Net/DNS'
|
26
|
+
# res = Net::DNS::Resolver::Recurse.new
|
27
|
+
#
|
28
|
+
#= DESCRIPTION
|
29
|
+
#
|
30
|
+
#This module is a sub class of Net::DNS::Resolver. So the methods for
|
31
|
+
#Net::DNS::Resolver still work for this module as well. There are just a
|
32
|
+
#couple methods added
|
33
|
+
#
|
34
|
+
#=head1 AUTHOR
|
35
|
+
#
|
36
|
+
#Rob Brown, bbb@cpan.org
|
37
|
+
#
|
38
|
+
#=head1 SEE ALSO
|
39
|
+
#
|
40
|
+
#L<Net::DNS::Resolver>,
|
41
|
+
#
|
42
|
+
#=head1 COPYRIGHT
|
43
|
+
#
|
44
|
+
#Copyright (c) 2002, Rob Brown. All rights reserved.
|
45
|
+
#Portions Copyright (c) 2005, Olaf M Kolkman.
|
46
|
+
#Ruby version Copyright (c) 2006, AlexD (Nominet UK)
|
47
|
+
#
|
48
|
+
#This module is free software; you can redistribute
|
49
|
+
#it and/or modify it under the same terms as Perl itself.
|
50
|
+
#
|
51
|
+
#Example lookup process:
|
52
|
+
#
|
53
|
+
#[root@box root]# dig +trace www.rob.com.au.
|
54
|
+
#
|
55
|
+
#; <<>> DiG 9.2.0 <<>> +trace www.rob.com.au.
|
56
|
+
#;; global options: printcmd
|
57
|
+
#. 507343 IN NS C.ROOT-SERVERS.NET.
|
58
|
+
#. 507343 IN NS D.ROOT-SERVERS.NET.
|
59
|
+
#. 507343 IN NS E.ROOT-SERVERS.NET.
|
60
|
+
#. 507343 IN NS F.ROOT-SERVERS.NET.
|
61
|
+
#. 507343 IN NS G.ROOT-SERVERS.NET.
|
62
|
+
#. 507343 IN NS H.ROOT-SERVERS.NET.
|
63
|
+
#. 507343 IN NS I.ROOT-SERVERS.NET.
|
64
|
+
#. 507343 IN NS J.ROOT-SERVERS.NET.
|
65
|
+
#. 507343 IN NS K.ROOT-SERVERS.NET.
|
66
|
+
#. 507343 IN NS L.ROOT-SERVERS.NET.
|
67
|
+
#. 507343 IN NS M.ROOT-SERVERS.NET.
|
68
|
+
#. 507343 IN NS A.ROOT-SERVERS.NET.
|
69
|
+
#. 507343 IN NS B.ROOT-SERVERS.NET.
|
70
|
+
#;; Received 436 bytes from 127.0.0.1#53(127.0.0.1) in 9 ms
|
71
|
+
# ;;; But these should be hard coded as the hints
|
72
|
+
#
|
73
|
+
# ;;; Ask H.ROOT-SERVERS.NET gave:
|
74
|
+
#au. 172800 IN NS NS2.BERKELEY.EDU.
|
75
|
+
#au. 172800 IN NS NS1.BERKELEY.EDU.
|
76
|
+
#au. 172800 IN NS NS.UU.NET.
|
77
|
+
#au. 172800 IN NS BOX2.AUNIC.NET.
|
78
|
+
#au. 172800 IN NS SEC1.APNIC.NET.
|
79
|
+
#au. 172800 IN NS SEC3.APNIC.NET.
|
80
|
+
#;; Received 300 bytes from 128.63.2.53#53(H.ROOT-SERVERS.NET) in 322 ms
|
81
|
+
# ;;; A little closer than before
|
82
|
+
#
|
83
|
+
# ;;; Ask NS2.BERKELEY.EDU gave:
|
84
|
+
#com.au. 259200 IN NS ns4.ausregistry.net.
|
85
|
+
#com.au. 259200 IN NS dns1.telstra.net.
|
86
|
+
#com.au. 259200 IN NS au2ld.CSIRO.au.
|
87
|
+
#com.au. 259200 IN NS audns01.syd.optus.net.
|
88
|
+
#com.au. 259200 IN NS ns.ripe.net.
|
89
|
+
#com.au. 259200 IN NS ns1.ausregistry.net.
|
90
|
+
#com.au. 259200 IN NS ns2.ausregistry.net.
|
91
|
+
#com.au. 259200 IN NS ns3.ausregistry.net.
|
92
|
+
#com.au. 259200 IN NS ns3.melbourneit.com.
|
93
|
+
#;; Received 387 bytes from 128.32.206.12#53(NS2.BERKELEY.EDU) in 10312 ms
|
94
|
+
# ;;; A little closer than before
|
95
|
+
#
|
96
|
+
# ;;; Ask ns4.ausregistry.net gave:
|
97
|
+
#com.au. 259200 IN NS ns1.ausregistry.net.
|
98
|
+
#com.au. 259200 IN NS ns2.ausregistry.net.
|
99
|
+
#com.au. 259200 IN NS ns3.ausregistry.net.
|
100
|
+
#com.au. 259200 IN NS ns4.ausregistry.net.
|
101
|
+
#com.au. 259200 IN NS ns3.melbourneit.com.
|
102
|
+
#com.au. 259200 IN NS dns1.telstra.net.
|
103
|
+
#com.au. 259200 IN NS au2ld.CSIRO.au.
|
104
|
+
#com.au. 259200 IN NS ns.ripe.net.
|
105
|
+
#com.au. 259200 IN NS audns01.syd.optus.net.
|
106
|
+
#;; Received 259 bytes from 137.39.1.3#53(ns4.ausregistry.net) in 606 ms
|
107
|
+
# ;;; Uh... yeah... I already knew this
|
108
|
+
# ;;; from what NS2.BERKELEY.EDU told me.
|
109
|
+
# ;;; ns4.ausregistry.net must have brain damage
|
110
|
+
#
|
111
|
+
# ;;; Ask ns1.ausregistry.net gave:
|
112
|
+
#rob.com.au. 86400 IN NS sy-dns02.tmns.net.au.
|
113
|
+
#rob.com.au. 86400 IN NS sy-dns01.tmns.net.au.
|
114
|
+
#;; Received 87 bytes from 203.18.56.41#53(ns1.ausregistry.net) in 372 ms
|
115
|
+
# ;;; Ah, much better. Something more useful.
|
116
|
+
#
|
117
|
+
# ;;; Ask sy-dns02.tmns.net.au gave:
|
118
|
+
#www.rob.com.au. 7200 IN A 139.134.5.123
|
119
|
+
#rob.com.au. 7200 IN NS sy-dns01.tmns.net.au.
|
120
|
+
#rob.com.au. 7200 IN NS sy-dns02.tmns.net.au.
|
121
|
+
#;; Received 135 bytes from 139.134.2.18#53(sy-dns02.tmns.net.au) in 525 ms
|
122
|
+
# ;;; FINALLY, THE ANSWER!
|
123
|
+
class Recurse < Resolver
|
124
|
+
attr_accessor :nameservers, :callback, :recurse
|
125
|
+
attr_reader :hints
|
126
|
+
#Initialize the hint servers. Recursive queries need a starting name
|
127
|
+
#server to work off of. This method takes a list of IP addresses to use
|
128
|
+
#as the starting servers. These name servers should be authoritative for
|
129
|
+
#the root (.) zone.
|
130
|
+
#
|
131
|
+
# res.hints=(ips)
|
132
|
+
#
|
133
|
+
#If no hints are passed, the default nameserver is asked for the hints.
|
134
|
+
#Normally these IPs can be obtained from the following location:
|
135
|
+
#
|
136
|
+
# ftp://ftp.internic.net/domain/named.root
|
137
|
+
#
|
138
|
+
def hints=(hints)
|
139
|
+
print ";; hints(#{hints.inspect})\n" if @debug
|
140
|
+
if (!hints && @nameservers)
|
141
|
+
@hints=(@nameservers)
|
142
|
+
else
|
143
|
+
@nameservers=(hints)
|
144
|
+
end
|
145
|
+
print ";; verifying (root) zone...\n" if @debug
|
146
|
+
# bind always asks one of the hint servers
|
147
|
+
# for who it thinks is authoritative for
|
148
|
+
# the (root) zone as a sanity check.
|
149
|
+
# Nice idea.
|
150
|
+
|
151
|
+
recurse=(1)
|
152
|
+
packet=query(".", "NS", "IN")
|
153
|
+
|
154
|
+
hints = Hash.new
|
155
|
+
if (packet)
|
156
|
+
if (ans = packet.answer)
|
157
|
+
# foreach my $rr (@ans)
|
158
|
+
ans.each do |rr|
|
159
|
+
if (rr.name =~ /^\.?$/ and
|
160
|
+
rr.type == "NS")
|
161
|
+
# Found root authority
|
162
|
+
server = rr.rdatastr.downcase
|
163
|
+
server.sub!(/\.$/,"")
|
164
|
+
print ";; FOUND HINT: #{server}\n" if @debug
|
165
|
+
hints[server] = []
|
166
|
+
end
|
167
|
+
end
|
168
|
+
# foreach my $rr ($packet->additional) {
|
169
|
+
packet.additional.each do |rr|
|
170
|
+
print ";; ADDITIONAL: ",rr.inspect,"\n" if @debug
|
171
|
+
if (server = rr.name.downcase)
|
172
|
+
if ( rr.type == "A")
|
173
|
+
#print ";; ADDITIONAL HELP: $server -> [".$rr->rdatastr."]\n" if $self->{'debug'};
|
174
|
+
if (hints[server]!=nil)
|
175
|
+
print ";; STORING IP: #{server} IN A ",rr.rdatastr,"\n" if @debug
|
176
|
+
hints[server]=rr.rdatastr
|
177
|
+
end
|
178
|
+
end
|
179
|
+
if ( rr.type == "AAAA")
|
180
|
+
#print ";; ADDITIONAL HELP: $server -> [".$rr->rdatastr."]\n" if $self->{'debug'};
|
181
|
+
if (hints[server])
|
182
|
+
print ";; STORING IP6: #{server} IN AAAA ",rr.rdatastr,"\n" if @debug
|
183
|
+
hints[server]=rr.rdatastr
|
184
|
+
end
|
185
|
+
end
|
186
|
+
|
187
|
+
end
|
188
|
+
end
|
189
|
+
end
|
190
|
+
# foreach my $server (keys %hints) {
|
191
|
+
hints.keys.each do |server|
|
192
|
+
if (!hints[server] || hints[server]==[])
|
193
|
+
# Wipe the servers without lookups
|
194
|
+
hints.delete(server)
|
195
|
+
end
|
196
|
+
end
|
197
|
+
@hints = hints
|
198
|
+
else
|
199
|
+
@hints = []
|
200
|
+
end
|
201
|
+
if (@hints.size > 0)
|
202
|
+
if (@debug)
|
203
|
+
print ";; USING THE FOLLOWING HINT IPS:\n";
|
204
|
+
# foreach my $ips (values %{ $self->{'hints'} }) {
|
205
|
+
@hints.values.each do |ips|
|
206
|
+
# foreach my $server (@{ $ips }) {
|
207
|
+
ips.each do |server|
|
208
|
+
print ";; #{server}\n";
|
209
|
+
end
|
210
|
+
end
|
211
|
+
end
|
212
|
+
else
|
213
|
+
warn "Server ["+(@nameservers)[0]+"] did not give answers"
|
214
|
+
end
|
215
|
+
|
216
|
+
# Disable recursion flag.
|
217
|
+
@recurse=(0)
|
218
|
+
|
219
|
+
# return $self->nameservers( map { @{ $_ } } values %{ $self->{'hints'} } );
|
220
|
+
@nameservers = @hints.values
|
221
|
+
return @nameservers
|
222
|
+
end
|
223
|
+
|
224
|
+
|
225
|
+
#This method is takes a code reference, which is then invoked each time a
|
226
|
+
#packet is received during the recursive lookup. For example to emulate
|
227
|
+
#dig's C<+trace> function:
|
228
|
+
#
|
229
|
+
# res.recursion_callback(Proc.new { |packet|
|
230
|
+
# print packet.additional.inspect
|
231
|
+
#
|
232
|
+
# print";; Received %d bytes from %s\n\n",
|
233
|
+
# packetanswersize,
|
234
|
+
# packet.answerfrom);
|
235
|
+
# })
|
236
|
+
#
|
237
|
+
def recursion_callback=(sub)
|
238
|
+
# if (sub && UNIVERSAL::isa(sub, 'CODE'))
|
239
|
+
@callback = sub
|
240
|
+
# end
|
241
|
+
end
|
242
|
+
|
243
|
+
def recursion_callback
|
244
|
+
return @callback
|
245
|
+
end
|
246
|
+
|
247
|
+
|
248
|
+
#
|
249
|
+
#This method is much like the normal query() method except it disables
|
250
|
+
#the recurse flag in the packet and explicitly performs the recursion.
|
251
|
+
#
|
252
|
+
# packet = res.query_dorecursion( "www.netscape.com.", "A")
|
253
|
+
#
|
254
|
+
#
|
255
|
+
def query_dorecursion(*args)
|
256
|
+
|
257
|
+
# Make sure the hint servers are initialized.
|
258
|
+
@hints=Hash.new unless @hints
|
259
|
+
@recurse=(0)
|
260
|
+
# Make sure the authority cache is clean.
|
261
|
+
# It is only used to store A and AAAA records of
|
262
|
+
# the suposedly authoritative name servers.
|
263
|
+
@authority_cache = Hash.new
|
264
|
+
|
265
|
+
# Obtain real question Net::DNS::Packet
|
266
|
+
query_packet = make_query_packet(args)
|
267
|
+
|
268
|
+
# Seed name servers with hints
|
269
|
+
return _dorecursion( query_packet, ".", @hints, 0)
|
270
|
+
end
|
271
|
+
|
272
|
+
def _dorecursion(query_packet, known_zone, known_authorities, depth)
|
273
|
+
cache = @authority_cache
|
274
|
+
|
275
|
+
# die "Recursion too deep, aborting..." if $depth > 255;
|
276
|
+
if ( depth > 255 )
|
277
|
+
print ";; _dorecursion() Recursion too deep, aborting...\n" if @debug
|
278
|
+
@errorstring="Recursion too deep, aborted"
|
279
|
+
return nil
|
280
|
+
end
|
281
|
+
|
282
|
+
known_zone.sub!(/\.*$/, ".")
|
283
|
+
|
284
|
+
# Get IPs from authorities
|
285
|
+
ns = []
|
286
|
+
# foreach my $ns (keys %{ $known_authorities }) {
|
287
|
+
known_authorities.keys.each do |ns_rec|
|
288
|
+
if (known_authorities[ns_rec] != nil && known_authorities[ns_rec] != [] )
|
289
|
+
cache[ns_rec] = known_authorities[ns_rec]
|
290
|
+
ns.push(cache[ns_rec])
|
291
|
+
elsif (cache[ns_rec]!=nil && cache[ns_rec]!=[])
|
292
|
+
known_authorities[ns_rec] = cache[ns_rec]
|
293
|
+
ns.push(cache[ns_rec])
|
294
|
+
end
|
295
|
+
end
|
296
|
+
|
297
|
+
if (ns.length == 0)
|
298
|
+
found_auth = 0
|
299
|
+
if (@debug)
|
300
|
+
print ";; _dorecursion() Failed to extract nameserver IPs:\n";
|
301
|
+
print known_authorities.inspect + cache.inspect + "\n"
|
302
|
+
end
|
303
|
+
# foreach my $ns (keys %{ $known_authorities }) {
|
304
|
+
known_authorities.keys.each do |ns_rec|
|
305
|
+
if (known_authorities[ns_rec]==nil || known_authorities[ns_rec]==[])
|
306
|
+
print ";; _dorecursion() Manual lookup for authority [#{ns_rec}]\n" if @debug
|
307
|
+
|
308
|
+
auth_packet=nil
|
309
|
+
ans=[]
|
310
|
+
|
311
|
+
# Don't query for V6 if its not there.
|
312
|
+
if (! @force_v4)
|
313
|
+
auth_packet = _dorecursion(make_query_packet([ns_rec,"AAAA"]), # packet
|
314
|
+
".", # known_zone
|
315
|
+
@hints, # known_authorities
|
316
|
+
depth+1); # depth
|
317
|
+
ans = auth_packet.answer if auth_packet
|
318
|
+
end
|
319
|
+
|
320
|
+
auth_packet = _dorecursion(make_query_packet([ns_rec,"A"]), # packet
|
321
|
+
".", # known_zone
|
322
|
+
@hints, # known_authorities
|
323
|
+
depth+1); # depth
|
324
|
+
|
325
|
+
ans.push(auth_packet.answer ) if auth_packet
|
326
|
+
|
327
|
+
if ( ans.length > 0 )
|
328
|
+
print ";; _dorecursion() Answers found for [#{ns_rec}]\n" if @debug
|
329
|
+
# foreach my $rr (@ans) {
|
330
|
+
ans.each do |rr_arr|
|
331
|
+
rr_arr.each do |rr|
|
332
|
+
print ";; RR:" + rr.inspect + "\n" if @debug
|
333
|
+
if (rr.type == "CNAME")
|
334
|
+
# Follow CNAME
|
335
|
+
server = rr.name.downcase
|
336
|
+
if (server)
|
337
|
+
server.sub!(/\.*$/, ".")
|
338
|
+
if (server == ns_rec)
|
339
|
+
cname = rr.rdatastr.downcase
|
340
|
+
cname.sub!(/\.*$/, ".")
|
341
|
+
print ";; _dorecursion() Following CNAME ns [#{ns_rec}] -> [#{cname}]\n" if @debug
|
342
|
+
known_authorities[cname] ||= []
|
343
|
+
known_authorities.delete[ns_rec]
|
344
|
+
next
|
345
|
+
end
|
346
|
+
end
|
347
|
+
elsif (rr.type == "A" || rr.type == "AAAA" )
|
348
|
+
server = rr.name.downcase
|
349
|
+
if (server)
|
350
|
+
server.sub!(/\.*$/, ".")
|
351
|
+
if (known_authorities[server]!=nil)
|
352
|
+
ip = rr.rdatastr
|
353
|
+
print ";; _dorecursion() Found ns: #{server} IN A #{ip}\n" if @debug
|
354
|
+
cache[server] = known_authorities[server]
|
355
|
+
cache[ns_rec].push(ip)
|
356
|
+
found_auth+=1
|
357
|
+
next
|
358
|
+
end
|
359
|
+
end
|
360
|
+
end
|
361
|
+
print ";; _dorecursion() Ignoring useless answer: " + rr.inspect + "\n" if @debug
|
362
|
+
end
|
363
|
+
end
|
364
|
+
else
|
365
|
+
print ";; _dorecursion() Could not find A records for [#{ns_rec}]\n" if @debug
|
366
|
+
end
|
367
|
+
end
|
368
|
+
end
|
369
|
+
if (found_auth > 0)
|
370
|
+
print ";; _dorecursion() Found #{found_auth} new NS authorities...\n" if @debug
|
371
|
+
return _dorecursion( query_packet, known_zone, known_authorities, depth+1)
|
372
|
+
end
|
373
|
+
print ";; _dorecursion() No authority information could be obtained.\n" if @debug
|
374
|
+
return nil
|
375
|
+
end
|
376
|
+
|
377
|
+
# Cut the deck of IPs in a random place.
|
378
|
+
print ";; _dorecursion() cutting deck of (" + ns.length.to_s + ") authorities...\n" if @debug
|
379
|
+
splitpos = rand(ns.length)
|
380
|
+
start = ns[0, splitpos]
|
381
|
+
endarr = ns[splitpos, ns.length - splitpos]
|
382
|
+
ns = endarr + start
|
383
|
+
|
384
|
+
|
385
|
+
ns.each do |levelns|
|
386
|
+
print ";; _dorecursion() Trying nameserver [#{levelns}]\n" if @debug
|
387
|
+
@nameservers=(levelns)
|
388
|
+
|
389
|
+
packet = send( query_packet )
|
390
|
+
if (packet)
|
391
|
+
|
392
|
+
if (@callback)
|
393
|
+
@callback.call(packet)
|
394
|
+
end
|
395
|
+
|
396
|
+
of = nil
|
397
|
+
print ";; _dorecursion() Response received from [" + @answerfrom + "]\n" if @debug
|
398
|
+
status = packet.header.rcode
|
399
|
+
authority = packet.authority
|
400
|
+
if (status)
|
401
|
+
if (status == "NXDOMAIN")
|
402
|
+
# I guess NXDOMAIN is the best we'll ever get
|
403
|
+
print ";; _dorecursion() returning NXDOMAIN\n" if @debug
|
404
|
+
return packet
|
405
|
+
elsif (packet.answer.length > 0)
|
406
|
+
print ";; _dorecursion() Answers were found.\n" if @debug
|
407
|
+
return packet
|
408
|
+
elsif (authority.length > 0)
|
409
|
+
auth = Hash.new
|
410
|
+
# foreach my $rr (@authority) {
|
411
|
+
authority.each do |rr|
|
412
|
+
if (rr.type =~ /^(NS|SOA)$/)
|
413
|
+
server = (rr.type == "NS" ? rr.nsdname : rr.mname).downcase
|
414
|
+
server.sub!(/\.*$/, ".")
|
415
|
+
of = rr.name.downcase
|
416
|
+
of.sub!(/\.*$/, ".")
|
417
|
+
print ";; _dorecursion() Received authority [#{of}] [" + rr.type() + "] [#{server}]\n" if @debug
|
418
|
+
if (of.length <= known_zone.length)
|
419
|
+
print ";; _dorecursion() Deadbeat name server did not provide new information.\n" if @debug
|
420
|
+
next
|
421
|
+
elsif (of =~ /#{known_zone}/)
|
422
|
+
print ";; _dorecursion() FOUND closer authority for [#{of}] at [#{server}].\n" if @debug
|
423
|
+
auth[server] ||= []
|
424
|
+
else
|
425
|
+
print ";; _dorecursion() Confused name server [" + @answerfrom + "] thinks [#{of}] is closer than [#{known_zone}]?\n" if @debug
|
426
|
+
last
|
427
|
+
end
|
428
|
+
else
|
429
|
+
print ";; _dorecursion() Ignoring NON NS entry found in authority section: " + rr.inspect + "\n" if @debug
|
430
|
+
end
|
431
|
+
end
|
432
|
+
# foreach my $rr ($packet->additional)
|
433
|
+
packet.additional.each do |rr|
|
434
|
+
if (rr.type == "CNAME")
|
435
|
+
# Store this CNAME into %auth too
|
436
|
+
server = rr.name.downcase
|
437
|
+
if (server)
|
438
|
+
server.sub!(/\.*$/, ".")
|
439
|
+
if (auth[server]!=nil && auth[server]!=[])
|
440
|
+
cname = rr.rdatastr.downcase
|
441
|
+
cname.sub!(/\.*$/, ".")
|
442
|
+
print ";; _dorecursion() FOUND CNAME authority: " + rr.string + "\n" if @debug
|
443
|
+
auth[cname] ||= []
|
444
|
+
auth[server] = auth[cname]
|
445
|
+
next
|
446
|
+
end
|
447
|
+
|
448
|
+
end
|
449
|
+
elsif (rr.type == "A" || rr.type == "AAAA")
|
450
|
+
server = rr.name.downcase
|
451
|
+
if (server)
|
452
|
+
server.sub!(/\.*$/, ".")
|
453
|
+
if (auth[server]!=nil)
|
454
|
+
print ";; _dorecursion() STORING: #{server} IN A " + rr.rdatastr + "\n" if @debug && rr.type == "A"
|
455
|
+
print ";; _dorecursion() STORING: #{server} IN AAAA " + rr.rdatastr + "\n" if @debug && rr.type == "AAAA"
|
456
|
+
auth[server].push(rr.rdatastr)
|
457
|
+
next
|
458
|
+
end
|
459
|
+
end
|
460
|
+
end
|
461
|
+
print ";; _dorecursion() Ignoring useless: " + rr.inspect + "\n" if @debug
|
462
|
+
end
|
463
|
+
if (of =~ /#{known_zone}/)
|
464
|
+
return _dorecursion( query_packet, of, auth, depth+1 )
|
465
|
+
else
|
466
|
+
return _dorecursion( query_packet, known_zone, known_authorities, depth+1 )
|
467
|
+
end
|
468
|
+
end
|
469
|
+
end
|
470
|
+
end
|
471
|
+
end
|
472
|
+
|
473
|
+
return nil
|
474
|
+
end
|
475
|
+
end
|
476
|
+
end
|
477
|
+
end
|
478
|
+
end
|