2 * Copyright (c) 2000-2008 Apple Inc. All rights reserved.
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
29 * Copyright (c) 1982, 1986, 1989, 1993
30 * The Regents of the University of California. All rights reserved.
32 * This code is derived from software contributed to Berkeley by
33 * Mike Karels at Berkeley Software Design, Inc.
35 * Quite extensively rewritten by Poul-Henning Kamp of the FreeBSD
36 * project, to make these variables more userfriendly.
38 * Redistribution and use in source and binary forms, with or without
39 * modification, are permitted provided that the following conditions
41 * 1. Redistributions of source code must retain the above copyright
42 * notice, this list of conditions and the following disclaimer.
43 * 2. Redistributions in binary form must reproduce the above copyright
44 * notice, this list of conditions and the following disclaimer in the
45 * documentation and/or other materials provided with the distribution.
46 * 3. All advertising materials mentioning features or use of this software
47 * must display the following acknowledgement:
48 * This product includes software developed by the University of
49 * California, Berkeley and its contributors.
50 * 4. Neither the name of the University nor the names of its contributors
51 * may be used to endorse or promote products derived from this software
52 * without specific prior written permission.
54 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
55 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
56 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
57 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
58 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
59 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
60 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
61 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
62 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
63 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
66 * @(#)kern_sysctl.c 8.4 (Berkeley) 4/14/94
70 #include <sys/param.h>
72 #include <sys/kernel.h>
73 #include <sys/sysctl.h>
74 #include <sys/malloc.h>
75 #include <sys/proc_internal.h>
76 #include <sys/systm.h>
78 #include <security/audit/audit.h>
81 struct sysctl_oid_list sysctl__debug_children;
82 struct sysctl_oid_list sysctl__kern_children;
83 struct sysctl_oid_list sysctl__net_children;
84 struct sysctl_oid_list sysctl__sysctl_children;
87 lck_rw_t
* sysctl_geometry_lock
= NULL
;
90 * Conditionally allow dtrace to see these functions for debugging purposes.
101 /* forward declarations of static functions */
102 STATIC funnel_t
*spl_kernel_funnel(void);
103 STATIC
void sysctl_sysctl_debug_dump_node(struct sysctl_oid_list
*l
, int i
);
104 STATIC
int sysctl_sysctl_debug(struct sysctl_oid
*oidp
, void *arg1
,
105 int arg2
, struct sysctl_req
*req
);
106 STATIC
int sysctl_sysctl_name(struct sysctl_oid
*oidp
, void *arg1
,
107 int arg2
, struct sysctl_req
*req
);
108 STATIC
int sysctl_sysctl_next_ls (struct sysctl_oid_list
*lsp
,
109 int *name
, u_int namelen
, int *next
, int *len
, int level
,
110 struct sysctl_oid
**oidpp
);
111 STATIC
int sysctl_old_kernel(struct sysctl_req
*req
, const void *p
, size_t l
);
112 STATIC
int sysctl_new_kernel(struct sysctl_req
*req
, void *p
, size_t l
);
113 STATIC
int name2oid (char *name
, int *oid
, int *len
);
114 STATIC
int sysctl_sysctl_name2oid(struct sysctl_oid
*oidp
, void *arg1
, int arg2
, struct sysctl_req
*req
);
115 STATIC
int sysctl_sysctl_next(struct sysctl_oid
*oidp
, void *arg1
, int arg2
,
116 struct sysctl_req
*req
);
117 STATIC
int sysctl_sysctl_oidfmt(struct sysctl_oid
*oidp
, void *arg1
, int arg2
, struct sysctl_req
*req
);
118 STATIC
void splx_kernel_funnel(funnel_t
*saved
);
119 STATIC
int sysctl_old_user(struct sysctl_req
*req
, const void *p
, size_t l
);
120 STATIC
int sysctl_new_user(struct sysctl_req
*req
, void *p
, size_t l
);
121 STATIC
int sysctl(int *name
, u_int namelen
, void *oldp
, size_t *oldlenp
, void *newp
, size_t newlen
);
122 STATIC
int sysctlnametomib(const char *name
, int *mibp
, size_t *sizep
);
131 * XXX this does not belong here
134 spl_kernel_funnel(void)
138 cfunnel
= thread_funnel_get();
139 if (cfunnel
!= kernel_flock
) {
141 thread_funnel_set(cfunnel
, FALSE
);
142 thread_funnel_set(kernel_flock
, TRUE
);
148 splx_kernel_funnel(funnel_t
*saved
)
150 if (saved
!= kernel_flock
) {
151 thread_funnel_set(kernel_flock
, FALSE
);
153 thread_funnel_set(saved
, TRUE
);
157 STATIC
int sysctl_root SYSCTL_HANDLER_ARGS
;
159 struct sysctl_oid_list sysctl__children
; /* root list */
162 * Initialization of the MIB tree.
164 * Order by number in each list.
168 sysctl_register_oid(struct sysctl_oid
*new_oidp
)
170 struct sysctl_oid
*oidp
= NULL
;
171 struct sysctl_oid_list
*parent
= new_oidp
->oid_parent
;
172 struct sysctl_oid
*p
;
173 struct sysctl_oid
*q
;
175 funnel_t
*fnl
= NULL
; /* compiler doesn't notice CTLFLAG_LOCKED */
178 * The OID can be old-style (needs copy), new style without an earlier
179 * version (also needs copy), or new style with a matching version (no
180 * copy needed). Later versions are rejected (presumably, the OID
181 * structure was changed for a necessary reason).
183 if (!(new_oidp
->oid_kind
& CTLFLAG_OID2
)) {
185 * XXX: M_TEMP is perhaps not the most apropriate zone, as it
186 * XXX: will subject us to use-after-free by other consumers.
188 MALLOC(oidp
, struct sysctl_oid
*, sizeof(*oidp
), M_TEMP
, M_WAITOK
| M_ZERO
);
190 return; /* reject: no memory */
193 * Copy the structure only through the oid_fmt field, which
194 * is the last field in a non-OID2 OID structure.
196 * Note: We may want to set the oid_descr to the
197 * oid_name (or "") at some future date.
199 memcpy(oidp
, new_oidp
, offsetof(struct sysctl_oid
, oid_descr
));
201 /* It's a later version; handle the versions we know about */
202 switch (new_oidp
->oid_version
) {
203 case SYSCTL_OID_VERSION
:
204 /* current version */
208 return; /* rejects unknown version */
213 * If it's a locked OID being registered, we can assume that the
214 * caller is doing their own reentrancy locking before calling us.
216 if (!(oidp
->oid_kind
& CTLFLAG_LOCKED
))
217 fnl
= spl_kernel_funnel();
219 if(sysctl_geometry_lock
== NULL
)
222 * Initialise the geometry lock for reading/modifying the
223 * sysctl tree. This is done here because IOKit registers
224 * some sysctl's before bsd_init() calls
225 * sysctl_register_fixed().
228 lck_grp_t
* lck_grp
= lck_grp_alloc_init("sysctl", NULL
);
229 sysctl_geometry_lock
= lck_rw_alloc_init(lck_grp
, NULL
);
231 /* Get the write lock to modify the geometry */
232 lck_rw_lock_exclusive(sysctl_geometry_lock
);
235 * If this oid has a number OID_AUTO, give it a number which
236 * is greater than any current oid. Make sure it is at least
237 * OID_AUTO_START to leave space for pre-assigned oid numbers.
239 if (oidp
->oid_number
== OID_AUTO
) {
240 /* First, find the highest oid in the parent list >OID_AUTO_START-1 */
242 SLIST_FOREACH(p
, parent
, oid_link
) {
243 if (p
->oid_number
> n
)
246 oidp
->oid_number
= n
+ 1;
248 * Reflect the number in an llocated OID into the template
249 * of the caller for sysctl_unregister_oid() compares.
251 if (oidp
!= new_oidp
)
252 new_oidp
->oid_number
= oidp
->oid_number
;
256 * Insert the oid into the parent's list in order.
259 SLIST_FOREACH(p
, parent
, oid_link
) {
260 if (oidp
->oid_number
< p
->oid_number
)
265 SLIST_INSERT_AFTER(q
, oidp
, oid_link
);
267 SLIST_INSERT_HEAD(parent
, oidp
, oid_link
);
269 /* Release the write lock */
270 lck_rw_unlock_exclusive(sysctl_geometry_lock
);
272 if (!(oidp
->oid_kind
& CTLFLAG_LOCKED
))
273 splx_kernel_funnel(fnl
);
277 sysctl_unregister_oid(struct sysctl_oid
*oidp
)
279 struct sysctl_oid
*removed_oidp
= NULL
; /* OID removed from tree */
280 struct sysctl_oid
*old_oidp
= NULL
; /* OID compatibility copy */
281 funnel_t
*fnl
= NULL
; /* compiler doesn't notice CTLFLAG_LOCKED */
283 if (!(oidp
->oid_kind
& CTLFLAG_LOCKED
))
284 fnl
= spl_kernel_funnel();
286 /* Get the write lock to modify the geometry */
287 lck_rw_lock_exclusive(sysctl_geometry_lock
);
289 if (!(oidp
->oid_kind
& CTLFLAG_OID2
)) {
291 * We're using a copy so we can get the new fields in an
292 * old structure, so we have to iterate to compare the
293 * partial structure; when we find a match, we remove it
294 * normally and free the memory.
296 SLIST_FOREACH(old_oidp
, oidp
->oid_parent
, oid_link
) {
297 if (!memcmp(&oidp
->oid_number
, &old_oidp
->oid_number
, (offsetof(struct sysctl_oid
, oid_descr
)-offsetof(struct sysctl_oid
, oid_number
)))) {
301 if (old_oidp
!= NULL
) {
302 SLIST_REMOVE(old_oidp
->oid_parent
, old_oidp
, sysctl_oid
, oid_link
);
303 removed_oidp
= old_oidp
;
306 /* It's a later version; handle the versions we know about */
307 switch (oidp
->oid_version
) {
308 case SYSCTL_OID_VERSION
:
309 /* We can just remove the OID directly... */
310 SLIST_REMOVE(oidp
->oid_parent
, oidp
, sysctl_oid
, oid_link
);
314 /* XXX: Can't happen; probably tree coruption.*/
315 break; /* rejects unknown version */
320 * We've removed it from the list at this point, but we don't want
321 * to return to the caller until all handler references have drained
322 * out. Doing things in this order prevent other people coming in
323 * and starting new operations against the OID node we want removed.
325 * Note: oidp could be NULL if it wasn't found.
327 while(removed_oidp
&& removed_oidp
->oid_refcnt
) {
328 lck_rw_sleep(sysctl_geometry_lock
, LCK_SLEEP_EXCLUSIVE
, &removed_oidp
->oid_refcnt
, THREAD_UNINT
);
331 /* Release the write lock */
332 lck_rw_unlock_exclusive(sysctl_geometry_lock
);
334 /* If it was allocated, free it after dropping the lock */
335 if (old_oidp
!= NULL
) {
336 FREE(old_oidp
, M_TEMP
);
339 /* And drop the funnel interlock, if needed */
340 if (!(oidp
->oid_kind
& CTLFLAG_LOCKED
))
341 splx_kernel_funnel(fnl
);
345 * Bulk-register all the oids in a linker_set.
348 sysctl_register_set(const char *set
)
350 struct sysctl_oid
**oidpp
, *oidp
;
352 LINKER_SET_FOREACH(oidpp
, struct sysctl_oid
**, set
) {
354 if (!(oidp
->oid_kind
& CTLFLAG_NOAUTO
)) {
355 sysctl_register_oid(oidp
);
361 sysctl_unregister_set(const char *set
)
363 struct sysctl_oid
**oidpp
, *oidp
;
365 LINKER_SET_FOREACH(oidpp
, struct sysctl_oid
**, set
) {
367 if (!(oidp
->oid_kind
& CTLFLAG_NOAUTO
)) {
368 sysctl_unregister_oid(oidp
);
375 * Register the kernel's oids on startup.
379 sysctl_register_all()
381 sysctl_register_set("__sysctl_set");
385 sysctl_register_fixed(void)
387 sysctl_register_all();
391 * New handler interface
392 * If the sysctl caller (user mode or kernel mode) is interested in the
393 * value (req->oldptr != NULL), we copy the data (bigValue etc.) out,
394 * if the caller wants to set the value (req->newptr), we copy
395 * the data in (*pValue etc.).
399 sysctl_io_number(struct sysctl_req
*req
, long long bigValue
, size_t valueSize
, void *pValue
, int *changed
) {
403 if (changed
) *changed
= 0;
406 * Handle the various combinations of caller buffer size and
407 * data value size. We are generous in the case where the
408 * caller has specified a 32-bit buffer but the value is 64-bit
412 /* 32 bit value expected or 32 bit buffer offered */
413 if (((valueSize
== sizeof(int)) ||
414 ((req
->oldlen
== sizeof(int)) && (valueSize
== sizeof(long long))))
416 smallValue
= (int)bigValue
;
417 if ((long long)smallValue
!= bigValue
)
419 error
= SYSCTL_OUT(req
, &smallValue
, sizeof(smallValue
));
421 /* any other case is either size-equal or a bug */
422 error
= SYSCTL_OUT(req
, &bigValue
, valueSize
);
424 /* error or nothing to set */
425 if (error
|| !req
->newptr
)
428 /* set request for constant */
432 /* set request needs to convert? */
433 if ((req
->newlen
== sizeof(int)) && (valueSize
== sizeof(long long))) {
434 /* new value is 32 bits, upconvert to 64 bits */
435 error
= SYSCTL_IN(req
, &smallValue
, sizeof(smallValue
));
437 *(long long *)pValue
= (long long)smallValue
;
438 } else if ((req
->newlen
== sizeof(long long)) && (valueSize
== sizeof(int))) {
439 /* new value is 64 bits, downconvert to 32 bits and range check */
440 error
= SYSCTL_IN(req
, &bigValue
, sizeof(bigValue
));
442 smallValue
= (int)bigValue
;
443 if ((long long)smallValue
!= bigValue
)
445 *(int *)pValue
= smallValue
;
448 /* sizes match, just copy in */
449 error
= SYSCTL_IN(req
, pValue
, valueSize
);
451 if (!error
&& changed
)
457 sysctl_io_string(struct sysctl_req
*req
, char *pValue
, size_t valueSize
, int trunc
, int *changed
)
461 if (changed
) *changed
= 0;
463 if (trunc
&& req
->oldptr
&& req
->oldlen
&& (req
->oldlen
<strlen(pValue
) + 1)) {
464 /* If trunc != 0, if you give it a too small (but larger than
465 * 0 bytes) buffer, instead of returning ENOMEM, it truncates the
466 * returned string to the buffer size. This preserves the semantics
467 * of some library routines implemented via sysctl, which truncate
468 * their returned data, rather than simply returning an error. The
469 * returned string is always NUL terminated. */
470 error
= SYSCTL_OUT(req
, pValue
, req
->oldlen
-1);
473 error
= SYSCTL_OUT(req
, &c
, 1);
476 /* Copy string out */
477 error
= SYSCTL_OUT(req
, pValue
, strlen(pValue
) + 1);
480 /* error or no new value */
481 if (error
|| !req
->newptr
)
484 /* attempt to set read-only value */
488 /* make sure there's room for the new string */
489 if (req
->newlen
>= valueSize
)
492 /* copy the string in and force NUL termination */
493 error
= SYSCTL_IN(req
, pValue
, req
->newlen
);
494 pValue
[req
->newlen
] = '\0';
496 if (!error
&& changed
)
501 int sysctl_io_opaque(struct sysctl_req
*req
,void *pValue
, size_t valueSize
, int *changed
)
505 if (changed
) *changed
= 0;
508 error
= SYSCTL_OUT(req
, pValue
, valueSize
);
510 /* error or nothing to set */
511 if (error
|| !req
->newptr
)
514 error
= SYSCTL_IN(req
, pValue
, valueSize
);
516 if (!error
&& changed
)
524 * These functions implement a presently undocumented interface
525 * used by the sysctl program to walk the tree, and get the type
526 * so it can print the value.
527 * This interface is under work and consideration, and should probably
528 * be killed with a big axe by the first person who can find the time.
529 * (be aware though, that the proper interface isn't as obvious as it
530 * may seem, there are various conflicting requirements.
532 * {0,0} printf the entire MIB-tree.
533 * {0,1,...} return the name of the "..." OID.
534 * {0,2,...} return the next OID.
535 * {0,3} return the OID of the name in "new"
536 * {0,4,...} return the kind & format info for the "..." OID.
540 * sysctl_sysctl_debug_dump_node
542 * Description: Dump debug information for a given sysctl_oid_list at the
543 * given oid depth out to the kernel log, via printf
545 * Parameters: l sysctl_oid_list pointer
546 * i current node depth
550 * Implicit: kernel log, modified
552 * Locks: Assumes sysctl_geometry_lock is held prior to calling
554 * Notes: This function may call itself recursively to resolve Node
555 * values, which potentially have an inferioer sysctl_oid_list
557 * This function is only callable indirectly via the function
558 * sysctl_sysctl_debug()
560 * Bugs: The node depth indentation does not work; this may be an
561 * artifact of leading space removal by the log daemon itself
562 * or some intermediate routine.
565 sysctl_sysctl_debug_dump_node(struct sysctl_oid_list
*l
, int i
)
568 struct sysctl_oid
*oidp
;
570 SLIST_FOREACH(oidp
, l
, oid_link
) {
575 printf("%d %s ", oidp
->oid_number
, oidp
->oid_name
);
578 oidp
->oid_kind
& CTLFLAG_LOCKED
? 'L':' ',
579 oidp
->oid_kind
& CTLFLAG_RD
? 'R':' ',
580 oidp
->oid_kind
& CTLFLAG_WR
? 'W':' ');
582 if (oidp
->oid_handler
)
585 switch (oidp
->oid_kind
& CTLTYPE
) {
588 if (!oidp
->oid_handler
) {
589 sysctl_sysctl_debug_dump_node(
590 oidp
->oid_arg1
, i
+2);
593 case CTLTYPE_INT
: printf(" Int\n"); break;
594 case CTLTYPE_STRING
: printf(" String\n"); break;
595 case CTLTYPE_QUAD
: printf(" Quad\n"); break;
596 case CTLTYPE_OPAQUE
: printf(" Opaque/struct\n"); break;
597 default: printf("\n");
604 * sysctl_sysctl_debug
606 * Description: This function implements the "sysctl.debug" portion of the
607 * OID space for sysctl.
611 * Parameters: __unused
615 * Implicit: kernel log, modified
617 * Locks: Acquires and then releases a read lock on the
618 * sysctl_geometry_lock
621 sysctl_sysctl_debug(__unused
struct sysctl_oid
*oidp
, __unused
void *arg1
,
622 __unused
int arg2
, __unused
struct sysctl_req
*req
)
624 lck_rw_lock_shared(sysctl_geometry_lock
);
625 sysctl_sysctl_debug_dump_node(&sysctl__children
, 0);
626 lck_rw_done(sysctl_geometry_lock
);
630 SYSCTL_PROC(_sysctl
, 0, debug
, CTLTYPE_STRING
|CTLFLAG_RD
| CTLFLAG_LOCKED
,
631 0, 0, sysctl_sysctl_debug
, "-", "");
636 * Description: Convert an OID into a string name; this is used by the user
637 * space sysctl() command line utility; this is done in a purely
638 * advisory capacity (e.g. to provide node names for "sysctl -A"
643 * Parameters: oidp __unused
644 * arg1 A pointer to the OID name list
645 * integer array, beginning at
646 * adjusted option base 2
647 * arg2 The number of elements which
648 * remain in the name array
651 * SYSCTL_OUT:EPERM Permission denied
652 * SYSCTL_OUT:EFAULT Bad user supplied buffer
653 * SYSCTL_OUT:??? Return value from user function
654 * for SYSCTL_PROC leaf node
656 * Implict: Contents of user request buffer, modified
658 * Locks: Acquires and then releases a read lock on the
659 * sysctl_geometry_lock
661 * Notes: SPI (System Programming Interface); this is subject to change
662 * and may not be relied upon by third party applications; use
663 * a subprocess to communicate with the "sysctl" command line
664 * command instead, if you believe you need this functionality.
665 * Preferrably, use sysctlbyname() instead.
667 * Setting of the NULL termination of the output string is
668 * delayed until after the geometry lock is dropped. If there
669 * are no Entries remaining in the OID name list when this
670 * function is called, it will still write out the termination
673 * This function differs from other sysctl functions in that
674 * it can not take an output buffer length of 0 to determine the
675 * space which will be required. It is suggested that the buffer
676 * length be PATH_MAX, and that authors of new sysctl's refrain
677 * from exceeding this string length.
680 sysctl_sysctl_name(__unused
struct sysctl_oid
*oidp
, void *arg1
, int arg2
,
681 struct sysctl_req
*req
)
683 int *name
= (int *) arg1
;
684 u_int namelen
= arg2
;
686 struct sysctl_oid
*oid
;
687 struct sysctl_oid_list
*lsp
= &sysctl__children
, *lsp2
;
690 lck_rw_lock_shared(sysctl_geometry_lock
);
693 snprintf(tempbuf
,sizeof(tempbuf
),"%d",*name
);
695 error
= SYSCTL_OUT(req
, ".", 1);
697 error
= SYSCTL_OUT(req
, tempbuf
, strlen(tempbuf
));
699 lck_rw_done(sysctl_geometry_lock
);
707 SLIST_FOREACH(oid
, lsp
, oid_link
) {
708 if (oid
->oid_number
!= *name
)
712 error
= SYSCTL_OUT(req
, ".", 1);
714 error
= SYSCTL_OUT(req
, oid
->oid_name
,
715 strlen(oid
->oid_name
));
717 lck_rw_done(sysctl_geometry_lock
);
724 if ((oid
->oid_kind
& CTLTYPE
) != CTLTYPE_NODE
)
727 if (oid
->oid_handler
)
730 lsp2
= (struct sysctl_oid_list
*)oid
->oid_arg1
;
735 lck_rw_done(sysctl_geometry_lock
);
736 return (SYSCTL_OUT(req
, "", 1));
739 SYSCTL_NODE(_sysctl
, 1, name
, CTLFLAG_RD
| CTLFLAG_LOCKED
, sysctl_sysctl_name
, "");
742 * sysctl_sysctl_next_ls
744 * Description: For a given OID name value, return the next consecutive OID
745 * name value within the geometry tree
747 * Parameters: lsp The OID list to look in
748 * name The OID name to start from
749 * namelen The length of the OID name
750 * next Pointer to new oid storage to
752 * len Pointer to receive new OID
753 * length value of storage written
754 * level OID tree depth (used to compute
756 * oidpp Pointer to OID list entry
757 * pointer; used to walk the list
758 * forward across recursion
760 * Returns: 0 Returning a new entry
761 * 1 End of geometry list reached
763 * Implicit: *next Modified to contain the new OID
764 * *len Modified to contain new length
766 * Locks: Assumes sysctl_geometry_lock is held prior to calling
768 * Notes: This function will not return OID values that have special
769 * handlers, since we can not tell wheter these handlers consume
770 * elements from the OID space as parameters. For this reason,
771 * we STRONGLY discourage these types of handlers
774 sysctl_sysctl_next_ls (struct sysctl_oid_list
*lsp
, int *name
, u_int namelen
,
775 int *next
, int *len
, int level
, struct sysctl_oid
**oidpp
)
777 struct sysctl_oid
*oidp
;
780 SLIST_FOREACH(oidp
, lsp
, oid_link
) {
781 *next
= oidp
->oid_number
;
785 if ((oidp
->oid_kind
& CTLTYPE
) != CTLTYPE_NODE
)
787 if (oidp
->oid_handler
)
788 /* We really should call the handler here...*/
790 lsp
= (struct sysctl_oid_list
*)oidp
->oid_arg1
;
792 if (!SLIST_FIRST(lsp
))
793 /* This node had no children - skip it! */
796 if (!sysctl_sysctl_next_ls (lsp
, 0, 0, next
+1,
797 len
, level
+1, oidpp
))
802 if (oidp
->oid_number
< *name
)
805 if (oidp
->oid_number
> *name
) {
806 if ((oidp
->oid_kind
& CTLTYPE
) != CTLTYPE_NODE
)
808 if (oidp
->oid_handler
)
810 lsp
= (struct sysctl_oid_list
*)oidp
->oid_arg1
;
811 if (!sysctl_sysctl_next_ls (lsp
, name
+1, namelen
-1,
812 next
+1, len
, level
+1, oidpp
))
816 if ((oidp
->oid_kind
& CTLTYPE
) != CTLTYPE_NODE
)
819 if (oidp
->oid_handler
)
822 lsp
= (struct sysctl_oid_list
*)oidp
->oid_arg1
;
823 if (!sysctl_sysctl_next_ls (lsp
, name
+1, namelen
-1, next
+1,
824 len
, level
+1, oidpp
))
836 * Description: This is an iterator function designed to iterate the oid tree
837 * and provide a list of OIDs for use by the user space "sysctl"
842 * Parameters: oidp __unused
843 * arg1 Pointer to start OID name
844 * arg2 Start OID name length
845 * req Pointer to user request buffer
848 * ENOENT Reached end of OID space
849 * SYSCTL_OUT:EPERM Permission denied
850 * SYSCTL_OUT:EFAULT Bad user supplied buffer
851 * SYSCTL_OUT:??? Return value from user function
852 * for SYSCTL_PROC leaf node
854 * Implict: Contents of user request buffer, modified
856 * Locks: Acquires and then releases a read lock on the
857 * sysctl_geometry_lock
859 * Notes: SPI (System Programming Interface); this is subject to change
860 * and may not be relied upon by third party applications; use
861 * a subprocess to communicate with the "sysctl" command line
862 * command instead, if you believe you need this functionality.
863 * Preferrably, use sysctlbyname() instead.
865 * This function differs from other sysctl functions in that
866 * it can not take an output buffer length of 0 to determine the
867 * space which will be required. It is suggested that the buffer
868 * length be PATH_MAX, and that authors of new sysctl's refrain
869 * from exceeding this string length.
872 sysctl_sysctl_next(__unused
struct sysctl_oid
*oidp
, void *arg1
, int arg2
,
873 struct sysctl_req
*req
)
875 int *name
= (int *) arg1
;
876 u_int namelen
= arg2
;
878 struct sysctl_oid
*oid
;
879 struct sysctl_oid_list
*lsp
= &sysctl__children
;
880 int newoid
[CTL_MAXNAME
];
882 lck_rw_lock_shared(sysctl_geometry_lock
);
883 i
= sysctl_sysctl_next_ls (lsp
, name
, namelen
, newoid
, &j
, 1, &oid
);
884 lck_rw_done(sysctl_geometry_lock
);
887 error
= SYSCTL_OUT(req
, newoid
, j
* sizeof (int));
891 SYSCTL_NODE(_sysctl
, 2, next
, CTLFLAG_RD
| CTLFLAG_LOCKED
, sysctl_sysctl_next
, "");
896 * Description: Support function for use by sysctl_sysctl_name2oid(); looks
897 * up an OID name given a string name.
899 * Parameters: name NULL terminated string name
900 * oid Pointer to receive OID name
901 * len Pointer to receive OID length
902 * pointer value (see "Notes")
905 * ENOENT Entry not found
907 * Implicit: *oid Modified to contain OID value
908 * *len Modified to contain OID length
910 * Locks: Assumes sysctl_geometry_lock is held prior to calling
913 name2oid (char *name
, int *oid
, int *len
)
916 struct sysctl_oid
*oidp
;
917 struct sysctl_oid_list
*lsp
= &sysctl__children
;
923 p
= name
+ strlen(name
) - 1 ;
929 for (p
= name
; *p
&& *p
!= '.'; p
++)
935 oidp
= SLIST_FIRST(lsp
);
937 while (oidp
&& *len
< CTL_MAXNAME
) {
938 if (strcmp(name
, oidp
->oid_name
)) {
939 oidp
= SLIST_NEXT(oidp
, oid_link
);
942 *oid
++ = oidp
->oid_number
;
949 if ((oidp
->oid_kind
& CTLTYPE
) != CTLTYPE_NODE
)
952 if (oidp
->oid_handler
)
955 lsp
= (struct sysctl_oid_list
*)oidp
->oid_arg1
;
956 oidp
= SLIST_FIRST(lsp
);
958 for (p
= name
; *p
&& *p
!= '.'; p
++)
968 * sysctl_sysctl_name2oid
970 * Description: Translate a string name to an OID name value; this is used by
971 * the sysctlbyname() function as well as by the "sysctl" command
976 * Parameters: oidp __unused
979 * req Request structure
981 * Returns: ENOENT Input length too short
982 * ENAMETOOLONG Input length too long
983 * ENOMEM Could not allocate work area
984 * SYSCTL_IN/OUT:EPERM Permission denied
985 * SYSCTL_IN/OUT:EFAULT Bad user supplied buffer
986 * SYSCTL_IN/OUT:??? Return value from user function
987 * name2oid:ENOENT Not found
989 * Implicit: *req Contents of request, modified
991 * Locks: Acquires and then releases a read lock on the
992 * sysctl_geometry_lock
994 * Notes: SPI (System Programming Interface); this is subject to change
995 * and may not be relied upon by third party applications; use
996 * a subprocess to communicate with the "sysctl" command line
997 * command instead, if you believe you need this functionality.
998 * Preferrably, use sysctlbyname() instead.
1000 * This function differs from other sysctl functions in that
1001 * it can not take an output buffer length of 0 to determine the
1002 * space which will be required. It is suggested that the buffer
1003 * length be PATH_MAX, and that authors of new sysctl's refrain
1004 * from exceeding this string length.
1007 sysctl_sysctl_name2oid(__unused
struct sysctl_oid
*oidp
, __unused
void *arg1
,
1008 __unused
int arg2
, struct sysctl_req
*req
)
1011 int error
, oid
[CTL_MAXNAME
];
1012 int len
= 0; /* set by name2oid() */
1014 if (req
->newlen
< 1)
1016 if (req
->newlen
>= MAXPATHLEN
) /* XXX arbitrary, undocumented */
1017 return (ENAMETOOLONG
);
1019 MALLOC(p
, char *,req
->newlen
+1, M_TEMP
, M_WAITOK
);
1023 error
= SYSCTL_IN(req
, p
, req
->newlen
);
1029 p
[req
->newlen
] = '\0';
1032 * Note: We acquire and release the geometry lock here to
1033 * avoid making name2oid needlessly complex.
1035 lck_rw_lock_shared(sysctl_geometry_lock
);
1036 error
= name2oid(p
, oid
, &len
);
1037 lck_rw_done(sysctl_geometry_lock
);
1044 error
= SYSCTL_OUT(req
, oid
, len
* sizeof *oid
);
1048 SYSCTL_PROC(_sysctl
, 3, name2oid
, CTLFLAG_RW
|CTLFLAG_ANYBODY
|CTLFLAG_KERN
| CTLFLAG_LOCKED
, 0, 0,
1049 sysctl_sysctl_name2oid
, "I", "");
1052 * sysctl_sysctl_oidfmt
1054 * Description: For a given OID name, determine the format of the data which
1055 * is associated with it. This is used by the "sysctl" command
1060 * Parameters: oidp __unused
1061 * arg1 The OID name to look up
1062 * arg2 The length of the OID name
1063 * req Pointer to user request buffer
1065 * Returns: 0 Success
1066 * EISDIR Malformed request
1067 * ENOENT No such OID name
1068 * SYSCTL_OUT:EPERM Permission denied
1069 * SYSCTL_OUT:EFAULT Bad user supplied buffer
1070 * SYSCTL_OUT:??? Return value from user function
1072 * Implict: Contents of user request buffer, modified
1074 * Locks: Acquires and then releases a read lock on the
1075 * sysctl_geometry_lock
1077 * Notes: SPI (System Programming Interface); this is subject to change
1078 * and may not be relied upon by third party applications; use
1079 * a subprocess to communicate with the "sysctl" command line
1080 * command instead, if you believe you need this functionality.
1082 * This function differs from other sysctl functions in that
1083 * it can not take an output buffer length of 0 to determine the
1084 * space which will be required. It is suggested that the buffer
1085 * length be PATH_MAX, and that authors of new sysctl's refrain
1086 * from exceeding this string length.
1089 sysctl_sysctl_oidfmt(__unused
struct sysctl_oid
*oidp
, void *arg1
, int arg2
,
1090 struct sysctl_req
*req
)
1092 int *name
= (int *) arg1
;
1093 int error
= ENOENT
; /* default error: not found */
1094 u_int namelen
= arg2
;
1096 struct sysctl_oid
*oid
;
1097 struct sysctl_oid_list
*lsp
= &sysctl__children
;
1099 lck_rw_lock_shared(sysctl_geometry_lock
);
1100 oid
= SLIST_FIRST(lsp
);
1103 while (oid
&& indx
< CTL_MAXNAME
) {
1104 if (oid
->oid_number
== name
[indx
]) {
1106 if ((oid
->oid_kind
& CTLTYPE
) == CTLTYPE_NODE
) {
1107 if (oid
->oid_handler
)
1109 if (indx
== namelen
)
1111 lsp
= (struct sysctl_oid_list
*)oid
->oid_arg1
;
1112 oid
= SLIST_FIRST(lsp
);
1114 if (indx
!= namelen
) {
1121 oid
= SLIST_NEXT(oid
, oid_link
);
1130 error
= SYSCTL_OUT(req
,
1131 &oid
->oid_kind
, sizeof(oid
->oid_kind
));
1133 error
= SYSCTL_OUT(req
, oid
->oid_fmt
,
1134 strlen(oid
->oid_fmt
)+1);
1136 lck_rw_done(sysctl_geometry_lock
);
1140 SYSCTL_NODE(_sysctl
, 4, oidfmt
, CTLFLAG_RD
| CTLFLAG_LOCKED
, sysctl_sysctl_oidfmt
, "");
1144 * Default "handler" functions.
1148 * Handle an int, signed or unsigned.
1150 * a variable: point arg1 at it.
1151 * a constant: pass it in arg2.
1155 sysctl_handle_int(__unused
struct sysctl_oid
*oidp
, void *arg1
, int arg2
,
1156 struct sysctl_req
*req
)
1158 return sysctl_io_number(req
, arg1
? *(int*)arg1
: arg2
, sizeof(int), arg1
, NULL
);
1162 * Handle a long, signed or unsigned. arg1 points to it.
1166 sysctl_handle_long(__unused
struct sysctl_oid
*oidp
, void *arg1
,
1167 __unused
int arg2
, struct sysctl_req
*req
)
1171 return sysctl_io_number(req
, *(long*)arg1
, sizeof(long), arg1
, NULL
);
1175 * Handle a quad, signed or unsigned. arg1 points to it.
1179 sysctl_handle_quad(__unused
struct sysctl_oid
*oidp
, void *arg1
,
1180 __unused
int arg2
, struct sysctl_req
*req
)
1184 return sysctl_io_number(req
, *(long long*)arg1
, sizeof(long long), arg1
, NULL
);
1188 * Expose an int value as a quad.
1190 * This interface allows us to support interfaces defined
1191 * as using quad values while the implementation is still
1195 sysctl_handle_int2quad(__unused
struct sysctl_oid
*oidp
, void *arg1
,
1196 __unused
int arg2
, struct sysctl_req
*req
)
1204 val
= (long long)*(int *)arg1
;
1205 error
= SYSCTL_OUT(req
, &val
, sizeof(long long));
1207 if (error
|| !req
->newptr
)
1210 error
= SYSCTL_IN(req
, &val
, sizeof(long long));
1213 * Value must be representable; check by
1214 * casting and then casting back.
1217 if ((long long)newval
!= val
) {
1220 *(int *)arg1
= newval
;
1227 * Handle our generic '\0' terminated 'C' string.
1229 * a variable string: point arg1 at it, arg2 is max length.
1230 * a constant string: point arg1 at it, arg2 is zero.
1234 sysctl_handle_string( __unused
struct sysctl_oid
*oidp
, void *arg1
, int arg2
,
1235 struct sysctl_req
*req
)
1237 return sysctl_io_string(req
, arg1
, arg2
, 0, NULL
);
1241 * Handle any kind of opaque data.
1242 * arg1 points to it, arg2 is the size.
1246 sysctl_handle_opaque(__unused
struct sysctl_oid
*oidp
, void *arg1
, int arg2
,
1247 struct sysctl_req
*req
)
1249 return sysctl_io_opaque(req
, arg1
, arg2
, NULL
);
1253 * Transfer functions to/from kernel space.
1256 sysctl_old_kernel(struct sysctl_req
*req
, const void *p
, size_t l
)
1262 if (i
> req
->oldlen
- req
->oldidx
)
1263 i
= req
->oldlen
- req
->oldidx
;
1265 bcopy((const void*)p
, CAST_DOWN(char *, (req
->oldptr
+ req
->oldidx
)), i
);
1268 if (req
->oldptr
&& i
!= l
)
1274 sysctl_new_kernel(struct sysctl_req
*req
, void *p
, size_t l
)
1278 if (req
->newlen
- req
->newidx
< l
)
1280 bcopy(CAST_DOWN(char *, (req
->newptr
+ req
->newidx
)), p
, l
);
1286 kernel_sysctl(struct proc
*p
, int *name
, u_int namelen
, void *old
, size_t *oldlenp
, void *new, size_t newlen
)
1289 struct sysctl_req req
;
1292 * Construct request.
1294 bzero(&req
, sizeof req
);
1297 req
.oldlen
= *oldlenp
;
1299 req
.oldptr
= CAST_USER_ADDR_T(old
);
1301 req
.newlen
= newlen
;
1302 req
.newptr
= CAST_USER_ADDR_T(new);
1304 req
.oldfunc
= sysctl_old_kernel
;
1305 req
.newfunc
= sysctl_new_kernel
;
1308 /* make the request */
1309 error
= sysctl_root(0, name
, namelen
, &req
);
1311 /* unlock memory if required */
1313 vsunlock(req
.oldptr
, (user_size_t
)req
.oldlen
, B_WRITE
);
1315 if (error
&& error
!= ENOMEM
)
1319 *oldlenp
= req
.oldidx
;
1325 * Transfer function to/from user space.
1328 sysctl_old_user(struct sysctl_req
*req
, const void *p
, size_t l
)
1334 if (req
->oldlen
- req
->oldidx
< l
)
1337 if (i
> req
->oldlen
- req
->oldidx
)
1338 i
= req
->oldlen
- req
->oldidx
;
1340 error
= copyout((const void*)p
, (req
->oldptr
+ req
->oldidx
), i
);
1345 if (req
->oldptr
&& i
< l
)
1351 sysctl_new_user(struct sysctl_req
*req
, void *p
, size_t l
)
1357 if (req
->newlen
- req
->newidx
< l
)
1359 error
= copyin((req
->newptr
+ req
->newidx
), p
, l
);
1365 * Traverse our tree, and find the right node, execute whatever it points
1366 * at, and return the resulting error code.
1370 sysctl_root(__unused
struct sysctl_oid
*oidp
, void *arg1
, int arg2
,
1371 struct sysctl_req
*req
)
1373 int *name
= (int *) arg1
;
1374 u_int namelen
= arg2
;
1377 struct sysctl_oid
*oid
;
1378 struct sysctl_oid_list
*lsp
= &sysctl__children
;
1380 funnel_t
*fnl
= NULL
;
1381 boolean_t funnel_held
= FALSE
;
1383 /* Get the read lock on the geometry */
1384 lck_rw_lock_shared(sysctl_geometry_lock
);
1386 oid
= SLIST_FIRST(lsp
);
1389 while (oid
&& indx
< CTL_MAXNAME
) {
1390 if (oid
->oid_number
== name
[indx
]) {
1392 if (!(oid
->oid_kind
& CTLFLAG_LOCKED
))
1395 printf("sysctl_root: missing CTLFLAG_LOCKED: ");
1396 for(i = 0; i < (int)(indx - 1); i++)
1397 printf("oid[%d] = %d ", i, name[i]);
1402 if (oid
->oid_kind
& CTLFLAG_NOLOCK
)
1405 * For SYSCTL_PROC() functions which are for sysctl's
1406 * which have parameters at the end of their OID
1407 * space, you need to OR CTLTYPE_NODE into their
1410 * NOTE: For binary backward compatibility ONLY! Do
1411 * NOT add new sysctl's that do this! Existing
1412 * sysctl's which do this will eventually have
1413 * compatibility code in user space, and this method
1414 * will become unsupported.
1416 if ((oid
->oid_kind
& CTLTYPE
) == CTLTYPE_NODE
) {
1417 if (oid
->oid_handler
)
1419 if (indx
== namelen
)
1425 lsp
= (struct sysctl_oid_list
*)oid
->oid_arg1
;
1426 oid
= SLIST_FIRST(lsp
);
1428 if (indx
!= namelen
)
1436 oid
= SLIST_NEXT(oid
, oid_link
);
1442 /* If writing isn't allowed */
1443 if (req
->newptr
&& (!(oid
->oid_kind
& CTLFLAG_WR
) ||
1444 ((oid
->oid_kind
& CTLFLAG_SECURE
) && securelevel
> 0))) {
1450 * If we're inside the kernel, the OID must be marked as kernel-valid.
1451 * XXX This mechanism for testing is bad.
1453 if ((req
->oldfunc
== sysctl_old_kernel
) && !(oid
->oid_kind
& CTLFLAG_KERN
))
1460 * This is where legacy enforcement of permissions occurs. If the
1461 * flag does not say CTLFLAG_ANYBODY, then we prohibit anyone but
1462 * root from writing new values down. If local enforcement happens
1463 * at the leaf node, then it needs to be set as CTLFLAG_ANYBODY. In
1464 * addition, if the leaf node is set this way, then in order to do
1465 * specific enforcement, it has to be of type SYSCTL_PROC.
1467 if (!(oid
->oid_kind
& CTLFLAG_ANYBODY
) &&
1468 req
->newptr
&& req
->p
&&
1469 (error
= proc_suser(req
->p
)))
1472 if (!oid
->oid_handler
) {
1478 * Reference the OID and drop the geometry lock; this prevents the
1479 * OID from being deleted out from under the handler call, but does
1480 * not prevent other calls into handlers or calls to manage the
1481 * geometry elsewhere from blocking...
1483 OSAddAtomic(1, &oid
->oid_refcnt
);
1485 lck_rw_done(sysctl_geometry_lock
);
1488 * ...however, we still have to grab the funnel for those calls which
1489 * may be into code whose reentrancy is protected by the funnel; a
1490 * blocking operation should not prevent reentrancy, at this point.
1494 fnl
= spl_kernel_funnel();
1497 if ((oid
->oid_kind
& CTLTYPE
) == CTLTYPE_NODE
) {
1498 i
= (oid
->oid_handler
) (oid
,
1499 name
+ indx
, namelen
- indx
,
1502 i
= (oid
->oid_handler
) (oid
,
1503 oid
->oid_arg1
, oid
->oid_arg2
,
1510 splx_kernel_funnel(fnl
);
1514 * This is tricky... we re-grab the geometry lock in order to drop
1515 * the reference and wake on the address; since the geometry
1516 * lock is a reader/writer lock rather than a mutex, we have to
1517 * wake on all apparent 1->0 transitions. This abuses the drop
1518 * after the reference decrement in order to wake any lck_rw_sleep()
1519 * in progress in sysctl_unregister_oid() that slept because of a
1520 * non-zero reference count.
1522 * Note: OSAddAtomic() is defined to return the previous value;
1523 * we use this and the fact that the lock itself is a
1524 * barrier to avoid waking every time through on "hot"
1527 lck_rw_lock_shared(sysctl_geometry_lock
);
1528 if (OSAddAtomic(-1, &oid
->oid_refcnt
) == 1)
1529 wakeup(&oid
->oid_refcnt
);
1532 lck_rw_done(sysctl_geometry_lock
);
1536 #ifndef _SYS_SYSPROTO_H_
1537 struct sysctl_args
{
1548 /* __sysctl(struct proc *p, struct sysctl_args *uap) */
1549 new_sysctl(struct proc
*p
, struct sysctl_args
*uap
)
1551 int error
, i
, name
[CTL_MAXNAME
];
1554 if (uap
->namelen
> CTL_MAXNAME
|| uap
->namelen
< 2)
1557 error
= copyin(CAST_USER_ADDR_T(uap
->name
), &name
, uap
->namelen
* sizeof(int));
1561 error
= userland_sysctl(p
, name
, uap
->namelen
,
1562 CAST_USER_ADDR_T(uap
->old
), uap
->oldlenp
,
1563 CAST_USER_ADDR_T(uap
->new), uap
->newlen
, &j
);
1564 if (error
&& error
!= ENOMEM
)
1567 i
= copyout(&j
, CAST_USER_ADDR_T(uap
->oldlenp
), sizeof(j
));
1575 * This is used from various compatibility syscalls too. That's why name
1576 * must be in kernel space.
1579 userland_sysctl(struct proc
*p
, int *name
, u_int namelen
, user_addr_t oldp
,
1580 size_t *oldlenp
, user_addr_t newp
, size_t newlen
,
1584 struct sysctl_req req
, req2
;
1586 bzero(&req
, sizeof req
);
1591 req
.oldlen
= *oldlenp
;
1599 req
.newlen
= newlen
;
1603 req
.oldfunc
= sysctl_old_user
;
1604 req
.newfunc
= sysctl_new_user
;
1609 error
= sysctl_root(0, name
, namelen
, &req2
);
1610 } while (error
== EAGAIN
);
1614 if (error
&& error
!= ENOMEM
)
1618 if (req
.oldptr
&& req
.oldidx
> req
.oldlen
)
1619 *retval
= req
.oldlen
;
1621 *retval
= req
.oldidx
;
1626 /* Non-standard BSDI extension - only present on their 4.3 net-2 releases */
1627 #define KINFO_BSDI_SYSINFO (101<<8)
1630 * Kernel versions of the userland sysctl helper functions.
1632 * These allow sysctl to be used in the same fashion in both
1633 * userland and the kernel.
1635 * Note that some sysctl handlers use copyin/copyout, which
1636 * may not work correctly.
1640 sysctl(int *name
, u_int namelen
, void *oldp
, size_t *oldlenp
, void *newp
, size_t newlen
)
1643 return(kernel_sysctl(current_proc(), name
, namelen
, oldp
, oldlenp
, newp
, newlen
));
1647 sysctlnametomib(const char *name
, int *mibp
, size_t *sizep
)
1651 char *non_const_name
;
1654 * NOTE: This cast is safe because the service node does not modify
1655 * the contents of the string as part of its operation.
1657 non_const_name
= __CAST_AWAY_QUALIFIER(name
, const, char *);
1659 /* magic service node */
1663 /* look up OID for name */
1664 *sizep
*= sizeof(int);
1665 error
= sysctl(oid
, 2, mibp
, sizep
, non_const_name
, strlen(name
));
1666 *sizep
/= sizeof(int);
1672 sysctlbyname(const char *name
, void *oldp
, size_t *oldlenp
, void *newp
, size_t newlen
)
1674 int oid
[CTL_MAXNAME
+ 2];
1678 /* look up the OID */
1679 oidlen
= CTL_MAXNAME
;
1680 error
= sysctlnametomib(name
, oid
, &oidlen
);
1682 /* now use the OID */
1684 error
= sysctl(oid
, oidlen
, oldp
, oldlenp
, newp
, newlen
);