kern/135608: sysctl should be able to handle byte values
Kirill Stepanchuk
kstepanchuk at sandvine.com
Mon Jun 15 21:10:12 UTC 2009
>Number: 135608
>Category: kern
>Synopsis: sysctl should be able to handle byte values
>Confidential: no
>Severity: non-critical
>Priority: low
>Responsible: freebsd-bugs
>State: open
>Quarter:
>Keywords:
>Date-Required:
>Class: change-request
>Submitter-Id: current-users
>Arrival-Date: Mon Jun 15 21:10:06 UTC 2009
>Closed-Date:
>Last-Modified:
>Originator: Kirill Stepanchuk
>Release: HEAD
>Organization:
Sandvine
>Environment:
>Description:
Here is a patch to allow the sysctl interface to export byte values properly. This is sometimes needed if certain hardware needs to store a value as a byte in a struct. The sysctl interface would assume that the value is an 'int', with extraneous bits coming from neighbouring fields. This change adds a byte handler that internally converts unsigned bytes to ints, and then exports them to sysctl like a regular unsigned integer.
>How-To-Repeat:
>Fix:
Patch attached with submission follows:
--- sysctl.h.orig 2009-06-15 16:58:07.961115600 -0400
+++ sysctl.h 2009-06-15 16:57:49.007384100 -0400
@@ -170,6 +170,7 @@
#define SYSCTL_IN(r, p, l) (r->newfunc)(r, p, l)
#define SYSCTL_OUT(r, p, l) (r->oldfunc)(r, p, l)
+int sysctl_handle_byte(SYSCTL_HANDLER_ARGS);
int sysctl_handle_int(SYSCTL_HANDLER_ARGS);
int sysctl_msec_to_ticks(SYSCTL_HANDLER_ARGS);
int sysctl_handle_long(SYSCTL_HANDLER_ARGS);
@@ -287,6 +288,15 @@
sysctl_add_oid(ctx, parent, nbr, name, CTLTYPE_STRING|(access), \
arg, len, sysctl_handle_string, "A", __DESCR(descr))
+/* Oid for an unsigned byte. If ptr is NULL, val is returned. */
+#define SYSCTL_BYTE(parent, nbr, name, access, ptr, val, descr) \
+ SYSCTL_OID(parent, nbr, name, CTLTYPE_UINT|(access), \
+ ptr, val, sysctl_handle_byte, "IU", descr)
+
+#define SYSCTL_ADD_BYTE(ctx, parent, nbr, name, access, ptr, val, descr) \
+ sysctl_add_oid(ctx, parent, nbr, name, CTLTYPE_UINT|(access), \
+ ptr, val, sysctl_handle_byte, "IU", descr)
+
/* Oid for an int. If ptr is NULL, val is returned. */
#define SYSCTL_INT(parent, nbr, name, access, ptr, val, descr) \
SYSCTL_OID(parent, nbr, name, CTLTYPE_INT|CTLFLAG_MPSAFE|(access), \
--- kern_sysctl.c.orig 2009-06-15 16:59:21.041579100 -0400
+++ kern_sysctl.c 2009-06-15 16:59:03.103505100 -0400
@@ -906,6 +906,45 @@
*/
/*
+ * Handle an unsigned byte, converting to an int in the process
+ * Two cases:
+ * a variable: point arg1 at it.
+ * a constant: pass it in arg2.
+ */
+
+int
+sysctl_handle_byte(SYSCTL_HANDLER_ARGS)
+{
+ int tmp, error = 0;
+
+ /*
+ * Attempt to get a coherent snapshot by making a copy of the data.
+ * Convert unsigned byte to int
+ */
+ if (arg1)
+ tmp = *(uint8_t *)arg1;
+ else
+ tmp = arg2;
+ error = SYSCTL_OUT(req, &tmp, sizeof(int));
+
+ if (error || !req->newptr)
+ return (error);
+
+ if (!arg1)
+ error = EPERM;
+ else {
+ error = SYSCTL_IN(req, &tmp, sizeof(int));
+ if (!error) {
+ if (tmp > 255 || tmp < 0)
+ error = EINVAL;
+ else
+ *(uint8_t*)arg1 = (uint8_t)tmp;
+ }
+ }
+ return (error);
+}
+
+/*
* Handle an int, signed or unsigned.
* Two cases:
* a variable: point arg1 at it.
>Release-Note:
>Audit-Trail:
>Unformatted:
More information about the freebsd-bugs
mailing list