git: b44cc1b479fe - main - loader: do not try to open directories with TFTP

From: Simon J. Gerraty <sjg_at_FreeBSD.org>
Date: Wed, 20 Aug 2025 22:48:38 UTC
The branch main has been updated by sjg:

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

commit b44cc1b479fefc8570611309c3f5a6966fb26e3b
Author:     Simon J. Gerraty <sjg@FreeBSD.org>
AuthorDate: 2025-08-20 22:45:54 +0000
Commit:     Simon J. Gerraty <sjg@FreeBSD.org>
CommitDate: 2025-08-20 22:45:54 +0000

    loader: do not try to open directories with TFTP
    
    Attempting to mount or even open / with some tftp servers
    causes a several minute delay in boot.
    
    Since opening a directory via TFTP does not make sense, we
    avoid it.  We don't know if using TFTP until after net_open()
    has been called.
    
    Add an is_tftp() accessor to avoid everyone having to include
    all the net* headers.
    
    Sponsored by:   Juniper Networks, Inc.
    Differential Revision:  https://reviews.freebsd.org/D51447
---
 stand/common/dev_net.c | 9 ++++++++-
 stand/libsa/mount.c    | 5 ++++-
 stand/libsa/open.c     | 8 ++++++++
 stand/libsa/stand.h    | 3 +++
 4 files changed, 23 insertions(+), 2 deletions(-)

diff --git a/stand/common/dev_net.c b/stand/common/dev_net.c
index 964fa514cac5..10389db27b99 100644
--- a/stand/common/dev_net.c
+++ b/stand/common/dev_net.c
@@ -182,6 +182,7 @@ net_open(struct open_file *f, ...)
 			setenv("boot.netif.mtu", mtu, 1);
 		}
 
+		DEBUG_PRINTF(1,("%s: netproto=%d\n", __func__, netproto));
 	}
 	netdev_opens++;
 	dev->d_opendata = &netdev_sock;
@@ -193,7 +194,7 @@ net_close(struct open_file *f)
 {
 	struct devdesc *dev;
 
-	DEBUG_PRINTF(1,("%s: opens=%d\n", __func__, netdev_opens));
+	DEBUG_PRINTF(2,("%s: opens=%d\n", __func__, netdev_opens));
 
 	dev = f->f_devdata;
 	dev->d_opendata = NULL;
@@ -344,6 +345,12 @@ net_print(int verbose)
 	return (ret);
 }
 
+bool
+is_tftp(void)
+{
+    return (netproto == NET_TFTP);
+}
+
 /*
  * Parses the rootpath if present
  *
diff --git a/stand/libsa/mount.c b/stand/libsa/mount.c
index 73bf6ab8118c..c866dc9c7055 100644
--- a/stand/libsa/mount.c
+++ b/stand/libsa/mount.c
@@ -107,7 +107,10 @@ mount(const char *dev, const char *path, int flags __unused, void *data)
 		fs = file_system[i];
 		if (fs->fo_mount == NULL)
 			continue;
-
+		DEBUG_PRINTF(1,("%s: fs=%s path=%s\n",
+			__func__, fs->fs_name, path));
+		if (is_tftp())
+			break;
 		if (fs->fo_mount(dev, path, &data) != 0)
 			continue;
 
diff --git a/stand/libsa/open.c b/stand/libsa/open.c
index c97aa5977f9e..91848aca7dbe 100644
--- a/stand/libsa/open.c
+++ b/stand/libsa/open.c
@@ -138,6 +138,8 @@ open(const char *fname, int mode)
 	struct fs_ops *fs;
 	struct open_file *f;
 	int fd, i, error, besterror;
+	bool is_dir;
+	size_t n;
 	const char *file;
 
 	TSENTER();
@@ -182,8 +184,14 @@ open(const char *fname, int mode)
 
 	/* pass file name to the different filesystem open routines */
 	besterror = ENOENT;
+	n = strlen(file);
+	is_dir = (n > 0 && file[n - 1] == '/');
 	for (i = 0; file_system[i] != NULL; i++) {
 		fs = file_system[i];
+		if (is_dir && is_tftp()) {
+			error = EOPNOTSUPP;
+			goto err;
+		}
 		error = (fs->fo_open)(file, f);
 		if (error == 0)
 			goto ok;
diff --git a/stand/libsa/stand.h b/stand/libsa/stand.h
index c6a08be2f7e3..233d11ab3ecb 100644
--- a/stand/libsa/stand.h
+++ b/stand/libsa/stand.h
@@ -507,6 +507,9 @@ extern void *reallocf(void *, size_t);
  */
 caddr_t ptov(uintptr_t);
 
+/* dev_net.c */
+bool is_tftp(void);
+
 /* features.c */
 typedef void (feature_iter_fn)(void *, const char *, const char *, bool);