summaryrefslogtreecommitdiff
path: root/ftp/atftp/files/patch-tftpd_file.c
diff options
context:
space:
mode:
Diffstat (limited to 'ftp/atftp/files/patch-tftpd_file.c')
-rw-r--r--ftp/atftp/files/patch-tftpd_file.c386
1 files changed, 0 insertions, 386 deletions
diff --git a/ftp/atftp/files/patch-tftpd_file.c b/ftp/atftp/files/patch-tftpd_file.c
deleted file mode 100644
index 7f81c6935a4c..000000000000
--- a/ftp/atftp/files/patch-tftpd_file.c
+++ /dev/null
@@ -1,386 +0,0 @@
---- tftpd_file.c.orig 2004-02-18 10:21:47.000000000 +0800
-+++ tftpd_file.c 2010-10-11 13:22:54.000000000 +0800
-@@ -89,6 +89,28 @@
- return OK;
- }
-
-+int opt_same_file(struct tftp_opt *opt1, struct tftp_opt *opt2)
-+{
-+ if ((strncmp(opt1->option, "filename", OPT_SIZE) == 0) &&
-+ (strncmp(opt2->option, "filename", OPT_SIZE) == 0))
-+ {
-+ char tofilename[MAXLEN];
-+ char fromfilename[MAXLEN];
-+ struct stat tostat;
-+ struct stat fromstat;
-+
-+ Strncpy(tofilename, opt1->value, MAXLEN);
-+ tftpd_rules_check(tofilename);
-+ Strncpy(fromfilename, opt2->value, MAXLEN);
-+ tftpd_rules_check(fromfilename);
-+ if (stat(tofilename, &tostat) || stat(fromfilename, &fromstat))
-+ return 0;
-+
-+ return (tostat.st_ino == fromstat.st_ino);
-+ }
-+ return 0;
-+}
-+
- /*
- * Receive a file. It is implemented as a state machine using a while loop
- * and a switch statement. Function flow is as follow:
-@@ -117,7 +139,6 @@
- char filename[MAXLEN];
- char string[MAXLEN];
- int timeout = data->timeout;
-- int number_of_timeout = 0;
- int all_blocks_received = 0; /* temporary kludge */
- int convert = 0; /* if true, do netascii convertion */
-
-@@ -240,9 +261,13 @@
- break;
- case S_SEND_ACK:
- timeout_state = state;
-- tftp_send_ack(sockfd, sa, block_number);
-- if (data->trace)
-- logger(LOG_DEBUG, "sent ACK <block: %d>", block_number);
-+ result = tftp_send_ack(sockfd, sa, block_number);
-+ if (result == OK)
-+ {
-+ if (data->trace)
-+ logger(LOG_DEBUG, "sent ACK <block: %d>",
-+ block_number);
-+ }
- if (all_blocks_received)
- state = S_END;
- else
-@@ -265,8 +290,8 @@
- switch (result)
- {
- case GET_TIMEOUT:
-- number_of_timeout++;
-- if (number_of_timeout > NB_OF_RETRY)
-+ data->client_info->number_of_timeout++;
-+ if (data->client_info->number_of_timeout > NB_OF_RETRY)
- {
- logger(LOG_INFO, "client (%s) not responding",
- inet_ntoa(data->client_info->client.sin_addr));
-@@ -322,7 +347,7 @@
- else
- logger(LOG_WARNING, "source port mismatch, check bypassed");
- }
-- number_of_timeout = 0;
-+ data->client_info->number_of_timeout = 0;
- state = S_DATA_RECEIVED;
- break;
- case GET_DISCARD:
-@@ -413,13 +438,13 @@
- char filename[MAXLEN];
- char string[MAXLEN];
- int timeout = data->timeout;
-- int number_of_timeout = 0;
- int mcast_switch = data->mcast_switch_client;
- struct stat file_stat;
- int convert = 0; /* if true, do netascii conversion */
- struct thread_data *thread = NULL; /* used when looking for a multicast
- thread */
- int multicast = 0; /* set to 1 if multicast */
-+ time_t last_send_time = -1;
-
- struct client_info *client_info = data->client_info;
- struct client_info *client_old = NULL;
-@@ -428,6 +453,8 @@
- int prev_block_number = 0; /* needed to support netascii convertion */
- int prev_file_pos = 0;
- int temp = 0;
-+ int total_bytes_sent = 0;
-+ int clients_served = 0;
-
- /* look for mode option */
- if (strcasecmp(data->tftp_options[OPT_MODE].value, "netascii") == 0)
-@@ -535,6 +562,34 @@
- return ERR;
- }
-
-+ /* make sure that the oack packet will fit in the buffer */
-+ int oacklen = 2;
-+ int i;
-+ for (i = 2; i < OPT_NUMBER; i++)
-+ {
-+ if (data->tftp_options[i].enabled &&
-+ data->tftp_options[i].specified)
-+ {
-+ oacklen += strlen(data->tftp_options[i].option);
-+ oacklen++;
-+ oacklen += strlen(data->tftp_options[i].value);
-+ oacklen++;
-+ }
-+ }
-+
-+ if (oacklen > result)
-+ {
-+ logger(LOG_NOTICE, "OACK will not fit in buffer of size %d.",
-+ " Options rejected.", result);
-+ tftp_send_error(sockfd, sa, EOPTNEG, data->data_buffer,
-+ data->data_buffer_size);
-+ if (data->trace)
-+ logger(LOG_DEBUG, "sent ERROR <code: %d, msg: %s>",
-+ EOPTNEG, tftp_errmsg[EOPTNEG]);
-+ fclose(fp);
-+ return ERR;
-+ }
-+
- data->data_buffer_size = result + 4;
- data->data_buffer = realloc(data->data_buffer, data->data_buffer_size);
-
-@@ -559,11 +614,16 @@
- logger(LOG_INFO, "blksize option -> %d", result);
- }
-
-+ /* multicast option */
-+ if (data->tftp_options[OPT_MULTICAST].specified &&
-+ data->tftp_options[OPT_MULTICAST].enabled && !convert)
-+ {
- /* Verify that the file can be sent in 2^16 block of BLKSIZE octets */
- if ((file_stat.st_size / (data->data_buffer_size - 4)) > 65535)
- {
- tftp_send_error(sockfd, sa, EUNDEF, data->data_buffer, data->data_buffer_size);
-- logger(LOG_NOTICE, "Requested file to big, increase BLKSIZE");
-+ logger(LOG_NOTICE, "Requested file too big, increase BLKSIZE, ",
-+ "cannot rollover in multicast transfer");
- if (data->trace)
- logger(LOG_DEBUG, "sent ERROR <code: %d, msg: %s>", EUNDEF,
- tftp_errmsg[EUNDEF]);
-@@ -571,10 +631,6 @@
- return ERR;
- }
-
-- /* multicast option */
-- if (data->tftp_options[OPT_MULTICAST].specified &&
-- data->tftp_options[OPT_MULTICAST].enabled && !convert)
-- {
- /*
- * Find a server with the same options to give up the client.
- */
-@@ -649,10 +705,16 @@
- /* initialise multicast address structure */
- data->mcastaddr.imr_multiaddr.s_addr =
- data->sa_mcast.sin_addr.s_addr;
-- data->mcastaddr.imr_interface.s_addr = htonl(INADDR_ANY);
-+
- setsockopt(data->sockfd, IPPROTO_IP, IP_MULTICAST_TTL,
- &data->mcast_ttl, sizeof(data->mcast_ttl));
-
-+ logger(LOG_DEBUG, "Multicast interface = %s",
-+ inet_ntoa(data->mcastaddr.imr_interface));
-+ setsockopt(data->sockfd, IPPROTO_IP, IP_MULTICAST_IF,
-+ &(data->mcastaddr.imr_interface.s_addr),
-+ sizeof(data->mcastaddr.imr_interface.s_addr));
-+
- /* set options data for OACK */
- opt_set_multicast(data->tftp_options, data->mc_addr,
- data->mc_port, 1);
-@@ -661,7 +723,7 @@
-
- /* the socket must be unconnected for multicast */
- sa->sin_family = AF_UNSPEC;
-- connect(sockfd, (struct sockaddr *)sa, sizeof(sa));
-+ connect(sockfd, (struct sockaddr *)sa, sizeof(*sa));
-
- /* set multicast flag */
- multicast = 1;
-@@ -669,6 +731,11 @@
- tftpd_clientlist_ready(data);
- }
- }
-+ if ((file_stat.st_size / (data->data_buffer_size - 4)) > 65535)
-+ {
-+ logger(LOG_NOTICE, "Requested file bigger than tftp is designed to ",
-+ "handle, attempting rollover, but not officially in a tftp spec");
-+ }
-
- /* copy options to local structure, used when falling back a client to slave */
- memcpy(options, data->tftp_options, sizeof(options));
-@@ -706,10 +773,14 @@
- case S_SEND_OACK:
- timeout_state = state;
- opt_options_to_string(data->tftp_options, string, MAXLEN);
-- if (data->trace)
-- logger(LOG_DEBUG, "sent OACK <%s>", string);
-- tftp_send_oack(sockfd, sa, data->tftp_options,
-- data->data_buffer, data->data_buffer_size);
-+ result = tftp_send_oack(sockfd, sa, data->tftp_options,
-+ data->data_buffer,
-+ data->data_buffer_size);
-+ if (result == OK)
-+ {
-+ if (data->trace)
-+ logger(LOG_DEBUG, "sent OACK <%s>", string);
-+ }
- state = S_WAIT_PACKET;
- break;
- case S_SEND_DATA:
-@@ -725,18 +796,24 @@
-
- if (multicast)
- {
-- tftp_send_data(sockfd, &data->sa_mcast,
-- block_number + 1, data_size,
-- data->data_buffer);
-+ result = tftp_send_data(sockfd, &data->sa_mcast,
-+ block_number + 1, data_size,
-+ data->data_buffer);
-+ client_info->bytes_sent += data_size-4;
- }
- else
- {
-- tftp_send_data(sockfd, sa, block_number + 1,
-- data_size, data->data_buffer);
-+ result = tftp_send_data(sockfd, sa, block_number + 1,
-+ data_size, data->data_buffer);
- }
-- if (data->trace)
-- logger(LOG_DEBUG, "sent DATA <block: %d, size %d>",
-- block_number + 1, data_size - 4);
-+
-+ if (result == OK)
-+ {
-+ if (data->trace)
-+ logger(LOG_DEBUG, "sent DATA <block: %d, size %d>",
-+ block_number + 1, data_size - 4);
-+ }
-+ time(&last_send_time);
- state = S_WAIT_PACKET;
- break;
- case S_WAIT_PACKET:
-@@ -746,12 +823,14 @@
- switch (result)
- {
- case GET_TIMEOUT:
-- number_of_timeout++;
-+ client_info->number_of_timeout++;
-
-- if (number_of_timeout > NB_OF_RETRY)
-+ if (client_info->number_of_timeout > NB_OF_RETRY)
- {
-- logger(LOG_INFO, "client (%s) not responding",
-- inet_ntoa(client_info->client.sin_addr));
-+ logger(LOG_INFO, "client (%s) not responding.",
-+ " state=%d block_number=%d",
-+ inet_ntoa(client_info->client.sin_addr),
-+ timeout_state,block_number);
- state = S_END;
- }
- else
-@@ -779,7 +858,8 @@
- /* Proceed normally with the next client,
- going to OACK state */
- logger(LOG_INFO,
-- "Serving next client: %s:%d",
-+ "Serving next client after timeout: state=%d, block_number=%d: %s:%d",
-+ timeout_state,block_number,
- inet_ntoa(client_info->client.sin_addr),
- ntohs(client_info->client.sin_port));
- sa = &client_info->client;
-@@ -796,7 +876,9 @@
- break;
- }
- }
-- logger(LOG_WARNING, "timeout: retrying...");
-+ logger(LOG_WARNING, "timeout: retrying... state=%d,",
-+ " block_number=%d", timeout_state,
-+ block_number);
- state = timeout_state;
- }
- break;
-@@ -811,7 +893,13 @@
- * If this is an ACK for the last block, mark this client as
- * done
- */
-- if ((last_block != -1) && (block_number > last_block))
-+ logger(LOG_DEBUG,
-+ "received ACK <block: %d> from wrong client: %s:%d",
-+ ntohs(tftphdr->th_block),
-+ inet_ntoa(from.sin_addr),
-+ ntohs(from.sin_port));
-+
-+ if ((last_block != -1) && (ntohs(tftphdr->th_block) > last_block))
- {
- if (tftpd_clientlist_done(data, NULL, &from) == 1)
- logger(LOG_DEBUG, "client done <%s>",
-@@ -851,8 +939,33 @@
- }
- }
- /* The ACK is from the current client */
-- number_of_timeout = 0;
-- block_number = ntohs(tftphdr->th_block);
-+ client_info->number_of_timeout = 0;
-+ int ACK_block_number = ntohs(tftphdr->th_block);
-+ if (ACK_block_number == client_info->last_ack)
-+ {
-+ /* duplicate ACK, ignore */
-+ time_t now;
-+ time(&now);
-+ /* if a timeout has occurred, resend last block */
-+ if ((now-last_send_time) > timeout)
-+ {
-+ state = S_SEND_DATA;
-+ logger(LOG_DEBUG, "Duplicate ACK packet discarded <%d>, timeout. Resend last block.", ACK_block_number);
-+ }
-+ else
-+ {
-+ logger(LOG_DEBUG, "Duplicate ACK packet discarded <%d>.", ACK_block_number);
-+ }
-+ break;
-+ }
-+
-+ client_info->last_ack = ACK_block_number;
-+
-+ if (block_number < 65534)
-+ block_number = ACK_block_number;
-+ else
-+ block_number++;
-+
- if (data->trace)
- logger(LOG_DEBUG, "received ACK <block: %d>",
- block_number);
-@@ -932,10 +1045,16 @@
- }
- break;
- case S_END:
-+ total_bytes_sent += client_info->bytes_sent;
- if (multicast)
- {
- logger(LOG_DEBUG, "End of multicast transfer");
-+ logger(LOG_INFO,
-+ "Bytes sent while this client was master: %d",
-+ client_info->bytes_sent);
-+
- /* mark the current client done */
-+ clients_served++;
- tftpd_clientlist_done(data, client_info, NULL);
- /* Look if there is another client to serve. We lock list of
- client to make sure no other thread try to add clients in
-@@ -948,13 +1067,20 @@
- ntohs(client_info->client.sin_port));
- /* client is a new client structure */
- sa = &client_info->client;
-- /* nedd to send an oack to that client */
-+ /* send an oack to that client */
- state = S_SEND_OACK;
- fseek(fp, 0, SEEK_SET);
- }
- else
- {
-- logger(LOG_INFO, "No more client, end of tranfers");
-+ int fs = file_stat.st_size;
-+ int blksze = (data->data_buffer_size - 4);
-+ int ttlblks = fs / blksze;
-+ int blksretry = (total_bytes_sent-file_stat.st_size) / blksze;
-+ logger(LOG_INFO, "No more client, end of tranfers. %d clients served", clients_served);
-+ logger(LOG_INFO, "Bytes saved over unicast: %ld", (clients_served*file_stat.st_size) - total_bytes_sent);
-+ logger(LOG_INFO, "File size: %d, total data bytes sent %d", file_stat.st_size, total_bytes_sent);
-+ logger(LOG_INFO, "Block re-sent: %d of %d = %f percent", blksretry, ttlblks, ((float)blksretry/(float)ttlblks) * 100);
- fclose(fp);
- return OK;
- }