forked from mirrors/tftp-hpa-google
Downgrade client-side errors from LOG_ERR to LOG_WARN
This commit is contained in:
parent
c980666bbe
commit
d2692c9f98
1 changed files with 105 additions and 53 deletions
158
tftpd/tftpd.c
158
tftpd/tftpd.c
|
@ -79,15 +79,17 @@ int allow_severity = -1; /* Don't log at all */
|
|||
struct request_info wrap_request;
|
||||
#endif
|
||||
|
||||
#define TIMEOUT 5 /* Default timeout (seconds) */
|
||||
#define TRIES 4 /* Number of attempts to send each packet */
|
||||
#define TIMEOUT_LIMIT (TRIES*(TRIES+1)/2)
|
||||
#define TIMEOUT 1000 /* Default timeout (ms) */
|
||||
#define TRIES 6 /* Number of attempts to send each packet */
|
||||
#define TIMEOUT_LIMIT ((1 << TRIES)-1)
|
||||
|
||||
char *__progname;
|
||||
int peer;
|
||||
int timeout = TIMEOUT;
|
||||
int rexmtval = TIMEOUT;
|
||||
int timeout = TIMEOUT; /* Current timeout value */
|
||||
int timeout_quit = 0;
|
||||
int rexmtval = TIMEOUT; /* Basic timeout value */
|
||||
int maxtimeout = TIMEOUT_LIMIT*TIMEOUT;
|
||||
sigjmp_buf timeoutbuf;
|
||||
|
||||
#define PKTSIZE MAX_SEGSIZE+4
|
||||
char buf[PKTSIZE];
|
||||
|
@ -121,6 +123,7 @@ int set_blksize(char *, char **);
|
|||
int set_blksize2(char *, char **);
|
||||
int set_tsize(char *, char **);
|
||||
int set_timeout(char *, char **);
|
||||
int set_utimeout(char *, char **);
|
||||
|
||||
struct options {
|
||||
const char *o_opt;
|
||||
|
@ -130,6 +133,7 @@ struct options {
|
|||
{ "blksize2", set_blksize2 },
|
||||
{ "tsize", set_tsize },
|
||||
{ "timeout", set_timeout },
|
||||
{ "utimeout", set_utimeout },
|
||||
{ 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
|
||||
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
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
|
@ -589,7 +647,6 @@ main(int argc, char **argv)
|
|||
|
||||
/* Other basic setup */
|
||||
from.sin_family = AF_INET;
|
||||
alarm(0);
|
||||
|
||||
/* 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
|
||||
set_timeout(char *val, char **ret)
|
||||
|
@ -824,14 +883,32 @@ set_timeout(char *val, char **ret)
|
|||
if ( to < 1 || to > 255 || *vend )
|
||||
return 0;
|
||||
|
||||
timeout = to;
|
||||
rexmtval = to;
|
||||
maxtimeout = TIMEOUT_LIMIT*to;
|
||||
rexmtval = timeout = to;
|
||||
maxtimeout = rexmtval*TIMEOUT_LIMIT;
|
||||
|
||||
sprintf(*ret = b_ret, "%lu", to);
|
||||
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
|
||||
*/
|
||||
|
@ -1030,20 +1107,6 @@ validate_access(char *filename, int mode, struct formats *pf)
|
|||
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.
|
||||
*/
|
||||
|
@ -1058,28 +1121,24 @@ tftp_sendfile(struct formats *pf, struct tftphdr *oap, int oacklen)
|
|||
ap = (struct tftphdr *)ackbuf;
|
||||
|
||||
if (oap) {
|
||||
timeout = 0;
|
||||
timeout = rexmtval;
|
||||
(void)sigsetjmp(timeoutbuf,1);
|
||||
oack:
|
||||
if (send(peer, oap, oacklen, 0) != oacklen) {
|
||||
syslog(LOG_ERR, "tftpd: oack: %m\n");
|
||||
syslog(LOG_WARN, "tftpd: oack: %m\n");
|
||||
goto abort;
|
||||
}
|
||||
for ( ; ; ) {
|
||||
set_signal(SIGALRM, timer, SA_RESTART);
|
||||
alarm(rexmtval);
|
||||
n = recv(peer, ackbuf, sizeof(ackbuf), 0);
|
||||
alarm(0);
|
||||
n = recv_time(peer, ackbuf, sizeof(ackbuf), 0, timeout);
|
||||
if (n < 0) {
|
||||
syslog(LOG_ERR, "tftpd: read: %m\n");
|
||||
syslog(LOG_WARN, "tftpd: read: %m\n");
|
||||
goto abort;
|
||||
}
|
||||
ap->th_opcode = ntohs((u_short)ap->th_opcode);
|
||||
ap->th_block = ntohs((u_short)ap->th_block);
|
||||
|
||||
if (ap->th_opcode == ERROR) {
|
||||
syslog(LOG_ERR, "tftp: client does not accept "
|
||||
"options\n");
|
||||
syslog(LOG_WARN, "tftp: client does not accept options\n");
|
||||
goto abort;
|
||||
}
|
||||
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_block = htons((u_short)block);
|
||||
timeout = 0;
|
||||
timeout = rexmtval;
|
||||
(void) sigsetjmp(timeoutbuf,1);
|
||||
|
||||
if (send(peer, dp, size + 4, 0) != size + 4) {
|
||||
syslog(LOG_ERR, "tftpd: write: %m");
|
||||
syslog(LOG_WARN, "tftpd: write: %m");
|
||||
goto abort;
|
||||
}
|
||||
read_ahead(file, pf->f_convert);
|
||||
for ( ; ; ) {
|
||||
set_signal(SIGALRM, timer, SA_RESTART);
|
||||
alarm(rexmtval); /* read the ack */
|
||||
n = recv(peer, ackbuf, sizeof (ackbuf), 0);
|
||||
alarm(0);
|
||||
n = recv_time(peer, ackbuf, sizeof (ackbuf), 0, timeout);
|
||||
if (n < 0) {
|
||||
syslog(LOG_ERR, "tftpd: read(ack): %m");
|
||||
syslog(LOG_WARN, "tftpd: read(ack): %m");
|
||||
goto abort;
|
||||
}
|
||||
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();
|
||||
do {
|
||||
timeout = 0;
|
||||
timeout = rexmtval;
|
||||
|
||||
if (!block && oap) {
|
||||
ap = (struct tftphdr *)ackbuf;
|
||||
|
@ -1181,20 +1237,16 @@ tftp_recvfile(struct formats *pf, struct tftphdr *oap, int oacklen)
|
|||
}
|
||||
block++;
|
||||
(void) sigsetjmp(timeoutbuf,1);
|
||||
set_signal(SIGALRM, timer, SA_RESTART);
|
||||
send_ack:
|
||||
if (send(peer, ackbuf, acksize, 0) != acksize) {
|
||||
syslog(LOG_ERR, "tftpd: write(ack): %m");
|
||||
syslog(LOG_WARN, "tftpd: write(ack): %m");
|
||||
goto abort;
|
||||
}
|
||||
write_behind(file, pf->f_convert);
|
||||
for ( ; ; ) {
|
||||
set_signal(SIGALRM, timer, SA_RESTART);
|
||||
alarm(rexmtval);
|
||||
n = recv(peer, dp, PKTSIZE, 0);
|
||||
alarm(0);
|
||||
n = recv_time(peer, dp, PKTSIZE, 0, timeout);
|
||||
if (n < 0) { /* really? */
|
||||
syslog(LOG_ERR, "tftpd: read: %m");
|
||||
syslog(LOG_WARN, "tftpd: read: %m");
|
||||
goto abort;
|
||||
}
|
||||
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));
|
||||
(void) send(peer, ackbuf, 4, 0);
|
||||
|
||||
set_signal(SIGALRM, justquit, 0); /* just quit on timeout */
|
||||
alarm(rexmtval);
|
||||
n = recv(peer, buf, sizeof (buf), 0); /* normally times out and quits */
|
||||
alarm(0);
|
||||
timeout_quit = 1; /* just quit on timeout */
|
||||
n = recv_time(peer, buf, sizeof (buf), 0, timeout); /* normally times out and quits */
|
||||
timeout_quit = 0;
|
||||
|
||||
if (n >= 4 && /* if read some data */
|
||||
dp->th_opcode == DATA && /* and got a data block */
|
||||
block == dp->th_block) { /* then my last ack was lost */
|
||||
|
@ -1289,5 +1341,5 @@ nak(int error)
|
|||
}
|
||||
|
||||
if (send(peer, buf, length, 0) != length)
|
||||
syslog(LOG_ERR, "nak: %m");
|
||||
syslog(LOG_WARN, "nak: %m");
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue