2 * Copyright (c) 2000 Apple Computer, 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 <bsm/audit_kernel.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 extern struct sysctl_oid
*newsysctl_list
[];
88 extern struct sysctl_oid
*machdep_sysctl_list
[];
92 sysctl_sysctl_debug_dump_node(struct sysctl_oid_list
*l
, int i
);
99 static struct sysctl_lock
{
106 * XXX this does not belong here
109 spl_kernel_funnel(void)
113 cfunnel
= thread_funnel_get();
114 if (cfunnel
!= kernel_flock
) {
116 thread_funnel_set(cfunnel
, FALSE
);
117 thread_funnel_set(kernel_flock
, TRUE
);
123 splx_kernel_funnel(funnel_t
*saved
)
125 if (saved
!= kernel_flock
) {
126 thread_funnel_set(kernel_flock
, FALSE
);
128 thread_funnel_set(saved
, TRUE
);
132 static int sysctl_root SYSCTL_HANDLER_ARGS
;
134 struct sysctl_oid_list sysctl__children
; /* root list */
137 * Initialization of the MIB tree.
139 * Order by number in each list.
142 void sysctl_register_oid(struct sysctl_oid
*oidp
)
144 struct sysctl_oid_list
*parent
= oidp
->oid_parent
;
145 struct sysctl_oid
*p
;
146 struct sysctl_oid
*q
;
150 fnl
= spl_kernel_funnel();
153 * If this oid has a number OID_AUTO, give it a number which
154 * is greater than any current oid. Make sure it is at least
155 * 100 to leave space for pre-assigned oid numbers.
157 /* sysctl_sysctl_debug_dump_node(parent, 3); */
158 if (oidp
->oid_number
== OID_AUTO
) {
159 /* First, find the highest oid in the parent list >99 */
161 SLIST_FOREACH(p
, parent
, oid_link
) {
162 if (p
->oid_number
> n
)
165 oidp
->oid_number
= n
+ 1;
169 * Insert the oid into the parent's list in order.
172 SLIST_FOREACH(p
, parent
, oid_link
) {
173 if (oidp
->oid_number
< p
->oid_number
)
178 SLIST_INSERT_AFTER(q
, oidp
, oid_link
);
180 SLIST_INSERT_HEAD(parent
, oidp
, oid_link
);
182 splx_kernel_funnel(fnl
);
185 void sysctl_unregister_oid(struct sysctl_oid
*oidp
)
189 fnl
= spl_kernel_funnel();
190 SLIST_REMOVE(oidp
->oid_parent
, oidp
, sysctl_oid
, oid_link
);
191 splx_kernel_funnel(fnl
);
195 * Bulk-register all the oids in a linker_set.
197 void sysctl_register_set(struct linker_set
*lsp
)
199 int count
= lsp
->ls_length
;
201 for (i
= 0; i
< count
; i
++)
202 sysctl_register_oid((struct sysctl_oid
*) lsp
->ls_items
[i
]);
205 void sysctl_unregister_set(struct linker_set
*lsp
)
207 int count
= lsp
->ls_length
;
209 for (i
= 0; i
< count
; i
++)
210 sysctl_unregister_oid((struct sysctl_oid
*) lsp
->ls_items
[i
]);
215 * Register OID's from fixed list
218 void sysctl_register_fixed()
222 for (i
=0; newsysctl_list
[i
]; i
++) {
223 sysctl_register_oid(newsysctl_list
[i
]);
225 for (i
=0; machdep_sysctl_list
[i
]; i
++) {
226 sysctl_register_oid(machdep_sysctl_list
[i
]);
231 * Register the kernel's oids on startup.
233 struct linker_set sysctl_set
;
235 void sysctl_register_all(void *arg
)
237 sysctl_register_set(&sysctl_set
);
240 SYSINIT(sysctl
, SI_SUB_KMEM
, SI_ORDER_ANY
, sysctl_register_all
, 0);
245 * These functions implement a presently undocumented interface
246 * used by the sysctl program to walk the tree, and get the type
247 * so it can print the value.
248 * This interface is under work and consideration, and should probably
249 * be killed with a big axe by the first person who can find the time.
250 * (be aware though, that the proper interface isn't as obvious as it
251 * may seem, there are various conflicting requirements.
253 * {0,0} printf the entire MIB-tree.
254 * {0,1,...} return the name of the "..." OID.
255 * {0,2,...} return the next OID.
256 * {0,3} return the OID of the name in "new"
257 * {0,4,...} return the kind & format info for the "..." OID.
261 sysctl_sysctl_debug_dump_node(struct sysctl_oid_list
*l
, int i
)
264 struct sysctl_oid
*oidp
;
266 SLIST_FOREACH(oidp
, l
, oid_link
) {
271 printf("%d %s ", oidp
->oid_number
, oidp
->oid_name
);
274 oidp
->oid_kind
& CTLFLAG_RD
? 'R':' ',
275 oidp
->oid_kind
& CTLFLAG_WR
? 'W':' ');
277 if (oidp
->oid_handler
)
280 switch (oidp
->oid_kind
& CTLTYPE
) {
283 if (!oidp
->oid_handler
) {
284 sysctl_sysctl_debug_dump_node(
285 oidp
->oid_arg1
, i
+2);
288 case CTLTYPE_INT
: printf(" Int\n"); break;
289 case CTLTYPE_STRING
: printf(" String\n"); break;
290 case CTLTYPE_QUAD
: printf(" Quad\n"); break;
291 case CTLTYPE_OPAQUE
: printf(" Opaque/struct\n"); break;
292 default: printf("\n");
299 sysctl_sysctl_debug SYSCTL_HANDLER_ARGS
301 sysctl_sysctl_debug_dump_node(&sysctl__children
, 0);
305 SYSCTL_PROC(_sysctl
, 0, debug
, CTLTYPE_STRING
|CTLFLAG_RD
,
306 0, 0, sysctl_sysctl_debug
, "-", "");
309 sysctl_sysctl_name SYSCTL_HANDLER_ARGS
311 int *name
= (int *) arg1
;
312 u_int namelen
= arg2
;
314 struct sysctl_oid
*oid
;
315 struct sysctl_oid_list
*lsp
= &sysctl__children
, *lsp2
;
320 snprintf(tempbuf
,sizeof(tempbuf
),"%d",*name
);
322 error
= SYSCTL_OUT(req
, ".", 1);
324 error
= SYSCTL_OUT(req
, tempbuf
, strlen(tempbuf
));
332 SLIST_FOREACH(oid
, lsp
, oid_link
) {
333 if (oid
->oid_number
!= *name
)
337 error
= SYSCTL_OUT(req
, ".", 1);
339 error
= SYSCTL_OUT(req
, oid
->oid_name
,
340 strlen(oid
->oid_name
));
347 if ((oid
->oid_kind
& CTLTYPE
) != CTLTYPE_NODE
)
350 if (oid
->oid_handler
)
353 lsp2
= (struct sysctl_oid_list
*)oid
->oid_arg1
;
358 return (SYSCTL_OUT(req
, "", 1));
361 SYSCTL_NODE(_sysctl
, 1, name
, CTLFLAG_RD
, sysctl_sysctl_name
, "");
364 sysctl_sysctl_next_ls (struct sysctl_oid_list
*lsp
, int *name
, u_int namelen
,
365 int *next
, int *len
, int level
, struct sysctl_oid
**oidpp
)
367 struct sysctl_oid
*oidp
;
370 SLIST_FOREACH(oidp
, lsp
, oid_link
) {
371 *next
= oidp
->oid_number
;
375 if ((oidp
->oid_kind
& CTLTYPE
) != CTLTYPE_NODE
)
377 if (oidp
->oid_handler
)
378 /* We really should call the handler here...*/
380 lsp
= (struct sysctl_oid_list
*)oidp
->oid_arg1
;
381 if (!sysctl_sysctl_next_ls (lsp
, 0, 0, next
+1,
382 len
, level
+1, oidpp
))
387 if (oidp
->oid_number
< *name
)
390 if (oidp
->oid_number
> *name
) {
391 if ((oidp
->oid_kind
& CTLTYPE
) != CTLTYPE_NODE
)
393 if (oidp
->oid_handler
)
395 lsp
= (struct sysctl_oid_list
*)oidp
->oid_arg1
;
396 if (!sysctl_sysctl_next_ls (lsp
, name
+1, namelen
-1,
397 next
+1, len
, level
+1, oidpp
))
401 if ((oidp
->oid_kind
& CTLTYPE
) != CTLTYPE_NODE
)
404 if (oidp
->oid_handler
)
407 lsp
= (struct sysctl_oid_list
*)oidp
->oid_arg1
;
408 if (!sysctl_sysctl_next_ls (lsp
, name
+1, namelen
-1, next
+1,
409 len
, level
+1, oidpp
))
419 sysctl_sysctl_next SYSCTL_HANDLER_ARGS
421 int *name
= (int *) arg1
;
422 u_int namelen
= arg2
;
424 struct sysctl_oid
*oid
;
425 struct sysctl_oid_list
*lsp
= &sysctl__children
;
426 int newoid
[CTL_MAXNAME
];
428 i
= sysctl_sysctl_next_ls (lsp
, name
, namelen
, newoid
, &j
, 1, &oid
);
431 error
= SYSCTL_OUT(req
, newoid
, j
* sizeof (int));
435 SYSCTL_NODE(_sysctl
, 2, next
, CTLFLAG_RD
, sysctl_sysctl_next
, "");
438 name2oid (char *name
, int *oid
, int *len
, struct sysctl_oid
**oidpp
)
441 struct sysctl_oid
*oidp
;
442 struct sysctl_oid_list
*lsp
= &sysctl__children
;
448 p
= name
+ strlen(name
) - 1 ;
454 for (p
= name
; *p
&& *p
!= '.'; p
++)
460 oidp
= SLIST_FIRST(lsp
);
462 while (oidp
&& *len
< CTL_MAXNAME
) {
463 if (strcmp(name
, oidp
->oid_name
)) {
464 oidp
= SLIST_NEXT(oidp
, oid_link
);
467 *oid
++ = oidp
->oid_number
;
476 if ((oidp
->oid_kind
& CTLTYPE
) != CTLTYPE_NODE
)
479 if (oidp
->oid_handler
)
482 lsp
= (struct sysctl_oid_list
*)oidp
->oid_arg1
;
483 oidp
= SLIST_FIRST(lsp
);
485 for (p
= name
; *p
&& *p
!= '.'; p
++)
495 sysctl_sysctl_name2oid SYSCTL_HANDLER_ARGS
498 int error
, oid
[CTL_MAXNAME
], len
;
499 struct sysctl_oid
*op
= 0;
503 if (req
->newlen
>= MAXPATHLEN
) /* XXX arbitrary, undocumented */
504 return (ENAMETOOLONG
);
506 MALLOC(p
, char *,req
->newlen
+1, M_TEMP
, M_WAITOK
);
510 error
= SYSCTL_IN(req
, p
, req
->newlen
);
516 p
[req
->newlen
] = '\0';
518 error
= name2oid(p
, oid
, &len
, &op
);
525 error
= SYSCTL_OUT(req
, oid
, len
* sizeof *oid
);
529 SYSCTL_PROC(_sysctl
, 3, name2oid
, CTLFLAG_RW
|CTLFLAG_ANYBODY
|CTLFLAG_KERN
, 0, 0,
530 sysctl_sysctl_name2oid
, "I", "");
533 sysctl_sysctl_oidfmt SYSCTL_HANDLER_ARGS
535 int *name
= (int *) arg1
, error
;
536 u_int namelen
= arg2
;
538 struct sysctl_oid
*oid
;
539 struct sysctl_oid_list
*lsp
= &sysctl__children
;
541 oid
= SLIST_FIRST(lsp
);
544 while (oid
&& indx
< CTL_MAXNAME
) {
545 if (oid
->oid_number
== name
[indx
]) {
547 if ((oid
->oid_kind
& CTLTYPE
) == CTLTYPE_NODE
) {
548 if (oid
->oid_handler
)
552 lsp
= (struct sysctl_oid_list
*)oid
->oid_arg1
;
553 oid
= SLIST_FIRST(lsp
);
560 oid
= SLIST_NEXT(oid
, oid_link
);
567 error
= SYSCTL_OUT(req
,
568 &oid
->oid_kind
, sizeof(oid
->oid_kind
));
570 error
= SYSCTL_OUT(req
, oid
->oid_fmt
,
571 strlen(oid
->oid_fmt
)+1);
576 SYSCTL_NODE(_sysctl
, 4, oidfmt
, CTLFLAG_RD
, sysctl_sysctl_oidfmt
, "");
579 * Default "handler" functions.
583 * Handle an int, signed or unsigned.
585 * a variable: point arg1 at it.
586 * a constant: pass it in arg2.
590 sysctl_handle_int SYSCTL_HANDLER_ARGS
595 error
= SYSCTL_OUT(req
, arg1
, sizeof(int));
597 error
= SYSCTL_OUT(req
, &arg2
, sizeof(int));
599 if (error
|| !req
->newptr
)
605 error
= SYSCTL_IN(req
, arg1
, sizeof(int));
608 AUDIT_ARG(value
, *(int *)arg1
);
613 * Handle a long, signed or unsigned. arg1 points to it.
617 sysctl_handle_long SYSCTL_HANDLER_ARGS
623 error
= SYSCTL_OUT(req
, arg1
, sizeof(long));
625 if (error
|| !req
->newptr
)
628 error
= SYSCTL_IN(req
, arg1
, sizeof(long));
633 * Handle a quad, signed or unsigned. arg1 points to it.
637 sysctl_handle_quad SYSCTL_HANDLER_ARGS
643 error
= SYSCTL_OUT(req
, arg1
, sizeof(long long));
645 if (error
|| !req
->newptr
)
648 error
= SYSCTL_IN(req
, arg1
, sizeof(long long));
653 * Expose an int value as a quad.
655 * This interface allows us to support interfaces defined
656 * as using quad values while the implementation is still
660 sysctl_handle_int2quad SYSCTL_HANDLER_ARGS
668 val
= (long long)*(int *)arg1
;
669 error
= SYSCTL_OUT(req
, &val
, sizeof(long long));
671 if (error
|| !req
->newptr
)
674 error
= SYSCTL_IN(req
, &val
, sizeof(long long));
677 * Value must be representable; check by
678 * casting and then casting back.
681 if ((long long)newval
!= val
) {
684 *(int *)arg1
= newval
;
691 * Handle our generic '\0' terminated 'C' string.
693 * a variable string: point arg1 at it, arg2 is max length.
694 * a constant string: point arg1 at it, arg2 is zero.
698 sysctl_handle_string SYSCTL_HANDLER_ARGS
702 error
= SYSCTL_OUT(req
, arg1
, strlen((char *)arg1
)+1);
704 if (error
|| !req
->newptr
)
707 if ((req
->newlen
- req
->newidx
) >= arg2
) {
710 arg2
= (req
->newlen
- req
->newidx
);
711 error
= SYSCTL_IN(req
, arg1
, arg2
);
712 ((char *)arg1
)[arg2
] = '\0';
719 * Handle any kind of opaque data.
720 * arg1 points to it, arg2 is the size.
724 sysctl_handle_opaque SYSCTL_HANDLER_ARGS
728 error
= SYSCTL_OUT(req
, arg1
, arg2
);
730 if (error
|| !req
->newptr
)
733 error
= SYSCTL_IN(req
, arg1
, arg2
);
739 * Transfer functions to/from kernel space.
742 sysctl_old_kernel(struct sysctl_req
*req
, const void *p
, size_t l
)
748 if (i
> req
->oldlen
- req
->oldidx
)
749 i
= req
->oldlen
- req
->oldidx
;
751 bcopy((void*)p
, CAST_DOWN(char *, (req
->oldptr
+ req
->oldidx
)), i
);
754 if (req
->oldptr
&& i
!= l
)
760 sysctl_new_kernel(struct sysctl_req
*req
, void *p
, size_t l
)
764 if (req
->newlen
- req
->newidx
< l
)
766 bcopy(CAST_DOWN(char *, (req
->newptr
+ req
->newidx
)), p
, l
);
772 kernel_sysctl(struct proc
*p
, int *name
, u_int namelen
, void *old
, size_t *oldlenp
, void *new, size_t newlen
)
775 struct sysctl_req req
;
781 bzero(&req
, sizeof req
);
784 req
.oldlen
= *oldlenp
;
786 req
.oldptr
= CAST_USER_ADDR_T(old
);
789 req
.newptr
= CAST_USER_ADDR_T(new);
791 req
.oldfunc
= sysctl_old_kernel
;
792 req
.newfunc
= sysctl_new_kernel
;
796 * Locking. Tree traversal always begins with the kernel funnel held.
798 fnl
= spl_kernel_funnel();
800 /* XXX this should probably be done in a general way */
801 while (memlock
.sl_lock
) {
803 (void) tsleep((caddr_t
)&memlock
, PRIBIO
+1, "sysctl", 0);
808 /* make the request */
809 error
= sysctl_root(0, name
, namelen
, &req
);
811 /* unlock memory if required */
813 vsunlock(req
.oldptr
, (user_size_t
)req
.oldlen
, B_WRITE
);
817 if (memlock
.sl_want
) {
819 wakeup((caddr_t
)&memlock
);
825 splx_kernel_funnel(fnl
);
827 if (error
&& error
!= ENOMEM
)
831 *oldlenp
= req
.oldidx
;
837 * Transfer function to/from user space.
840 sysctl_old_user(struct sysctl_req
*req
, const void *p
, size_t l
)
846 if (req
->oldlen
- req
->oldidx
< l
)
849 if (i
> req
->oldlen
- req
->oldidx
)
850 i
= req
->oldlen
- req
->oldidx
;
852 error
= copyout((void*)p
, (req
->oldptr
+ req
->oldidx
), i
);
857 if (req
->oldptr
&& i
< l
)
863 sysctl_new_user(struct sysctl_req
*req
, void *p
, size_t l
)
869 if (req
->newlen
- req
->newidx
< l
)
871 error
= copyin((req
->newptr
+ req
->newidx
), p
, l
);
877 * Traverse our tree, and find the right node, execute whatever it points
878 * at, and return the resulting error code.
882 sysctl_root SYSCTL_HANDLER_ARGS
884 int *name
= (int *) arg1
;
885 u_int namelen
= arg2
;
887 struct sysctl_oid
*oid
;
888 struct sysctl_oid_list
*lsp
= &sysctl__children
;
891 oid
= SLIST_FIRST(lsp
);
894 while (oid
&& indx
< CTL_MAXNAME
) {
895 if (oid
->oid_number
== name
[indx
]) {
897 if (oid
->oid_kind
& CTLFLAG_NOLOCK
)
899 if ((oid
->oid_kind
& CTLTYPE
) == CTLTYPE_NODE
) {
900 if (oid
->oid_handler
)
904 lsp
= (struct sysctl_oid_list
*)oid
->oid_arg1
;
905 oid
= SLIST_FIRST(lsp
);
912 oid
= SLIST_NEXT(oid
, oid_link
);
917 /* If writing isn't allowed */
918 if (req
->newptr
&& (!(oid
->oid_kind
& CTLFLAG_WR
) ||
919 ((oid
->oid_kind
& CTLFLAG_SECURE
) && securelevel
> 0))) {
924 * If we're inside the kernel, the OID must be marked as kernel-valid.
925 * XXX This mechanism for testing is bad.
927 if ((req
->oldfunc
== sysctl_old_kernel
) && !(oid
->oid_kind
& CTLFLAG_KERN
))
930 /* Most likely only root can write */
931 if (!(oid
->oid_kind
& CTLFLAG_ANYBODY
) &&
932 req
->newptr
&& req
->p
&&
933 (error
= suser(req
->p
->p_ucred
, &req
->p
->p_acflag
)))
936 if (!oid
->oid_handler
) {
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
,
954 #ifndef _SYS_SYSPROTO_H_
966 /* __sysctl(struct proc *p, struct sysctl_args *uap) */
967 new_sysctl(struct proc
*p
, struct sysctl_args
*uap
)
969 int error
, i
, name
[CTL_MAXNAME
];
972 if (uap
->namelen
> CTL_MAXNAME
|| uap
->namelen
< 2)
975 error
= copyin(CAST_USER_ADDR_T(uap
->name
), &name
, uap
->namelen
* sizeof(int));
979 error
= userland_sysctl(p
, name
, uap
->namelen
,
980 CAST_USER_ADDR_T(uap
->old
), uap
->oldlenp
, 0,
981 CAST_USER_ADDR_T(uap
->new), uap
->newlen
, &j
);
982 if (error
&& error
!= ENOMEM
)
985 i
= copyout(&j
, CAST_USER_ADDR_T(uap
->oldlenp
), sizeof(j
));
993 * This is used from various compatibility syscalls too. That's why name
994 * must be in kernel space.
997 userland_sysctl(struct proc
*p
, int *name
, u_int namelen
, user_addr_t oldp
,
998 size_t *oldlenp
, int inkernel
, user_addr_t newp
, size_t newlen
,
1002 struct sysctl_req req
, req2
;
1004 bzero(&req
, sizeof req
);
1010 req
.oldlen
= *oldlenp
;
1012 error
= copyin(CAST_USER_ADDR_T(oldlenp
), &req
.oldlen
, sizeof(*oldlenp
));
1023 req
.newlen
= newlen
;
1027 req
.oldfunc
= sysctl_old_user
;
1028 req
.newfunc
= sysctl_new_user
;
1033 error
= sysctl_root(0, name
, namelen
, &req2
);
1034 } while (error
== EAGAIN
);
1038 if (error
&& error
!= ENOMEM
)
1042 if (req
.oldptr
&& req
.oldidx
> req
.oldlen
)
1043 *retval
= req
.oldlen
;
1045 *retval
= req
.oldidx
;
1050 /* Non-standard BSDI extension - only present on their 4.3 net-2 releases */
1051 #define KINFO_BSDI_SYSINFO (101<<8)
1054 * Kernel versions of the userland sysctl helper functions.
1056 * These allow sysctl to be used in the same fashion in both
1057 * userland and the kernel.
1059 * Note that some sysctl handlers use copyin/copyout, which
1060 * may not work correctly.
1064 sysctl(int *name
, u_int namelen
, void *oldp
, size_t *oldlenp
, void *newp
, size_t newlen
)
1067 return(kernel_sysctl(current_proc(), name
, namelen
, oldp
, oldlenp
, newp
, newlen
));
1071 sysctlnametomib(const char *name
, int *mibp
, size_t *sizep
)
1076 /* magic service node */
1080 /* look up OID for name */
1081 *sizep
*= sizeof(int);
1082 error
= sysctl(oid
, 2, mibp
, sizep
, (void *)name
, strlen(name
));
1083 *sizep
/= sizeof(int);
1088 sysctlbyname(const char *name
, void *oldp
, size_t *oldlenp
, void *newp
, size_t newlen
)
1090 int oid
[CTL_MAXNAME
+ 2];
1094 /* look up the OID */
1095 oidlen
= CTL_MAXNAME
;
1096 error
= sysctlnametomib(name
, oid
, &oidlen
);
1098 /* now use the OID */
1100 error
= sysctl(oid
, oidlen
, oldp
, oldlenp
, newp
, newlen
);