Deleted Added
full compact
45c45
< "$FreeBSD: head/libexec/tftpd/tftpd.c 71926 2001-02-02 10:53:02Z asmodai $";
---
> "$FreeBSD: head/libexec/tftpd/tftpd.c 84047 2001-09-27 20:50:14Z obrien $";
81a82
> #define MAX_TIMEOUTS 5
85c86
< int maxtimeout = 5*TIMEOUT;
---
> int max_rexmtval = 2*TIMEOUT;
112a114
> static void oack __P(());
313a316,330
> struct options {
> char *o_type;
> char *o_request;
> int o_reply; /* turn into union if need be */
> } options[] = {
> { "tsize" }, /* OPT_TSIZE */
> { "timeout" }, /* OPT_TIMEOUT */
> { NULL }
> };
>
> enum opt_enum {
> OPT_TSIZE = 0,
> OPT_TIMEOUT,
> };
>
323c340
< int first = 1, ecode;
---
> int i, first = 1, has_options = 0, ecode;
325c342
< char *filename, *mode;
---
> char *filename, *mode, *option, *ccp;
352a370,400
> while (++cp < buf + size) {
> for (i = 2, ccp = cp; i > 0; ccp++) {
> if (ccp >= buf + size) {
> nak(EBADOP);
> exit(1);
> } else if (*ccp == '\0')
> i--;
> }
> for (option = cp; *cp; cp++)
> if (isupper(*cp))
> *cp = tolower(*cp);
> for (i = 0; options[i].o_type != NULL; i++)
> if (strcmp(option, options[i].o_type) == 0) {
> options[i].o_request = ++cp;
> has_options = 1;
> }
> cp = ccp-1;
> }
>
> if (options[OPT_TIMEOUT].o_request) {
> int to = atoi(options[OPT_TIMEOUT].o_request);
> if (to < 1 || to > 255) {
> nak(EBADOP);
> exit(1);
> }
> else if (to <= max_rexmtval)
> options[OPT_TIMEOUT].o_reply = rexmtval = to;
> else
> options[OPT_TIMEOUT].o_request = NULL;
> }
>
353a402,403
> if (has_options)
> oack();
470a521,528
> if (options[OPT_TSIZE].o_request) {
> if (mode == RRQ)
> options[OPT_TSIZE].o_reply = stbuf.st_size;
> else
> /* XXX Allows writes of all sizes. */
> options[OPT_TSIZE].o_reply =
> atoi(options[OPT_TSIZE].o_request);
> }
481c539
< int timeout;
---
> int timeouts;
487,489c545
<
< timeout += rexmtval;
< if (timeout >= maxtimeout)
---
> if (++timeouts > MAX_TIMEOUTS)
518c574
< timeout = 0;
---
> timeouts = 0;
581c637
< timeout = 0;
---
> timeouts = 0;
653a710
> { EOPTNEG, "Option negotiation" },
702a760,813
>
> /*
> * Send an oack packet (option acknowledgement).
> */
> static void
> oack()
> {
> struct tftphdr *tp, *ap;
> int size, i, n;
> char *bp;
>
> tp = (struct tftphdr *)buf;
> bp = buf + 2;
> size = sizeof(buf) - 2;
> tp->th_opcode = htons((u_short)OACK);
> for (i = 0; options[i].o_type != NULL; i++) {
> if (options[i].o_request) {
> n = snprintf(bp, size, "%s%c%d", options[i].o_type,
> 0, options[i].o_reply);
> bp += n+1;
> size -= n+1;
> if (size < 0) {
> syslog(LOG_ERR, "oack: buffer overflow");
> exit(1);
> }
> }
> }
> size = bp - buf;
> ap = (struct tftphdr *)ackbuf;
> signal(SIGALRM, timer);
> timeouts = 0;
>
> (void)setjmp(timeoutbuf);
> if (send(peer, buf, size, 0) != size) {
> syslog(LOG_INFO, "oack: %m");
> exit(1);
> }
>
> for (;;) {
> alarm(rexmtval);
> n = recv(peer, ackbuf, sizeof (ackbuf), 0);
> alarm(0);
> if (n < 0) {
> syslog(LOG_ERR, "recv: %m");
> exit(1);
> }
> ap->th_opcode = ntohs((u_short)ap->th_opcode);
> ap->th_block = ntohs((u_short)ap->th_block);
> if (ap->th_opcode == ERROR)
> exit(1);
> if (ap->th_opcode == ACK && ap->th_block == 0)
> break;
> }
> }