git: 92570f67c791 - main - tftp: Correctly propagate transfer errors.

From: Dag-Erling Smørgrav <des_at_FreeBSD.org>
Date: Fri, 10 Mar 2023 13:29:18 UTC
The branch main has been updated by des:

URL: https://cgit.FreeBSD.org/src/commit/?id=92570f67c7911126ce742a3dfe1b97046091ed0e

commit 92570f67c7911126ce742a3dfe1b97046091ed0e
Author:     Dag-Erling Smørgrav <des@FreeBSD.org>
AuthorDate: 2023-03-10 13:24:28 +0000
Commit:     Dag-Erling Smørgrav <des@FreeBSD.org>
CommitDate: 2023-03-10 13:25:16 +0000

    tftp: Correctly propagate transfer errors.
    
    Sponsored by:   Klara, Inc.
    Reviewed by:    markj
    Differential Revision:  https://reviews.freebsd.org/D38958
---
 usr.bin/tftp/main.c | 14 +++++++++-----
 usr.bin/tftp/tftp.c | 44 +++++++++++++++++++++++---------------------
 usr.bin/tftp/tftp.h |  5 ++---
 3 files changed, 34 insertions(+), 29 deletions(-)

diff --git a/usr.bin/tftp/main.c b/usr.bin/tftp/main.c
index 05d8b31331f6..9cc18fbb0d5b 100644
--- a/usr.bin/tftp/main.c
+++ b/usr.bin/tftp/main.c
@@ -84,7 +84,7 @@ typedef struct	sockaddr_storage peeraddr;
 static int	connected;
 static char	mode[32];
 static jmp_buf	toplevel;
-volatile int	txrx_error;
+static int	txrx_error;
 static int	peer;
 
 #define	MAX_MARGV	20
@@ -501,7 +501,8 @@ put(int argc, char *argv[])
 		if (verbose)
 			printf("putting %s to %s:%s [%s]\n",
 			    cp, hostname, targ, mode);
-		xmitfile(peer, port, fd, targ, mode);
+		if (xmitfile(peer, port, fd, targ, mode))
+			txrx_error = 1;
 		close(fd);
 		return;
 	}
@@ -529,7 +530,8 @@ put(int argc, char *argv[])
 		if (verbose)
 			printf("putting %s to %s:%s [%s]\n",
 			    argv[n], hostname, path, mode);
-		xmitfile(peer, port, fd, path, mode);
+		if (xmitfile(peer, port, fd, path, mode) != 0)
+			txrx_error = 1;
 		close(fd);
 
 		free(path);
@@ -605,7 +607,8 @@ get(int argc, char *argv[])
 			if (verbose)
 				printf("getting from %s:%s to %s [%s]\n",
 				    hostname, src, cp, mode);
-			recvfile(peer, port, fd, src, mode);
+			if (recvfile(peer, port, fd, src, mode) != 0)
+				txrx_error = 1;
 			break;
 		}
 		cp = tail(src);         /* new .. jdg */
@@ -617,7 +620,8 @@ get(int argc, char *argv[])
 		if (verbose)
 			printf("getting from %s:%s to %s [%s]\n",
 			    hostname, src, cp, mode);
-		recvfile(peer, port, fd, src, mode);
+		if (recvfile(peer, port, fd, src, mode) != 0)
+			txrx_error = 1;
 	}
 }
 
diff --git a/usr.bin/tftp/tftp.c b/usr.bin/tftp/tftp.c
index 31fefd8f22e2..d5f36e77d853 100644
--- a/usr.bin/tftp/tftp.c
+++ b/usr.bin/tftp/tftp.c
@@ -68,11 +68,11 @@ __FBSDID("$FreeBSD$");
 /*
  * Send the requested file.
  */
-void
+int
 xmitfile(int peer, char *port, int fd, char *name, char *mode)
 {
 	struct tftphdr *rp;
-	int n, i;
+	int n, i, ret = 0;
 	uint16_t block;
 	struct sockaddr_storage serv;	/* valid server port number */
 	char recvbuffer[MAXPKTSIZE];
@@ -102,7 +102,7 @@ xmitfile(int peer, char *port, int fd, char *name, char *mode)
 		n = send_wrq(peer, name, mode);
 		if (n > 0) {
 			printf("Cannot send WRQ packet\n");
-			return;
+			return -1;
 		}
 
 		/*
@@ -131,11 +131,11 @@ xmitfile(int peer, char *port, int fd, char *name, char *mode)
 	}
 	if (i == 12) {
 		printf("Transfer timed out.\n");
-		return;
+		return -1;
 	}
 	if (rp->th_opcode == ERROR) {
 		printf("Got ERROR, aborted\n");
-		return;
+		return -1;
 	}
 
 	/*
@@ -146,7 +146,7 @@ xmitfile(int peer, char *port, int fd, char *name, char *mode)
 		if (!options_rfc_enabled) {
 			printf("Got OACK while options are not enabled!\n");
 			send_error(peer, EBADOP);
-			return;
+			return -1;
 		}
 
 		parse_options(peer, rp->th_stuff, n + 2);
@@ -154,29 +154,29 @@ xmitfile(int peer, char *port, int fd, char *name, char *mode)
 
 	if (read_init(fd, NULL, mode) < 0) {
 		warn("read_init()");
-		return;
+		return -1;
 	}
 
 	block = 1;
-	tftp_send(peer, &block, &tftp_stats);
+	if (tftp_send(peer, &block, &tftp_stats) != 0)
+		ret = -1;
 
 	read_close();
 	if (tftp_stats.amount > 0)
 		printstats("Sent", verbose, &tftp_stats);
-
-	txrx_error = 1;
+	return ret;
 }
 
 /*
  * Receive a file.
  */
-void
+int
 recvfile(int peer, char *port, int fd, char *name, char *mode)
 {
 	struct tftphdr *rp;
 	uint16_t block;
 	char recvbuffer[MAXPKTSIZE];
-	int n, i;
+	int n, i, ret = 0;
 	struct tftp_stats tftp_stats;
 
 	stats_init(&tftp_stats);
@@ -202,7 +202,7 @@ recvfile(int peer, char *port, int fd, char *name, char *mode)
 		n = send_rrq(peer, name, mode);
 		if (n > 0) {
 			printf("Cannot send RRQ packet\n");
-			return;
+			return -1;
 		}
 
 		/*
@@ -231,16 +231,16 @@ recvfile(int peer, char *port, int fd, char *name, char *mode)
 	}
 	if (i == 12) {
 		printf("Transfer timed out.\n");
-		return;
+		return -1;
 	}
 	if (rp->th_opcode == ERROR) {
 		tftp_log(LOG_ERR, "Error code %d: %s", rp->th_code, rp->th_msg);
-		return;
+		return -1;
 	}
 
 	if (write_init(fd, NULL, mode) < 0) {
 		warn("write_init");
-		return;
+		return -1;
 	}
 
 	/*
@@ -251,7 +251,7 @@ recvfile(int peer, char *port, int fd, char *name, char *mode)
 		if (!options_rfc_enabled) {
 			printf("Got OACK while options are not enabled!\n");
 			send_error(peer, EBADOP);
-			return;
+			return -1;
 		}
 
 		parse_options(peer, rp->th_stuff, n + 2);
@@ -259,16 +259,18 @@ recvfile(int peer, char *port, int fd, char *name, char *mode)
 		n = send_ack(peer, 0);
 		if (n > 0) {
 			printf("Cannot send ACK on OACK.\n");
-			return;
+			return -1;
 		}
 		block = 0;
-		tftp_receive(peer, &block, &tftp_stats, NULL, 0);
+		if (tftp_receive(peer, &block, &tftp_stats, NULL, 0) != 0)
+			ret = -1;
 	} else {
 		block = 1;
-		tftp_receive(peer, &block, &tftp_stats, rp, n);
+		if (tftp_receive(peer, &block, &tftp_stats, rp, n) != 0)
+			ret = -1;
 	}
 
 	if (tftp_stats.amount > 0)
 		printstats("Received", verbose, &tftp_stats);
-	return;
+	return ret;
 }
diff --git a/usr.bin/tftp/tftp.h b/usr.bin/tftp/tftp.h
index 26e5652d0fdd..680ea2ea4fb6 100644
--- a/usr.bin/tftp/tftp.h
+++ b/usr.bin/tftp/tftp.h
@@ -32,9 +32,8 @@
  * $FreeBSD$
  */
 
-void	recvfile(int peer, char *port, int fd, char *name, char *mode);
-void	xmitfile(int peer, char *port, int fd, char *name, char *mode);
+int	recvfile(int peer, char *port, int fd, char *name, char *mode);
+int	xmitfile(int peer, char *port, int fd, char *name, char *mode);
 
 extern int	verbose;
 extern int	maxtimeout;
-extern volatile int txrx_error;