Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 23 Oct 2018 13:38:40 +0000 (UTC)
From:      Toomas Soome <tsoome@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r339651 - head/stand/libsa
Message-ID:  <201810231338.w9NDceNX031909@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: tsoome
Date: Tue Oct 23 13:38:39 2018
New Revision: 339651
URL: https://svnweb.freebsd.org/changeset/base/339651

Log:
  libsa: re-send ACK for older data packets in tftp
  
  In current tftp code we drop out-of-order packets; however, we should play
  nice and re-send ACK for older data packets we are receiving. This will
  hopefully stop server repeating those packets we already have received.
  Note we do not answer duplicates from "previous" session (that is, session
  with different port number), those will eventually time out.
  
  Differential Revision:	https://reviews.freebsd.org/D17087

Modified:
  head/stand/libsa/tftp.c

Modified: head/stand/libsa/tftp.c
==============================================================================
--- head/stand/libsa/tftp.c	Tue Oct 23 13:12:42 2018	(r339650)
+++ head/stand/libsa/tftp.c	Tue Oct 23 13:38:39 2018	(r339651)
@@ -163,7 +163,7 @@ tftp_senderr(struct tftp_handle *h, u_short errcode, c
 }
 
 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 @@ tftp_sendack(struct tftp_handle *h)
 
 	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 @@ recvtftp(struct iodesc *d, void **pkt, void **payload,
 	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 @@ recvtftp(struct iodesc *d, void **pkt, void **payload,
 			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 @@ tftp_makereq(struct tftp_handle *h)
 			h->islastblock = 0;
 			if (res < h->tftp_blksize) {
 				h->islastblock = 1;	/* very short file */
-				tftp_sendack(h);
+				tftp_sendack(h, h->currblock);
 			}
 			return (0);
 		}



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201810231338.w9NDceNX031909>