2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_OSREFERENCE_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
10 * License may not be used to create, or enable the creation or
11 * redistribution of, unlawful or unlicensed copies of an Apple operating
12 * system, or to circumvent, violate, or enable the circumvention or
13 * violation of, any terms of an Apple operating system software license
16 * Please obtain a copy of the License at
17 * http://www.opensource.apple.com/apsl/ and read it before using this
20 * The Original Code and all software distributed under the License are
21 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
22 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
23 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
24 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
25 * Please see the License for the specific language governing rights and
26 * limitations under the License.
28 * @APPLE_LICENSE_OSREFERENCE_HEADER_END@
31 * Copyright (c) 1982, 1986, 1989, 1993
32 * The Regents of the University of California. All rights reserved.
34 * This code is derived from software contributed to Berkeley by
35 * Mike Karels at Berkeley Software Design, Inc.
37 * Quite extensively rewritten by Poul-Henning Kamp of the FreeBSD
38 * project, to make these variables more userfriendly.
40 * Redistribution and use in source and binary forms, with or without
41 * modification, are permitted provided that the following conditions
43 * 1. Redistributions of source code must retain the above copyright
44 * notice, this list of conditions and the following disclaimer.
45 * 2. Redistributions in binary form must reproduce the above copyright
46 * notice, this list of conditions and the following disclaimer in the
47 * documentation and/or other materials provided with the distribution.
48 * 3. All advertising materials mentioning features or use of this software
49 * must display the following acknowledgement:
50 * This product includes software developed by the University of
51 * California, Berkeley and its contributors.
52 * 4. Neither the name of the University nor the names of its contributors
53 * may be used to endorse or promote products derived from this software
54 * without specific prior written permission.
56 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
57 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
58 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
59 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
60 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
61 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
62 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
63 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
64 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
65 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
68 * @(#)kern_sysctl.c 8.4 (Berkeley) 4/14/94
72 #include <sys/param.h>
74 #include <sys/kernel.h>
75 #include <sys/sysctl.h>
76 #include <sys/malloc.h>
77 #include <sys/proc_internal.h>
78 #include <sys/systm.h>
80 #include <bsm/audit_kernel.h>
83 struct sysctl_oid_list sysctl__debug_children;
84 struct sysctl_oid_list sysctl__kern_children;
85 struct sysctl_oid_list sysctl__net_children;
86 struct sysctl_oid_list sysctl__sysctl_children;
89 extern struct sysctl_oid
*newsysctl_list
[];
90 extern struct sysctl_oid
*machdep_sysctl_list
[];
94 sysctl_sysctl_debug_dump_node(struct sysctl_oid_list
*l
, int i
);
101 static struct sysctl_lock
{
108 * XXX this does not belong here
111 spl_kernel_funnel(void)
115 cfunnel
= thread_funnel_get();
116 if (cfunnel
!= kernel_flock
) {
118 thread_funnel_set(cfunnel
, FALSE
);
119 thread_funnel_set(kernel_flock
, TRUE
);
125 splx_kernel_funnel(funnel_t
*saved
)
127 if (saved
!= kernel_flock
) {
128 thread_funnel_set(kernel_flock
, FALSE
);
130 thread_funnel_set(saved
, TRUE
);
134 static int sysctl_root SYSCTL_HANDLER_ARGS
;
136 struct sysctl_oid_list sysctl__children
; /* root list */
139 * Initialization of the MIB tree.
141 * Order by number in each list.
144 void sysctl_register_oid(struct sysctl_oid
*oidp
)
146 struct sysctl_oid_list
*parent
= oidp
->oid_parent
;
147 struct sysctl_oid
*p
;
148 struct sysctl_oid
*q
;
152 fnl
= spl_kernel_funnel();
155 * If this oid has a number OID_AUTO, give it a number which
156 * is greater than any current oid. Make sure it is at least
157 * 100 to leave space for pre-assigned oid numbers.
159 /* sysctl_sysctl_debug_dump_node(parent, 3); */
160 if (oidp
->oid_number
== OID_AUTO
) {
161 /* First, find the highest oid in the parent list >99 */
163 SLIST_FOREACH(p
, parent
, oid_link
) {
164 if (p
->oid_number
> n
)
167 oidp
->oid_number
= n
+ 1;
171 * Insert the oid into the parent's list in order.
174 SLIST_FOREACH(p
, parent
, oid_link
) {
175 if (oidp
->oid_number
< p
->oid_number
)
180 SLIST_INSERT_AFTER(q
, oidp
, oid_link
);
182 SLIST_INSERT_HEAD(parent
, oidp
, oid_link
);
184 splx_kernel_funnel(fnl
);
187 void sysctl_unregister_oid(struct sysctl_oid
*oidp
)
191 fnl
= spl_kernel_funnel();
192 SLIST_REMOVE(oidp
->oid_parent
, oidp
, sysctl_oid
, oid_link
);
193 splx_kernel_funnel(fnl
);
197 * Bulk-register all the oids in a linker_set.
199 void sysctl_register_set(struct linker_set
*lsp
)
201 int count
= lsp
->ls_length
;
203 for (i
= 0; i
< count
; i
++)
204 sysctl_register_oid((struct sysctl_oid
*) lsp
->ls_items
[i
]);
207 void sysctl_unregister_set(struct linker_set
*lsp
)
209 int count
= lsp
->ls_length
;
211 for (i
= 0; i
< count
; i
++)
212 sysctl_unregister_oid((struct sysctl_oid
*) lsp
->ls_items
[i
]);
217 * Register OID's from fixed list
220 void sysctl_register_fixed()
224 for (i
=0; newsysctl_list
[i
]; i
++) {
225 sysctl_register_oid(newsysctl_list
[i
]);
227 for (i
=0; machdep_sysctl_list
[i
]; i
++) {
228 sysctl_register_oid(machdep_sysctl_list
[i
]);
233 * Register the kernel's oids on startup.
235 struct linker_set sysctl_set
;
237 void sysctl_register_all(void *arg
)
239 sysctl_register_set(&sysctl_set
);
242 SYSINIT(sysctl
, SI_SUB_KMEM
, SI_ORDER_ANY
, sysctl_register_all
, 0);
247 * These functions implement a presently undocumented interface
248 * used by the sysctl program to walk the tree, and get the type
249 * so it can print the value.
250 * This interface is under work and consideration, and should probably
251 * be killed with a big axe by the first person who can find the time.
252 * (be aware though, that the proper interface isn't as obvious as it
253 * may seem, there are various conflicting requirements.
255 * {0,0} printf the entire MIB-tree.
256 * {0,1,...} return the name of the "..." OID.
257 * {0,2,...} return the next OID.
258 * {0,3} return the OID of the name in "new"
259 * {0,4,...} return the kind & format info for the "..." OID.
263 sysctl_sysctl_debug_dump_node(struct sysctl_oid_list
*l
, int i
)
266 struct sysctl_oid
*oidp
;
268 SLIST_FOREACH(oidp
, l
, oid_link
) {
273 printf("%d %s ", oidp
->oid_number
, oidp
->oid_name
);
276 oidp
->oid_kind
& CTLFLAG_RD
? 'R':' ',
277 oidp
->oid_kind
& CTLFLAG_WR
? 'W':' ');
279 if (oidp
->oid_handler
)
282 switch (oidp
->oid_kind
& CTLTYPE
) {
285 if (!oidp
->oid_handler
) {
286 sysctl_sysctl_debug_dump_node(
287 oidp
->oid_arg1
, i
+2);
290 case CTLTYPE_INT
: printf(" Int\n"); break;
291 case CTLTYPE_STRING
: printf(" String\n"); break;
292 case CTLTYPE_QUAD
: printf(" Quad\n"); break;
293 case CTLTYPE_OPAQUE
: printf(" Opaque/struct\n"); break;
294 default: printf("\n");
301 sysctl_sysctl_debug SYSCTL_HANDLER_ARGS
303 sysctl_sysctl_debug_dump_node(&sysctl__children
, 0);
307 SYSCTL_PROC(_sysctl
, 0, debug
, CTLTYPE_STRING
|CTLFLAG_RD
,
308 0, 0, sysctl_sysctl_debug
, "-", "");
311 sysctl_sysctl_name SYSCTL_HANDLER_ARGS
313 int *name
= (int *) arg1
;
314 u_int namelen
= arg2
;
316 struct sysctl_oid
*oid
;
317 struct sysctl_oid_list
*lsp
= &sysctl__children
, *lsp2
;
322 snprintf(tempbuf
,sizeof(tempbuf
),"%d",*name
);
324 error
= SYSCTL_OUT(req
, ".", 1);
326 error
= SYSCTL_OUT(req
, tempbuf
, strlen(tempbuf
));
334 SLIST_FOREACH(oid
, lsp
, oid_link
) {
335 if (oid
->oid_number
!= *name
)
339 error
= SYSCTL_OUT(req
, ".", 1);
341 error
= SYSCTL_OUT(req
, oid
->oid_name
,
342 strlen(oid
->oid_name
));
349 if ((oid
->oid_kind
& CTLTYPE
) != CTLTYPE_NODE
)
352 if (oid
->oid_handler
)
355 lsp2
= (struct sysctl_oid_list
*)oid
->oid_arg1
;
360 return (SYSCTL_OUT(req
, "", 1));
363 SYSCTL_NODE(_sysctl
, 1, name
, CTLFLAG_RD
, sysctl_sysctl_name
, "");
366 sysctl_sysctl_next_ls (struct sysctl_oid_list
*lsp
, int *name
, u_int namelen
,
367 int *next
, int *len
, int level
, struct sysctl_oid
**oidpp
)
369 struct sysctl_oid
*oidp
;
372 SLIST_FOREACH(oidp
, lsp
, oid_link
) {
373 *next
= oidp
->oid_number
;
377 if ((oidp
->oid_kind
& CTLTYPE
) != CTLTYPE_NODE
)
379 if (oidp
->oid_handler
)
380 /* We really should call the handler here...*/
382 lsp
= (struct sysctl_oid_list
*)oidp
->oid_arg1
;
383 if (!sysctl_sysctl_next_ls (lsp
, 0, 0, next
+1,
384 len
, level
+1, oidpp
))
389 if (oidp
->oid_number
< *name
)
392 if (oidp
->oid_number
> *name
) {
393 if ((oidp
->oid_kind
& CTLTYPE
) != CTLTYPE_NODE
)
395 if (oidp
->oid_handler
)
397 lsp
= (struct sysctl_oid_list
*)oidp
->oid_arg1
;
398 if (!sysctl_sysctl_next_ls (lsp
, name
+1, namelen
-1,
399 next
+1, len
, level
+1, oidpp
))
403 if ((oidp
->oid_kind
& CTLTYPE
) != CTLTYPE_NODE
)
406 if (oidp
->oid_handler
)
409 lsp
= (struct sysctl_oid_list
*)oidp
->oid_arg1
;
410 if (!sysctl_sysctl_next_ls (lsp
, name
+1, namelen
-1, next
+1,
411 len
, level
+1, oidpp
))
421 sysctl_sysctl_next SYSCTL_HANDLER_ARGS
423 int *name
= (int *) arg1
;
424 u_int namelen
= arg2
;
426 struct sysctl_oid
*oid
;
427 struct sysctl_oid_list
*lsp
= &sysctl__children
;
428 int newoid
[CTL_MAXNAME
];
430 i
= sysctl_sysctl_next_ls (lsp
, name
, namelen
, newoid
, &j
, 1, &oid
);
433 error
= SYSCTL_OUT(req
, newoid
, j
* sizeof (int));
437 SYSCTL_NODE(_sysctl
, 2, next
, CTLFLAG_RD
, sysctl_sysctl_next
, "");
440 name2oid (char *name
, int *oid
, int *len
, struct sysctl_oid
**oidpp
)
443 struct sysctl_oid
*oidp
;
444 struct sysctl_oid_list
*lsp
= &sysctl__children
;
450 p
= name
+ strlen(name
) - 1 ;
456 for (p
= name
; *p
&& *p
!= '.'; p
++)
462 oidp
= SLIST_FIRST(lsp
);
464 while (oidp
&& *len
< CTL_MAXNAME
) {
465 if (strcmp(name
, oidp
->oid_name
)) {
466 oidp
= SLIST_NEXT(oidp
, oid_link
);
469 *oid
++ = oidp
->oid_number
;
478 if ((oidp
->oid_kind
& CTLTYPE
) != CTLTYPE_NODE
)
481 if (oidp
->oid_handler
)
484 lsp
= (struct sysctl_oid_list
*)oidp
->oid_arg1
;
485 oidp
= SLIST_FIRST(lsp
);
487 for (p
= name
; *p
&& *p
!= '.'; p
++)
497 sysctl_sysctl_name2oid SYSCTL_HANDLER_ARGS
500 int error
, oid
[CTL_MAXNAME
], len
;
501 struct sysctl_oid
*op
= 0;
505 if (req
->newlen
>= MAXPATHLEN
) /* XXX arbitrary, undocumented */
506 return (ENAMETOOLONG
);
508 MALLOC(p
, char *,req
->newlen
+1, M_TEMP
, M_WAITOK
);
512 error
= SYSCTL_IN(req
, p
, req
->newlen
);
518 p
[req
->newlen
] = '\0';
520 error
= name2oid(p
, oid
, &len
, &op
);
527 error
= SYSCTL_OUT(req
, oid
, len
* sizeof *oid
);
531 SYSCTL_PROC(_sysctl
, 3, name2oid
, CTLFLAG_RW
|CTLFLAG_ANYBODY
|CTLFLAG_KERN
, 0, 0,
532 sysctl_sysctl_name2oid
, "I", "");
535 sysctl_sysctl_oidfmt SYSCTL_HANDLER_ARGS
537 int *name
= (int *) arg1
, error
;
538 u_int namelen
= arg2
;
540 struct sysctl_oid
*oid
;
541 struct sysctl_oid_list
*lsp
= &sysctl__children
;
543 oid
= SLIST_FIRST(lsp
);
546 while (oid
&& indx
< CTL_MAXNAME
) {
547 if (oid
->oid_number
== name
[indx
]) {
549 if ((oid
->oid_kind
& CTLTYPE
) == CTLTYPE_NODE
) {
550 if (oid
->oid_handler
)
554 lsp
= (struct sysctl_oid_list
*)oid
->oid_arg1
;
555 oid
= SLIST_FIRST(lsp
);
562 oid
= SLIST_NEXT(oid
, oid_link
);
569 error
= SYSCTL_OUT(req
,
570 &oid
->oid_kind
, sizeof(oid
->oid_kind
));
572 error
= SYSCTL_OUT(req
, oid
->oid_fmt
,
573 strlen(oid
->oid_fmt
)+1);
578 SYSCTL_NODE(_sysctl
, 4, oidfmt
, CTLFLAG_RD
, sysctl_sysctl_oidfmt
, "");
581 * Default "handler" functions.
585 * Handle an int, signed or unsigned.
587 * a variable: point arg1 at it.
588 * a constant: pass it in arg2.
592 sysctl_handle_int SYSCTL_HANDLER_ARGS
597 error
= SYSCTL_OUT(req
, arg1
, sizeof(int));
599 error
= SYSCTL_OUT(req
, &arg2
, sizeof(int));
601 if (error
|| !req
->newptr
)
607 error
= SYSCTL_IN(req
, arg1
, sizeof(int));
610 AUDIT_ARG(value
, *(int *)arg1
);
615 * Handle a long, signed or unsigned. arg1 points to it.
619 sysctl_handle_long SYSCTL_HANDLER_ARGS
625 error
= SYSCTL_OUT(req
, arg1
, sizeof(long));
627 if (error
|| !req
->newptr
)
630 error
= SYSCTL_IN(req
, arg1
, sizeof(long));
635 * Handle a quad, signed or unsigned. arg1 points to it.
639 sysctl_handle_quad SYSCTL_HANDLER_ARGS
645 error
= SYSCTL_OUT(req
, arg1
, sizeof(long long));
647 if (error
|| !req
->newptr
)
650 error
= SYSCTL_IN(req
, arg1
, sizeof(long long));
655 * Expose an int value as a quad.
657 * This interface allows us to support interfaces defined
658 * as using quad values while the implementation is still
662 sysctl_handle_int2quad SYSCTL_HANDLER_ARGS
670 val
= (long long)*(int *)arg1
;
671 error
= SYSCTL_OUT(req
, &val
, sizeof(long long));
673 if (error
|| !req
->newptr
)
676 error
= SYSCTL_IN(req
, &val
, sizeof(long long));
679 * Value must be representable; check by
680 * casting and then casting back.
683 if ((long long)newval
!= val
) {
686 *(int *)arg1
= newval
;
693 * Handle our generic '\0' terminated 'C' string.
695 * a variable string: point arg1 at it, arg2 is max length.
696 * a constant string: point arg1 at it, arg2 is zero.
700 sysctl_handle_string SYSCTL_HANDLER_ARGS
704 error
= SYSCTL_OUT(req
, arg1
, strlen((char *)arg1
)+1);
706 if (error
|| !req
->newptr
)
709 if ((req
->newlen
- req
->newidx
) >= arg2
) {
712 arg2
= (req
->newlen
- req
->newidx
);
713 error
= SYSCTL_IN(req
, arg1
, arg2
);
714 ((char *)arg1
)[arg2
] = '\0';
721 * Handle any kind of opaque data.
722 * arg1 points to it, arg2 is the size.
726 sysctl_handle_opaque SYSCTL_HANDLER_ARGS
730 error
= SYSCTL_OUT(req
, arg1
, arg2
);
732 if (error
|| !req
->newptr
)
735 error
= SYSCTL_IN(req
, arg1
, arg2
);
741 * Transfer functions to/from kernel space.
744 sysctl_old_kernel(struct sysctl_req
*req
, const void *p
, size_t l
)
750 if (i
> req
->oldlen
- req
->oldidx
)
751 i
= req
->oldlen
- req
->oldidx
;
753 bcopy((void*)p
, CAST_DOWN(char *, (req
->oldptr
+ req
->oldidx
)), i
);
756 if (req
->oldptr
&& i
!= l
)
762 sysctl_new_kernel(struct sysctl_req
*req
, void *p
, size_t l
)
766 if (req
->newlen
- req
->newidx
< l
)
768 bcopy(CAST_DOWN(char *, (req
->newptr
+ req
->newidx
)), p
, l
);
774 kernel_sysctl(struct proc
*p
, int *name
, u_int namelen
, void *old
, size_t *oldlenp
, void *new, size_t newlen
)
777 struct sysctl_req req
;
783 bzero(&req
, sizeof req
);
786 req
.oldlen
= *oldlenp
;
788 req
.oldptr
= CAST_USER_ADDR_T(old
);
791 req
.newptr
= CAST_USER_ADDR_T(new);
793 req
.oldfunc
= sysctl_old_kernel
;
794 req
.newfunc
= sysctl_new_kernel
;
798 * Locking. Tree traversal always begins with the kernel funnel held.
800 fnl
= spl_kernel_funnel();
802 /* XXX this should probably be done in a general way */
803 while (memlock
.sl_lock
) {
805 (void) tsleep((caddr_t
)&memlock
, PRIBIO
+1, "sysctl", 0);
810 /* make the request */
811 error
= sysctl_root(0, name
, namelen
, &req
);
813 /* unlock memory if required */
815 vsunlock(req
.oldptr
, (user_size_t
)req
.oldlen
, B_WRITE
);
819 if (memlock
.sl_want
) {
821 wakeup((caddr_t
)&memlock
);
827 splx_kernel_funnel(fnl
);
829 if (error
&& error
!= ENOMEM
)
833 *oldlenp
= req
.oldidx
;
839 * Transfer function to/from user space.
842 sysctl_old_user(struct sysctl_req
*req
, const void *p
, size_t l
)
848 if (req
->oldlen
- req
->oldidx
< l
)
851 if (i
> req
->oldlen
- req
->oldidx
)
852 i
= req
->oldlen
- req
->oldidx
;
854 error
= copyout((void*)p
, (req
->oldptr
+ req
->oldidx
), i
);
859 if (req
->oldptr
&& i
< l
)
865 sysctl_new_user(struct sysctl_req
*req
, void *p
, size_t l
)
871 if (req
->newlen
- req
->newidx
< l
)
873 error
= copyin((req
->newptr
+ req
->newidx
), p
, l
);
879 * Traverse our tree, and find the right node, execute whatever it points
880 * at, and return the resulting error code.
884 sysctl_root SYSCTL_HANDLER_ARGS
886 int *name
= (int *) arg1
;
887 u_int namelen
= arg2
;
889 struct sysctl_oid
*oid
;
890 struct sysctl_oid_list
*lsp
= &sysctl__children
;
893 oid
= SLIST_FIRST(lsp
);
896 while (oid
&& indx
< CTL_MAXNAME
) {
897 if (oid
->oid_number
== name
[indx
]) {
899 if (oid
->oid_kind
& CTLFLAG_NOLOCK
)
901 if ((oid
->oid_kind
& CTLTYPE
) == CTLTYPE_NODE
) {
902 if (oid
->oid_handler
)
906 lsp
= (struct sysctl_oid_list
*)oid
->oid_arg1
;
907 oid
= SLIST_FIRST(lsp
);
914 oid
= SLIST_NEXT(oid
, oid_link
);
919 /* If writing isn't allowed */
920 if (req
->newptr
&& (!(oid
->oid_kind
& CTLFLAG_WR
) ||
921 ((oid
->oid_kind
& CTLFLAG_SECURE
) && securelevel
> 0))) {
926 * If we're inside the kernel, the OID must be marked as kernel-valid.
927 * XXX This mechanism for testing is bad.
929 if ((req
->oldfunc
== sysctl_old_kernel
) && !(oid
->oid_kind
& CTLFLAG_KERN
))
932 /* Most likely only root can write */
933 if (!(oid
->oid_kind
& CTLFLAG_ANYBODY
) &&
934 req
->newptr
&& req
->p
&&
935 (error
= suser(req
->p
->p_ucred
, &req
->p
->p_acflag
)))
938 if (!oid
->oid_handler
) {
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
,
956 #ifndef _SYS_SYSPROTO_H_
968 /* __sysctl(struct proc *p, struct sysctl_args *uap) */
969 new_sysctl(struct proc
*p
, struct sysctl_args
*uap
)
971 int error
, i
, name
[CTL_MAXNAME
];
974 if (uap
->namelen
> CTL_MAXNAME
|| uap
->namelen
< 2)
977 error
= copyin(CAST_USER_ADDR_T(uap
->name
), &name
, uap
->namelen
* sizeof(int));
981 error
= userland_sysctl(p
, name
, uap
->namelen
,
982 CAST_USER_ADDR_T(uap
->old
), uap
->oldlenp
, 0,
983 CAST_USER_ADDR_T(uap
->new), uap
->newlen
, &j
);
984 if (error
&& error
!= ENOMEM
)
987 i
= copyout(&j
, CAST_USER_ADDR_T(uap
->oldlenp
), sizeof(j
));
995 * This is used from various compatibility syscalls too. That's why name
996 * must be in kernel space.
999 userland_sysctl(struct proc
*p
, int *name
, u_int namelen
, user_addr_t oldp
,
1000 size_t *oldlenp
, int inkernel
, user_addr_t newp
, size_t newlen
,
1004 struct sysctl_req req
, req2
;
1006 bzero(&req
, sizeof req
);
1012 req
.oldlen
= *oldlenp
;
1014 error
= copyin(CAST_USER_ADDR_T(oldlenp
), &req
.oldlen
, sizeof(*oldlenp
));
1025 req
.newlen
= newlen
;
1029 req
.oldfunc
= sysctl_old_user
;
1030 req
.newfunc
= sysctl_new_user
;
1035 error
= sysctl_root(0, name
, namelen
, &req2
);
1036 } while (error
== EAGAIN
);
1040 if (error
&& error
!= ENOMEM
)
1044 if (req
.oldptr
&& req
.oldidx
> req
.oldlen
)
1045 *retval
= req
.oldlen
;
1047 *retval
= req
.oldidx
;
1052 /* Non-standard BSDI extension - only present on their 4.3 net-2 releases */
1053 #define KINFO_BSDI_SYSINFO (101<<8)
1056 * Kernel versions of the userland sysctl helper functions.
1058 * These allow sysctl to be used in the same fashion in both
1059 * userland and the kernel.
1061 * Note that some sysctl handlers use copyin/copyout, which
1062 * may not work correctly.
1066 sysctl(int *name
, u_int namelen
, void *oldp
, size_t *oldlenp
, void *newp
, size_t newlen
)
1069 return(kernel_sysctl(current_proc(), name
, namelen
, oldp
, oldlenp
, newp
, newlen
));
1073 sysctlnametomib(const char *name
, int *mibp
, size_t *sizep
)
1078 /* magic service node */
1082 /* look up OID for name */
1083 *sizep
*= sizeof(int);
1084 error
= sysctl(oid
, 2, mibp
, sizep
, (void *)name
, strlen(name
));
1085 *sizep
/= sizeof(int);
1090 sysctlbyname(const char *name
, void *oldp
, size_t *oldlenp
, void *newp
, size_t newlen
)
1092 int oid
[CTL_MAXNAME
+ 2];
1096 /* look up the OID */
1097 oidlen
= CTL_MAXNAME
;
1098 error
= sysctlnametomib(name
, oid
, &oidlen
);
1100 /* now use the OID */
1102 error
= sysctl(oid
, oidlen
, oldp
, oldlenp
, newp
, newlen
);