Skip to content

Commit 157bab4

Browse files
author
Brent Cook
committed
Land rapid7#5518, TFTP::Client retransmit lost data blocks on upload
2 parents d9a76bb + b40c366 commit 157bab4

File tree

1 file changed

+35
-14
lines changed

1 file changed

+35
-14
lines changed

lib/rex/proto/tftp/client.rb

Lines changed: 35 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -295,38 +295,59 @@ def send_data(host,port)
295295
end
296296
sent_data = 0
297297
sent_blocks = 0
298+
send_retries = 0
298299
expected_blocks = data_blocks.size
299300
expected_size = data_blocks.join.size
300301
if block_given?
301302
yield "Source file: #{self.local_file =~ /^DATA:/ ? "(Data)" : self.remote_file}, destination file: #{self.remote_file}"
302303
yield "Sending #{expected_size} bytes (#{expected_blocks} blocks)"
303304
end
304305
data_blocks.each_with_index do |data_block,idx|
305-
req = [OpData, (idx + 1), data_block].pack("nnA*")
306-
if self.server_sock.sendto(req, host, port) > 0
307-
sent_data += data_block.size
308-
end
309-
res = self.server_sock.recvfrom(65535)
310-
if res
311-
code, type, msg = parse_tftp_response(res[0])
312-
if code == 4
313-
sent_blocks += 1
314-
yield "Sent #{data_block.size} bytes in block #{sent_blocks}" if block_given?
315-
else
316-
if block_given?
317-
yield "Got an unexpected response: Code:%d, Type:%d, Message:'%s'. Aborting." % [code, type, msg]
306+
loop do
307+
req = [OpData, (idx + 1), data_block].pack("nnA*")
308+
if self.server_sock.sendto(req, host, port) <= 0
309+
send_retries += 1
310+
if send_retries > 100
311+
break
312+
else
313+
next
314+
end
315+
end
316+
send_retries = 0
317+
res = self.server_sock.recvfrom(65535)
318+
if res
319+
code, type, msg = parse_tftp_response(res[0])
320+
if code == 4
321+
if type == idx + 1
322+
sent_blocks += 1
323+
sent_data += data_block.size
324+
yield "Sent #{data_block.size} bytes in block #{idx+1}" if block_given?
325+
break
326+
else
327+
next
328+
end
329+
else
330+
if block_given?
331+
yield "Got an unexpected response: Code:%d, Type:%d, Message:'%s'. Aborting." % [code, type, msg]
332+
end
333+
break
318334
end
319-
break
320335
end
321336
end
322337
end
338+
339+
if send_retries > 100
340+
yield "Too many send retries, aborted"
341+
end
342+
323343
if block_given?
324344
if(sent_data == expected_size)
325345
yield("Transferred #{sent_data} bytes in #{sent_blocks} blocks, upload complete!")
326346
else
327347
yield "Upload complete, but with errors."
328348
end
329349
end
350+
330351
if sent_data == expected_size
331352
self.status = {:success => [
332353
self.local_file,

0 commit comments

Comments
 (0)