cURL / Mailing Lists / curl-library / Single Mail

curl-library

BUG in TFTP upload, patch included

From: Carsten Lange <carsten.lange_at_aastra.com>
Date: Wed, 12 Aug 2009 08:12:23 +0200

I am using libcurl to upload files to a TFTP server.
I noticed that this is not working anymore since I am using version
7.19.5, the latest snapshot curl-7.19.6-20090811 shows the same problem:

The problem can be reproduced with the following command:

./curl -T file tftp://host/file
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
0 5828 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0
0 5828 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0
curl: (71) invalid tsize value in OACK packet

The tftp server that I use is tftp-hpa 0.42 runing on a CentOS 5.3.

I looked into the packets that curl sends and receives:

The write request holds the following options:
tsize=0
blksize=512
interval=6

The server answers with an option acknowledgement packet with the
following
Options:
tsize=0
blksize=512

What does the RFC says about the tsize option:

RFC2349 - TFTP Timeout Interval and Transfer Size Options says about
write requests that the server will echo back the tsize value that the
client has send, what else could he do?

... snip
In Write Request packets, the size of the file, in octets, is specified
in the request and echoed back in the OACK. If the file is too large for
the server to handle, it may abort the transfer with an Error packet
(error code 3).
... snap

So the server behaviour is correct.

I than looked into the code lib/tftp.c and found that the tsize option
is hardcoded in the write request to 0.
When parsing the option acknoledgement packet from the server libcurl
checks that the value is not 0, otherwise an error is reported and
libcurl returns with CURLE_TFTP_ILLEGAL.

I changed the code so that write request will use the filesize of the
file to transfer, read requests still use tsize=0.

I am attaching my changes as a patch to version
$Id: tftp.c,v 1.92 2009-07-24 22:20:22 gknauf Exp $ of lib/tftp.c which
is the latest version at the time of this writing.

Please look into it before applying it to the sources because I am not
familiar with curl/libcurl internals.

 Carsten

########################################################################
#######

diff -urN curl-7.19.6-20090811/lib/tftp.c
curl-7.19.6-20090811-tftp-write-fix/lib/tftp.c
--- curl-7.19.6-20090811/lib/tftp.c 2009-07-25 04:00:06.000000000
+0200
+++ curl-7.19.6-20090811-tftp-write-fix/lib/tftp.c 2009-08-11
17:38:43.000000000 +0200
@@ -443,7 +443,7 @@
   size_t sbytes;
   const char *mode = "octet";
   char *filename;
- char buf[8];
+ char buf[64];
   struct SessionHandle *data = state->conn->data;
   CURLcode res = CURLE_OK;
 
@@ -489,11 +489,17 @@
     sbytes = 4 + strlen(filename) + strlen(mode);
 
     /* add tsize option */
+ if(data->set.upload && (data->set.infilesize != -1)) {
+ snprintf( buf, sizeof(buf), "%d", data->set.infilesize );
+ } else {
+ snprintf( buf, sizeof(buf), "%d", 0 );
+ }
     sbytes += tftp_option_add(state, sbytes,
                               (char *)state->spacket.data+sbytes,
                               TFTP_OPTION_TSIZE);
     sbytes += tftp_option_add(state, sbytes,
- (char *)state->spacket.data+sbytes, "0");
+ (char *)state->spacket.data+sbytes, buf);
+
     /* add blksize option */
     snprintf( buf, sizeof(buf), "%d", state->requested_blksize );
     sbytes += tftp_option_add(state, sbytes,

########################################################################
#######
Received on 2009-08-12