forked from pool/atftp
Accepting request 155400 from home:vitezslav_cizek:branches:network
- create capabilites provided by both tftp and atftp (bnc#801481 or bnc#725378) - change ownership of /srv/tftpboot, because atftpd running as tftp:tftp can't write to that directory - create pid directory on service start - manpage changes: * substitute /tftpboot with /srv/tftpboot * default user is now tftp:tftp * added patches: atftp-0.7-default_user_man.patch atftp-0.7-default_dir_man.patch - use Vladimir Nadvornik's heuristic for packet retransmission by default (see bnc#774376) The RFC1350 compliant behaviour stays optional. (added atftp-0.7-ack_heuristic.patch) - merged the two sorcerer's apprentice syndrome patches to one (removed atftp-0.7-prevent-sas.patch) OBS-URL: https://build.opensuse.org/request/show/155400 OBS-URL: https://build.opensuse.org/package/show/network/atftp?expand=0&rev=18
This commit is contained in:
parent
f048de6c7b
commit
967cd543e5
163
atftp-0.7-ack_heuristic.patch
Normal file
163
atftp-0.7-ack_heuristic.patch
Normal file
@ -0,0 +1,163 @@
|
|||||||
|
Index: atftp-0.7/tftpd_file.c
|
||||||
|
===================================================================
|
||||||
|
--- atftp-0.7.orig/tftpd_file.c 2013-02-06 16:15:50.178332917 +0100
|
||||||
|
+++ atftp-0.7/tftpd_file.c 2013-02-06 16:16:49.608140471 +0100
|
||||||
|
@@ -402,7 +402,6 @@ int tftpd_send_file(struct thread_data *
|
||||||
|
int timeout_state = state;
|
||||||
|
int result;
|
||||||
|
long block_number = 0;
|
||||||
|
- long last_requested_block = -1;
|
||||||
|
long last_block = -1;
|
||||||
|
int block_loops = 0;
|
||||||
|
int data_size;
|
||||||
|
@@ -430,6 +429,11 @@ int tftpd_send_file(struct thread_data *
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
@@ -786,8 +790,8 @@ int tftpd_send_file(struct thread_data *
|
||||||
|
ntohs(client_info->client.sin_port));
|
||||||
|
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;
|
||||||
|
@@ -856,6 +860,7 @@ int tftpd_send_file(struct thread_data *
|
||||||
|
"source port mismatch, check bypassed");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
+
|
||||||
|
/* The ACK is from the current client */
|
||||||
|
number_of_timeout = 0;
|
||||||
|
block_number = (block_loops * 65536) + ntohs(tftphdr->th_block);
|
||||||
|
@@ -864,28 +869,88 @@ int tftpd_send_file(struct thread_data *
|
||||||
|
logger(LOG_DEBUG, "received ACK <block: %d>", block_number);
|
||||||
|
}
|
||||||
|
|
||||||
|
- /* if turned on, check whether the block request isn't already fulfilled */
|
||||||
|
- if (tftpd_prevent_sas) {
|
||||||
|
- /* multicast, block numbers could contain gaps */
|
||||||
|
- if (multicast) {
|
||||||
|
- if (last_requested_block >= block_number)
|
||||||
|
+ /* Now check the ACK number and possibly ignore the request */
|
||||||
|
+
|
||||||
|
+ /* multicast, block numbers could contain gaps */
|
||||||
|
+ if (multicast) {
|
||||||
|
+ /* 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 {
|
||||||
|
+ 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;
|
||||||
|
}
|
||||||
|
- else
|
||||||
|
- last_requested_block = block_number;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -898,6 +963,8 @@ int tftpd_send_file(struct thread_data *
|
||||||
|
state = S_END;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
+
|
||||||
|
+ curr_sent_count++;
|
||||||
|
state = S_SEND_DATA;
|
||||||
|
break;
|
||||||
|
case GET_ERROR:
|
||||||
|
@@ -989,7 +1056,7 @@ int tftpd_send_file(struct thread_data *
|
||||||
|
state = S_SEND_OACK;
|
||||||
|
fseek(fp, 0, SEEK_SET);
|
||||||
|
/* reset the last block received counter */
|
||||||
|
- last_requested_block = -1;
|
||||||
|
+ prev_sent_block = -1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
13
atftp-0.7-default_dir_man.patch
Normal file
13
atftp-0.7-default_dir_man.patch
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
Index: atftp-0.7/atftpd.8
|
||||||
|
===================================================================
|
||||||
|
--- atftp-0.7.orig/atftpd.8 2012-11-16 11:50:17.618281568 +0100
|
||||||
|
+++ atftp-0.7/atftpd.8 2013-01-03 14:27:00.913280412 +0100
|
||||||
|
@@ -210,7 +210,7 @@ Show summary of options.
|
||||||
|
.B path
|
||||||
|
This is the root directory used by the TFTP server. All requested
|
||||||
|
files from a TFTP client must reside in this directory. If not
|
||||||
|
-specified, the directory defaults to /tftpboot. Since
|
||||||
|
+specified, the directory defaults to /srv/tftpboot. Since
|
||||||
|
atftpd run as the tftp user, the permission of the directory
|
||||||
|
must be set properly to allow file reading and writing.
|
||||||
|
|
37
atftp-0.7-default_user_man.patch
Normal file
37
atftp-0.7-default_user_man.patch
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
Index: atftp-0.7/atftpd.8
|
||||||
|
===================================================================
|
||||||
|
--- atftp-0.7.orig/atftpd.8 2012-11-16 11:46:18.798067178 +0100
|
||||||
|
+++ atftp-0.7/atftpd.8 2012-11-16 11:50:17.618281568 +0100
|
||||||
|
@@ -80,10 +80,10 @@ acknowledging the 'multicast' request by
|
||||||
|
|
||||||
|
.TP
|
||||||
|
.B \-\-logfile <logfile>
|
||||||
|
-Log to a specific file instead of only syslog. 'nobody' (or any user
|
||||||
|
+Log to a specific file instead of only syslog. 'tftp' (or any user
|
||||||
|
used to run the server) must have permissions on the given
|
||||||
|
file. Assuming the file is /var/log/atftpd.log, simply run: "touch
|
||||||
|
-/var/log/atftpd.log" and then "chown nobody.nogroup
|
||||||
|
+/var/log/atftpd.log" and then "chown tftp.tftp
|
||||||
|
/var/log/atftpd.log". When the server is ran in daemon mode,
|
||||||
|
/dev/stdout or /dev/stderr can be used.
|
||||||
|
|
||||||
|
@@ -105,8 +105,8 @@ specialized usage.
|
||||||
|
|
||||||
|
.TP
|
||||||
|
.B \-\-user <user[.group]>
|
||||||
|
-By default, the server change identity to the user nobody and group
|
||||||
|
-nogroup. Specify an alternate user.group with this option.
|
||||||
|
+By default, the server change identity to the user tftp and group
|
||||||
|
+tftp. Specify an alternate user.group with this option.
|
||||||
|
|
||||||
|
.TP
|
||||||
|
.B \-\-group <group>
|
||||||
|
@@ -211,7 +211,7 @@ Show summary of options.
|
||||||
|
This is the root directory used by the TFTP server. All requested
|
||||||
|
files from a TFTP client must reside in this directory. If not
|
||||||
|
specified, the directory defaults to /tftpboot. Since
|
||||||
|
-atftpd run as the nobody user, the permission of the directory
|
||||||
|
+atftpd run as the tftp user, the permission of the directory
|
||||||
|
must be set properly to allow file reading and writing.
|
||||||
|
|
||||||
|
.SH STATS
|
@ -1,219 +0,0 @@
|
|||||||
Index: atftp-0.7/tftpd.c
|
|
||||||
===================================================================
|
|
||||||
--- atftp-0.7.orig/tftpd.c 2012-09-11 13:55:28.303292010 +0200
|
|
||||||
+++ atftp-0.7/tftpd.c 2012-09-11 13:58:20.701437613 +0200
|
|
||||||
@@ -62,6 +62,7 @@ int retry_timeout = S_TIMEOUT;
|
|
||||||
|
|
||||||
int tftpd_daemon = 0; /* By default we are started by inetd */
|
|
||||||
int tftpd_daemon_no_fork = 0; /* For who want a false daemon mode */
|
|
||||||
+int tftpd_prevent_sas = 0; /* For who don't want the sorcerer's apprentice syndrome */
|
|
||||||
short tftpd_port = 0; /* Port atftpd listen to */
|
|
||||||
char tftpd_addr[MAXLEN] = ""; /* IP address atftpd binds to */
|
|
||||||
|
|
||||||
@@ -833,6 +834,7 @@ int tftpd_cmd_line_options(int argc, cha
|
|
||||||
{ "mtftp", 1, NULL, OPT_MTFTP },
|
|
||||||
{ "mtftp-port", 1, NULL, OPT_MTFTP_PORT },
|
|
||||||
#endif
|
|
||||||
+ { "prevent-sas", 0, NULL, 'X' },
|
|
||||||
{ "no-source-port-checking", 0, NULL, OPT_PORT_CHECK },
|
|
||||||
{ "mcast-switch-client", 0, NULL, OPT_MCAST_SWITCH },
|
|
||||||
{ "version", 0, NULL, 'V' },
|
|
||||||
@@ -896,6 +898,9 @@ int tftpd_cmd_line_options(int argc, cha
|
|
||||||
case 'N':
|
|
||||||
tftpd_daemon_no_fork = 1;
|
|
||||||
break;
|
|
||||||
+ case 'X':
|
|
||||||
+ tftpd_prevent_sas = 1;
|
|
||||||
+ break;
|
|
||||||
case 'U':
|
|
||||||
tmp = strtok(optarg, ".");
|
|
||||||
if (tmp != NULL)
|
|
||||||
@@ -1120,6 +1125,7 @@ void tftpd_usage(void)
|
|
||||||
" --pidfile <file> : write PID to this file\n"
|
|
||||||
" --daemon : run atftpd standalone (no inetd)\n"
|
|
||||||
" --no-fork : run as a daemon, don't fork\n"
|
|
||||||
+ " --prevent-sas : prevent Sorcerer's Apprentice Syndrome\n"
|
|
||||||
" --user <user[.group]> : default is nobody\n"
|
|
||||||
" --group <group> : default is nogroup\n"
|
|
||||||
" --port <port> : port on which atftp listen\n"
|
|
||||||
Index: atftp-0.7/tftpd_file.c
|
|
||||||
===================================================================
|
|
||||||
--- atftp-0.7.orig/tftpd_file.c 2012-09-11 13:55:28.405295054 +0200
|
|
||||||
+++ atftp-0.7/tftpd_file.c 2012-09-11 13:55:28.422295562 +0200
|
|
||||||
@@ -55,6 +55,7 @@
|
|
||||||
extern char directory[MAXLEN];
|
|
||||||
/* read only except for the main thread */
|
|
||||||
extern int tftpd_cancel;
|
|
||||||
+extern int tftpd_prevent_sas;
|
|
||||||
|
|
||||||
#ifdef HAVE_PCRE
|
|
||||||
extern tftpd_pcre_self_t *pcre_top;
|
|
||||||
@@ -863,31 +864,31 @@ int tftpd_send_file(struct thread_data *
|
|
||||||
logger(LOG_DEBUG, "received ACK <block: %d>", block_number);
|
|
||||||
}
|
|
||||||
|
|
||||||
- /* check whether the block request isn't already fulfilled */
|
|
||||||
-
|
|
||||||
- /* multicast, block numbers could contain gaps */
|
|
||||||
- if (multicast) {
|
|
||||||
- if (last_requested_block >= block_number)
|
|
||||||
- {
|
|
||||||
- if (data->trace)
|
|
||||||
- logger(LOG_DEBUG, "received duplicated ACK <block: %d >= %d>", last_requested_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)
|
|
||||||
- {
|
|
||||||
- if (data->trace)
|
|
||||||
- logger(LOG_DEBUG, "received out of order ACK <block: %d != %d>", last_requested_block + 1, block_number);
|
|
||||||
- break;
|
|
||||||
+ /* if turned on, check whether the block request isn't already fulfilled */
|
|
||||||
+ if (tftpd_prevent_sas) {
|
|
||||||
+ /* multicast, block numbers could contain gaps */
|
|
||||||
+ if (multicast) {
|
|
||||||
+ if (last_requested_block >= block_number)
|
|
||||||
+ {
|
|
||||||
+ if (data->trace)
|
|
||||||
+ logger(LOG_DEBUG, "received duplicated ACK <block: %d >= %d>", last_requested_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)
|
|
||||||
+ {
|
|
||||||
+ if (data->trace)
|
|
||||||
+ logger(LOG_DEBUG, "received out of order ACK <block: %d != %d>", last_requested_block + 1, block_number);
|
|
||||||
+ break;
|
|
||||||
+ }
|
|
||||||
+ else
|
|
||||||
+ last_requested_block = block_number;
|
|
||||||
}
|
|
||||||
- else
|
|
||||||
- last_requested_block = block_number;
|
|
||||||
}
|
|
||||||
|
|
||||||
-
|
|
||||||
if (ntohs(tftphdr->th_block) == 65535)
|
|
||||||
{
|
|
||||||
block_loops++;
|
|
||||||
Index: atftp-0.7/tftp_file.c
|
|
||||||
===================================================================
|
|
||||||
--- atftp-0.7.orig/tftp_file.c 2012-09-11 13:55:28.387294518 +0200
|
|
||||||
+++ atftp-0.7/tftp_file.c 2012-09-11 13:55:28.422295562 +0200
|
|
||||||
@@ -49,6 +49,7 @@
|
|
||||||
#define NB_BLOCK 2048
|
|
||||||
|
|
||||||
extern int tftp_cancel;
|
|
||||||
+extern int tftp_prevent_sas;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Find a hole in the file bitmap.
|
|
||||||
@@ -767,15 +768,18 @@ int tftp_send_file(struct client_data *d
|
|
||||||
}
|
|
||||||
block_number = ntohs(tftphdr->th_block);
|
|
||||||
|
|
||||||
- if (last_requested_block >= block_number)
|
|
||||||
- {
|
|
||||||
- if (data->trace)
|
|
||||||
- fprintf(stderr, "received duplicated ACK <block: %ld >= %ld>\n",
|
|
||||||
- last_requested_block, block_number);
|
|
||||||
- break;
|
|
||||||
+ /* if turned on, check whether the block request isn't already fulfilled */
|
|
||||||
+ if (tftp_prevent_sas) {
|
|
||||||
+ if (last_requested_block >= block_number)
|
|
||||||
+ {
|
|
||||||
+ if (data->trace)
|
|
||||||
+ fprintf(stderr, "received duplicated ACK <block: %ld >= %ld>\n",
|
|
||||||
+ last_requested_block, block_number);
|
|
||||||
+ break;
|
|
||||||
+ }
|
|
||||||
+ else
|
|
||||||
+ last_requested_block = block_number;
|
|
||||||
}
|
|
||||||
- else
|
|
||||||
- last_requested_block = block_number;
|
|
||||||
|
|
||||||
if (data->trace)
|
|
||||||
fprintf(stderr, "received ACK <block: %ld>\n",
|
|
||||||
Index: atftp-0.7/tftp.c
|
|
||||||
===================================================================
|
|
||||||
--- atftp-0.7.orig/tftp.c 2012-09-11 13:55:28.255290577 +0200
|
|
||||||
+++ atftp-0.7/tftp.c 2012-09-11 14:01:13.437593304 +0200
|
|
||||||
@@ -57,6 +57,7 @@
|
|
||||||
/* defined as extern in tftp_file.c and mtftp_file.c, set by the signal
|
|
||||||
handler */
|
|
||||||
int tftp_cancel = 0;
|
|
||||||
+int tftp_prevent_sas = 0;
|
|
||||||
|
|
||||||
/* local flags */
|
|
||||||
int interactive = 1; /* if false, we run in batch mode */
|
|
||||||
@@ -982,6 +983,7 @@ int tftp_cmd_line_options(int argc, char
|
|
||||||
#endif
|
|
||||||
{ "mtftp", 1, NULL, '1'},
|
|
||||||
{ "no-source-port-checking", 0, NULL, '0'},
|
|
||||||
+ { "prevent-sas", 0, NULL, 'X'},
|
|
||||||
{ "verbose", 0, NULL, 'v'},
|
|
||||||
{ "trace", 0, NULL, 'd'},
|
|
||||||
#if DEBUG
|
|
||||||
@@ -1086,6 +1088,9 @@ int tftp_cmd_line_options(int argc, char
|
|
||||||
case '0':
|
|
||||||
data.checkport = 0;
|
|
||||||
break;
|
|
||||||
+ case 'X':
|
|
||||||
+ tftp_prevent_sas = 1;
|
|
||||||
+ break;
|
|
||||||
case 'v':
|
|
||||||
snprintf(string, sizeof(string), "verbose on");
|
|
||||||
make_arg(string, &ac, &av);
|
|
||||||
@@ -1182,6 +1187,7 @@ void tftp_usage(void)
|
|
||||||
" --mtftp <\"name value\"> : set mtftp variable to value\n"
|
|
||||||
#endif
|
|
||||||
" --no-source-port-checking: violate RFC, see man page\n"
|
|
||||||
+ " --prevent-sas : prevent Sorcerer's Apprentice Syndrome\n"
|
|
||||||
" --verbose : set verbose mode on\n"
|
|
||||||
" --trace : set trace mode on\n"
|
|
||||||
#if DEBUG
|
|
||||||
Index: atftp-0.7/atftpd.8
|
|
||||||
===================================================================
|
|
||||||
--- atftp-0.7.orig/atftpd.8 2004-03-06 21:41:40.000000000 +0100
|
|
||||||
+++ atftp-0.7/atftpd.8 2012-09-11 13:55:28.423295591 +0200
|
|
||||||
@@ -180,6 +180,14 @@ implication. Be aware that this option v
|
|
||||||
option has effect only for non-multicast transfer.
|
|
||||||
|
|
||||||
.TP
|
|
||||||
+.B \-\-prevent\-sas
|
|
||||||
+Address the Sorcerer's Apprentice Syndrome situation as requested by RFC 1350.
|
|
||||||
+This RFC requires repeated responses to a single packet to be
|
|
||||||
+rejected. Thus a block will only get retransmitted on a timeout.
|
|
||||||
+For backward compatibility, the default stays to ignore this RFC.
|
|
||||||
+So blocks get transmitted on every request.
|
|
||||||
+
|
|
||||||
+.TP
|
|
||||||
.B \-\-mcast\-switch\-client
|
|
||||||
This option allow the server to proceed with the next multicast client
|
|
||||||
as soon as the current client timeout. When the current master client
|
|
||||||
Index: atftp-0.7/atftp.1
|
|
||||||
===================================================================
|
|
||||||
--- atftp-0.7.orig/atftp.1 2004-03-06 21:41:40.000000000 +0100
|
|
||||||
+++ atftp-0.7/atftp.1 2012-09-11 13:55:28.423295591 +0200
|
|
||||||
@@ -77,6 +77,14 @@ to configure client side port to use.
|
|
||||||
See atftpd's man page.
|
|
||||||
|
|
||||||
.TP
|
|
||||||
+.B \-\-prevent\-sas
|
|
||||||
+Address the Sorcerer's Apprentice Syndrome situation as requested by RFC 1350.
|
|
||||||
+This RFC requires repeated responses to a single packet to be
|
|
||||||
+rejected. Thus a block will only get retransmitted on a timeout.
|
|
||||||
+For backward compatibility, the default stays to ignore this RFC.
|
|
||||||
+So blocks get transmitted on every request.
|
|
||||||
+
|
|
||||||
+.TP
|
|
||||||
.B \-\-verbose
|
|
||||||
Instruct atftp to be verbose. It will print more information about
|
|
||||||
what's going on.
|
|
@ -1,8 +1,15 @@
|
|||||||
Index: atftp-0.7/tftp_file.c
|
diff -u atftp-0.7/tftp_file.c atftp-0.7/tftp_file.c
|
||||||
===================================================================
|
--- atftp-0.7/tftp_file.c 2012-03-27 11:39:59.441167084 +0200
|
||||||
--- atftp-0.7.orig/tftp_file.c 2011-11-22 15:12:53.792744083 +0100
|
+++ atftp-0.7/tftp_file.c 2012-09-11 13:55:28.422295562 +0200
|
||||||
+++ atftp-0.7/tftp_file.c 2011-11-22 15:13:51.706421893 +0100
|
@@ -49,6 +49,7 @@
|
||||||
@@ -605,6 +605,7 @@
|
#define NB_BLOCK 2048
|
||||||
|
|
||||||
|
extern int tftp_cancel;
|
||||||
|
+extern int tftp_prevent_sas;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Find a hole in the file bitmap.
|
||||||
|
@@ -605,6 +606,7 @@
|
||||||
int timeout_state = state; /* what state should we go on when timeout */
|
int timeout_state = state; /* what state should we go on when timeout */
|
||||||
int result;
|
int result;
|
||||||
long block_number = 0;
|
long block_number = 0;
|
||||||
@ -10,11 +17,13 @@ Index: atftp-0.7/tftp_file.c
|
|||||||
long last_block = -1;
|
long last_block = -1;
|
||||||
int data_size; /* size of data received */
|
int data_size; /* size of data received */
|
||||||
int sockfd = data->sockfd; /* just to simplify calls */
|
int sockfd = data->sockfd; /* just to simplify calls */
|
||||||
@@ -765,6 +766,17 @@
|
@@ -765,6 +767,20 @@
|
||||||
connected = 1;
|
connected = 1;
|
||||||
}
|
}
|
||||||
block_number = ntohs(tftphdr->th_block);
|
block_number = ntohs(tftphdr->th_block);
|
||||||
+
|
+
|
||||||
|
+ /* if turned on, check whether the block request isn't already fulfilled */
|
||||||
|
+ if (tftp_prevent_sas) {
|
||||||
+ if (last_requested_block >= block_number)
|
+ if (last_requested_block >= block_number)
|
||||||
+ {
|
+ {
|
||||||
+ if (data->trace)
|
+ if (data->trace)
|
||||||
@ -24,15 +33,23 @@ Index: atftp-0.7/tftp_file.c
|
|||||||
+ }
|
+ }
|
||||||
+ else
|
+ else
|
||||||
+ last_requested_block = block_number;
|
+ last_requested_block = block_number;
|
||||||
|
+ }
|
||||||
+
|
+
|
||||||
if (data->trace)
|
if (data->trace)
|
||||||
fprintf(stderr, "received ACK <block: %ld>\n",
|
fprintf(stderr, "received ACK <block: %ld>\n",
|
||||||
block_number);
|
block_number);
|
||||||
Index: atftp-0.7/tftpd_file.c
|
diff -u atftp-0.7/tftpd_file.c atftp-0.7/tftpd_file.c
|
||||||
===================================================================
|
--- atftp-0.7/tftpd_file.c 2012-03-30 14:02:04.335089843 +0200
|
||||||
--- atftp-0.7.orig/tftpd_file.c 2011-11-22 15:12:53.793744112 +0100
|
+++ atftp-0.7/tftpd_file.c 2012-09-11 13:55:28.422295562 +0200
|
||||||
+++ atftp-0.7/tftpd_file.c 2011-11-22 15:15:04.617534260 +0100
|
@@ -55,6 +55,7 @@
|
||||||
@@ -403,6 +403,7 @@
|
extern char directory[MAXLEN];
|
||||||
|
/* read only except for the main thread */
|
||||||
|
extern int tftpd_cancel;
|
||||||
|
+extern int tftpd_prevent_sas;
|
||||||
|
|
||||||
|
#ifdef HAVE_PCRE
|
||||||
|
extern tftpd_pcre_self_t *pcre_top;
|
||||||
|
@@ -403,6 +404,7 @@
|
||||||
int timeout_state = state;
|
int timeout_state = state;
|
||||||
int result;
|
int result;
|
||||||
long block_number = 0;
|
long block_number = 0;
|
||||||
@ -40,13 +57,23 @@ Index: atftp-0.7/tftpd_file.c
|
|||||||
long last_block = -1;
|
long last_block = -1;
|
||||||
int block_loops = 0;
|
int block_loops = 0;
|
||||||
int data_size;
|
int data_size;
|
||||||
@@ -859,6 +860,32 @@
|
@@ -785,6 +787,10 @@
|
||||||
{
|
inet_ntoa(client_info->client.sin_addr),
|
||||||
|
ntohs(client_info->client.sin_port));
|
||||||
|
sa = &client_info->client;
|
||||||
|
+
|
||||||
|
+ /* rewind the last_requested_block counter */
|
||||||
|
+ last_requested_block = -1;
|
||||||
|
+
|
||||||
|
state = S_SEND_OACK;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
@@ -858,5 +864,31 @@
|
||||||
logger(LOG_DEBUG, "received ACK <block: %d>", block_number);
|
logger(LOG_DEBUG, "received ACK <block: %d>", block_number);
|
||||||
}
|
}
|
||||||
+
|
+
|
||||||
+ /* check whether the block request isn't already fulfilled */
|
+ /* if turned on, check whether the block request isn't already fulfilled */
|
||||||
+
|
+ if (tftpd_prevent_sas) {
|
||||||
+ /* multicast, block numbers could contain gaps */
|
+ /* multicast, block numbers could contain gaps */
|
||||||
+ if (multicast) {
|
+ if (multicast) {
|
||||||
+ if (last_requested_block >= block_number)
|
+ if (last_requested_block >= block_number)
|
||||||
@ -68,12 +95,12 @@ Index: atftp-0.7/tftpd_file.c
|
|||||||
+ else
|
+ else
|
||||||
+ last_requested_block = block_number;
|
+ last_requested_block = block_number;
|
||||||
+ }
|
+ }
|
||||||
+
|
+ }
|
||||||
+
|
+
|
||||||
if (ntohs(tftphdr->th_block) == 65535)
|
if (ntohs(tftphdr->th_block) == 65535)
|
||||||
{
|
{
|
||||||
block_loops++;
|
block_loops++;
|
||||||
@@ -958,6 +985,8 @@
|
@@ -958,6 +990,8 @@
|
||||||
/* nedd to send an oack to that client */
|
/* nedd to send an oack to that client */
|
||||||
state = S_SEND_OACK;
|
state = S_SEND_OACK;
|
||||||
fseek(fp, 0, SEEK_SET);
|
fseek(fp, 0, SEEK_SET);
|
||||||
@ -82,3 +109,117 @@ Index: atftp-0.7/tftpd_file.c
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
only in patch2:
|
||||||
|
unchanged:
|
||||||
|
--- atftp-0.7.orig/tftpd.c 2012-09-11 13:55:28.303292010 +0200
|
||||||
|
+++ atftp-0.7/tftpd.c 2012-09-11 13:58:20.701437613 +0200
|
||||||
|
@@ -62,6 +62,7 @@ int retry_timeout = S_TIMEOUT;
|
||||||
|
|
||||||
|
int tftpd_daemon = 0; /* By default we are started by inetd */
|
||||||
|
int tftpd_daemon_no_fork = 0; /* For who want a false daemon mode */
|
||||||
|
+int tftpd_prevent_sas = 0; /* For who don't want the sorcerer's apprentice syndrome */
|
||||||
|
short tftpd_port = 0; /* Port atftpd listen to */
|
||||||
|
char tftpd_addr[MAXLEN] = ""; /* IP address atftpd binds to */
|
||||||
|
|
||||||
|
@@ -833,6 +834,7 @@ int tftpd_cmd_line_options(int argc, cha
|
||||||
|
{ "mtftp", 1, NULL, OPT_MTFTP },
|
||||||
|
{ "mtftp-port", 1, NULL, OPT_MTFTP_PORT },
|
||||||
|
#endif
|
||||||
|
+ { "prevent-sas", 0, NULL, 'X' },
|
||||||
|
{ "no-source-port-checking", 0, NULL, OPT_PORT_CHECK },
|
||||||
|
{ "mcast-switch-client", 0, NULL, OPT_MCAST_SWITCH },
|
||||||
|
{ "version", 0, NULL, 'V' },
|
||||||
|
@@ -896,6 +898,9 @@ int tftpd_cmd_line_options(int argc, cha
|
||||||
|
case 'N':
|
||||||
|
tftpd_daemon_no_fork = 1;
|
||||||
|
break;
|
||||||
|
+ case 'X':
|
||||||
|
+ tftpd_prevent_sas = 1;
|
||||||
|
+ break;
|
||||||
|
case 'U':
|
||||||
|
tmp = strtok(optarg, ".");
|
||||||
|
if (tmp != NULL)
|
||||||
|
@@ -1120,6 +1125,7 @@ void tftpd_usage(void)
|
||||||
|
" --pidfile <file> : write PID to this file\n"
|
||||||
|
" --daemon : run atftpd standalone (no inetd)\n"
|
||||||
|
" --no-fork : run as a daemon, don't fork\n"
|
||||||
|
+ " --prevent-sas : prevent Sorcerer's Apprentice Syndrome\n"
|
||||||
|
" --user <user[.group]> : default is nobody\n"
|
||||||
|
" --group <group> : default is nogroup\n"
|
||||||
|
" --port <port> : port on which atftp listen\n"
|
||||||
|
only in patch2:
|
||||||
|
unchanged:
|
||||||
|
--- atftp-0.7.orig/tftp.c 2012-09-11 13:55:28.255290577 +0200
|
||||||
|
+++ atftp-0.7/tftp.c 2012-09-11 14:01:13.437593304 +0200
|
||||||
|
@@ -57,6 +57,7 @@
|
||||||
|
/* defined as extern in tftp_file.c and mtftp_file.c, set by the signal
|
||||||
|
handler */
|
||||||
|
int tftp_cancel = 0;
|
||||||
|
+int tftp_prevent_sas = 0;
|
||||||
|
|
||||||
|
/* local flags */
|
||||||
|
int interactive = 1; /* if false, we run in batch mode */
|
||||||
|
@@ -982,6 +983,7 @@ int tftp_cmd_line_options(int argc, char
|
||||||
|
#endif
|
||||||
|
{ "mtftp", 1, NULL, '1'},
|
||||||
|
{ "no-source-port-checking", 0, NULL, '0'},
|
||||||
|
+ { "prevent-sas", 0, NULL, 'X'},
|
||||||
|
{ "verbose", 0, NULL, 'v'},
|
||||||
|
{ "trace", 0, NULL, 'd'},
|
||||||
|
#if DEBUG
|
||||||
|
@@ -1086,6 +1088,9 @@ int tftp_cmd_line_options(int argc, char
|
||||||
|
case '0':
|
||||||
|
data.checkport = 0;
|
||||||
|
break;
|
||||||
|
+ case 'X':
|
||||||
|
+ tftp_prevent_sas = 1;
|
||||||
|
+ break;
|
||||||
|
case 'v':
|
||||||
|
snprintf(string, sizeof(string), "verbose on");
|
||||||
|
make_arg(string, &ac, &av);
|
||||||
|
@@ -1182,6 +1187,7 @@ void tftp_usage(void)
|
||||||
|
" --mtftp <\"name value\"> : set mtftp variable to value\n"
|
||||||
|
#endif
|
||||||
|
" --no-source-port-checking: violate RFC, see man page\n"
|
||||||
|
+ " --prevent-sas : prevent Sorcerer's Apprentice Syndrome\n"
|
||||||
|
" --verbose : set verbose mode on\n"
|
||||||
|
" --trace : set trace mode on\n"
|
||||||
|
#if DEBUG
|
||||||
|
only in patch2:
|
||||||
|
unchanged:
|
||||||
|
--- atftp-0.7.orig/atftpd.8 2004-03-06 21:41:40.000000000 +0100
|
||||||
|
+++ atftp-0.7/atftpd.8 2012-09-11 13:55:28.423295591 +0200
|
||||||
|
@@ -180,6 +180,14 @@ implication. Be aware that this option v
|
||||||
|
option has effect only for non-multicast transfer.
|
||||||
|
|
||||||
|
.TP
|
||||||
|
+.B \-\-prevent\-sas
|
||||||
|
+Address the Sorcerer's Apprentice Syndrome situation as requested by RFC 1350.
|
||||||
|
+This RFC requires repeated responses to a single packet to be
|
||||||
|
+rejected. Thus a block will only get retransmitted on a timeout.
|
||||||
|
+For backward compatibility, the default stays to ignore this RFC.
|
||||||
|
+So blocks get transmitted on every request.
|
||||||
|
+
|
||||||
|
+.TP
|
||||||
|
.B \-\-mcast\-switch\-client
|
||||||
|
This option allow the server to proceed with the next multicast client
|
||||||
|
as soon as the current client timeout. When the current master client
|
||||||
|
only in patch2:
|
||||||
|
unchanged:
|
||||||
|
--- atftp-0.7.orig/atftp.1 2004-03-06 21:41:40.000000000 +0100
|
||||||
|
+++ atftp-0.7/atftp.1 2012-09-11 13:55:28.423295591 +0200
|
||||||
|
@@ -77,6 +77,14 @@ to configure client side port to use.
|
||||||
|
See atftpd's man page.
|
||||||
|
|
||||||
|
.TP
|
||||||
|
+.B \-\-prevent\-sas
|
||||||
|
+Address the Sorcerer's Apprentice Syndrome situation as requested by RFC 1350.
|
||||||
|
+This RFC requires repeated responses to a single packet to be
|
||||||
|
+rejected. Thus a block will only get retransmitted on a timeout.
|
||||||
|
+For backward compatibility, the default stays to ignore this RFC.
|
||||||
|
+So blocks get transmitted on every request.
|
||||||
|
+
|
||||||
|
+.TP
|
||||||
|
.B \-\-verbose
|
||||||
|
Instruct atftp to be verbose. It will print more information about
|
||||||
|
what's going on.
|
||||||
|
@ -1,3 +1,32 @@
|
|||||||
|
-------------------------------------------------------------------
|
||||||
|
Thu Feb 7 13:05:52 UTC 2013 - vcizek@suse.com
|
||||||
|
|
||||||
|
- create capabilites provided by both tftp and atftp
|
||||||
|
(bnc#801481 or bnc#725378)
|
||||||
|
|
||||||
|
-------------------------------------------------------------------
|
||||||
|
Thu Jan 3 13:28:02 UTC 2013 - vcizek@suse.com
|
||||||
|
|
||||||
|
- change ownership of /srv/tftpboot, because atftpd running as
|
||||||
|
tftp:tftp can't write to that directory
|
||||||
|
- create pid directory on service start
|
||||||
|
- manpage changes:
|
||||||
|
* substitute /tftpboot with /srv/tftpboot
|
||||||
|
* default user is now tftp:tftp
|
||||||
|
* added patches:
|
||||||
|
atftp-0.7-default_user_man.patch
|
||||||
|
atftp-0.7-default_dir_man.patch
|
||||||
|
|
||||||
|
-------------------------------------------------------------------
|
||||||
|
Mon Oct 8 08:49:53 UTC 2012 - vcizek@suse.com
|
||||||
|
|
||||||
|
- use Vladimir Nadvornik's heuristic for packet retransmission
|
||||||
|
by default (see bnc#774376)
|
||||||
|
The RFC1350 compliant behaviour stays optional.
|
||||||
|
(added atftp-0.7-ack_heuristic.patch)
|
||||||
|
- merged the two sorcerer's apprentice syndrome patches to one
|
||||||
|
(removed atftp-0.7-prevent-sas.patch)
|
||||||
|
|
||||||
-------------------------------------------------------------------
|
-------------------------------------------------------------------
|
||||||
Tue Sep 11 13:01:20 UTC 2012 - vcizek@suse.com
|
Tue Sep 11 13:01:20 UTC 2012 - vcizek@suse.com
|
||||||
|
|
||||||
|
19
atftp.spec
19
atftp.spec
@ -1,7 +1,7 @@
|
|||||||
#
|
#
|
||||||
# spec file for package atftp
|
# spec file for package atftp
|
||||||
#
|
#
|
||||||
# Copyright (c) 2012 SUSE LINUX Products GmbH, Nuernberg, Germany.
|
# Copyright (c) 2013 SUSE LINUX Products GmbH, Nuernberg, Germany.
|
||||||
#
|
#
|
||||||
# All modifications and additions to the file contributed by third parties
|
# All modifications and additions to the file contributed by third parties
|
||||||
# remain the property of their copyright owners, unless otherwise agreed
|
# remain the property of their copyright owners, unless otherwise agreed
|
||||||
@ -44,8 +44,14 @@ Patch8: atftpd-0.7_circumvent_tftp_size_restrictions.patch
|
|||||||
Patch9: atftp-0.7-sorcerers_apprentice.patch
|
Patch9: atftp-0.7-sorcerers_apprentice.patch
|
||||||
# PATCH-FIX-SUSE server receive thread race (bnc#599856)
|
# PATCH-FIX-SUSE server receive thread race (bnc#599856)
|
||||||
Patch10: atftp-0.7-server_receive_race.patch
|
Patch10: atftp-0.7-server_receive_race.patch
|
||||||
Patch11: atftp-0.7-prevent-sas.patch
|
# PATCH-FIX-SUSE drop one duplicated ACK each round (bnc#774376)
|
||||||
|
Patch12: atftp-0.7-ack_heuristic.patch
|
||||||
|
Patch13: atftp-0.7-default_user_man.patch
|
||||||
|
# PATCH-FIX-SUSE update default directory in man (bnc#507011)
|
||||||
|
Patch14: atftp-0.7-default_dir_man.patch
|
||||||
BuildRoot: %{_tmppath}/%{name}-%{version}-build
|
BuildRoot: %{_tmppath}/%{name}-%{version}-build
|
||||||
|
Provides: tftp(client)
|
||||||
|
Provides: tftp(server)
|
||||||
PreReq: %insserv_prereq %fillup_prereq
|
PreReq: %insserv_prereq %fillup_prereq
|
||||||
PreReq: pwdutils
|
PreReq: pwdutils
|
||||||
BuildRequires: autoconf
|
BuildRequires: autoconf
|
||||||
@ -77,7 +83,9 @@ boot of hundreds of machines simultaneously.
|
|||||||
%patch8
|
%patch8
|
||||||
%patch9 -p1
|
%patch9 -p1
|
||||||
%patch10 -p0
|
%patch10 -p0
|
||||||
%patch11 -p1
|
%patch12 -p1
|
||||||
|
%patch13 -p1
|
||||||
|
%patch14 -p1
|
||||||
|
|
||||||
%build
|
%build
|
||||||
autoreconf -fi
|
autoreconf -fi
|
||||||
@ -134,7 +142,8 @@ fi
|
|||||||
%{_mandir}/man8/atftpd.8.gz
|
%{_mandir}/man8/atftpd.8.gz
|
||||||
%{_mandir}/man8/in.tftpd.8.gz
|
%{_mandir}/man8/in.tftpd.8.gz
|
||||||
%config %{_fwdefdir}/atftp
|
%config %{_fwdefdir}/atftp
|
||||||
%dir %attr(0750,root,tftp) /srv/tftpboot
|
%dir %attr(0750,tftp,tftp) /srv/tftpboot
|
||||||
%dir %attr(0750,tftp,root) /var/log/atftpd/
|
%dir %attr(0750,tftp,tftp) /var/log/atftpd/
|
||||||
|
%ghost %dir /var/run/atftpd
|
||||||
|
|
||||||
%changelog
|
%changelog
|
||||||
|
@ -74,13 +74,12 @@ ATFTP_BIND=${ATFTP_BIND_ADDRESSES:=""}
|
|||||||
# start as daemon with some default opts
|
# start as daemon with some default opts
|
||||||
ATFTP_DEF_OPTS="--daemon --user $ATFTP_USR --group $ATFTP_GRP --logfile $ATFTP_LOG_FILE"
|
ATFTP_DEF_OPTS="--daemon --user $ATFTP_USR --group $ATFTP_GRP --logfile $ATFTP_LOG_FILE"
|
||||||
|
|
||||||
# set correct perm on log_dir/pid_dir
|
# create logfile and PID directory if they don't exist
|
||||||
# IN: $ATFTP_USR
|
create_logfile_and_piddir(){
|
||||||
set_perm(){
|
# /var/run is mounted as tmpfs on openSUSE >= 11.4
|
||||||
[ ! -f "$ATFTP_LOG_FILE" ] && touch "$ATFTP_LOG_FILE";
|
[ ! -d "$ATFTP_PID_DIR" ] && /usr/bin/install -o ${ATFTP_USR} -g ${ATFTP_GRP} -d "$ATFTP_PID_DIR";
|
||||||
chown -R ${1}:root "$ATFTP_LOG_DIR"
|
# must exist otherwise atftp will log to syslog
|
||||||
[ ! -d "$ATFTP_PID_DIR" ] && /usr/bin/install -d "$ATFTP_PID_DIR";
|
[ ! -f "$ATFTP_PID_DIR" ] && /usr/bin/install -m 0644 -o ${ATFTP_USR} -g ${ATFTP_GRP} /dev/null "$ATFTP_LOG_FILE"
|
||||||
chown -R ${1}:root "$ATFTP_PID_DIR"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if [ "$ATFTP_USE_INETD" = "yes" ]; then
|
if [ "$ATFTP_USE_INETD" = "yes" ]; then
|
||||||
@ -90,7 +89,7 @@ fi
|
|||||||
|
|
||||||
case "$1" in
|
case "$1" in
|
||||||
start)
|
start)
|
||||||
set_perm "${ATFTP_USR}"
|
create_logfile_and_piddir
|
||||||
if [ -n "$ATFTP_BIND" ]; then
|
if [ -n "$ATFTP_BIND" ]; then
|
||||||
for IP in $ATFTP_BIND; do
|
for IP in $ATFTP_BIND; do
|
||||||
echo -n "Starting Advanced Trivial FTP server on $IP: "
|
echo -n "Starting Advanced Trivial FTP server on $IP: "
|
||||||
|
Loading…
Reference in New Issue
Block a user