Subject: Re: Reading sysctl values in the kernel
To: Alan Ritter <rittera@cc.wwu.edu>
From: Andrew Brown <atatat@atatdot.net>
List: tech-kern
Date: 07/24/2005 17:27:17
>I'm trying to port the FreeBSD NDIS driver to NetBSD, and right now I'm
>having a bit of trouble figuring out some stuff to do with sysctl's
>(FreeBSD's NDIS driver uses sysctl nodes to emulate the Windows registry).
> I've gotten all of the registry entries from the .inf file entered into
>sysctl nodes using sysctl_createv() (man 9 sysctl), and they seem to be in
>there just fine, since I can see a bunch of stuff from the .inf file from
>typing "sysctl -A".
>
>My problem is that I'm having trouble figuring out how to retrieve a
>"struct sysctlnode" based on it's name.  It seems like the way to do this
>from a user program would be sysctlbyname() (man 3 sysctl), but this can't
>be used inside the kernel.  From reading man 9 sysctl I get the impression
>that sysctl_dispatch() should be used to look up a node, but I haven't
>gotten it to work yet.  I'm guessing that the sysctl dispatch function
>works sort of the same way as sysctl(3), as sysctl() is implemented using
>sysctl_dispatch() (in sys/kern/kern_sysctl.c).  Anyway, here's a general
>outline of what I'm trying, I'm not sure that it makes any sense, but I
>thought it might help demonstrate my lack of understanding.

correct.  there is not currently an in-kernel implementation of
sysctlbyname() (or sysctlnametomib()), mainly as a result of ~no
in-kernel consumers of sysctl so you end up having to use
sysctl_dispatch().  or you could use old_sysctl() (which will do the
locking for you and doesn't have the seemingly redundant arguments
that sysctl_dispatch() has), though that's a rather unfortunate name.
i should rename that.

>struct sysctlnode node;
>int len;
>int error;
>char buf[256];
>int mib[2];
>
>memset(&node, 0, sizeof(node));
>node.sysctl_flags = SYSCTL_VERSION;
>mib[0] = sc->ndis_sysctl_mib;     /* the ndis subtree */
>mib[1] = CTL_QUERY;
>strcpy(node.sysctl_name, keystr);
>node.sysctl_data = buf;
>len = sizeof(node);
>
>sysctl_lock(curlwp, &node, len);
>error = sysctl_dispatch(&mib[0], 2, &node, &len, &node,
>                        len, &mib[0], curlwp, NULL);
>sysctl_unlock(curlwp);

the problem is probably that you're doing a query but only providing
sysctl the space for one node under sc->ndis_sysctl_mib in the
response.

(1) sc->ndis_sysctl_mib is the top-level mib number?

(2) do you have more than one node under sc->ndis_sysctl_mib?

(3) when you get back the response from sysctl_dispatch(), you'll have
an array of nodes which you'll have to look through to find the one
you want.

-- 
|-----< "CODE WARRIOR" >-----|
codewarrior@daemon.org             * "ah!  i see you have the internet
twofsonet@graffiti.com (Andrew Brown)                that goes *ping*!"
werdna@squooshy.com       * "information is power -- share the wealth."