summaryrefslogtreecommitdiff
path: root/sys/src/boot
diff options
context:
space:
mode:
authorcinap_lenrek <cinap_lenrek@gmx.de>2012-09-20 09:33:40 +0200
committercinap_lenrek <cinap_lenrek@gmx.de>2012-09-20 09:33:40 +0200
commit9a06f93b71e339741ac6078a0246e11e789aa784 (patch)
tree48312aa7a5c42c174f1c6b94f7bcd6e9a83d15d3 /sys/src/boot
parent9d182f906d2d97316b151851039ffb33bb4e79e0 (diff)
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).
Diffstat (limited to 'sys/src/boot')
-rw-r--r--sys/src/boot/pc/pxe.c15
1 files changed, 10 insertions, 5 deletions
diff --git a/sys/src/boot/pc/pxe.c b/sys/src/boot/pc/pxe.c
index 97ee259cb..9f6d74b29 100644
--- a/sys/src/boot/pc/pxe.c
+++ b/sys/src/boot/pc/pxe.c
@@ -249,16 +249,21 @@ read(void *f, void *data, int len)
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 @@ tftpopen(Tftp *t, char *path, IP4 sip, IP4 dip, IP4 gip)
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))