git: b1479a5409cf - stable/13 - LinuxKPI: add kstrtou32_from_user() and mac_pton()

From: Bjoern A. Zeeb <bz_at_FreeBSD.org>
Date: Wed, 18 Jan 2023 16:25:04 UTC
The branch stable/13 has been updated by bz:

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

commit b1479a5409cfe186b45322dbed034f024bfc6ed0
Author:     Bjoern A. Zeeb <bz@FreeBSD.org>
AuthorDate: 2022-10-22 18:02:58 +0000
Commit:     Bjoern A. Zeeb <bz@FreeBSD.org>
CommitDate: 2023-01-18 13:26:37 +0000

    LinuxKPI: add kstrtou32_from_user() and mac_pton()
    
    While here:
    - fix an argument of kstrtouint_from_user() to correct signedness.
    - make kstrtou32() call kstrtouint() to avoid duplication (keep inline
      function)
    
    Add kstrtou32_from_user() based on other examples in the file
    making it a copy of the now fixed kstrtouint_from_user().
    
    Also add a rudimentarily hacked up version of mac_pton() which is
    leanient accepting non-well-formed input but so far only with ':'
    separators.  It does not seem to obviously belong to any networking
    header file so add it here.
    
    Both new functions are needed for debugfs support for iwlwifi hence
    coming together in one commit.
    
    Sponsored by:   The FreeBSD Foundation
    Commented on by:        emaste
    Differential Revision: https://reviews.freebsd.org/D37088
    
    (cherry picked from commit f82cf28b317b6b3ffd1418ab9c5b230145da8f75)
---
 sys/compat/linuxkpi/common/include/linux/kernel.h | 65 ++++++++++++++++++-----
 1 file changed, 52 insertions(+), 13 deletions(-)

diff --git a/sys/compat/linuxkpi/common/include/linux/kernel.h b/sys/compat/linuxkpi/common/include/linux/kernel.h
index 2c40b2f33c41..f3078d94b2b5 100644
--- a/sys/compat/linuxkpi/common/include/linux/kernel.h
+++ b/sys/compat/linuxkpi/common/include/linux/kernel.h
@@ -437,19 +437,8 @@ kstrtou16(const char *cp, unsigned int base, u16 *res)
 static inline int
 kstrtou32(const char *cp, unsigned int base, u32 *res)
 {
-	char *end;
-	unsigned long temp;
-
-	*res = temp = strtoul(cp, &end, base);
 
-	/* skip newline character, if any */
-	if (*end == '\n')
-		end++;
-	if (*cp == 0 || *end != 0)
-		return (-EINVAL);
-	if (temp != (u32)temp)
-		return (-ERANGE);
-	return (0);
+	return (kstrtouint(cp, base, res));
 }
 
 static inline int
@@ -530,7 +519,7 @@ kstrtoint_from_user(const char __user *s, size_t count, unsigned int base,
 
 static inline int
 kstrtouint_from_user(const char __user *s, size_t count, unsigned int base,
-    int *p)
+    unsigned int *p)
 {
 	char buf[36] = {};
 
@@ -543,6 +532,14 @@ kstrtouint_from_user(const char __user *s, size_t count, unsigned int base,
 	return (kstrtouint(buf, base, p));
 }
 
+static inline int
+kstrtou32_from_user(const char __user *s, size_t count, unsigned int base,
+    unsigned int *p)
+{
+
+	return (kstrtouint_from_user(s, count, base, p));
+}
+
 static inline int
 kstrtou8_from_user(const char __user *s, size_t count, unsigned int base,
     u8 *p)
@@ -716,6 +713,48 @@ hex2bin(uint8_t *bindst, const char *hexsrc, size_t binlen)
 	return (0);
 }
 
+static inline bool
+mac_pton(const char *macin, uint8_t *macout)
+{
+	const char *s, *d;
+	uint8_t mac[6], hx, lx;;
+	int i;
+
+	if (strlen(macin) < (3 * 6 - 1))
+		return (false);
+
+	i = 0;
+	s = macin;
+	do {
+		/* Should we also support '-'-delimiters? */
+		d = strchrnul(s, ':');
+		hx = lx = 0;
+		while (s < d) {
+			/* Fail on abc:123:xxx:... */
+			if ((d - s) > 2)
+				return (false);
+			/* We do support non-well-formed strings: 3:45:6:... */
+			if ((d - s) > 1) {
+				hx = _h2b(*s);
+				if (hx < 0)
+					return (false);
+				s++;
+			}
+			lx = _h2b(*s);
+			if (lx < 0)
+				return (false);
+			s++;
+		}
+		mac[i] = (hx << 4) | lx;
+		i++;
+		if (i >= 6)
+			return (false);
+	} while (d != NULL && *d != '\0');
+
+	memcpy(macout, mac, 6);
+	return (true);
+}
+
 #define	DECLARE_FLEX_ARRAY(_t, _n)					\
     struct { struct { } __dummy_ ## _n; _t _n[0]; }