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
[];
86 sysctl_sysctl_debug_dump_node(struct sysctl_oid_list
*l
, int i
);
93 static struct sysctl_lock
{
100 * XXX this does not belong here
103 spl_kernel_funnel(void)
107 cfunnel
= thread_funnel_get();
108 if (cfunnel
!= kernel_flock
) {
110 thread_funnel_set(cfunnel
, FALSE
);
111 thread_funnel_set(kernel_flock
, TRUE
);
117 splx_kernel_funnel(funnel_t
*saved
)
119 if (saved
!= kernel_flock
) {
120 thread_funnel_set(kernel_flock
, FALSE
);
122 thread_funnel_set(saved
, TRUE
);
126 static int sysctl_root SYSCTL_HANDLER_ARGS
;
128 struct sysctl_oid_list sysctl__children
; /* root list */
131 * Initialization of the MIB tree.
133 * Order by number in each list.
136 void sysctl_register_oid(struct sysctl_oid
*oidp
)
138 struct sysctl_oid_list
*parent
= oidp
->oid_parent
;
139 struct sysctl_oid
*p
;
140 struct sysctl_oid
*q
;
144 fnl
= spl_kernel_funnel();
147 * If this oid has a number OID_AUTO, give it a number which
148 * is greater than any current oid. Make sure it is at least
149 * 100 to leave space for pre-assigned oid numbers.
151 /* sysctl_sysctl_debug_dump_node(parent, 3); */
152 if (oidp
->oid_number
== OID_AUTO
) {
153 /* First, find the highest oid in the parent list >99 */
155 SLIST_FOREACH(p
, parent
, oid_link
) {
156 if (p
->oid_number
> n
)
159 oidp
->oid_number
= n
+ 1;
163 * Insert the oid into the parent's list in order.
166 SLIST_FOREACH(p
, parent
, oid_link
) {
167 if (oidp
->oid_number
< p
->oid_number
)
172 SLIST_INSERT_AFTER(q
, oidp
, oid_link
);
174 SLIST_INSERT_HEAD(parent
, oidp
, oid_link
);
176 splx_kernel_funnel(fnl
);
179 void sysctl_unregister_oid(struct sysctl_oid
*oidp
)
183 fnl
= spl_kernel_funnel();
184 SLIST_REMOVE(oidp
->oid_parent
, oidp
, sysctl_oid
, oid_link
);
185 splx_kernel_funnel(fnl
);
189 * Bulk-register all the oids in a linker_set.
191 void sysctl_register_set(struct linker_set
*lsp
)
193 int count
= lsp
->ls_length
;
195 for (i
= 0; i
< count
; i
++)
196 sysctl_register_oid((struct sysctl_oid
*) lsp
->ls_items
[i
]);
199 void sysctl_unregister_set(struct linker_set
*lsp
)
201 int count
= lsp
->ls_length
;
203 for (i
= 0; i
< count
; i
++)
204 sysctl_unregister_oid((struct sysctl_oid
*) lsp
->ls_items
[i
]);
209 * Register OID's from fixed list
212 void sysctl_register_fixed()
217 while (newsysctl_list
[i
]) {
218 /* printf("Registering %d\n", i); */
219 sysctl_register_oid(newsysctl_list
[i
++]);
224 * Register the kernel's oids on startup.
226 struct linker_set sysctl_set
;
228 void sysctl_register_all(void *arg
)
230 sysctl_register_set(&sysctl_set
);
233 SYSINIT(sysctl
, SI_SUB_KMEM
, SI_ORDER_ANY
, sysctl_register_all
, 0);
238 * These functions implement a presently undocumented interface
239 * used by the sysctl program to walk the tree, and get the type
240 * so it can print the value.
241 * This interface is under work and consideration, and should probably
242 * be killed with a big axe by the first person who can find the time.
243 * (be aware though, that the proper interface isn't as obvious as it
244 * may seem, there are various conflicting requirements.
246 * {0,0} printf the entire MIB-tree.
247 * {0,1,...} return the name of the "..." OID.
248 * {0,2,...} return the next OID.
249 * {0,3} return the OID of the name in "new"
250 * {0,4,...} return the kind & format info for the "..." OID.
254 sysctl_sysctl_debug_dump_node(struct sysctl_oid_list
*l
, int i
)
257 struct sysctl_oid
*oidp
;
259 SLIST_FOREACH(oidp
, l
, oid_link
) {
264 printf("%d %s ", oidp
->oid_number
, oidp
->oid_name
);
267 oidp
->oid_kind
& CTLFLAG_RD
? 'R':' ',
268 oidp
->oid_kind
& CTLFLAG_WR
? 'W':' ');
270 if (oidp
->oid_handler
)
273 switch (oidp
->oid_kind
& CTLTYPE
) {
276 if (!oidp
->oid_handler
) {
277 sysctl_sysctl_debug_dump_node(
278 oidp
->oid_arg1
, i
+2);
281 case CTLTYPE_INT
: printf(" Int\n"); break;
282 case CTLTYPE_STRING
: printf(" String\n"); break;
283 case CTLTYPE_QUAD
: printf(" Quad\n"); break;
284 case CTLTYPE_OPAQUE
: printf(" Opaque/struct\n"); break;
285 default: printf("\n");
292 sysctl_sysctl_debug SYSCTL_HANDLER_ARGS
294 sysctl_sysctl_debug_dump_node(&sysctl__children
, 0);
298 SYSCTL_PROC(_sysctl
, 0, debug
, CTLTYPE_STRING
|CTLFLAG_RD
,
299 0, 0, sysctl_sysctl_debug
, "-", "");
302 sysctl_sysctl_name SYSCTL_HANDLER_ARGS
304 int *name
= (int *) arg1
;
305 u_int namelen
= arg2
;
307 struct sysctl_oid
*oid
;
308 struct sysctl_oid_list
*lsp
= &sysctl__children
, *lsp2
;
313 snprintf(buf
,sizeof(buf
),"%d",*name
);
315 error
= SYSCTL_OUT(req
, ".", 1);
317 error
= SYSCTL_OUT(req
, buf
, strlen(buf
));
325 SLIST_FOREACH(oid
, lsp
, oid_link
) {
326 if (oid
->oid_number
!= *name
)
330 error
= SYSCTL_OUT(req
, ".", 1);
332 error
= SYSCTL_OUT(req
, oid
->oid_name
,
333 strlen(oid
->oid_name
));
340 if ((oid
->oid_kind
& CTLTYPE
) != CTLTYPE_NODE
)
343 if (oid
->oid_handler
)
346 lsp2
= (struct sysctl_oid_list
*)oid
->oid_arg1
;
351 return (SYSCTL_OUT(req
, "", 1));
354 SYSCTL_NODE(_sysctl
, 1, name
, CTLFLAG_RD
, sysctl_sysctl_name
, "");
357 sysctl_sysctl_next_ls (struct sysctl_oid_list
*lsp
, int *name
, u_int namelen
,
358 int *next
, int *len
, int level
, struct sysctl_oid
**oidpp
)
360 struct sysctl_oid
*oidp
;
363 SLIST_FOREACH(oidp
, lsp
, oid_link
) {
364 *next
= oidp
->oid_number
;
368 if ((oidp
->oid_kind
& CTLTYPE
) != CTLTYPE_NODE
)
370 if (oidp
->oid_handler
)
371 /* We really should call the handler here...*/
373 lsp
= (struct sysctl_oid_list
*)oidp
->oid_arg1
;
374 if (!sysctl_sysctl_next_ls (lsp
, 0, 0, next
+1,
375 len
, level
+1, oidpp
))
380 if (oidp
->oid_number
< *name
)
383 if (oidp
->oid_number
> *name
) {
384 if ((oidp
->oid_kind
& CTLTYPE
) != CTLTYPE_NODE
)
386 if (oidp
->oid_handler
)
388 lsp
= (struct sysctl_oid_list
*)oidp
->oid_arg1
;
389 if (!sysctl_sysctl_next_ls (lsp
, name
+1, namelen
-1,
390 next
+1, len
, level
+1, oidpp
))
394 if ((oidp
->oid_kind
& CTLTYPE
) != CTLTYPE_NODE
)
397 if (oidp
->oid_handler
)
400 lsp
= (struct sysctl_oid_list
*)oidp
->oid_arg1
;
401 if (!sysctl_sysctl_next_ls (lsp
, name
+1, namelen
-1, next
+1,
402 len
, level
+1, oidpp
))
412 sysctl_sysctl_next SYSCTL_HANDLER_ARGS
414 int *name
= (int *) arg1
;
415 u_int namelen
= arg2
;
417 struct sysctl_oid
*oid
;
418 struct sysctl_oid_list
*lsp
= &sysctl__children
;
419 int newoid
[CTL_MAXNAME
];
421 i
= sysctl_sysctl_next_ls (lsp
, name
, namelen
, newoid
, &j
, 1, &oid
);
424 error
= SYSCTL_OUT(req
, newoid
, j
* sizeof (int));
428 SYSCTL_NODE(_sysctl
, 2, next
, CTLFLAG_RD
, sysctl_sysctl_next
, "");
431 name2oid (char *name
, int *oid
, int *len
, struct sysctl_oid
**oidpp
)
434 struct sysctl_oid
*oidp
;
435 struct sysctl_oid_list
*lsp
= &sysctl__children
;
441 p
= name
+ strlen(name
) - 1 ;
447 for (p
= name
; *p
&& *p
!= '.'; p
++)
453 oidp
= SLIST_FIRST(lsp
);
455 while (oidp
&& *len
< CTL_MAXNAME
) {
456 if (strcmp(name
, oidp
->oid_name
)) {
457 oidp
= SLIST_NEXT(oidp
, oid_link
);
460 *oid
++ = oidp
->oid_number
;
469 if ((oidp
->oid_kind
& CTLTYPE
) != CTLTYPE_NODE
)
472 if (oidp
->oid_handler
)
475 lsp
= (struct sysctl_oid_list
*)oidp
->oid_arg1
;
476 oidp
= SLIST_FIRST(lsp
);
478 for (p
= name
; *p
&& *p
!= '.'; p
++)
488 sysctl_sysctl_name2oid SYSCTL_HANDLER_ARGS
491 int error
, oid
[CTL_MAXNAME
], len
;
492 struct sysctl_oid
*op
= 0;
496 if (req
->newlen
>= MAXPATHLEN
) /* XXX arbitrary, undocumented */
497 return (ENAMETOOLONG
);
499 p
= _MALLOC(req
->newlen
+1, M_TEMP
, M_WAITOK
);
504 error
= SYSCTL_IN(req
, p
, req
->newlen
);
510 p
[req
->newlen
] = '\0';
512 error
= name2oid(p
, oid
, &len
, &op
);
519 error
= SYSCTL_OUT(req
, oid
, len
* sizeof *oid
);
523 SYSCTL_PROC(_sysctl
, 3, name2oid
, CTLFLAG_RW
|CTLFLAG_ANYBODY
, 0, 0,
524 sysctl_sysctl_name2oid
, "I", "");
527 sysctl_sysctl_oidfmt SYSCTL_HANDLER_ARGS
529 int *name
= (int *) arg1
, error
;
530 u_int namelen
= arg2
;
532 struct sysctl_oid
*oid
;
533 struct sysctl_oid_list
*lsp
= &sysctl__children
;
535 oid
= SLIST_FIRST(lsp
);
538 while (oid
&& indx
< CTL_MAXNAME
) {
539 if (oid
->oid_number
== name
[indx
]) {
541 if ((oid
->oid_kind
& CTLTYPE
) == CTLTYPE_NODE
) {
542 if (oid
->oid_handler
)
546 lsp
= (struct sysctl_oid_list
*)oid
->oid_arg1
;
547 oid
= SLIST_FIRST(lsp
);
554 oid
= SLIST_NEXT(oid
, oid_link
);
561 error
= SYSCTL_OUT(req
,
562 &oid
->oid_kind
, sizeof(oid
->oid_kind
));
564 error
= SYSCTL_OUT(req
, oid
->oid_fmt
,
565 strlen(oid
->oid_fmt
)+1);
570 SYSCTL_NODE(_sysctl
, 4, oidfmt
, CTLFLAG_RD
, sysctl_sysctl_oidfmt
, "");
573 * Default "handler" functions.
577 * Handle an int, signed or unsigned.
579 * a variable: point arg1 at it.
580 * a constant: pass it in arg2.
584 sysctl_handle_int SYSCTL_HANDLER_ARGS
589 error
= SYSCTL_OUT(req
, arg1
, sizeof(int));
591 error
= SYSCTL_OUT(req
, &arg2
, sizeof(int));
593 if (error
|| !req
->newptr
)
599 error
= SYSCTL_IN(req
, arg1
, sizeof(int));
604 * Handle a long, signed or unsigned. arg1 points to it.
608 sysctl_handle_long SYSCTL_HANDLER_ARGS
614 error
= SYSCTL_OUT(req
, arg1
, sizeof(long));
616 if (error
|| !req
->newptr
)
619 error
= SYSCTL_IN(req
, arg1
, sizeof(long));
624 * Handle a quad, signed or unsigned. arg1 points to it.
628 sysctl_handle_quad SYSCTL_HANDLER_ARGS
634 error
= SYSCTL_OUT(req
, arg1
, sizeof(long long));
636 if (error
|| !req
->newptr
)
639 error
= SYSCTL_IN(req
, arg1
, sizeof(long long));
644 * Expose an int value as a quad.
646 * This interface allows us to support interfaces defined
647 * as using quad values while the implementation is still
651 sysctl_handle_int2quad SYSCTL_HANDLER_ARGS
659 val
= (long long)*(int *)arg1
;
660 error
= SYSCTL_OUT(req
, &val
, sizeof(long long));
662 if (error
|| !req
->newptr
)
665 error
= SYSCTL_IN(req
, &val
, sizeof(long long));
668 * Value must be representable; check by
669 * casting and then casting back.
672 if ((long long)newval
!= val
) {
675 *(int *)arg1
= newval
;
682 * Handle our generic '\0' terminated 'C' string.
684 * a variable string: point arg1 at it, arg2 is max length.
685 * a constant string: point arg1 at it, arg2 is zero.
689 sysctl_handle_string SYSCTL_HANDLER_ARGS
693 error
= SYSCTL_OUT(req
, arg1
, strlen((char *)arg1
)+1);
695 if (error
|| !req
->newptr
)
698 if ((req
->newlen
- req
->newidx
) >= arg2
) {
701 arg2
= (req
->newlen
- req
->newidx
);
702 error
= SYSCTL_IN(req
, arg1
, arg2
);
703 ((char *)arg1
)[arg2
] = '\0';
710 * Handle any kind of opaque data.
711 * arg1 points to it, arg2 is the size.
715 sysctl_handle_opaque SYSCTL_HANDLER_ARGS
719 error
= SYSCTL_OUT(req
, arg1
, arg2
);
721 if (error
|| !req
->newptr
)
724 error
= SYSCTL_IN(req
, arg1
, arg2
);
730 * Transfer functions to/from kernel space.
733 sysctl_old_kernel(struct sysctl_req
*req
, const void *p
, size_t l
)
740 if (i
> req
->oldlen
- req
->oldidx
)
741 i
= req
->oldlen
- req
->oldidx
;
743 bcopy((void*)p
, (char *)req
->oldptr
+ req
->oldidx
, i
);
746 if (req
->oldptr
&& i
!= l
)
752 sysctl_new_kernel(struct sysctl_req
*req
, void *p
, size_t l
)
756 if (req
->newlen
- req
->newidx
< l
)
758 bcopy((char *)req
->newptr
+ req
->newidx
, p
, l
);
764 kernel_sysctl(struct proc
*p
, int *name
, u_int namelen
, void *old
, size_t *oldlenp
, void *new, size_t newlen
)
767 struct sysctl_req req
;
773 bzero(&req
, sizeof req
);
776 req
.oldlen
= *oldlenp
;
783 req
.oldfunc
= sysctl_old_kernel
;
784 req
.newfunc
= sysctl_new_kernel
;
788 * Locking. Tree traversal always begins with the kernel funnel held.
790 fnl
= spl_kernel_funnel();
792 /* XXX this should probably be done in a general way */
793 while (memlock
.sl_lock
) {
795 (void) tsleep((caddr_t
)&memlock
, PRIBIO
+1, "sysctl", 0);
800 /* make the request */
801 error
= sysctl_root(0, name
, namelen
, &req
);
803 /* unlock memory if required */
805 vsunlock(req
.oldptr
, req
.oldlen
, B_WRITE
);
809 if (memlock
.sl_want
) {
811 wakeup((caddr_t
)&memlock
);
817 splx_kernel_funnel(fnl
);
819 if (error
&& error
!= ENOMEM
)
823 *oldlenp
= req
.oldidx
;
829 * Transfer function to/from user space.
832 sysctl_old_user(struct sysctl_req
*req
, const void *p
, size_t l
)
838 if (req
->oldlen
- req
->oldidx
< l
)
841 if (i
> req
->oldlen
- req
->oldidx
)
842 i
= req
->oldlen
- req
->oldidx
;
844 error
= copyout((void*)p
, (char *)req
->oldptr
+ req
->oldidx
,
850 if (req
->oldptr
&& i
< l
)
856 sysctl_new_user(struct sysctl_req
*req
, void *p
, size_t l
)
862 if (req
->newlen
- req
->newidx
< l
)
864 error
= copyin((char *)req
->newptr
+ req
->newidx
, p
, l
);
870 * Traverse our tree, and find the right node, execute whatever it points
871 * at, and return the resulting error code.
875 sysctl_root SYSCTL_HANDLER_ARGS
877 int *name
= (int *) arg1
;
878 u_int namelen
= arg2
;
880 struct sysctl_oid
*oid
;
881 struct sysctl_oid_list
*lsp
= &sysctl__children
;
884 oid
= SLIST_FIRST(lsp
);
887 while (oid
&& indx
< CTL_MAXNAME
) {
888 if (oid
->oid_number
== name
[indx
]) {
890 if (oid
->oid_kind
& CTLFLAG_NOLOCK
)
892 if ((oid
->oid_kind
& CTLTYPE
) == CTLTYPE_NODE
) {
893 if (oid
->oid_handler
)
897 lsp
= (struct sysctl_oid_list
*)oid
->oid_arg1
;
898 oid
= SLIST_FIRST(lsp
);
905 oid
= SLIST_NEXT(oid
, oid_link
);
910 /* If writing isn't allowed */
911 if (req
->newptr
&& (!(oid
->oid_kind
& CTLFLAG_WR
) ||
912 ((oid
->oid_kind
& CTLFLAG_SECURE
) && securelevel
> 0))) {
917 * If we're inside the kernel, the OID must be marked as kernel-valid.
918 * XXX This mechanism for testing is bad.
920 if ((req
->oldfunc
== sysctl_old_kernel
) && !(oid
->oid_kind
& CTLFLAG_KERN
))
923 /* Most likely only root can write */
924 if (!(oid
->oid_kind
& CTLFLAG_ANYBODY
) &&
925 req
->newptr
&& req
->p
&&
926 (error
= suser(req
->p
->p_ucred
, &req
->p
->p_acflag
)))
929 if (!oid
->oid_handler
) {
934 * Switch to the NETWORK funnel for CTL_NET and KERN_IPC sysctls
937 if (((name
[0] == CTL_NET
) || ((name
[0] == CTL_KERN
) &&
938 (name
[1] == KERN_IPC
))))
939 thread_funnel_switch(KERNEL_FUNNEL
, NETWORK_FUNNEL
);
941 if ((oid
->oid_kind
& CTLTYPE
) == CTLTYPE_NODE
) {
942 i
= (oid
->oid_handler
) (oid
,
943 name
+ indx
, namelen
- indx
,
946 i
= (oid
->oid_handler
) (oid
,
947 oid
->oid_arg1
, oid
->oid_arg2
,
952 * Switch back to the KERNEL funnel, if necessary
955 if (((name
[0] == CTL_NET
) || ((name
[0] == CTL_KERN
) &&
956 (name
[1] == KERN_IPC
))))
957 thread_funnel_switch(NETWORK_FUNNEL
, KERNEL_FUNNEL
);
962 #ifndef _SYS_SYSPROTO_H_
974 /* __sysctl(struct proc *p, struct sysctl_args *uap) */
975 new_sysctl(struct proc
*p
, struct sysctl_args
*uap
)
977 int error
, i
, name
[CTL_MAXNAME
];
980 if (uap
->namelen
> CTL_MAXNAME
|| uap
->namelen
< 2)
983 error
= copyin(uap
->name
, &name
, uap
->namelen
* sizeof(int));
987 error
= userland_sysctl(p
, name
, uap
->namelen
,
988 uap
->old
, uap
->oldlenp
, 0,
989 uap
->new, uap
->newlen
, &j
);
990 if (error
&& error
!= ENOMEM
)
993 i
= copyout(&j
, uap
->oldlenp
, sizeof(j
));
1001 * This is used from various compatibility syscalls too. That's why name
1002 * must be in kernel space.
1005 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
)
1008 struct sysctl_req req
, req2
;
1010 bzero(&req
, sizeof req
);
1016 req
.oldlen
= *oldlenp
;
1018 error
= copyin(oldlenp
, &req
.oldlen
, sizeof(*oldlenp
));
1029 req
.newlen
= newlen
;
1033 req
.oldfunc
= sysctl_old_user
;
1034 req
.newfunc
= sysctl_new_user
;
1039 error
= sysctl_root(0, name
, namelen
, &req2
);
1040 } while (error
== EAGAIN
);
1044 if (error
&& error
!= ENOMEM
)
1048 if (req
.oldptr
&& req
.oldidx
> req
.oldlen
)
1049 *retval
= req
.oldlen
;
1051 *retval
= req
.oldidx
;
1057 * Kernel versions of the userland sysctl helper functions.
1059 * These allow sysctl to be used in the same fashion in both
1060 * userland and the kernel.
1062 * Note that some sysctl handlers use copyin/copyout, which
1063 * may not work correctly.
1067 sysctl(int *name
, u_int namelen
, void *oldp
, size_t *oldlenp
, void *newp
, size_t newlen
)
1070 return(kernel_sysctl(current_proc(), name
, namelen
, oldp
, oldlenp
, newp
, newlen
));
1074 sysctlnametomib(const char *name
, int *mibp
, size_t *sizep
)
1079 /* magic service node */
1083 /* look up OID for name */
1084 *sizep
*= sizeof(int);
1085 error
= sysctl(oid
, 2, mibp
, sizep
, (void *)name
, strlen(name
));
1086 *sizep
/= sizeof(int);
1091 sysctlbyname(const char *name
, void *oldp
, size_t *oldlenp
, void *newp
, size_t newlen
)
1093 int oid
[CTL_MAXNAME
+ 2];
1097 /* look up the OID */
1098 oidlen
= CTL_MAXNAME
;
1099 error
= sysctlnametomib(name
, oid
, &oidlen
);
1101 /* now use the OID */
1103 error
= sysctl(oid
, oidlen
, oldp
, oldlenp
, newp
, newlen
);