git: 9f0f30bc1f5f - main - libnvmf: Add nvmf_nqn_valid_strict() function

From: John Baldwin <jhb_at_FreeBSD.org>
Date: Mon, 28 Jul 2025 18:33:39 UTC
The branch main has been updated by jhb:

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

commit 9f0f30bc1f5f08d25243952bad3fdc6e13a75c2a
Author:     John Baldwin <jhb@FreeBSD.org>
AuthorDate: 2025-07-28 18:33:03 +0000
Commit:     John Baldwin <jhb@FreeBSD.org>
CommitDate: 2025-07-28 18:33:03 +0000

    libnvmf: Add nvmf_nqn_valid_strict() function
    
    This moves the checks previously under #ifdef STRICT in
    nvmf_nqn_valid() into a separate helper for userland.  This
    requires that the NQN starts with "nqn.YYYY-MM." followed by at
    least one additional character.
    
    Reviewed by:    asomers
    Differential Revision:  https://reviews.freebsd.org/D48767
---
 lib/libnvmf/libnvmf.h                |  7 ++++-
 lib/libnvmf/nvmf_controller.c        | 50 ++++++++++++++++++++++++++++++++++++
 sys/dev/nvmf/controller/nvmft_subr.c | 40 -----------------------------
 3 files changed, 56 insertions(+), 41 deletions(-)

diff --git a/lib/libnvmf/libnvmf.h b/lib/libnvmf/libnvmf.h
index 7cdd7e433455..6b38fd286596 100644
--- a/lib/libnvmf/libnvmf.h
+++ b/lib/libnvmf/libnvmf.h
@@ -111,8 +111,13 @@ const void *nvmf_capsule_cqe(const struct nvmf_capsule *nc);
 /* Return a string name for a transport type. */
 const char *nvmf_transport_type(uint8_t trtype);
 
-/* Validate a NVMe Qualified Name. */
+/*
+ * Validate a NVMe Qualified Name.  The second version enforces
+ * stricter checks inline with the specification.  The first version
+ * enforces more minimal checks.
+ */
 bool	nvmf_nqn_valid(const char *nqn);
+bool	nvmf_nqn_valid_strict(const char *nqn);
 
 /* Controller-specific APIs. */
 
diff --git a/lib/libnvmf/nvmf_controller.c b/lib/libnvmf/nvmf_controller.c
index 971dccbe039e..f26f11633e03 100644
--- a/lib/libnvmf/nvmf_controller.c
+++ b/lib/libnvmf/nvmf_controller.c
@@ -7,6 +7,7 @@
 
 #include <sys/utsname.h>
 #include <assert.h>
+#include <ctype.h>
 #include <errno.h>
 #include <string.h>
 #include <unistd.h>
@@ -15,6 +16,55 @@
 #include "internal.h"
 #include "nvmft_subr.h"
 
+bool
+nvmf_nqn_valid_strict(const char *nqn)
+{
+	size_t len;
+
+	if (!nvmf_nqn_valid(nqn))
+		return (false);
+
+	/*
+	 * Stricter checks from the spec.  Linux does not seem to
+	 * require these.
+	 */
+	len = strlen(nqn);
+
+	/*
+	 * NVMF_NQN_MIN_LEN does not include '.' and require at least
+	 * one character of a domain name.
+	 */
+	if (len < NVMF_NQN_MIN_LEN + 2)
+		return (false);
+	if (memcmp("nqn.", nqn, strlen("nqn.")) != 0)
+		return (false);
+	nqn += strlen("nqn.");
+
+	/* Next 4 digits must be a year. */
+	for (u_int i = 0; i < 4; i++) {
+		if (!isdigit(nqn[i]))
+			return (false);
+	}
+	nqn += 4;
+
+	/* '-' between year and month. */
+	if (nqn[0] != '-')
+		return (false);
+	nqn++;
+
+	/* 2 digit month. */
+	for (u_int i = 0; i < 2; i++) {
+		if (!isdigit(nqn[i]))
+			return (false);
+	}
+	nqn += 2;
+
+	/* '.' between month and reverse domain name. */
+	if (nqn[0] != '.')
+		return (false);
+	return (true);
+}
+
 void
 nvmf_init_cqe(void *cqe, const struct nvmf_capsule *nc, uint16_t status)
 {
diff --git a/sys/dev/nvmf/controller/nvmft_subr.c b/sys/dev/nvmf/controller/nvmft_subr.c
index bb2bc0988e81..245971813854 100644
--- a/sys/dev/nvmf/controller/nvmft_subr.c
+++ b/sys/dev/nvmf/controller/nvmft_subr.c
@@ -26,46 +26,6 @@ nvmf_nqn_valid(const char *nqn)
 	len = strnlen(nqn, NVME_NQN_FIELD_SIZE);
 	if (len == 0 || len > NVMF_NQN_MAX_LEN)
 		return (false);
-
-#ifdef STRICT_CHECKS
-	/*
-	 * Stricter checks from the spec.  Linux does not seem to
-	 * require these.
-	 */
-
-	/*
-	 * NVMF_NQN_MIN_LEN does not include '.', and require at least
-	 * one character of a domain name.
-	 */
-	if (len < NVMF_NQN_MIN_LEN + 2)
-		return (false);
-	if (memcmp("nqn.", nqn, strlen("nqn.")) != 0)
-		return (false);
-	nqn += strlen("nqn.");
-
-	/* Next 4 digits must be a year. */
-	for (u_int i = 0; i < 4; i++) {
-		if (!isdigit(nqn[i]))
-			return (false);
-	}
-	nqn += 4;
-
-	/* '-' between year and month. */
-	if (nqn[0] != '-')
-		return (false);
-	nqn++;
-
-	/* 2 digit month. */
-	for (u_int i = 0; i < 2; i++) {
-		if (!isdigit(nqn[i]))
-			return (false);
-	}
-	nqn += 2;
-
-	/* '.' between month and reverse domain name. */
-	if (nqn[0] != '.')
-		return (false);
-#endif
 	return (true);
 }