2013-11-15 12:54:26 +01:00
|
|
|
Index: tftpd_file.c
|
2013-02-14 11:50:57 +01:00
|
|
|
===================================================================
|
2013-11-15 12:54:26 +01:00
|
|
|
--- tftpd_file.c.orig
|
|
|
|
+++ tftpd_file.c
|
2019-04-26 11:54:01 +02:00
|
|
|
@@ -406,7 +406,6 @@ int tftpd_send_file(struct thread_data *
|
2013-02-14 11:50:57 +01:00
|
|
|
int timeout_state = state;
|
|
|
|
int result;
|
|
|
|
long block_number = 0;
|
|
|
|
- long last_requested_block = -1;
|
|
|
|
long last_block = -1;
|
|
|
|
int data_size;
|
2019-04-26 11:54:01 +02:00
|
|
|
struct sockaddr_storage *sa = &data->client_info->client;
|
|
|
|
@@ -434,6 +433,11 @@ int tftpd_send_file(struct thread_data *
|
2013-02-14 11:50:57 +01:00
|
|
|
long prev_file_pos = 0;
|
|
|
|
int temp = 0;
|
|
|
|
|
|
|
|
+ long prev_sent_block = -1;
|
|
|
|
+ int prev_sent_count = 0;
|
|
|
|
+ int prev_ack_count = 0;
|
|
|
|
+ int curr_sent_count = 0;
|
|
|
|
+
|
|
|
|
/* look for mode option */
|
|
|
|
if (strcasecmp(data->tftp_options[OPT_MODE].value, "netascii") == 0)
|
|
|
|
{
|
2019-04-26 11:54:01 +02:00
|
|
|
@@ -819,8 +823,8 @@ int tftpd_send_file(struct thread_data *
|
|
|
|
&client_info->client));
|
2013-02-14 11:50:57 +01:00
|
|
|
sa = &client_info->client;
|
|
|
|
|
|
|
|
- /* rewind the last_requested_block counter */
|
|
|
|
- last_requested_block = -1;
|
|
|
|
+ /* rewind the prev_sent_block counter */
|
|
|
|
+ prev_sent_block = -1;
|
|
|
|
|
|
|
|
state = S_SEND_OACK;
|
|
|
|
break;
|
2019-04-26 11:54:01 +02:00
|
|
|
@@ -895,6 +899,7 @@ int tftpd_send_file(struct thread_data *
|
2013-02-14 11:50:57 +01:00
|
|
|
"source port mismatch, check bypassed");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
+
|
|
|
|
/* The ACK is from the current client */
|
|
|
|
number_of_timeout = 0;
|
2019-04-26 11:54:01 +02:00
|
|
|
if (multicast)
|
|
|
|
@@ -908,24 +913,82 @@ int tftpd_send_file(struct thread_data *
|
|
|
|
logger(LOG_DEBUG, "received ACK <block: %ld>",
|
|
|
|
block_number);
|
2013-02-14 11:50:57 +01:00
|
|
|
|
2019-04-26 11:54:01 +02:00
|
|
|
- /* if turned on, check whether the block request isn't already fulfilled */
|
2013-02-14 11:50:57 +01:00
|
|
|
- if (tftpd_prevent_sas) {
|
2019-04-26 11:54:01 +02:00
|
|
|
- /* multicast, block numbers could contain gaps */
|
|
|
|
- if (multicast) {
|
|
|
|
- if (last_requested_block >= block_number) {
|
2013-02-14 11:50:57 +01:00
|
|
|
+ /* Now check the ACK number and possibly ignore the request */
|
|
|
|
+
|
|
|
|
+ /* multicast, block numbers could contain gaps */
|
|
|
|
+ if (multicast) {
|
2019-04-26 11:54:01 +02:00
|
|
|
+ /* if turned on, check whether the block request isn't already fulfilled */
|
|
|
|
+ if (tftpd_prevent_sas) {
|
|
|
|
+ if (prev_sent_block >= block_number) {
|
|
|
|
if (data->trace)
|
|
|
|
- logger(LOG_DEBUG, "received duplicated ACK <block: %d >= %d>", last_requested_block, block_number);
|
|
|
|
+ logger(LOG_DEBUG, "received duplicated ACK <block: %d >= %d>", prev_sent_block, block_number);
|
|
|
|
break;
|
|
|
|
} else
|
|
|
|
- last_requested_block = block_number;
|
|
|
|
- /* unicast, blocks should be requested one after another */
|
|
|
|
- } else {
|
|
|
|
- if (last_requested_block + 1 != block_number && last_requested_block != -1) {
|
|
|
|
+ prev_sent_block = block_number;
|
|
|
|
+ }
|
|
|
|
+ /* don't prevent thes SAS */
|
|
|
|
+ /* use a heuristic suggested by Vladimir Nadvornik */
|
|
|
|
+ else {
|
|
|
|
+ /* here comes the ACK again */
|
|
|
|
+ if (prev_sent_block == block_number) {
|
|
|
|
+ /* drop if number of ACKs == times of previous block sending */
|
|
|
|
+ if (++prev_ack_count == prev_sent_count) {
|
|
|
|
+ logger(LOG_DEBUG, "ACK count (%d) == previous block transmission count -> dropping ACK", prev_ack_count);
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+ /* else resend the block */
|
|
|
|
+ logger(LOG_DEBUG, "resending block %d", block_number + 1);
|
|
|
|
+ }
|
|
|
|
+ /* received ACK to sent block -> move on to next block */
|
|
|
|
+ else if (prev_sent_block < block_number) {
|
|
|
|
+ prev_sent_block = block_number;
|
|
|
|
+ prev_sent_count = curr_sent_count;
|
|
|
|
+ curr_sent_count = 0;
|
|
|
|
+ prev_ack_count = 1;
|
|
|
|
+ }
|
|
|
|
+ /* block with low number -> ignore it completely */
|
|
|
|
+ else {
|
|
|
|
+ logger(LOG_DEBUG, "ignoring ACK %d", block_number);
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ /* unicast, blocks should be requested one after another */
|
|
|
|
+ } else {
|
|
|
|
+ /* if turned on, check whether the block request isn't already fulfilled */
|
|
|
|
+ if (tftpd_prevent_sas) {
|
|
|
|
+ if (prev_sent_block + 1 != block_number) {
|
|
|
|
+ logger(LOG_WARNING, "timeout: retrying...");
|
|
|
|
if (data->trace)
|
|
|
|
- logger(LOG_DEBUG, "received out of order ACK <block: %d != %d>", last_requested_block + 1, block_number);
|
|
|
|
+ logger(LOG_DEBUG, "received out of order ACK <block: %d != %d>", prev_sent_block + 1, block_number);
|
|
|
|
break;
|
|
|
|
- } else
|
|
|
|
- last_requested_block = block_number;
|
|
|
|
+ } else {
|
|
|
|
+ prev_sent_block = block_number;
|
|
|
|
+ }
|
|
|
|
+ /* don't prevent thes SAS */
|
|
|
|
+ /* use a heuristic suggested by Vladimir Nadvornik */
|
|
|
|
+ } else {
|
|
|
|
+ /* here comes the ACK again */
|
|
|
|
+ if (prev_sent_block == block_number) {
|
|
|
|
+ /* drop if number of ACKs == times of previous block sending */
|
|
|
|
+ if (++prev_ack_count == prev_sent_count) {
|
|
|
|
+ logger(LOG_DEBUG, "ACK count (%d) == previous block transmission count -> dropping ACK", prev_ack_count);
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+ /* else resend the block */
|
|
|
|
+ logger(LOG_DEBUG, "resending block %d", block_number + 1);
|
|
|
|
+ }
|
|
|
|
+ /* received ACK to sent block -> move on to next block */
|
|
|
|
+ else if (prev_sent_block < block_number) {
|
|
|
|
+ prev_sent_block = block_number;
|
|
|
|
+ prev_sent_count = curr_sent_count;
|
|
|
|
+ curr_sent_count = 0;
|
|
|
|
+ prev_ack_count = 1;
|
|
|
|
+ }
|
|
|
|
+ /* nor previous nor current block number -> ignore it completely */
|
|
|
|
+ else {
|
|
|
|
+ logger(LOG_DEBUG, "ignoring ACK %d", block_number);
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
}
|
2013-02-14 11:50:57 +01:00
|
|
|
}
|
|
|
|
|
2019-04-26 11:54:01 +02:00
|
|
|
@@ -934,6 +997,8 @@ int tftpd_send_file(struct thread_data *
|
2013-02-14 11:50:57 +01:00
|
|
|
state = S_END;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
+
|
|
|
|
+ curr_sent_count++;
|
|
|
|
state = S_SEND_DATA;
|
|
|
|
break;
|
|
|
|
case GET_ERROR:
|
2019-04-26 11:54:01 +02:00
|
|
|
@@ -1028,7 +1093,7 @@ int tftpd_send_file(struct thread_data *
|
2013-02-14 11:50:57 +01:00
|
|
|
state = S_SEND_OACK;
|
|
|
|
fseek(fp, 0, SEEK_SET);
|
|
|
|
/* reset the last block received counter */
|
|
|
|
- last_requested_block = -1;
|
|
|
|
+ prev_sent_block = -1;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|