Fix some timeout-related bugs; allow the user to set the default timeout.

This commit is contained in:
hpa 2002-10-23 21:21:46 +00:00
parent ebc8f1f89d
commit 82eae1bcd6
3 changed files with 78 additions and 30 deletions

View file

@ -1,5 +1,14 @@
$Id$ $Id$
Changes in 0.31:
Put in a check to make sure xinetd (in particular) doesn't
pass us an IPv6 socket.
Fix some problems related to timeout negotiation.
Allow the user to set the default timeout speed.
Changes in 0.30: Changes in 0.30:
(Hopefully) better timeout algorithm. (Hopefully) better timeout algorithm.

View file

@ -31,7 +31,7 @@
.\" SUCH DAMAGE. .\" SUCH DAMAGE.
.\" .\"
.\"----------------------------------------------------------------------- */ .\"----------------------------------------------------------------------- */
.TH TFTPD 8 "16 November 2001" "tftp-hpa @@VERSION@@" "UNIX System Manager's Manual" .TH TFTPD 8 "23 October 2002" "tftp-hpa @@VERSION@@" "System Manager's Manual"
.SH NAME .SH NAME
.B tftpd .B tftpd
\- IPv4 Trivial File Transfer Protocol server \- IPv4 Trivial File Transfer Protocol server
@ -125,6 +125,14 @@ before terminating the server.
will then respawn the server when another request comes in. The will then respawn the server when another request comes in. The
default is 900 (15 minutes.) default is 900 (15 minutes.)
.TP .TP
\fB\-T\fP \fItimeout\fP
Determine the default timeout, in microseconds, before the first
packet is retransmitted. This can be modified by the client if the
.B timeout
or
.B utimeout
option is negotiated. The default is 1000000 (1 second.)
.TP
\fB\-m\fP \fIremap-file\fP \fB\-m\fP \fIremap-file\fP
Specify the use of filename remapping. The Specify the use of filename remapping. The
.I remap-file .I remap-file
@ -149,25 +157,44 @@ exit gracefully.
This version of This version of
.B tftpd .B tftpd
supports RFC 2347 option negotation. Currently implemented options supports RFC 2347 option negotation. Currently implemented options
are are:
.B blksize .TP
(RFC 2348), \fBblksize\fP (RFC 2348)
.B blksize2 Set the transfer block size to anything less than or equal to the
(nonstandard), specified option. This version of
.B tftpd
can support any block size up to the theoretical maximum of 65464
bytes.
.TP
\fBblksize2\fP (nonstandard)
Set the transfer block size to anything less than or equal to the
specified option, but restrict the possible responses to powers of 2.
The maximum is 32768 bytes (the largest power of 2 less than or equal
to 65464.)
.TP
\fBtsize\fP (RFC 2349)
Report the size of the file that is about to be transferred. This
version of
.B tftpd
only supports the
.B tsize .B tsize
(RFC 2349), and option for binary (octet) mode transfers.
.B timeout .TP
(RFC 2349). The nonstandard \fBtimeout\fP (RFC 2349)
.B blksize2 Set the time before the server retransmits a packet, in seconds.
TFTP option is functionally identical to the .TP
.B blksize \fButimeout\fP (nonstandard)
option, with the additional constraint that the Set the time before the server retransmits a packet, in microseconds.
blocksize is constrained to be a power of 2. and
.PP .PP
The The
.B \-r .B \-r
option can be used to disable specific options; this may be necessary option can be used to disable specific options; this may be necessary
to work around bugs in specific TFTP client implementations. to work around bugs in specific TFTP client implementations. For
example, some TFTP clients have been found to request the
.B blksize
option, but crash with an error if they actually get the option
accepted by the server.
.SH "FILENAME REMAPPING" .SH "FILENAME REMAPPING"
The The
.B \-m .B \-m

View file

@ -79,17 +79,17 @@ int allow_severity = -1; /* Don't log at all */
struct request_info wrap_request; struct request_info wrap_request;
#endif #endif
#define TIMEOUT 1000 /* Default timeout (ms) */ #define TIMEOUT 1000000 /* Default timeout (us) */
#define TRIES 6 /* Number of attempts to send each packet */ #define TRIES 6 /* Number of attempts to send each packet */
#define TIMEOUT_LIMIT ((1 << TRIES)-1) #define TIMEOUT_LIMIT ((1 << TRIES)-1)
char *__progname; const char *__progname;
int peer; int peer;
int timeout = TIMEOUT; /* Current timeout value */ unsigned long timeout = TIMEOUT; /* Current timeout value */
int timeout_quit = 0; unsigned long rexmtval = TIMEOUT; /* Basic timeout value */
int rexmtval = TIMEOUT; /* Basic timeout value */ unsigned long maxtimeout = TIMEOUT_LIMIT*TIMEOUT;
int maxtimeout = TIMEOUT_LIMIT*TIMEOUT; int timeout_quit = 0;
sigjmp_buf timeoutbuf; sigjmp_buf timeoutbuf;
#define PKTSIZE MAX_SEGSIZE+4 #define PKTSIZE MAX_SEGSIZE+4
char buf[PKTSIZE]; char buf[PKTSIZE];
@ -160,7 +160,7 @@ timer(int sig)
static void static void
usage(void) usage(void)
{ {
syslog(LOG_ERR, "Usage: %s [-vcl][-a address][-m mappings][-u user][-t timeout][-r option...] [-s] [directory ...]", syslog(LOG_ERR, "Usage: %s [-vcl][-a address][-m mappings][-u user][-t inetd_timeout][-T pkt_timeout][-r option...] [-s] [directory ...]",
__progname); __progname);
exit(EX_USAGE); exit(EX_USAGE);
} }
@ -208,7 +208,7 @@ set_socket_nonblock(int fd, int flag)
* Receive packet with synchronous timeout * Receive packet with synchronous timeout
*/ */
static int recv_time(int s, void *rbuf, int len, unsigned int flags, static int recv_time(int s, void *rbuf, int len, unsigned int flags,
unsigned long timeout_ms) unsigned long timeout_us)
{ {
fd_set fdset; fd_set fdset;
struct timeval tmv; struct timeval tmv;
@ -218,8 +218,8 @@ static int recv_time(int s, void *rbuf, int len, unsigned int flags,
FD_ZERO(&fdset); FD_ZERO(&fdset);
FD_SET(s, &fdset); FD_SET(s, &fdset);
tmv.tv_sec = timeout_ms/1000; tmv.tv_sec = timeout_us / 1000000;
tmv.tv_usec = (timeout_ms%1000)*1000; tmv.tv_usec = timeout_us % 1000000;
do { do {
rv = select(s+1, &fdset, NULL, NULL, &tmv); rv = select(s+1, &fdset, NULL, NULL, &tmv);
@ -278,7 +278,7 @@ main(int argc, char **argv)
openlog(__progname, LOG_PID|LOG_NDELAY, LOG_DAEMON); openlog(__progname, LOG_PID|LOG_NDELAY, LOG_DAEMON);
while ((c = getopt(argc, argv, "cspvVla:u:U:r:t:m:")) != -1) while ((c = getopt(argc, argv, "cspvVla:u:U:r:t:T:m:")) != -1)
switch (c) { switch (c) {
case 'c': case 'c':
cancreate = 1; cancreate = 1;
@ -298,6 +298,18 @@ main(int argc, char **argv)
case 't': case 't':
waittime = atoi(optarg); waittime = atoi(optarg);
break; break;
case 'T':
{
char *vp;
unsigned long tov = strtoul(optarg, &vp, 10);
if ( tov < 10000UL || tov > 255000000UL || *vp ) {
syslog(LOG_ERR, "Bad timeout value: %s", optarg);
exit(EX_USAGE);
}
rexmtval = timeout = tov;
maxtimeout = rexmtval*TIMEOUT_LIMIT;
}
break;
case 'u': case 'u':
user = optarg; user = optarg;
break; break;
@ -888,7 +900,7 @@ set_timeout(char *val, char **ret)
if ( to < 1 || to > 255 || *vend ) if ( to < 1 || to > 255 || *vend )
return 0; return 0;
rexmtval = timeout = to; rexmtval = timeout = to*1000000UL;
maxtimeout = rexmtval*TIMEOUT_LIMIT; maxtimeout = rexmtval*TIMEOUT_LIMIT;
sprintf(*ret = b_ret, "%lu", to); sprintf(*ret = b_ret, "%lu", to);
@ -908,7 +920,7 @@ set_utimeout(char *val, char **ret)
if ( to < 10000UL || to > 255000000UL || *vend ) if ( to < 10000UL || to > 255000000UL || *vend )
return 0; return 0;
rexmtval = timeout = to/1000UL; rexmtval = timeout = to;
maxtimeout = rexmtval*TIMEOUT_LIMIT; maxtimeout = rexmtval*TIMEOUT_LIMIT;
sprintf(*ret = b_ret, "%lu", to); sprintf(*ret = b_ret, "%lu", to);