In the old TFTP server, there was an undocumented behavior where

the block counter would rollover to 0 if a file larger
than 65535 blocks was transferred.  With the default block size
of 512 octets per block, this is a file size of approximately 32 megabytes.

The new TFTP server code would report an error and stop transferring
the file if a file was larger than 65535 blocks.

This patch restores the old TFTP server's behavior to the new
TFTP server code.  If a TFTP client transfers a file larger
than 65535 blocks, and does *not* specify the "rollover" option,
then automatically rollover the block counter to 0 every time
we reach 65535 blocks.

This restores interoperability with the FreeBSD 6 TFTP client.
Without this change, if a FreeBSD 6 TFTP client tried to
retrieve a file larger than 65535 blocks from a FreeBSD 9 TFTP server
, the transfer would fail.
The same file could be retrieved successfully if the same FreeBSD 6
TFTP client was used against a FreeBSD 6 TFTP server.

Approved by:  re (kib)
Tested by: Pawan Gupta <pawang at juniper dot net>,
Obtained from:  Juniper Networks
This commit is contained in:
Craig Rodrigues 2011-07-31 03:12:20 +00:00
parent cfc3f46787
commit 38bd7db313

View File

@ -129,14 +129,16 @@ tftp_send(int peer, uint16_t *block, struct tftp_stats *ts)
(*block)++;
if (oldblock > *block) {
if (options[OPT_ROLLOVER].o_request == NULL) {
tftp_log(LOG_ERR,
"Block rollover but not allowed.");
send_error(peer, EBADOP);
gettimeofday(&(ts->tstop), NULL);
return;
/*
* "rollover" option not specified in
* tftp client. Default to rolling block
* counter to 0.
*/
*block = 0;
} else {
*block = atoi(options[OPT_ROLLOVER].o_request);
}
*block = atoi(options[OPT_ROLLOVER].o_request);
ts->rollovers++;
}
gettimeofday(&(ts->tstop), NULL);
@ -196,14 +198,16 @@ tftp_receive(int peer, uint16_t *block, struct tftp_stats *ts,
(*block)++;
if (oldblock > *block) {
if (options[OPT_ROLLOVER].o_request == NULL) {
tftp_log(LOG_ERR,
"Block rollover but not allowed.");
send_error(peer, EBADOP);
gettimeofday(&(ts->tstop), NULL);
return;
/*
* "rollover" option not specified in
* tftp client. Default to rolling block
* counter to 0.
*/
*block = 0;
} else {
*block = atoi(options[OPT_ROLLOVER].o_request);
}
*block = atoi(options[OPT_ROLLOVER].o_request);
ts->rollovers++;
}