ftpget triggering TCP RST at end of download

Stephen Warren swarren at wwwdotorg.org
Sat Sep 24 04:01:45 UTC 2005


I have discovered a difference between busybox's ftpget and other FTP 
clients, such as wget and /usr/bin/ftp, in their implementation of FTP 
"get".

Most clients seem to do this:

1) Send RETR command
2) Open data connection
3) Read from data connection until EOF, saving data
4) Close data connection
5) Read status response from command conenction

However, busybox's ftpget (1.00 by testing, latest subversion by code 
reading) seem to do this:

1) Send SIZE command to determine how much to downoad
2) Send RETR command
3) Open data connection
4) Read from data connection exactly $SIZE bytes, saving data
5) Close data connection; note EOF won't be seen
6) Read status response from command conenction

The problem is that sometimes the kernel seems to send a TCP RST packet 
when ftpget calls close(). I believe this is something to do with the 
kernel thinking that ftpget hasn't read all the data from the socket, 
and is thus sending an error message to the server that all data was not 
reliably delivered.

This causes the FTP server (MS IIS 5.0 at least) to send back an error 
status message, and ftpget hence exits with a non-zero status.

If I modify ftpget to use bb_copyfd_eof instead of bb_copyfd_size, then 
everything works just fine (because the last thing ftpget does is read 
from the socket, which returns zero indicating EOF, satisfying the 
kernel that all data has been read)

Now, I know the server is sending exactly the number of bytes SIZE 
returns, since if I insert an extra read call after bb_copyfd_size, then 
no data is ever returned; zero is returned by read, indicating EOF. This 
change also causes the TCP RST to never get sent.

So, my question is - is this an application issue; is one supposed to 
always read until EOF is returned, or is reading the actual exact 
number of bytes sent enough?

Without this fix (bb_copyfd_eof), then ftpget fails from 10-50% of the time.

In the packet traces I took with tcpdump (1 OK, 1 failure), I note that 
in the failure case, all packets were delivered to the ftpget machine in 
order without retries (at least the last few packets). However, in the 
OK case, the last but one packet was dropped, the last packet got 
through, and then the last but one packet was then resent and got 
through. Is this triggering the kernel to know earlier than usual that 
the socket was closed, and the exact byte count, hence causing things to 
work where the otherwise wouldn't?

We're running stock kernel.org kernel 2.6.10, with a few non-networking 
patches built for x86 (athlon optimizations) and running on what is 
practically a standard PC.

-- 
Stephen Warren, Software Engineer, NVIDIA, Fort Collins, CO
swarren at wwwdotorg.org     http://www.wwwdotorg.org/pgp.html
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 251 bytes
Desc: OpenPGP digital signature
Url : http://lists.busybox.net/pipermail/busybox/attachments/20050923/96d9b201/attachment.pgp 


More information about the busybox mailing list