ref: e1d65ac3036ada75e2d68ca358af55473325d601
parent: dbe53b643f0b5f060a49f2bf2ee9ba913400edf4
author: cinap_lenrek <cinap_lenrek@gmx.de>
date: Thu Sep 20 05:33:40 EDT 2012
tftp: prevent it from hanging if ack packets get lost send ACK reply for duplicate data packets in case our ack response got lost. make sure packets are in sequence and ignore out of oder packets (except the ones we'v already acked).
--- a/sys/src/boot/pc/pxe.c
+++ b/sys/src/boot/pc/pxe.c
@@ -249,16 +249,21 @@
switch(nhgets(t->pkt)){case Tftp_DATA:
seq = nhgets(t->pkt+2);
- if(seq <= t->seq){- putc('@');+ if(seq > t->seq){+ putc('?');continue;
}
hnputs(t->pkt, Tftp_ACK);
while(udpwrite(t->dip, t->gip, t->sport, t->dport, 4, t->pkt))
putc('!');- t->seq = seq;
+ if(seq < t->seq){+ putc('@');+ continue;
+ }
+ t->seq = seq+1;
+ n -= 4;
t->rp = t->pkt + 4;
- t->ep = t->pkt + n;
+ t->ep = t->rp + n;
t->eof = n < Segsize;
break;
case Tftp_ERROR:
@@ -300,7 +305,7 @@
t->sport = xport++;
t->dport = 0;
t->rp = t->ep = 0;
- t->seq = -1;
+ t->seq = 1;
t->eof = 0;
t->nul = 0;
if(r = udpopen(t->sip))
--- a/sys/src/cmd/ip/tftpd.c
+++ b/sys/src/cmd/ip/tftpd.c
@@ -340,9 +340,6 @@
if (nopts == 0)
return 0; /* no options actually seen */
- if (bp + 3 >= ep)
- return -1;
-
if (write(fd, buf, bp - buf) < bp - buf) {syslog(dbg, flog, "tftpd network write error on oack to %s: %r",
raddr);
--- a/sys/src/cmd/ip/tftpfs.c
+++ b/sys/src/cmd/ip/tftpfs.c
@@ -147,7 +147,7 @@
static void
download(void *aux)
{- int fd, cfd, last, block, n, ndata;
+ int fd, cfd, last, block, seq, n, ndata;
char *err, adir[40];
uchar *data;
Channel *c;
@@ -197,6 +197,7 @@
notify(catch);
+ seq = 1;
last = 0;
while(!last){alarm(5000);
@@ -218,33 +219,36 @@
if(n < 4)
continue;
block = nhgets(msg.buf+2);
- if((n -= 4) > 0){- data = erealloc9p(data, ndata + n);
- memcpy(data + ndata, msg.buf+4, n);
- ndata += n;
-
-rloop: /* hanlde read request while downloading */
- if((r != nil) && (r->ifcall.type == Tread) && (r->ifcall.offset < ndata)){- readbuf(r, data, ndata);
- respond(r, nil);
- r = nil;
- }
- if((r == nil) && (nbrecv(c, &r) == 1)){- if(r == nil){- chanfree(c);
- c = nil;
- goto out;
- }
- goto rloop;
- }
- }
- if(n < Segsize)
- last = 1;
+ if(block > seq)
+ continue;
hnputs(msg.buf, Tftp_ACK);
- hnputs(msg.buf+2, block);
if(write(fd, &msg, sizeof(Udphdr) + 4) < 0){err = "send acknowledge: %r";
goto out;
+ }
+ if(block < seq)
+ continue;
+ seq = block+1;
+ n -= 4;
+ if(n < Segsize)
+ last = 1;
+ data = erealloc9p(data, ndata + n);
+ memcpy(data + ndata, msg.buf+4, n);
+ ndata += n;
+
+ rloop: /* hanlde read request while downloading */
+ if((r != nil) && (r->ifcall.type == Tread) && (r->ifcall.offset < ndata)){+ readbuf(r, data, ndata);
+ respond(r, nil);
+ r = nil;
+ }
+ if((r == nil) && (nbrecv(c, &r) == 1)){+ if(r == nil){+ chanfree(c);
+ c = nil;
+ goto out;
+ }
+ goto rloop;
}
break;
}
--
⑨