+2013-10-26 Vladimir Serbinenko <phcoder@gmail.com>
+
+ * grub-core/net/tftp.c: Retransmit ack when rereceiving old packet.
+ Try to handle more than 0xFFFF packets.
+ Reported by: Bernhard Übelacker <bernhardu>.
+ He also spotted few overflows in first version of this patch.
+
2013-10-26 Vladimir Serbinenko <phcoder@gmail.com>
* tests/date_unit_test.c: New test.
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;
grub_priority_queue_t pq;
} *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 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];
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;