diff --git a/CHANGES b/CHANGES index 77689d7..b39b502 100644 --- a/CHANGES +++ b/CHANGES @@ -1,5 +1,14 @@ $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: (Hopefully) better timeout algorithm. diff --git a/tftpd/tftpd.8.in b/tftpd/tftpd.8.in index 388da0a..aab8bf6 100644 --- a/tftpd/tftpd.8.in +++ b/tftpd/tftpd.8.in @@ -31,7 +31,7 @@ .\" 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 .B tftpd \- 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 default is 900 (15 minutes.) .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 Specify the use of filename remapping. The .I remap-file @@ -149,25 +157,44 @@ exit gracefully. This version of .B tftpd supports RFC 2347 option negotation. Currently implemented options -are -.B blksize -(RFC 2348), -.B blksize2 -(nonstandard), +are: +.TP +\fBblksize\fP (RFC 2348) +Set the transfer block size to anything less than or equal to the +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 -(RFC 2349), and -.B timeout -(RFC 2349). The nonstandard -.B blksize2 -TFTP option is functionally identical to the -.B blksize -option, with the additional constraint that the -blocksize is constrained to be a power of 2. +option for binary (octet) mode transfers. +.TP +\fBtimeout\fP (RFC 2349) +Set the time before the server retransmits a packet, in seconds. +.TP +\fButimeout\fP (nonstandard) +Set the time before the server retransmits a packet, in microseconds. +and .PP The .B \-r 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" The .B \-m diff --git a/tftpd/tftpd.c b/tftpd/tftpd.c index 052a450..2865f35 100644 --- a/tftpd/tftpd.c +++ b/tftpd/tftpd.c @@ -79,17 +79,17 @@ int allow_severity = -1; /* Don't log at all */ struct request_info wrap_request; #endif -#define TIMEOUT 1000 /* Default timeout (ms) */ +#define TIMEOUT 1000000 /* Default timeout (us) */ #define TRIES 6 /* Number of attempts to send each packet */ #define TIMEOUT_LIMIT ((1 << TRIES)-1) -char *__progname; -int peer; -int timeout = TIMEOUT; /* Current timeout value */ -int timeout_quit = 0; -int rexmtval = TIMEOUT; /* Basic timeout value */ -int maxtimeout = TIMEOUT_LIMIT*TIMEOUT; -sigjmp_buf timeoutbuf; +const char *__progname; +int peer; +unsigned long timeout = TIMEOUT; /* Current timeout value */ +unsigned long rexmtval = TIMEOUT; /* Basic timeout value */ +unsigned long maxtimeout = TIMEOUT_LIMIT*TIMEOUT; +int timeout_quit = 0; +sigjmp_buf timeoutbuf; #define PKTSIZE MAX_SEGSIZE+4 char buf[PKTSIZE]; @@ -160,7 +160,7 @@ timer(int sig) static 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); exit(EX_USAGE); } @@ -208,7 +208,7 @@ set_socket_nonblock(int fd, int flag) * Receive packet with synchronous timeout */ static int recv_time(int s, void *rbuf, int len, unsigned int flags, - unsigned long timeout_ms) + unsigned long timeout_us) { fd_set fdset; struct timeval tmv; @@ -218,8 +218,8 @@ static int recv_time(int s, void *rbuf, int len, unsigned int flags, FD_ZERO(&fdset); FD_SET(s, &fdset); - tmv.tv_sec = timeout_ms/1000; - tmv.tv_usec = (timeout_ms%1000)*1000; + tmv.tv_sec = timeout_us / 1000000; + tmv.tv_usec = timeout_us % 1000000; do { 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); - 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) { case 'c': cancreate = 1; @@ -298,6 +298,18 @@ main(int argc, char **argv) case 't': waittime = atoi(optarg); 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': user = optarg; break; @@ -888,7 +900,7 @@ set_timeout(char *val, char **ret) if ( to < 1 || to > 255 || *vend ) return 0; - rexmtval = timeout = to; + rexmtval = timeout = to*1000000UL; maxtimeout = rexmtval*TIMEOUT_LIMIT; sprintf(*ret = b_ret, "%lu", to); @@ -908,7 +920,7 @@ set_utimeout(char *val, char **ret) if ( to < 10000UL || to > 255000000UL || *vend ) return 0; - rexmtval = timeout = to/1000UL; + rexmtval = timeout = to; maxtimeout = rexmtval*TIMEOUT_LIMIT; sprintf(*ret = b_ret, "%lu", to);