2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_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. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
21 * @APPLE_LICENSE_HEADER_END@
24 * Copyright (c) 1982, 1986, 1989, 1993
25 * The Regents of the University of California. All rights reserved.
27 * This code is derived from software contributed to Berkeley by
28 * Mike Karels at Berkeley Software Design, Inc.
30 * Quite extensively rewritten by Poul-Henning Kamp of the FreeBSD
31 * project, to make these variables more userfriendly.
33 * Redistribution and use in source and binary forms, with or without
34 * modification, are permitted provided that the following conditions
36 * 1. Redistributions of source code must retain the above copyright
37 * notice, this list of conditions and the following disclaimer.
38 * 2. Redistributions in binary form must reproduce the above copyright
39 * notice, this list of conditions and the following disclaimer in the
40 * documentation and/or other materials provided with the distribution.
41 * 3. All advertising materials mentioning features or use of this software
42 * must display the following acknowledgement:
43 * This product includes software developed by the University of
44 * California, Berkeley and its contributors.
45 * 4. Neither the name of the University nor the names of its contributors
46 * may be used to endorse or promote products derived from this software
47 * without specific prior written permission.
49 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
50 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
51 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
52 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
53 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
54 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
55 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
56 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
57 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
58 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
61 * @(#)kern_sysctl.c 8.4 (Berkeley) 4/14/94
65 #include <sys/param.h>
67 #include <sys/kernel.h>
68 #include <sys/sysctl.h>
69 #include <sys/malloc.h>
70 #include <sys/proc_internal.h>
71 #include <sys/systm.h>
73 #include <bsm/audit_kernel.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(tempbuf
,sizeof(tempbuf
),"%d",*name
);
317 error
= SYSCTL_OUT(req
, ".", 1);
319 error
= SYSCTL_OUT(req
, tempbuf
, strlen(tempbuf
));
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 MALLOC(p
, char *,req
->newlen
+1, M_TEMP
, M_WAITOK
);
505 error
= SYSCTL_IN(req
, p
, req
->newlen
);
511 p
[req
->newlen
] = '\0';
513 error
= name2oid(p
, oid
, &len
, &op
);
520 error
= SYSCTL_OUT(req
, oid
, len
* sizeof *oid
);
524 SYSCTL_PROC(_sysctl
, 3, name2oid
, CTLFLAG_RW
|CTLFLAG_ANYBODY
|CTLFLAG_KERN
, 0, 0,
525 sysctl_sysctl_name2oid
, "I", "");
528 sysctl_sysctl_oidfmt SYSCTL_HANDLER_ARGS
530 int *name
= (int *) arg1
, error
;
531 u_int namelen
= arg2
;
533 struct sysctl_oid
*oid
;
534 struct sysctl_oid_list
*lsp
= &sysctl__children
;
536 oid
= SLIST_FIRST(lsp
);
539 while (oid
&& indx
< CTL_MAXNAME
) {
540 if (oid
->oid_number
== name
[indx
]) {
542 if ((oid
->oid_kind
& CTLTYPE
) == CTLTYPE_NODE
) {
543 if (oid
->oid_handler
)
547 lsp
= (struct sysctl_oid_list
*)oid
->oid_arg1
;
548 oid
= SLIST_FIRST(lsp
);
555 oid
= SLIST_NEXT(oid
, oid_link
);
562 error
= SYSCTL_OUT(req
,
563 &oid
->oid_kind
, sizeof(oid
->oid_kind
));
565 error
= SYSCTL_OUT(req
, oid
->oid_fmt
,
566 strlen(oid
->oid_fmt
)+1);
571 SYSCTL_NODE(_sysctl
, 4, oidfmt
, CTLFLAG_RD
, sysctl_sysctl_oidfmt
, "");
574 * Default "handler" functions.
578 * Handle an int, signed or unsigned.
580 * a variable: point arg1 at it.
581 * a constant: pass it in arg2.
585 sysctl_handle_int SYSCTL_HANDLER_ARGS
590 error
= SYSCTL_OUT(req
, arg1
, sizeof(int));
592 error
= SYSCTL_OUT(req
, &arg2
, sizeof(int));
594 if (error
|| !req
->newptr
)
600 error
= SYSCTL_IN(req
, arg1
, sizeof(int));
603 AUDIT_ARG(value
, *(int *)arg1
);
608 * Handle a long, signed or unsigned. arg1 points to it.
612 sysctl_handle_long SYSCTL_HANDLER_ARGS
618 error
= SYSCTL_OUT(req
, arg1
, sizeof(long));
620 if (error
|| !req
->newptr
)
623 error
= SYSCTL_IN(req
, arg1
, sizeof(long));
628 * Handle a quad, signed or unsigned. arg1 points to it.
632 sysctl_handle_quad SYSCTL_HANDLER_ARGS
638 error
= SYSCTL_OUT(req
, arg1
, sizeof(long long));
640 if (error
|| !req
->newptr
)
643 error
= SYSCTL_IN(req
, arg1
, sizeof(long long));
648 * Expose an int value as a quad.
650 * This interface allows us to support interfaces defined
651 * as using quad values while the implementation is still
655 sysctl_handle_int2quad SYSCTL_HANDLER_ARGS
663 val
= (long long)*(int *)arg1
;
664 error
= SYSCTL_OUT(req
, &val
, sizeof(long long));
666 if (error
|| !req
->newptr
)
669 error
= SYSCTL_IN(req
, &val
, sizeof(long long));
672 * Value must be representable; check by
673 * casting and then casting back.
676 if ((long long)newval
!= val
) {
679 *(int *)arg1
= newval
;
686 * Handle our generic '\0' terminated 'C' string.
688 * a variable string: point arg1 at it, arg2 is max length.
689 * a constant string: point arg1 at it, arg2 is zero.
693 sysctl_handle_string SYSCTL_HANDLER_ARGS
697 error
= SYSCTL_OUT(req
, arg1
, strlen((char *)arg1
)+1);
699 if (error
|| !req
->newptr
)
702 if ((req
->newlen
- req
->newidx
) >= arg2
) {
705 arg2
= (req
->newlen
- req
->newidx
);
706 error
= SYSCTL_IN(req
, arg1
, arg2
);
707 ((char *)arg1
)[arg2
] = '\0';
714 * Handle any kind of opaque data.
715 * arg1 points to it, arg2 is the size.
719 sysctl_handle_opaque SYSCTL_HANDLER_ARGS
723 error
= SYSCTL_OUT(req
, arg1
, arg2
);
725 if (error
|| !req
->newptr
)
728 error
= SYSCTL_IN(req
, arg1
, arg2
);
734 * Transfer functions to/from kernel space.
737 sysctl_old_kernel(struct sysctl_req
*req
, const void *p
, size_t l
)
743 if (i
> req
->oldlen
- req
->oldidx
)
744 i
= req
->oldlen
- req
->oldidx
;
746 bcopy((void*)p
, CAST_DOWN(char *, (req
->oldptr
+ req
->oldidx
)), i
);
749 if (req
->oldptr
&& i
!= l
)
755 sysctl_new_kernel(struct sysctl_req
*req
, void *p
, size_t l
)
759 if (req
->newlen
- req
->newidx
< l
)
761 bcopy(CAST_DOWN(char *, (req
->newptr
+ req
->newidx
)), p
, l
);
767 kernel_sysctl(struct proc
*p
, int *name
, u_int namelen
, void *old
, size_t *oldlenp
, void *new, size_t newlen
)
770 struct sysctl_req req
;
776 bzero(&req
, sizeof req
);
779 req
.oldlen
= *oldlenp
;
781 req
.oldptr
= CAST_USER_ADDR_T(old
);
784 req
.newptr
= CAST_USER_ADDR_T(new);
786 req
.oldfunc
= sysctl_old_kernel
;
787 req
.newfunc
= sysctl_new_kernel
;
791 * Locking. Tree traversal always begins with the kernel funnel held.
793 fnl
= spl_kernel_funnel();
795 /* XXX this should probably be done in a general way */
796 while (memlock
.sl_lock
) {
798 (void) tsleep((caddr_t
)&memlock
, PRIBIO
+1, "sysctl", 0);
803 /* make the request */
804 error
= sysctl_root(0, name
, namelen
, &req
);
806 /* unlock memory if required */
808 vsunlock(req
.oldptr
, (user_size_t
)req
.oldlen
, B_WRITE
);
812 if (memlock
.sl_want
) {
814 wakeup((caddr_t
)&memlock
);
820 splx_kernel_funnel(fnl
);
822 if (error
&& error
!= ENOMEM
)
826 *oldlenp
= req
.oldidx
;
832 * Transfer function to/from user space.
835 sysctl_old_user(struct sysctl_req
*req
, const void *p
, size_t l
)
841 if (req
->oldlen
- req
->oldidx
< l
)
844 if (i
> req
->oldlen
- req
->oldidx
)
845 i
= req
->oldlen
- req
->oldidx
;
847 error
= copyout((void*)p
, (req
->oldptr
+ req
->oldidx
), i
);
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((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 if ((oid
->oid_kind
& CTLTYPE
) == CTLTYPE_NODE
) {
937 i
= (oid
->oid_handler
) (oid
,
938 name
+ indx
, namelen
- indx
,
941 i
= (oid
->oid_handler
) (oid
,
942 oid
->oid_arg1
, oid
->oid_arg2
,
949 #ifndef _SYS_SYSPROTO_H_
961 /* __sysctl(struct proc *p, struct sysctl_args *uap) */
962 new_sysctl(struct proc
*p
, struct sysctl_args
*uap
)
964 int error
, i
, name
[CTL_MAXNAME
];
967 if (uap
->namelen
> CTL_MAXNAME
|| uap
->namelen
< 2)
970 error
= copyin(CAST_USER_ADDR_T(uap
->name
), &name
, uap
->namelen
* sizeof(int));
974 error
= userland_sysctl(p
, name
, uap
->namelen
,
975 CAST_USER_ADDR_T(uap
->old
), uap
->oldlenp
, 0,
976 CAST_USER_ADDR_T(uap
->new), uap
->newlen
, &j
);
977 if (error
&& error
!= ENOMEM
)
980 i
= copyout(&j
, CAST_USER_ADDR_T(uap
->oldlenp
), sizeof(j
));
988 * This is used from various compatibility syscalls too. That's why name
989 * must be in kernel space.
992 userland_sysctl(struct proc
*p
, int *name
, u_int namelen
, user_addr_t oldp
,
993 size_t *oldlenp
, int inkernel
, user_addr_t newp
, size_t newlen
,
997 struct sysctl_req req
, req2
;
999 bzero(&req
, sizeof req
);
1005 req
.oldlen
= *oldlenp
;
1007 error
= copyin(CAST_USER_ADDR_T(oldlenp
), &req
.oldlen
, sizeof(*oldlenp
));
1018 req
.newlen
= newlen
;
1022 req
.oldfunc
= sysctl_old_user
;
1023 req
.newfunc
= sysctl_new_user
;
1028 error
= sysctl_root(0, name
, namelen
, &req2
);
1029 } while (error
== EAGAIN
);
1033 if (error
&& error
!= ENOMEM
)
1037 if (req
.oldptr
&& req
.oldidx
> req
.oldlen
)
1038 *retval
= req
.oldlen
;
1040 *retval
= req
.oldidx
;
1045 /* Non-standard BSDI extension - only present on their 4.3 net-2 releases */
1046 #define KINFO_BSDI_SYSINFO (101<<8)
1049 * Kernel versions of the userland sysctl helper functions.
1051 * These allow sysctl to be used in the same fashion in both
1052 * userland and the kernel.
1054 * Note that some sysctl handlers use copyin/copyout, which
1055 * may not work correctly.
1059 sysctl(int *name
, u_int namelen
, void *oldp
, size_t *oldlenp
, void *newp
, size_t newlen
)
1062 return(kernel_sysctl(current_proc(), name
, namelen
, oldp
, oldlenp
, newp
, newlen
));
1066 sysctlnametomib(const char *name
, int *mibp
, size_t *sizep
)
1071 /* magic service node */
1075 /* look up OID for name */
1076 *sizep
*= sizeof(int);
1077 error
= sysctl(oid
, 2, mibp
, sizep
, (void *)name
, strlen(name
));
1078 *sizep
/= sizeof(int);
1083 sysctlbyname(const char *name
, void *oldp
, size_t *oldlenp
, void *newp
, size_t newlen
)
1085 int oid
[CTL_MAXNAME
+ 2];
1089 /* look up the OID */
1090 oidlen
= CTL_MAXNAME
;
1091 error
= sysctlnametomib(name
, oid
, &oidlen
);
1093 /* now use the OID */
1095 error
= sysctl(oid
, oidlen
, oldp
, oldlenp
, newp
, newlen
);