git: 62c7a7774fc7 - stable/13 - loader: tftp: Don't error on tftp error 0

From: Emmanuel Vadot <manu_at_FreeBSD.org>
Date: Thu, 13 Jan 2022 09:48:59 UTC
The branch stable/13 has been updated by manu:

URL: https://cgit.FreeBSD.org/src/commit/?id=62c7a7774fc73ba7d3bec16346c7e0522ceafb40

commit 62c7a7774fc73ba7d3bec16346c7e0522ceafb40
Author:     Emmanuel Vadot <manu@FreeBSD.org>
AuthorDate: 2021-12-08 15:18:49 +0000
Commit:     Emmanuel Vadot <manu@FreeBSD.org>
CommitDate: 2022-01-13 07:55:22 +0000

    loader: tftp: Don't error on tftp error 0
    
    tftp-hpa sends NAK with tftp error set to 0 when trying to get
    a directory and this is the first thing that loader tries to do
    and this make it hangs.
    
    Reviewed by:    imp, tsoome
    MFC after:      2 weeks
    Sponsored by:   Beckhoff Automation GmbH & Co. KG
    Differential Revision:  https://reviews.freebsd.org/D33406
    
    (cherry picked from commit bf07f2f8623d5e29e814b9dc49a0cdff920778c3)
---
 stand/libsa/tftp.c | 15 ++++++++++-----
 1 file changed, 10 insertions(+), 5 deletions(-)

diff --git a/stand/libsa/tftp.c b/stand/libsa/tftp.c
index 22e03ab58da1..6cfa670b6e22 100644
--- a/stand/libsa/tftp.c
+++ b/stand/libsa/tftp.c
@@ -121,7 +121,7 @@ struct tftprecv_extra {
 
 #define	TFTP_MAX_ERRCODE EOPTNEG
 static const int tftperrors[TFTP_MAX_ERRCODE + 1] = {
-	0,			/* ??? */
+	0,			/* NAK */
 	ENOENT,
 	EPERM,
 	ENOSPC,
@@ -187,6 +187,7 @@ recvtftp(struct iodesc *d, void **pkt, void **payload, time_t tleft,
 	struct tftphdr *t;
 	void *ptr = NULL;
 	ssize_t len;
+	int tftp_error;
 
 	errno = 0;
 	extra = recv_extra;
@@ -233,16 +234,20 @@ recvtftp(struct iodesc *d, void **pkt, void **payload, time_t tleft,
 		return (got);
 	}
 	case ERROR:
-		if ((unsigned)ntohs(t->th_code) > TFTP_MAX_ERRCODE) {
-			printf("illegal tftp error %d\n", ntohs(t->th_code));
+		tftp_error = ntohs(t->th_code);
+		if ((unsigned)tftp_error > TFTP_MAX_ERRCODE) {
+			printf("illegal tftp error %d\n", tftp_error);
 			errno = EIO;
 		} else {
 #ifdef TFTP_DEBUG
-			printf("tftp-error %d\n", ntohs(t->th_code));
+			printf("tftp-error %d\n", tftp_error);
 #endif
-			errno = tftperrors[ntohs(t->th_code)];
+			errno = tftperrors[tftp_error];
 		}
 		free(ptr);
+		/* If we got a NAK return 0, it's usually a directory */
+		if (tftp_error == 0)
+			return (0);
 		return (-1);
 	case OACK: {
 		struct udphdr *uh;