Tweak recently altered TFTP code.

This commit is contained in:
Simon Kelley
2025-08-21 16:19:58 +01:00
parent 06e2d479c9
commit 9a566c0913
2 changed files with 18 additions and 15 deletions

View File

@@ -1117,8 +1117,9 @@ struct tftp_file {
struct tftp_transfer {
int sockfd;
u16 block_hi, ackprev;
time_t retransmit, start;
unsigned int lastack, block, ackblock, blocksize, windowsize, timeout, expansion;
unsigned int lastack, block, blocksize, windowsize, timeout, expansion;
off_t offset;
union mysockaddr peer;
union all_addr source;

View File

@@ -326,7 +326,8 @@ static void tftp_request(struct listener *listen, time_t now)
transfer->start = now;
transfer->backoff = 1;
transfer->block = 1;
transfer->ackblock = 0;
transfer->ackprev = 0;
transfer->block_hi = 0;
transfer->blocksize = 512;
transfer->windowsize = 1;
@@ -757,37 +758,38 @@ static void handle_tftp(time_t now, struct tftp_transfer *transfer, ssize_t len)
{
/* Handle 16-bit block number wrap-around. */
u16 new = ntohs(mess->block);
u16 prev = transfer->ackblock;
transfer->ackblock = new | (transfer->ackblock & 0xffff0000);
u32 block;
/* If the last ack received was in the top quarter of a 64k block
and this one is in the bottom quarter, assume it has wrapped.
Since this is UDP and an old packet can in theory wander in we may also
need to drop back to a previous segment. Such an ACK is ignored below;
here we're just getting the most likely 32 bit value from the
16 bits that we have. */
if (new <= 0x4000 && prev >= 0xc000)
transfer->ackblock += 0x10000;
else if (new >= 0xc000 && prev <= 0x4000 && transfer->ackblock != 0)
transfer->ackblock -= 0x10000;
if (new <= 0x4000 && transfer->ackprev >= 0xc000)
transfer->block_hi++;
else if (new >= 0xc000 && transfer->ackprev <= 0x4000 && transfer->block_hi != 0)
transfer->block_hi--;
transfer->ackprev = new;
block = (((u32)transfer->block_hi) << 16) + (u32)new;
/* Ignore duplicate ACKs and ACKs for blocks we've not yet sent. */
if (transfer->ackblock >= transfer->lastack &&
transfer->ackblock <= transfer->block)
if (block >= transfer->lastack &&
block <= transfer->block)
{
/* Got ack, move forward and ensure we take the (re)transmit path */
transfer->retransmit = transfer->start = now;
transfer->backoff = 0;
transfer->lastack = transfer->ackblock + 1;
transfer->lastack = block + 1;
/* We have no easy function from block no. to file offset when
expanding line breaks in netascii mode, so we update the offset here
as each block is acknowledged. This explains why the window size must be
one for a netascii transfer; to avoid the block no. doing anything
other than incrementing by one. */
if (transfer->netascii && transfer->ackblock != 0)
if (transfer->netascii && block != 0)
transfer->offset += transfer->blocksize - transfer->expansion;
}
}