@@ -995,12 +995,54 @@ def send(argument,type=Net::DNS::A,cls=Net::DNS::IN)
995995 #
996996 # Performs a zone transfer for the zone passed as a parameter.
997997 #
998- # It is actually only a wrapper to a send with type set as Net::DNS::AXFR,
999- # since it is using the same infrastucture.
998+ # Returns a list of Net::DNS::Packet (not answers!)
1000999 #
10011000 def axfr ( name , cls = Net ::DNS ::IN )
10021001 @logger . info "Requested AXFR transfer, zone #{ name } class #{ cls } "
1003- send ( name , Net ::DNS ::AXFR , cls )
1002+ if @config [ :nameservers ] . size == 0
1003+ raise Resolver ::Error , "No nameservers specified!"
1004+ end
1005+
1006+ method = :send_tcp
1007+ packet = make_query_packet ( name , Net ::DNS ::AXFR , cls )
1008+
1009+ # Store packet_data for performance improvements,
1010+ # so methods don't keep on calling Packet#data
1011+ packet_data = packet . data
1012+ packet_size = packet_data . size
1013+
1014+ if @raw
1015+ @logger . warn "AXFR query, switching to TCP over RAW socket"
1016+ method = :send_raw_tcp
1017+ else
1018+ @logger . warn "AXFR query, switching to TCP"
1019+ method = :send_tcp
1020+ end
1021+
1022+ answers = [ ]
1023+ soa = 0
1024+ self . old_send ( method , packet , packet_data ) do |ans |
1025+ @logger . info "Received #{ ans [ 0 ] . size } bytes from #{ ans [ 1 ] [ 2 ] +":" +ans [ 1 ] [ 1 ] . to_s } "
1026+
1027+ begin
1028+ response = Net ::DNS ::Packet . parse ( ans [ 0 ] , ans [ 1 ] )
1029+ if response . answer [ 0 ] . type == "SOA"
1030+ soa += 1
1031+ if soa >= 2
1032+ break
1033+ end
1034+ end
1035+ answers << response
1036+ rescue NameError => e
1037+ @logger . warn "Error parsing axfr response: #{ e . message } "
1038+ end
1039+ end
1040+ if answers . empty?
1041+ @logger . fatal "No response from nameservers list: aborting"
1042+ raise NoResponseError
1043+ end
1044+
1045+ return answers
10041046 end
10051047
10061048 #
@@ -1119,45 +1161,64 @@ def send_tcp(packet,packet_data)
11191161
11201162 @config [ :nameservers ] . each do |ns |
11211163 begin
1122- buffer = ""
11231164 socket = Socket . new ( Socket ::AF_INET , Socket ::SOCK_STREAM , 0 )
11241165 socket . bind ( Socket . pack_sockaddr_in ( @config [ :source_port ] , @config [ :source_address ] . to_s ) )
11251166
11261167 sockaddr = Socket . pack_sockaddr_in ( @config [ :port ] , ns . to_s )
11271168
11281169 @config [ :tcp_timeout ] . timeout do
1129- socket . connect ( sockaddr )
1130- @logger . info "Contacting nameserver #{ ns } port #{ @config [ :port ] } "
1131- socket . write ( length +packet_data )
1132- ans = socket . recv ( Net ::DNS ::INT16SZ )
1133- len = ans . unpack ( "n" ) [ 0 ]
1134-
1135- @logger . info "Receiving #{ len } bytes..."
1136-
1137- if len == 0
1138- @logger . warn "Receiving 0 lenght packet from nameserver #{ ns } , trying next."
1139- next
1140- end
1141-
1142- while ( buffer . size < len )
1143- left = len - buffer . size
1144- temp , from = socket . recvfrom ( left )
1145- buffer += temp
1146- end
1147-
1148- unless buffer . size == len
1149- @logger . warn "Malformed packet from nameserver #{ ns } , trying next."
1150- next
1170+ catch "next nameserver" do
1171+ socket . connect ( sockaddr )
1172+ @logger . info "Contacting nameserver #{ ns } port #{ @config [ :port ] } "
1173+ socket . write ( length +packet_data )
1174+ got_something = false
1175+ loop do
1176+ buffer = ""
1177+ ans = socket . recv ( Net ::DNS ::INT16SZ )
1178+ if ans . size == 0
1179+ if got_something
1180+ break #Proper exit from loop
1181+ else
1182+ @logger . warn "Connection reset to nameserver #{ ns } , trying next."
1183+ throw "next nameserver"
1184+ end
1185+ end
1186+ got_something = true
1187+ len = ans . unpack ( "n" ) [ 0 ]
1188+
1189+ @logger . info "Receiving #{ len } bytes..."
1190+
1191+ if len == 0
1192+ @logger . warn "Receiving 0 length packet from nameserver #{ ns } , trying next."
1193+ throw "next nameserver"
1194+ end
1195+
1196+ while ( buffer . size < len )
1197+ left = len - buffer . size
1198+ temp , from = socket . recvfrom ( left )
1199+ buffer += temp
1200+ end
1201+
1202+ unless buffer . size == len
1203+ @logger . warn "Malformed packet from nameserver #{ ns } , trying next."
1204+ throw "next nameserver"
1205+ end
1206+ if block_given?
1207+ yield [ buffer , [ "" , @config [ :port ] , ns . to_s , ns . to_s ] ]
1208+ else
1209+ return [ buffer , [ "" , @config [ :port ] , ns . to_s , ns . to_s ] ]
1210+ end
1211+ end
11511212 end
11521213 end
1153- return [ buffer , [ "" , @config [ :port ] , ns . to_s , ns . to_s ] ]
11541214 rescue Timeout ::Error
11551215 @logger . warn "Nameserver #{ ns } not responding within TCP timeout, trying next one"
11561216 next
11571217 ensure
11581218 socket . close
11591219 end
11601220 end
1221+ return nil
11611222 end
11621223
11631224 def send_udp ( packet , packet_data )
0 commit comments