2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
8 * This file contains Original Code and/or Modifications of Original Code
9 * as defined in and that are subject to the Apple Public Source License
10 * Version 2.0 (the 'License'). You may not use this file except in
11 * compliance with the License. Please obtain a copy of the License at
12 * http://www.opensource.apple.com/apsl/ and read it before using this
15 * The Original Code and all software distributed under the License are
16 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
17 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
18 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
20 * Please see the License for the specific language governing rights and
21 * limitations under the License.
23 * @APPLE_LICENSE_HEADER_END@
26 * Copyright (c) 1982, 1986, 1989, 1993
27 * The Regents of the University of California. All rights reserved.
29 * This code is derived from software contributed to Berkeley by
30 * Mike Karels at Berkeley Software Design, Inc.
32 * Quite extensively rewritten by Poul-Henning Kamp of the FreeBSD
33 * project, to make these variables more userfriendly.
35 * Redistribution and use in source and binary forms, with or without
36 * modification, are permitted provided that the following conditions
38 * 1. Redistributions of source code must retain the above copyright
39 * notice, this list of conditions and the following disclaimer.
40 * 2. Redistributions in binary form must reproduce the above copyright
41 * notice, this list of conditions and the following disclaimer in the
42 * documentation and/or other materials provided with the distribution.
43 * 3. All advertising materials mentioning features or use of this software
44 * must display the following acknowledgement:
45 * This product includes software developed by the University of
46 * California, Berkeley and its contributors.
47 * 4. Neither the name of the University nor the names of its contributors
48 * may be used to endorse or promote products derived from this software
49 * without specific prior written permission.
51 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
52 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
53 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
54 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
55 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
56 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
57 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
58 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
59 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
60 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
63 * @(#)kern_sysctl.c 8.4 (Berkeley) 4/14/94
67 #include <sys/param.h>
69 #include <sys/kernel.h>
70 #include <sys/sysctl.h>
71 #include <sys/malloc.h>
73 #include <sys/systm.h>
76 struct sysctl_oid_list sysctl__debug_children;
77 struct sysctl_oid_list sysctl__kern_children;
78 struct sysctl_oid_list sysctl__net_children;
79 struct sysctl_oid_list sysctl__sysctl_children;
82 extern struct sysctl_oid
*newsysctl_list
[];
83 extern struct sysctl_oid
*machdep_sysctl_list
[];
87 sysctl_sysctl_debug_dump_node(struct sysctl_oid_list
*l
, int i
);
94 static struct sysctl_lock
{
101 * XXX this does not belong here
104 spl_kernel_funnel(void)
108 cfunnel
= thread_funnel_get();
109 if (cfunnel
!= kernel_flock
) {
111 thread_funnel_set(cfunnel
, FALSE
);
112 thread_funnel_set(kernel_flock
, TRUE
);
118 splx_kernel_funnel(funnel_t
*saved
)
120 if (saved
!= kernel_flock
) {
121 thread_funnel_set(kernel_flock
, FALSE
);
123 thread_funnel_set(saved
, TRUE
);
127 static int sysctl_root SYSCTL_HANDLER_ARGS
;
129 struct sysctl_oid_list sysctl__children
; /* root list */
132 * Initialization of the MIB tree.
134 * Order by number in each list.
137 void sysctl_register_oid(struct sysctl_oid
*oidp
)
139 struct sysctl_oid_list
*parent
= oidp
->oid_parent
;
140 struct sysctl_oid
*p
;
141 struct sysctl_oid
*q
;
145 fnl
= spl_kernel_funnel();
148 * If this oid has a number OID_AUTO, give it a number which
149 * is greater than any current oid. Make sure it is at least
150 * 100 to leave space for pre-assigned oid numbers.
152 /* sysctl_sysctl_debug_dump_node(parent, 3); */
153 if (oidp
->oid_number
== OID_AUTO
) {
154 /* First, find the highest oid in the parent list >99 */
156 SLIST_FOREACH(p
, parent
, oid_link
) {
157 if (p
->oid_number
> n
)
160 oidp
->oid_number
= n
+ 1;
164 * Insert the oid into the parent's list in order.
167 SLIST_FOREACH(p
, parent
, oid_link
) {
168 if (oidp
->oid_number
< p
->oid_number
)
173 SLIST_INSERT_AFTER(q
, oidp
, oid_link
);
175 SLIST_INSERT_HEAD(parent
, oidp
, oid_link
);
177 splx_kernel_funnel(fnl
);
180 void sysctl_unregister_oid(struct sysctl_oid
*oidp
)
184 fnl
= spl_kernel_funnel();
185 SLIST_REMOVE(oidp
->oid_parent
, oidp
, sysctl_oid
, oid_link
);
186 splx_kernel_funnel(fnl
);
190 * Bulk-register all the oids in a linker_set.
192 void sysctl_register_set(struct linker_set
*lsp
)
194 int count
= lsp
->ls_length
;
196 for (i
= 0; i
< count
; i
++)
197 sysctl_register_oid((struct sysctl_oid
*) lsp
->ls_items
[i
]);
200 void sysctl_unregister_set(struct linker_set
*lsp
)
202 int count
= lsp
->ls_length
;
204 for (i
= 0; i
< count
; i
++)
205 sysctl_unregister_oid((struct sysctl_oid
*) lsp
->ls_items
[i
]);
210 * Register OID's from fixed list
213 void sysctl_register_fixed()
217 for (i
=0; newsysctl_list
[i
]; i
++) {
218 sysctl_register_oid(newsysctl_list
[i
]);
220 for (i
=0; machdep_sysctl_list
[i
]; i
++) {
221 sysctl_register_oid(machdep_sysctl_list
[i
]);
226 * Register the kernel's oids on startup.
228 struct linker_set sysctl_set
;
230 void sysctl_register_all(void *arg
)
232 sysctl_register_set(&sysctl_set
);
235 SYSINIT(sysctl
, SI_SUB_KMEM
, SI_ORDER_ANY
, sysctl_register_all
, 0);
240 * These functions implement a presently undocumented interface
241 * used by the sysctl program to walk the tree, and get the type
242 * so it can print the value.
243 * This interface is under work and consideration, and should probably
244 * be killed with a big axe by the first person who can find the time.
245 * (be aware though, that the proper interface isn't as obvious as it
246 * may seem, there are various conflicting requirements.
248 * {0,0} printf the entire MIB-tree.
249 * {0,1,...} return the name of the "..." OID.
250 * {0,2,...} return the next OID.
251 * {0,3} return the OID of the name in "new"
252 * {0,4,...} return the kind & format info for the "..." OID.
256 sysctl_sysctl_debug_dump_node(struct sysctl_oid_list
*l
, int i
)
259 struct sysctl_oid
*oidp
;
261 SLIST_FOREACH(oidp
, l
, oid_link
) {
266 printf("%d %s ", oidp
->oid_number
, oidp
->oid_name
);
269 oidp
->oid_kind
& CTLFLAG_RD
? 'R':' ',
270 oidp
->oid_kind
& CTLFLAG_WR
? 'W':' ');
272 if (oidp
->oid_handler
)
275 switch (oidp
->oid_kind
& CTLTYPE
) {
278 if (!oidp
->oid_handler
) {
279 sysctl_sysctl_debug_dump_node(
280 oidp
->oid_arg1
, i
+2);
283 case CTLTYPE_INT
: printf(" Int\n"); break;
284 case CTLTYPE_STRING
: printf(" String\n"); break;
285 case CTLTYPE_QUAD
: printf(" Quad\n"); break;
286 case CTLTYPE_OPAQUE
: printf(" Opaque/struct\n"); break;
287 default: printf("\n");
294 sysctl_sysctl_debug SYSCTL_HANDLER_ARGS
296 sysctl_sysctl_debug_dump_node(&sysctl__children
, 0);
300 SYSCTL_PROC(_sysctl
, 0, debug
, CTLTYPE_STRING
|CTLFLAG_RD
,
301 0, 0, sysctl_sysctl_debug
, "-", "");
304 sysctl_sysctl_name SYSCTL_HANDLER_ARGS
306 int *name
= (int *) arg1
;
307 u_int namelen
= arg2
;
309 struct sysctl_oid
*oid
;
310 struct sysctl_oid_list
*lsp
= &sysctl__children
, *lsp2
;
315 snprintf(buf
,sizeof(buf
),"%d",*name
);
317 error
= SYSCTL_OUT(req
, ".", 1);
319 error
= SYSCTL_OUT(req
, buf
, strlen(buf
));
327 SLIST_FOREACH(oid
, lsp
, oid_link
) {
328 if (oid
->oid_number
!= *name
)
332 error
= SYSCTL_OUT(req
, ".", 1);
334 error
= SYSCTL_OUT(req
, oid
->oid_name
,
335 strlen(oid
->oid_name
));
342 if ((oid
->oid_kind
& CTLTYPE
) != CTLTYPE_NODE
)
345 if (oid
->oid_handler
)
348 lsp2
= (struct sysctl_oid_list
*)oid
->oid_arg1
;
353 return (SYSCTL_OUT(req
, "", 1));
356 SYSCTL_NODE(_sysctl
, 1, name
, CTLFLAG_RD
, sysctl_sysctl_name
, "");
359 sysctl_sysctl_next_ls (struct sysctl_oid_list
*lsp
, int *name
, u_int namelen
,
360 int *next
, int *len
, int level
, struct sysctl_oid
**oidpp
)
362 struct sysctl_oid
*oidp
;
365 SLIST_FOREACH(oidp
, lsp
, oid_link
) {
366 *next
= oidp
->oid_number
;
370 if ((oidp
->oid_kind
& CTLTYPE
) != CTLTYPE_NODE
)
372 if (oidp
->oid_handler
)
373 /* We really should call the handler here...*/
375 lsp
= (struct sysctl_oid_list
*)oidp
->oid_arg1
;
376 if (!sysctl_sysctl_next_ls (lsp
, 0, 0, next
+1,
377 len
, level
+1, oidpp
))
382 if (oidp
->oid_number
< *name
)
385 if (oidp
->oid_number
> *name
) {
386 if ((oidp
->oid_kind
& CTLTYPE
) != CTLTYPE_NODE
)
388 if (oidp
->oid_handler
)
390 lsp
= (struct sysctl_oid_list
*)oidp
->oid_arg1
;
391 if (!sysctl_sysctl_next_ls (lsp
, name
+1, namelen
-1,
392 next
+1, len
, level
+1, oidpp
))
396 if ((oidp
->oid_kind
& CTLTYPE
) != CTLTYPE_NODE
)
399 if (oidp
->oid_handler
)
402 lsp
= (struct sysctl_oid_list
*)oidp
->oid_arg1
;
403 if (!sysctl_sysctl_next_ls (lsp
, name
+1, namelen
-1, next
+1,
404 len
, level
+1, oidpp
))
414 sysctl_sysctl_next SYSCTL_HANDLER_ARGS
416 int *name
= (int *) arg1
;
417 u_int namelen
= arg2
;
419 struct sysctl_oid
*oid
;
420 struct sysctl_oid_list
*lsp
= &sysctl__children
;
421 int newoid
[CTL_MAXNAME
];
423 i
= sysctl_sysctl_next_ls (lsp
, name
, namelen
, newoid
, &j
, 1, &oid
);
426 error
= SYSCTL_OUT(req
, newoid
, j
* sizeof (int));
430 SYSCTL_NODE(_sysctl
, 2, next
, CTLFLAG_RD
, sysctl_sysctl_next
, "");
433 name2oid (char *name
, int *oid
, int *len
, struct sysctl_oid
**oidpp
)
436 struct sysctl_oid
*oidp
;
437 struct sysctl_oid_list
*lsp
= &sysctl__children
;
443 p
= name
+ strlen(name
) - 1 ;
449 for (p
= name
; *p
&& *p
!= '.'; p
++)
455 oidp
= SLIST_FIRST(lsp
);
457 while (oidp
&& *len
< CTL_MAXNAME
) {
458 if (strcmp(name
, oidp
->oid_name
)) {
459 oidp
= SLIST_NEXT(oidp
, oid_link
);
462 *oid
++ = oidp
->oid_number
;
471 if ((oidp
->oid_kind
& CTLTYPE
) != CTLTYPE_NODE
)
474 if (oidp
->oid_handler
)
477 lsp
= (struct sysctl_oid_list
*)oidp
->oid_arg1
;
478 oidp
= SLIST_FIRST(lsp
);
480 for (p
= name
; *p
&& *p
!= '.'; p
++)
490 sysctl_sysctl_name2oid SYSCTL_HANDLER_ARGS
493 int error
, oid
[CTL_MAXNAME
], len
;
494 struct sysctl_oid
*op
= 0;
498 if (req
->newlen
>= MAXPATHLEN
) /* XXX arbitrary, undocumented */
499 return (ENAMETOOLONG
);
501 p
= _MALLOC(req
->newlen
+1, M_TEMP
, M_WAITOK
);
506 error
= SYSCTL_IN(req
, p
, req
->newlen
);
512 p
[req
->newlen
] = '\0';
514 error
= name2oid(p
, oid
, &len
, &op
);
521 error
= SYSCTL_OUT(req
, oid
, len
* sizeof *oid
);
525 SYSCTL_PROC(_sysctl
, 3, name2oid
, CTLFLAG_RW
|CTLFLAG_ANYBODY
|CTLFLAG_KERN
, 0, 0,
526 sysctl_sysctl_name2oid
, "I", "");
529 sysctl_sysctl_oidfmt SYSCTL_HANDLER_ARGS
531 int *name
= (int *) arg1
, error
;
532 u_int namelen
= arg2
;
534 struct sysctl_oid
*oid
;
535 struct sysctl_oid_list
*lsp
= &sysctl__children
;
537 oid
= SLIST_FIRST(lsp
);
540 while (oid
&& indx
< CTL_MAXNAME
) {
541 if (oid
->oid_number
== name
[indx
]) {
543 if ((oid
->oid_kind
& CTLTYPE
) == CTLTYPE_NODE
) {
544 if (oid
->oid_handler
)
548 lsp
= (struct sysctl_oid_list
*)oid
->oid_arg1
;
549 oid
= SLIST_FIRST(lsp
);
556 oid
= SLIST_NEXT(oid
, oid_link
);
563 error
= SYSCTL_OUT(req
,
564 &oid
->oid_kind
, sizeof(oid
->oid_kind
));
566 error
= SYSCTL_OUT(req
, oid
->oid_fmt
,
567 strlen(oid
->oid_fmt
)+1);
572 SYSCTL_NODE(_sysctl
, 4, oidfmt
, CTLFLAG_RD
, sysctl_sysctl_oidfmt
, "");
575 * Default "handler" functions.
579 * Handle an int, signed or unsigned.
581 * a variable: point arg1 at it.
582 * a constant: pass it in arg2.
586 sysctl_handle_int SYSCTL_HANDLER_ARGS
591 error
= SYSCTL_OUT(req
, arg1
, sizeof(int));
593 error
= SYSCTL_OUT(req
, &arg2
, sizeof(int));
595 if (error
|| !req
->newptr
)
601 error
= SYSCTL_IN(req
, arg1
, sizeof(int));
606 * Handle a long, signed or unsigned. arg1 points to it.
610 sysctl_handle_long SYSCTL_HANDLER_ARGS
616 error
= SYSCTL_OUT(req
, arg1
, sizeof(long));
618 if (error
|| !req
->newptr
)
621 error
= SYSCTL_IN(req
, arg1
, sizeof(long));
626 * Handle a quad, signed or unsigned. arg1 points to it.
630 sysctl_handle_quad SYSCTL_HANDLER_ARGS
636 error
= SYSCTL_OUT(req
, arg1
, sizeof(long long));
638 if (error
|| !req
->newptr
)
641 error
= SYSCTL_IN(req
, arg1
, sizeof(long long));
646 * Expose an int value as a quad.
648 * This interface allows us to support interfaces defined
649 * as using quad values while the implementation is still
653 sysctl_handle_int2quad SYSCTL_HANDLER_ARGS
661 val
= (long long)*(int *)arg1
;
662 error
= SYSCTL_OUT(req
, &val
, sizeof(long long));
664 if (error
|| !req
->newptr
)
667 error
= SYSCTL_IN(req
, &val
, sizeof(long long));
670 * Value must be representable; check by
671 * casting and then casting back.
674 if ((long long)newval
!= val
) {
677 *(int *)arg1
= newval
;
684 * Handle our generic '\0' terminated 'C' string.
686 * a variable string: point arg1 at it, arg2 is max length.
687 * a constant string: point arg1 at it, arg2 is zero.
691 sysctl_handle_string SYSCTL_HANDLER_ARGS
695 error
= SYSCTL_OUT(req
, arg1
, strlen((char *)arg1
)+1);
697 if (error
|| !req
->newptr
)
700 if ((req
->newlen
- req
->newidx
) >= arg2
) {
703 arg2
= (req
->newlen
- req
->newidx
);
704 error
= SYSCTL_IN(req
, arg1
, arg2
);
705 ((char *)arg1
)[arg2
] = '\0';
712 * Handle any kind of opaque data.
713 * arg1 points to it, arg2 is the size.
717 sysctl_handle_opaque SYSCTL_HANDLER_ARGS
721 error
= SYSCTL_OUT(req
, arg1
, arg2
);
723 if (error
|| !req
->newptr
)
726 error
= SYSCTL_IN(req
, arg1
, arg2
);
732 * Transfer functions to/from kernel space.
735 sysctl_old_kernel(struct sysctl_req
*req
, const void *p
, size_t l
)
742 if (i
> req
->oldlen
- req
->oldidx
)
743 i
= req
->oldlen
- req
->oldidx
;
745 bcopy((void*)p
, (char *)req
->oldptr
+ req
->oldidx
, i
);
748 if (req
->oldptr
&& i
!= l
)
754 sysctl_new_kernel(struct sysctl_req
*req
, void *p
, size_t l
)
758 if (req
->newlen
- req
->newidx
< l
)
760 bcopy((char *)req
->newptr
+ req
->newidx
, p
, l
);
766 kernel_sysctl(struct proc
*p
, int *name
, u_int namelen
, void *old
, size_t *oldlenp
, void *new, size_t newlen
)
769 struct sysctl_req req
;
775 bzero(&req
, sizeof req
);
778 req
.oldlen
= *oldlenp
;
785 req
.oldfunc
= sysctl_old_kernel
;
786 req
.newfunc
= sysctl_new_kernel
;
790 * Locking. Tree traversal always begins with the kernel funnel held.
792 fnl
= spl_kernel_funnel();
794 /* XXX this should probably be done in a general way */
795 while (memlock
.sl_lock
) {
797 (void) tsleep((caddr_t
)&memlock
, PRIBIO
+1, "sysctl", 0);
802 /* make the request */
803 error
= sysctl_root(0, name
, namelen
, &req
);
805 /* unlock memory if required */
807 vsunlock(req
.oldptr
, req
.oldlen
, B_WRITE
);
811 if (memlock
.sl_want
) {
813 wakeup((caddr_t
)&memlock
);
819 splx_kernel_funnel(fnl
);
821 if (error
&& error
!= ENOMEM
)
825 *oldlenp
= req
.oldidx
;
831 * Transfer function to/from user space.
834 sysctl_old_user(struct sysctl_req
*req
, const void *p
, size_t l
)
840 if (req
->oldlen
- req
->oldidx
< l
)
843 if (i
> req
->oldlen
- req
->oldidx
)
844 i
= req
->oldlen
- req
->oldidx
;
846 error
= copyout((void*)p
, (char *)req
->oldptr
+ req
->oldidx
,
852 if (req
->oldptr
&& i
< l
)
858 sysctl_new_user(struct sysctl_req
*req
, void *p
, size_t l
)
864 if (req
->newlen
- req
->newidx
< l
)
866 error
= copyin((char *)req
->newptr
+ req
->newidx
, p
, l
);
872 * Traverse our tree, and find the right node, execute whatever it points
873 * at, and return the resulting error code.
877 sysctl_root SYSCTL_HANDLER_ARGS
879 int *name
= (int *) arg1
;
880 u_int namelen
= arg2
;
882 struct sysctl_oid
*oid
;
883 struct sysctl_oid_list
*lsp
= &sysctl__children
;
886 oid
= SLIST_FIRST(lsp
);
889 while (oid
&& indx
< CTL_MAXNAME
) {
890 if (oid
->oid_number
== name
[indx
]) {
892 if (oid
->oid_kind
& CTLFLAG_NOLOCK
)
894 if ((oid
->oid_kind
& CTLTYPE
) == CTLTYPE_NODE
) {
895 if (oid
->oid_handler
)
899 lsp
= (struct sysctl_oid_list
*)oid
->oid_arg1
;
900 oid
= SLIST_FIRST(lsp
);
907 oid
= SLIST_NEXT(oid
, oid_link
);
912 /* If writing isn't allowed */
913 if (req
->newptr
&& (!(oid
->oid_kind
& CTLFLAG_WR
) ||
914 ((oid
->oid_kind
& CTLFLAG_SECURE
) && securelevel
> 0))) {
919 * If we're inside the kernel, the OID must be marked as kernel-valid.
920 * XXX This mechanism for testing is bad.
922 if ((req
->oldfunc
== sysctl_old_kernel
) && !(oid
->oid_kind
& CTLFLAG_KERN
))
925 /* Most likely only root can write */
926 if (!(oid
->oid_kind
& CTLFLAG_ANYBODY
) &&
927 req
->newptr
&& req
->p
&&
928 (error
= suser(req
->p
->p_ucred
, &req
->p
->p_acflag
)))
931 if (!oid
->oid_handler
) {
936 * Switch to the NETWORK funnel for CTL_NET and KERN_IPC sysctls
939 if (((name
[0] == CTL_NET
) || ((name
[0] == CTL_KERN
) &&
940 (name
[1] == KERN_IPC
))))
941 thread_funnel_switch(KERNEL_FUNNEL
, NETWORK_FUNNEL
);
943 if ((oid
->oid_kind
& CTLTYPE
) == CTLTYPE_NODE
) {
944 i
= (oid
->oid_handler
) (oid
,
945 name
+ indx
, namelen
- indx
,
948 i
= (oid
->oid_handler
) (oid
,
949 oid
->oid_arg1
, oid
->oid_arg2
,
954 * Switch back to the KERNEL funnel, if necessary
957 if (((name
[0] == CTL_NET
) || ((name
[0] == CTL_KERN
) &&
958 (name
[1] == KERN_IPC
))))
959 thread_funnel_switch(NETWORK_FUNNEL
, KERNEL_FUNNEL
);
964 #ifndef _SYS_SYSPROTO_H_
976 /* __sysctl(struct proc *p, struct sysctl_args *uap) */
977 new_sysctl(struct proc
*p
, struct sysctl_args
*uap
)
979 int error
, i
, name
[CTL_MAXNAME
];
982 if (uap
->namelen
> CTL_MAXNAME
|| uap
->namelen
< 2)
985 error
= copyin(uap
->name
, &name
, uap
->namelen
* sizeof(int));
989 error
= userland_sysctl(p
, name
, uap
->namelen
,
990 uap
->old
, uap
->oldlenp
, 0,
991 uap
->new, uap
->newlen
, &j
);
992 if (error
&& error
!= ENOMEM
)
995 i
= copyout(&j
, uap
->oldlenp
, sizeof(j
));
1003 * This is used from various compatibility syscalls too. That's why name
1004 * must be in kernel space.
1007 userland_sysctl(struct proc
*p
, int *name
, u_int namelen
, void *old
, size_t *oldlenp
, int inkernel
, void *new, size_t newlen
, size_t *retval
)
1010 struct sysctl_req req
, req2
;
1012 bzero(&req
, sizeof req
);
1018 req
.oldlen
= *oldlenp
;
1020 error
= copyin(oldlenp
, &req
.oldlen
, sizeof(*oldlenp
));
1031 req
.newlen
= newlen
;
1035 req
.oldfunc
= sysctl_old_user
;
1036 req
.newfunc
= sysctl_new_user
;
1041 error
= sysctl_root(0, name
, namelen
, &req2
);
1042 } while (error
== EAGAIN
);
1046 if (error
&& error
!= ENOMEM
)
1050 if (req
.oldptr
&& req
.oldidx
> req
.oldlen
)
1051 *retval
= req
.oldlen
;
1053 *retval
= req
.oldidx
;
1058 /* Non-standard BSDI extension - only present on their 4.3 net-2 releases */
1059 #define KINFO_BSDI_SYSINFO (101<<8)
1062 * Kernel versions of the userland sysctl helper functions.
1064 * These allow sysctl to be used in the same fashion in both
1065 * userland and the kernel.
1067 * Note that some sysctl handlers use copyin/copyout, which
1068 * may not work correctly.
1072 sysctl(int *name
, u_int namelen
, void *oldp
, size_t *oldlenp
, void *newp
, size_t newlen
)
1075 return(kernel_sysctl(current_proc(), name
, namelen
, oldp
, oldlenp
, newp
, newlen
));
1079 sysctlnametomib(const char *name
, int *mibp
, size_t *sizep
)
1084 /* magic service node */
1088 /* look up OID for name */
1089 *sizep
*= sizeof(int);
1090 error
= sysctl(oid
, 2, mibp
, sizep
, (void *)name
, strlen(name
));
1091 *sizep
/= sizeof(int);
1096 sysctlbyname(const char *name
, void *oldp
, size_t *oldlenp
, void *newp
, size_t newlen
)
1098 int oid
[CTL_MAXNAME
+ 2];
1102 /* look up the OID */
1103 oidlen
= CTL_MAXNAME
;
1104 error
= sysctlnametomib(name
, oid
, &oidlen
);
1106 /* now use the OID */
1108 error
= sysctl(oid
, oidlen
, oldp
, oldlenp
, newp
, newlen
);