Downgrade client-side errors from LOG_ERR to LOG_WARN

This commit is contained in:
hpa 2002-09-03 19:02:02 +00:00
parent c980666bbe
commit d2692c9f98

View file

@ -79,15 +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 5 /* Default timeout (seconds) */ #define TIMEOUT 1000 /* Default timeout (ms) */
#define TRIES 4 /* Number of attempts to send each packet */ #define TRIES 6 /* Number of attempts to send each packet */
#define TIMEOUT_LIMIT (TRIES*(TRIES+1)/2) #define TIMEOUT_LIMIT ((1 << TRIES)-1)
char *__progname; char *__progname;
int peer; int peer;
int timeout = TIMEOUT; int timeout = TIMEOUT; /* Current timeout value */
int rexmtval = TIMEOUT; int timeout_quit = 0;
int rexmtval = TIMEOUT; /* Basic timeout value */
int maxtimeout = TIMEOUT_LIMIT*TIMEOUT; int maxtimeout = TIMEOUT_LIMIT*TIMEOUT;
sigjmp_buf timeoutbuf;
#define PKTSIZE MAX_SEGSIZE+4 #define PKTSIZE MAX_SEGSIZE+4
char buf[PKTSIZE]; char buf[PKTSIZE];
@ -121,6 +123,7 @@ int set_blksize(char *, char **);
int set_blksize2(char *, char **); int set_blksize2(char *, char **);
int set_tsize(char *, char **); int set_tsize(char *, char **);
int set_timeout(char *, char **); int set_timeout(char *, char **);
int set_utimeout(char *, char **);
struct options { struct options {
const char *o_opt; const char *o_opt;
@ -130,6 +133,7 @@ struct options {
{ "blksize2", set_blksize2 }, { "blksize2", set_blksize2 },
{ "tsize", set_tsize }, { "tsize", set_tsize },
{ "timeout", set_timeout }, { "timeout", set_timeout },
{ "utimeout", set_utimeout },
{ NULL, NULL } { NULL, NULL }
}; };
@ -142,6 +146,17 @@ static void handle_sighup(int sig)
} }
/* Handle timeout signal or timeout event */
void
timer(int sig)
{
(void)sig; /* Suppress unused warning */
timeout <<= 1;
if (timeout >= maxtimeout || timeout_quit)
exit(0);
siglongjmp(timeoutbuf, 1);
}
static void static void
usage(void) usage(void)
{ {
@ -189,6 +204,49 @@ 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)
{
fd_set fdset;
struct timeval tmv;
int rv, err;
for ( ; ; ) {
FD_ZERO(&fdset);
FD_SET(s, &fdset);
tmv.tv_sec = timeout_ms/1000;
tmv.tv_usec = (timeout_ms%1000)*1000;
do {
rv = select(s+1, &fdset, NULL, NULL, &tmv);
} while ( rv == -1 && errno == EINTR );
if ( rv == 0 ) {
timer(0); /* Should not return */
return -1;
}
set_socket_nonblock(s, 1);
rv = recv(s, rbuf, len, flags);
err = errno;
set_socket_nonblock(s, 0);
if ( rv < 0 ) {
if ( E_WOULD_BLOCK(err) || err == EINTR ) {
continue; /* Once again, with feeling... */
} else {
errno = err;
return rv;
}
} else {
return rv;
}
}
}
int int
main(int argc, char **argv) main(int argc, char **argv)
{ {
@ -589,7 +647,6 @@ main(int argc, char **argv)
/* Other basic setup */ /* Other basic setup */
from.sin_family = AF_INET; from.sin_family = AF_INET;
alarm(0);
/* Process the request... */ /* Process the request... */
@ -810,7 +867,9 @@ set_tsize(char *val, char **ret)
} }
/* /*
* Set the timeout (c.f. RFC2349) * Set the timeout (c.f. RFC2349). This is supposed
* to be the (default) retransmission timeout, but being an
* integer in seconds it seems a bit limited.
*/ */
int int
set_timeout(char *val, char **ret) set_timeout(char *val, char **ret)
@ -824,14 +883,32 @@ set_timeout(char *val, char **ret)
if ( to < 1 || to > 255 || *vend ) if ( to < 1 || to > 255 || *vend )
return 0; return 0;
timeout = to; rexmtval = timeout = to;
rexmtval = to; maxtimeout = rexmtval*TIMEOUT_LIMIT;
maxtimeout = TIMEOUT_LIMIT*to;
sprintf(*ret = b_ret, "%lu", to); sprintf(*ret = b_ret, "%lu", to);
return(1); return(1);
} }
/* Similar, but in microseconds. We allow down to 10 ms. */
int
set_utimeout(char *val, char **ret)
{
static char b_ret[4];
unsigned long to;
char *vend;
to = strtoul(val, &vend, 10);
if ( to < 10000UL || to > 255000000UL || *vend )
return 0;
rexmtval = timeout = to/1000UL;
maxtimeout = rexmtval*TIMEOUT_LIMIT;
sprintf(*ret = b_ret, "%lu", to);
return(1);
}
/* /*
* Parse RFC2347 style options * Parse RFC2347 style options
*/ */
@ -1030,20 +1107,6 @@ validate_access(char *filename, int mode, struct formats *pf)
return (0); return (0);
} }
int timeout;
sigjmp_buf timeoutbuf;
/* Handle timeout signal */
void
timer(int sig)
{
(void)sig; /* Suppress unused warning */
timeout += rexmtval;
if (timeout >= maxtimeout)
exit(0);
siglongjmp(timeoutbuf, 1);
}
/* /*
* Send the requested file. * Send the requested file.
*/ */
@ -1058,28 +1121,24 @@ tftp_sendfile(struct formats *pf, struct tftphdr *oap, int oacklen)
ap = (struct tftphdr *)ackbuf; ap = (struct tftphdr *)ackbuf;
if (oap) { if (oap) {
timeout = 0; timeout = rexmtval;
(void)sigsetjmp(timeoutbuf,1); (void)sigsetjmp(timeoutbuf,1);
oack: oack:
if (send(peer, oap, oacklen, 0) != oacklen) { if (send(peer, oap, oacklen, 0) != oacklen) {
syslog(LOG_ERR, "tftpd: oack: %m\n"); syslog(LOG_WARN, "tftpd: oack: %m\n");
goto abort; goto abort;
} }
for ( ; ; ) { for ( ; ; ) {
set_signal(SIGALRM, timer, SA_RESTART); n = recv_time(peer, ackbuf, sizeof(ackbuf), 0, timeout);
alarm(rexmtval);
n = recv(peer, ackbuf, sizeof(ackbuf), 0);
alarm(0);
if (n < 0) { if (n < 0) {
syslog(LOG_ERR, "tftpd: read: %m\n"); syslog(LOG_WARN, "tftpd: read: %m\n");
goto abort; goto abort;
} }
ap->th_opcode = ntohs((u_short)ap->th_opcode); ap->th_opcode = ntohs((u_short)ap->th_opcode);
ap->th_block = ntohs((u_short)ap->th_block); ap->th_block = ntohs((u_short)ap->th_block);
if (ap->th_opcode == ERROR) { if (ap->th_opcode == ERROR) {
syslog(LOG_ERR, "tftp: client does not accept " syslog(LOG_WARN, "tftp: client does not accept options\n");
"options\n");
goto abort; goto abort;
} }
if (ap->th_opcode == ACK) { if (ap->th_opcode == ACK) {
@ -1101,21 +1160,18 @@ tftp_sendfile(struct formats *pf, struct tftphdr *oap, int oacklen)
} }
dp->th_opcode = htons((u_short)DATA); dp->th_opcode = htons((u_short)DATA);
dp->th_block = htons((u_short)block); dp->th_block = htons((u_short)block);
timeout = 0; timeout = rexmtval;
(void) sigsetjmp(timeoutbuf,1); (void) sigsetjmp(timeoutbuf,1);
if (send(peer, dp, size + 4, 0) != size + 4) { if (send(peer, dp, size + 4, 0) != size + 4) {
syslog(LOG_ERR, "tftpd: write: %m"); syslog(LOG_WARN, "tftpd: write: %m");
goto abort; goto abort;
} }
read_ahead(file, pf->f_convert); read_ahead(file, pf->f_convert);
for ( ; ; ) { for ( ; ; ) {
set_signal(SIGALRM, timer, SA_RESTART); n = recv_time(peer, ackbuf, sizeof (ackbuf), 0, timeout);
alarm(rexmtval); /* read the ack */
n = recv(peer, ackbuf, sizeof (ackbuf), 0);
alarm(0);
if (n < 0) { if (n < 0) {
syslog(LOG_ERR, "tftpd: read(ack): %m"); syslog(LOG_WARN, "tftpd: read(ack): %m");
goto abort; goto abort;
} }
ap->th_opcode = ntohs((u_short)ap->th_opcode); ap->th_opcode = ntohs((u_short)ap->th_opcode);
@ -1168,7 +1224,7 @@ tftp_recvfile(struct formats *pf, struct tftphdr *oap, int oacklen)
dp = w_init(); dp = w_init();
do { do {
timeout = 0; timeout = rexmtval;
if (!block && oap) { if (!block && oap) {
ap = (struct tftphdr *)ackbuf; ap = (struct tftphdr *)ackbuf;
@ -1181,20 +1237,16 @@ tftp_recvfile(struct formats *pf, struct tftphdr *oap, int oacklen)
} }
block++; block++;
(void) sigsetjmp(timeoutbuf,1); (void) sigsetjmp(timeoutbuf,1);
set_signal(SIGALRM, timer, SA_RESTART);
send_ack: send_ack:
if (send(peer, ackbuf, acksize, 0) != acksize) { if (send(peer, ackbuf, acksize, 0) != acksize) {
syslog(LOG_ERR, "tftpd: write(ack): %m"); syslog(LOG_WARN, "tftpd: write(ack): %m");
goto abort; goto abort;
} }
write_behind(file, pf->f_convert); write_behind(file, pf->f_convert);
for ( ; ; ) { for ( ; ; ) {
set_signal(SIGALRM, timer, SA_RESTART); n = recv_time(peer, dp, PKTSIZE, 0, timeout);
alarm(rexmtval);
n = recv(peer, dp, PKTSIZE, 0);
alarm(0);
if (n < 0) { /* really? */ if (n < 0) { /* really? */
syslog(LOG_ERR, "tftpd: read: %m"); syslog(LOG_WARN, "tftpd: read: %m");
goto abort; goto abort;
} }
dp->th_opcode = ntohs((u_short)dp->th_opcode); dp->th_opcode = ntohs((u_short)dp->th_opcode);
@ -1226,10 +1278,10 @@ tftp_recvfile(struct formats *pf, struct tftphdr *oap, int oacklen)
ap->th_block = htons((u_short)(block)); ap->th_block = htons((u_short)(block));
(void) send(peer, ackbuf, 4, 0); (void) send(peer, ackbuf, 4, 0);
set_signal(SIGALRM, justquit, 0); /* just quit on timeout */ timeout_quit = 1; /* just quit on timeout */
alarm(rexmtval); n = recv_time(peer, buf, sizeof (buf), 0, timeout); /* normally times out and quits */
n = recv(peer, buf, sizeof (buf), 0); /* normally times out and quits */ timeout_quit = 0;
alarm(0);
if (n >= 4 && /* if read some data */ if (n >= 4 && /* if read some data */
dp->th_opcode == DATA && /* and got a data block */ dp->th_opcode == DATA && /* and got a data block */
block == dp->th_block) { /* then my last ack was lost */ block == dp->th_block) { /* then my last ack was lost */
@ -1289,5 +1341,5 @@ nak(int error)
} }
if (send(peer, buf, length, 0) != length) if (send(peer, buf, length, 0) != length)
syslog(LOG_ERR, "nak: %m"); syslog(LOG_WARN, "nak: %m");
} }