Date: Mon, 15 Jun 2009 21:07:15 GMT From: Kirill Stepanchuk <kstepanchuk@sandvine.com> To: freebsd-gnats-submit@FreeBSD.org Subject: kern/135608: sysctl should be able to handle byte values Message-ID: <200906152107.n5FL7FBU071482@www.freebsd.org> Resent-Message-ID: <200906152110.n5FLA7UI045306@freefall.freebsd.org>
next in thread | raw e-mail | index | archive | help
>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:
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200906152107.n5FL7FBU071482>