Index: head/stand/libsa/tftp.c =================================================================== --- head/stand/libsa/tftp.c +++ head/stand/libsa/tftp.c @@ -163,7 +163,7 @@ } static void -tftp_sendack(struct tftp_handle *h) +tftp_sendack(struct tftp_handle *h, u_short block) { struct { u_char header[HEADER_SIZE]; @@ -173,7 +173,7 @@ wbuf.t.th_opcode = htons((u_short) ACK); wtail = (char *) &wbuf.t.th_block; - wbuf.t.th_block = htons((u_short) h->currblock); + wbuf.t.th_block = htons(block); wtail += 2; sendudp(h->iodesc, &wbuf.t, wtail - (char *) &wbuf.t); @@ -205,9 +205,17 @@ case DATA: { int got; + if (htons(t->th_block) < (u_short) d->xid) { + /* + * Apparently our ACK was missed, re-send. + */ + tftp_sendack(h, htons(t->th_block)); + free(ptr); + return (-1); + } if (htons(t->th_block) != (u_short) d->xid) { /* - * Expected block? + * Packet from the future, drop this. */ free(ptr); return (-1); @@ -219,7 +227,7 @@ struct udphdr *uh; uh = (struct udphdr *) t - 1; d->destport = uh->uh_sport; - } /* else check uh_sport has not changed??? */ + } got = len - (t->th_data - (char *)t); *pkt = ptr; *payload = t; @@ -364,7 +372,7 @@ h->islastblock = 0; if (res < h->tftp_blksize) { h->islastblock = 1; /* very short file */ - tftp_sendack(h); + tftp_sendack(h, h->currblock); } return (0); }