mail archive of the barebox mailing list
 help / color / mirror / Atom feed
From: Enrico Scholz <enrico.scholz@sigma-chemnitz.de>
To: barebox@lists.infradead.org
Cc: Enrico Scholz <enrico.scholz@sigma-chemnitz.de>
Subject: [PATCH v3 08/18] tftp: allocate buffers and fifo dynamically
Date: Mon, 15 Aug 2022 10:42:12 +0200	[thread overview]
Message-ID: <1dca8aa1f29d25f28b90f0c29c339df82e7d977f.1660552646.git.enrico.scholz@sigma-chemnitz.de> (raw)
In-Reply-To: <cover.1660552646.git.enrico.scholz@sigma-chemnitz.de>

Use the actual blocksize for allocating buffers instead of assuming an
hardcoded value.

This requires to add an additional 'START' state which is entered
after receiving (RRQ) or sending (WRQ) the OACK.  Without it, the next
state would be entered and the (not allocated yet) fifo be used.

Signed-off-by: Enrico Scholz <enrico.scholz@sigma-chemnitz.de>
---
 fs/tftp.c | 91 ++++++++++++++++++++++++++++++++++++-------------------
 1 file changed, 59 insertions(+), 32 deletions(-)

diff --git a/fs/tftp.c b/fs/tftp.c
index b552a5dc2f63..0b6d57c4603f 100644
--- a/fs/tftp.c
+++ b/fs/tftp.c
@@ -63,10 +63,12 @@
 #define STATE_WAITACK	6
 #define STATE_LAST	7
 #define STATE_DONE	8
+/* OACK from server has been received and we can begin to sent either the ACK
+   (for RRQ) or data (for WRQ) */
+#define STATE_START	9
 
 #define TFTP_BLOCK_SIZE		512	/* default TFTP block size */
 #define TFTP_MTU_SIZE		1432	/* MTU based block size */
-#define TFTP_FIFO_SIZE		4096
 
 #define TFTP_ERR_RESEND	1
 
@@ -106,6 +108,7 @@ static char const * const tftp_states[] = {
 	[STATE_WAITACK] = "WAITACK",
 	[STATE_LAST] = "LAST",
 	[STATE_DONE] = "DONE",
+	[STATE_START] = "START",
 };
 
 static int tftp_send(struct file_priv *priv)
@@ -294,19 +297,9 @@ static void tftp_recv(struct file_priv *priv,
 	case TFTP_OACK:
 		tftp_parse_oack(priv, pkt, len);
 		priv->tftp_con->udp->uh_dport = uh_sport;
-
-		if (priv->push) {
-			/* send first block */
-			priv->state = STATE_WDATA;
-			priv->block = 1;
-		} else {
-			/* send ACK */
-			priv->state = STATE_OACK;
-			priv->block = 0;
-			tftp_send(priv);
-		}
-
+		priv->state = STATE_START;
 		break;
+
 	case TFTP_DATA:
 		len -= 2;
 		priv->block = ntohs(*(uint16_t *)pkt);
@@ -330,6 +323,12 @@ static void tftp_recv(struct file_priv *priv,
 			/* Same block again; ignore it. */
 			break;
 
+		if (len > priv->blocksize) {
+			pr_warn("tftp: oversized packet (%u > %d) received\n",
+				len, priv->blocksize);
+			break;
+		}
+
 		priv->last_block = priv->block;
 
 		tftp_timer_reset(priv);
@@ -372,6 +371,36 @@ static void tftp_handler(void *ctx, char *packet, unsigned len)
 	tftp_recv(priv, pkt, net_eth_to_udplen(packet), udp->uh_sport);
 }
 
+
+static int tftp_start_transfer(struct file_priv *priv)
+{
+	priv->fifo = kfifo_alloc(priv->blocksize);
+	if (!priv->fifo)
+		return -ENOMEM;
+
+	if (priv->push) {
+		priv->buf = xmalloc(priv->blocksize);
+		if (!priv->buf) {
+			kfifo_free(priv->fifo);
+			priv->fifo = NULL;
+			return -ENOMEM;
+		}
+	}
+
+	if (priv->push) {
+		/* send first block */
+		priv->state = STATE_WDATA;
+		priv->block = 1;
+	} else {
+		/* send ACK */
+		priv->state = STATE_OACK;
+		priv->block = 0;
+		tftp_send(priv);
+	}
+
+	return 0;
+}
+
 static struct file_priv *tftp_do_open(struct device_d *dev,
 		int accmode, struct dentry *dentry)
 {
@@ -403,47 +432,45 @@ static struct file_priv *tftp_do_open(struct device_d *dev,
 	priv->blocksize = TFTP_BLOCK_SIZE;
 	priv->block_requested = -1;
 
-	priv->fifo = kfifo_alloc(TFTP_FIFO_SIZE);
-	if (!priv->fifo) {
-		ret = -ENOMEM;
-		goto out;
-	}
-
 	parseopt_hu(fsdev->options, "port", &port);
 
 	priv->tftp_con = net_udp_new(tpriv->server, port, tftp_handler, priv);
 	if (IS_ERR(priv->tftp_con)) {
 		ret = PTR_ERR(priv->tftp_con);
-		goto out1;
+		goto out;
 	}
 
 	ret = tftp_send(priv);
 	if (ret)
-		goto out2;
+		goto out1;
 
 	tftp_timer_reset(priv);
-	while (priv->state != STATE_RDATA &&
-			priv->state != STATE_DONE &&
-			priv->state != STATE_WDATA) {
+	while (priv->state != STATE_DONE && priv->state != STATE_START) {
 		ret = tftp_poll(priv);
 		if (ret == TFTP_ERR_RESEND)
 			tftp_send(priv);
 		if (ret < 0)
-			goto out2;
+			goto out1;
 	}
 
-	if (priv->state == STATE_DONE && priv->err) {
+	if (priv->state == STATE_DONE) {
+		/* this should not happen; STATE_DONE without error happens
+		   after completing the transfer but this has not been started
+		   yet */
+		if (WARN_ON(priv->err == 0))
+			priv->err = -EIO;
+
 		ret = priv->err;
-		goto out2;
+		goto out1;
 	}
 
-	priv->buf = xmalloc(priv->blocksize);
+	ret = tftp_start_transfer(priv);
+	if (ret < 0)
+		goto out1;
 
 	return priv;
-out2:
-	net_unregister(priv->tftp_con);
 out1:
-	kfifo_free(priv->fifo);
+	net_unregister(priv->tftp_con);
 out:
 	free(priv);
 
@@ -561,7 +588,7 @@ static int tftp_read(struct device_d *dev, FILE *f, void *buf, size_t insize)
 		if (priv->state == STATE_DONE)
 			return outsize;
 
-		if (TFTP_FIFO_SIZE - kfifo_len(priv->fifo) >= priv->blocksize)
+		if (kfifo_len(priv->fifo) == 0)
 			tftp_send(priv);
 
 		ret = tftp_poll(priv);
-- 
2.37.1




  parent reply	other threads:[~2022-08-15  8:53 UTC|newest]

Thread overview: 25+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-08-15  8:42 [PATCH v3 00/18] add "windowsize" (RFC 7440) support for tftp Enrico Scholz
2022-08-15  8:42 ` [PATCH v3 01/18] progress: add close_progress() to display some statistics Enrico Scholz
2022-08-19  7:21   ` Sascha Hauer
2022-08-19  7:53     ` Enrico Scholz
2022-08-15  8:42 ` [PATCH v3 02/18] libfile:copy_file: show statistics in verbose mode Enrico Scholz
2022-08-15  8:42 ` [PATCH v3 03/18] tftp: add some 'const' annotations Enrico Scholz
2022-08-15  8:42 ` [PATCH v3 04/18] tftp: allow to change tftp port Enrico Scholz
2022-08-15  8:42 ` [PATCH v3 05/18] cmd:tftp: add '-P' option to set tftp server port number Enrico Scholz
2022-08-15  8:42 ` [PATCH v3 06/18] tftp: minor refactoring of RRQ/WRQ packet generation code Enrico Scholz
2022-08-15  8:42 ` [PATCH v3 07/18] tftp: replace hardcoded blksize by global constant Enrico Scholz
2022-08-15  8:42 ` Enrico Scholz [this message]
2022-08-15  8:42 ` [PATCH v3 09/18] tftp: add sanity check for OACK response Enrico Scholz
2022-08-15  8:42 ` [PATCH v3 10/18] tftp: record whether tftp file is opened for lookup operation only Enrico Scholz
2022-08-15  8:42 ` [PATCH v3 11/18] tftp: reduce block size on lookup requests Enrico Scholz
2022-08-15  8:42 ` [PATCH v3 12/18] tftp: refactor data processing Enrico Scholz
2022-08-15  8:42 ` [PATCH v3 13/18] tftp: detect out-of-memory situations Enrico Scholz
2022-08-15  8:42 ` [PATCH v3 14/18] tftp: implement 'windowsize' (RFC 7440) support Enrico Scholz
2022-08-15  8:42 ` [PATCH v3 15/18] tftp: do not use 'priv->block' for RRQ Enrico Scholz
2022-08-15  8:42 ` [PATCH v3 16/18] tftp: add debug_assert() macro Enrico Scholz
2022-08-15  8:42 ` [PATCH v3 17/18] tftp: reorder tftp packets Enrico Scholz
2022-08-15  8:42 ` [PATCH v3 18/18] tftp: add selftest Enrico Scholz
2022-08-16  9:19 ` [PATCH v3 00/18] add "windowsize" (RFC 7440) support for tftp Sascha Hauer
2022-08-16  9:40   ` Enrico Scholz
2022-08-19  7:10     ` Sascha Hauer
2022-08-19  7:22 ` Sascha Hauer

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1dca8aa1f29d25f28b90f0c29c339df82e7d977f.1660552646.git.enrico.scholz@sigma-chemnitz.de \
    --to=enrico.scholz@sigma-chemnitz.de \
    --cc=barebox@lists.infradead.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox