From 1ff55c8030ed529b17b02993877ac4803e7aa449 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Mon, 2 Jul 2012 11:22:50 +0200 Subject: [PATCH 1/3] * grub-core/net/tftp.c (ack): Fix endianness problem. (tftp_receive): Likewise. Reported by: Michael Davidsaver. (cherry picked from commit a706f4cc6bddd03e67a66620101209c471177b53) --- grub-core/net/tftp.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/grub-core/net/tftp.c b/grub-core/net/tftp.c index 9c70efb..d0f39ea 100644 --- a/grub-core/net/tftp.c +++ b/grub-core/net/tftp.c @@ -143,7 +143,7 @@ ack (tftp_data_t data, grub_uint16_t block) tftph_ack = (struct tftphdr *) nb_ack.data; tftph_ack->opcode = grub_cpu_to_be16 (TFTP_ACK); - tftph_ack->u.ack.block = block; + tftph_ack->u.ack.block = grub_cpu_to_be16 (block); err = grub_net_send_udp_packet (data->sock, &nb_ack); if (err) @@ -225,7 +225,7 @@ tftp_receive (grub_net_udp_socket_t sock __attribute__ ((unused)), grub_priority_queue_pop (data->pq); if (file->device->net->packs.count < 50) - err = ack (data, tftph->u.data.block); + err = ack (data, data->block + 1); else { file->device->net->stall = 1; -- 1.8.2 From 412928c729fff75cf53914cd4acac88c5e229397 Mon Sep 17 00:00:00 2001 From: Avik Sil Date: Wed, 14 Aug 2013 20:32:42 -0300 Subject: [PATCH 2/3] * grub-core/net/tftp.c: Send tftp ack packet before closing the socket. (cherry picked from commit 369508b3cb0a84c0118ee32adef923109ad187dc) --- grub-core/net/tftp.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/grub-core/net/tftp.c b/grub-core/net/tftp.c index d0f39ea..b9d9549 100644 --- a/grub-core/net/tftp.c +++ b/grub-core/net/tftp.c @@ -243,6 +243,8 @@ tftp_receive (grub_net_udp_socket_t sock __attribute__ ((unused)), data->block++; if (size < data->block_size) { + if (data->ack_sent < data->block) + ack (data, data->block); file->device->net->eof = 1; file->device->net->stall = 1; grub_net_udp_close (data->sock); -- 1.8.2 From e944f5bb19bb7f07ca065df75979ba3067306ae1 Mon Sep 17 00:00:00 2001 From: Vladimir Serbinenko Date: Sat, 26 Oct 2013 12:48:49 +0200 Subject: [PATCH 3/3] * grub-core/net/tftp.c: Retransmit ack when rereceiving old packet. Try to handle more than 0xFFFF packets. (cherry picked from commit cf8d6bbd9eb2f5c6cbb0b6e437466c77fc7b6e9b) --- grub-core/net/tftp.c | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/grub-core/net/tftp.c b/grub-core/net/tftp.c index b9d9549..97217d2 100644 --- a/grub-core/net/tftp.c +++ b/grub-core/net/tftp.c @@ -102,7 +102,7 @@ typedef struct tftp_data grub_uint64_t file_size; grub_uint64_t block; grub_uint32_t block_size; - grub_uint32_t ack_sent; + grub_uint64_t ack_sent; int have_oack; struct grub_error_saved save_err; grub_net_udp_socket_t sock; @@ -110,6 +110,17 @@ typedef struct tftp_data } *tftp_data_t; static int +cmp_block (grub_uint16_t a, grub_uint16_t b) +{ + grub_int16_t i = (grub_int16_t) (a - b); + if (i > 0) + return +1; + if (i < 0) + return -1; + return 0; +} + +static int cmp (const void *a__, const void *b__) { struct grub_net_buff *a_ = *(struct grub_net_buff **) a__; @@ -117,15 +128,11 @@ cmp (const void *a__, const void *b__) struct tftphdr *a = (struct tftphdr *) a_->data; struct tftphdr *b = (struct tftphdr *) b_->data; /* We want the first elements to be on top. */ - if (grub_be_to_cpu16 (a->u.data.block) < grub_be_to_cpu16 (b->u.data.block)) - return +1; - if (grub_be_to_cpu16 (a->u.data.block) > grub_be_to_cpu16 (b->u.data.block)) - return -1; - return 0; + return -cmp_block (grub_be_to_cpu16 (a->u.data.block), grub_be_to_cpu16 (b->u.data.block)); } static grub_err_t -ack (tftp_data_t data, grub_uint16_t block) +ack (tftp_data_t data, grub_uint64_t block) { struct tftphdr *tftph_ack; grub_uint8_t nbdata[512]; @@ -213,12 +220,13 @@ tftp_receive (grub_net_udp_socket_t sock __attribute__ ((unused)), return GRUB_ERR_NONE; nb_top = *nb_top_p; tftph = (struct tftphdr *) nb_top->data; - if (grub_be_to_cpu16 (tftph->u.data.block) >= data->block + 1) + if (cmp_block (grub_be_to_cpu16 (tftph->u.data.block), data->block + 1) >= 0) break; + ack (data, grub_be_to_cpu16 (tftph->u.data.block)); grub_netbuff_free (nb_top); grub_priority_queue_pop (data->pq); } - if (grub_be_to_cpu16 (tftph->u.data.block) == data->block + 1) + while (cmp_block (grub_be_to_cpu16 (tftph->u.data.block), data->block + 1) == 0) { unsigned size; -- 1.8.2