2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * The contents of this file constitute Original Code as defined in and
7 * are subject to the Apple Public Source License Version 1.1 (the
8 * "License"). You may not use this file except in compliance with the
9 * License. Please obtain a copy of the License at
10 * http://www.apple.com/publicsource and read it before using this file.
12 * This Original Code and all software distributed under the License are
13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17 * License for the specific language governing rights and limitations
20 * @APPLE_LICENSE_HEADER_END@
23 * Copyright (c) 1982, 1986, 1989, 1993
24 * The Regents of the University of California. All rights reserved.
26 * This code is derived from software contributed to Berkeley by
27 * Mike Karels at Berkeley Software Design, Inc.
29 * Quite extensively rewritten by Poul-Henning Kamp of the FreeBSD
30 * project, to make these variables more userfriendly.
32 * Redistribution and use in source and binary forms, with or without
33 * modification, are permitted provided that the following conditions
35 * 1. Redistributions of source code must retain the above copyright
36 * notice, this list of conditions and the following disclaimer.
37 * 2. Redistributions in binary form must reproduce the above copyright
38 * notice, this list of conditions and the following disclaimer in the
39 * documentation and/or other materials provided with the distribution.
40 * 3. All advertising materials mentioning features or use of this software
41 * must display the following acknowledgement:
42 * This product includes software developed by the University of
43 * California, Berkeley and its contributors.
44 * 4. Neither the name of the University nor the names of its contributors
45 * may be used to endorse or promote products derived from this software
46 * without specific prior written permission.
48 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
49 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
50 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
51 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
52 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
53 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
54 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
55 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
56 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
57 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
60 * @(#)kern_sysctl.c 8.4 (Berkeley) 4/14/94
64 #include <sys/param.h>
66 #include <sys/kernel.h>
67 #include <sys/sysctl.h>
68 #include <sys/malloc.h>
69 #include <sys/proc_internal.h>
70 #include <sys/systm.h>
72 #include <bsm/audit_kernel.h>
75 struct sysctl_oid_list sysctl__debug_children;
76 struct sysctl_oid_list sysctl__kern_children;
77 struct sysctl_oid_list sysctl__net_children;
78 struct sysctl_oid_list sysctl__sysctl_children;
81 extern struct sysctl_oid
*newsysctl_list
[];
82 extern struct sysctl_oid
*machdep_sysctl_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()
216 for (i
=0; newsysctl_list
[i
]; i
++) {
217 sysctl_register_oid(newsysctl_list
[i
]);
219 for (i
=0; machdep_sysctl_list
[i
]; i
++) {
220 sysctl_register_oid(machdep_sysctl_list
[i
]);
225 * Register the kernel's oids on startup.
227 struct linker_set sysctl_set
;
229 void sysctl_register_all(void *arg
)
231 sysctl_register_set(&sysctl_set
);
234 SYSINIT(sysctl
, SI_SUB_KMEM
, SI_ORDER_ANY
, sysctl_register_all
, 0);
239 * These functions implement a presently undocumented interface
240 * used by the sysctl program to walk the tree, and get the type
241 * so it can print the value.
242 * This interface is under work and consideration, and should probably
243 * be killed with a big axe by the first person who can find the time.
244 * (be aware though, that the proper interface isn't as obvious as it
245 * may seem, there are various conflicting requirements.
247 * {0,0} printf the entire MIB-tree.
248 * {0,1,...} return the name of the "..." OID.
249 * {0,2,...} return the next OID.
250 * {0,3} return the OID of the name in "new"
251 * {0,4,...} return the kind & format info for the "..." OID.
255 sysctl_sysctl_debug_dump_node(struct sysctl_oid_list
*l
, int i
)
258 struct sysctl_oid
*oidp
;
260 SLIST_FOREACH(oidp
, l
, oid_link
) {
265 printf("%d %s ", oidp
->oid_number
, oidp
->oid_name
);
268 oidp
->oid_kind
& CTLFLAG_RD
? 'R':' ',
269 oidp
->oid_kind
& CTLFLAG_WR
? 'W':' ');
271 if (oidp
->oid_handler
)
274 switch (oidp
->oid_kind
& CTLTYPE
) {
277 if (!oidp
->oid_handler
) {
278 sysctl_sysctl_debug_dump_node(
279 oidp
->oid_arg1
, i
+2);
282 case CTLTYPE_INT
: printf(" Int\n"); break;
283 case CTLTYPE_STRING
: printf(" String\n"); break;
284 case CTLTYPE_QUAD
: printf(" Quad\n"); break;
285 case CTLTYPE_OPAQUE
: printf(" Opaque/struct\n"); break;
286 default: printf("\n");
293 sysctl_sysctl_debug SYSCTL_HANDLER_ARGS
295 sysctl_sysctl_debug_dump_node(&sysctl__children
, 0);
299 SYSCTL_PROC(_sysctl
, 0, debug
, CTLTYPE_STRING
|CTLFLAG_RD
,
300 0, 0, sysctl_sysctl_debug
, "-", "");
303 sysctl_sysctl_name SYSCTL_HANDLER_ARGS
305 int *name
= (int *) arg1
;
306 u_int namelen
= arg2
;
308 struct sysctl_oid
*oid
;
309 struct sysctl_oid_list
*lsp
= &sysctl__children
, *lsp2
;
314 snprintf(tempbuf
,sizeof(tempbuf
),"%d",*name
);
316 error
= SYSCTL_OUT(req
, ".", 1);
318 error
= SYSCTL_OUT(req
, tempbuf
, strlen(tempbuf
));
326 SLIST_FOREACH(oid
, lsp
, oid_link
) {
327 if (oid
->oid_number
!= *name
)
331 error
= SYSCTL_OUT(req
, ".", 1);
333 error
= SYSCTL_OUT(req
, oid
->oid_name
,
334 strlen(oid
->oid_name
));
341 if ((oid
->oid_kind
& CTLTYPE
) != CTLTYPE_NODE
)
344 if (oid
->oid_handler
)
347 lsp2
= (struct sysctl_oid_list
*)oid
->oid_arg1
;
352 return (SYSCTL_OUT(req
, "", 1));
355 SYSCTL_NODE(_sysctl
, 1, name
, CTLFLAG_RD
, sysctl_sysctl_name
, "");
358 sysctl_sysctl_next_ls (struct sysctl_oid_list
*lsp
, int *name
, u_int namelen
,
359 int *next
, int *len
, int level
, struct sysctl_oid
**oidpp
)
361 struct sysctl_oid
*oidp
;
364 SLIST_FOREACH(oidp
, lsp
, oid_link
) {
365 *next
= oidp
->oid_number
;
369 if ((oidp
->oid_kind
& CTLTYPE
) != CTLTYPE_NODE
)
371 if (oidp
->oid_handler
)
372 /* We really should call the handler here...*/
374 lsp
= (struct sysctl_oid_list
*)oidp
->oid_arg1
;
375 if (!sysctl_sysctl_next_ls (lsp
, 0, 0, next
+1,
376 len
, level
+1, oidpp
))
381 if (oidp
->oid_number
< *name
)
384 if (oidp
->oid_number
> *name
) {
385 if ((oidp
->oid_kind
& CTLTYPE
) != CTLTYPE_NODE
)
387 if (oidp
->oid_handler
)
389 lsp
= (struct sysctl_oid_list
*)oidp
->oid_arg1
;
390 if (!sysctl_sysctl_next_ls (lsp
, name
+1, namelen
-1,
391 next
+1, len
, level
+1, oidpp
))
395 if ((oidp
->oid_kind
& CTLTYPE
) != CTLTYPE_NODE
)
398 if (oidp
->oid_handler
)
401 lsp
= (struct sysctl_oid_list
*)oidp
->oid_arg1
;
402 if (!sysctl_sysctl_next_ls (lsp
, name
+1, namelen
-1, next
+1,
403 len
, level
+1, oidpp
))
413 sysctl_sysctl_next SYSCTL_HANDLER_ARGS
415 int *name
= (int *) arg1
;
416 u_int namelen
= arg2
;
418 struct sysctl_oid
*oid
;
419 struct sysctl_oid_list
*lsp
= &sysctl__children
;
420 int newoid
[CTL_MAXNAME
];
422 i
= sysctl_sysctl_next_ls (lsp
, name
, namelen
, newoid
, &j
, 1, &oid
);
425 error
= SYSCTL_OUT(req
, newoid
, j
* sizeof (int));
429 SYSCTL_NODE(_sysctl
, 2, next
, CTLFLAG_RD
, sysctl_sysctl_next
, "");
432 name2oid (char *name
, int *oid
, int *len
, struct sysctl_oid
**oidpp
)
435 struct sysctl_oid
*oidp
;
436 struct sysctl_oid_list
*lsp
= &sysctl__children
;
442 p
= name
+ strlen(name
) - 1 ;
448 for (p
= name
; *p
&& *p
!= '.'; p
++)
454 oidp
= SLIST_FIRST(lsp
);
456 while (oidp
&& *len
< CTL_MAXNAME
) {
457 if (strcmp(name
, oidp
->oid_name
)) {
458 oidp
= SLIST_NEXT(oidp
, oid_link
);
461 *oid
++ = oidp
->oid_number
;
470 if ((oidp
->oid_kind
& CTLTYPE
) != CTLTYPE_NODE
)
473 if (oidp
->oid_handler
)
476 lsp
= (struct sysctl_oid_list
*)oidp
->oid_arg1
;
477 oidp
= SLIST_FIRST(lsp
);
479 for (p
= name
; *p
&& *p
!= '.'; p
++)
489 sysctl_sysctl_name2oid SYSCTL_HANDLER_ARGS
492 int error
, oid
[CTL_MAXNAME
], len
;
493 struct sysctl_oid
*op
= 0;
497 if (req
->newlen
>= MAXPATHLEN
) /* XXX arbitrary, undocumented */
498 return (ENAMETOOLONG
);
500 MALLOC(p
, char *,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
|CTLFLAG_KERN
, 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));
602 AUDIT_ARG(value
, *(int *)arg1
);
607 * Handle a long, signed or unsigned. arg1 points to it.
611 sysctl_handle_long SYSCTL_HANDLER_ARGS
617 error
= SYSCTL_OUT(req
, arg1
, sizeof(long));
619 if (error
|| !req
->newptr
)
622 error
= SYSCTL_IN(req
, arg1
, sizeof(long));
627 * Handle a quad, signed or unsigned. arg1 points to it.
631 sysctl_handle_quad SYSCTL_HANDLER_ARGS
637 error
= SYSCTL_OUT(req
, arg1
, sizeof(long long));
639 if (error
|| !req
->newptr
)
642 error
= SYSCTL_IN(req
, arg1
, sizeof(long long));
647 * Expose an int value as a quad.
649 * This interface allows us to support interfaces defined
650 * as using quad values while the implementation is still
654 sysctl_handle_int2quad SYSCTL_HANDLER_ARGS
662 val
= (long long)*(int *)arg1
;
663 error
= SYSCTL_OUT(req
, &val
, sizeof(long long));
665 if (error
|| !req
->newptr
)
668 error
= SYSCTL_IN(req
, &val
, sizeof(long long));
671 * Value must be representable; check by
672 * casting and then casting back.
675 if ((long long)newval
!= val
) {
678 *(int *)arg1
= newval
;
685 * Handle our generic '\0' terminated 'C' string.
687 * a variable string: point arg1 at it, arg2 is max length.
688 * a constant string: point arg1 at it, arg2 is zero.
692 sysctl_handle_string SYSCTL_HANDLER_ARGS
696 error
= SYSCTL_OUT(req
, arg1
, strlen((char *)arg1
)+1);
698 if (error
|| !req
->newptr
)
701 if ((req
->newlen
- req
->newidx
) >= arg2
) {
704 arg2
= (req
->newlen
- req
->newidx
);
705 error
= SYSCTL_IN(req
, arg1
, arg2
);
706 ((char *)arg1
)[arg2
] = '\0';
713 * Handle any kind of opaque data.
714 * arg1 points to it, arg2 is the size.
718 sysctl_handle_opaque SYSCTL_HANDLER_ARGS
722 error
= SYSCTL_OUT(req
, arg1
, arg2
);
724 if (error
|| !req
->newptr
)
727 error
= SYSCTL_IN(req
, arg1
, arg2
);
733 * Transfer functions to/from kernel space.
736 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
, CAST_DOWN(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(CAST_DOWN(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
;
780 req
.oldptr
= CAST_USER_ADDR_T(old
);
783 req
.newptr
= CAST_USER_ADDR_T(new);
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
, (user_size_t
)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
, (req
->oldptr
+ req
->oldidx
), i
);
851 if (req
->oldptr
&& i
< l
)
857 sysctl_new_user(struct sysctl_req
*req
, void *p
, size_t l
)
863 if (req
->newlen
- req
->newidx
< l
)
865 error
= copyin((req
->newptr
+ req
->newidx
), p
, l
);
871 * Traverse our tree, and find the right node, execute whatever it points
872 * at, and return the resulting error code.
876 sysctl_root SYSCTL_HANDLER_ARGS
878 int *name
= (int *) arg1
;
879 u_int namelen
= arg2
;
881 struct sysctl_oid
*oid
;
882 struct sysctl_oid_list
*lsp
= &sysctl__children
;
885 oid
= SLIST_FIRST(lsp
);
888 while (oid
&& indx
< CTL_MAXNAME
) {
889 if (oid
->oid_number
== name
[indx
]) {
891 if (oid
->oid_kind
& CTLFLAG_NOLOCK
)
893 if ((oid
->oid_kind
& CTLTYPE
) == CTLTYPE_NODE
) {
894 if (oid
->oid_handler
)
898 lsp
= (struct sysctl_oid_list
*)oid
->oid_arg1
;
899 oid
= SLIST_FIRST(lsp
);
906 oid
= SLIST_NEXT(oid
, oid_link
);
911 /* If writing isn't allowed */
912 if (req
->newptr
&& (!(oid
->oid_kind
& CTLFLAG_WR
) ||
913 ((oid
->oid_kind
& CTLFLAG_SECURE
) && securelevel
> 0))) {
918 * If we're inside the kernel, the OID must be marked as kernel-valid.
919 * XXX This mechanism for testing is bad.
921 if ((req
->oldfunc
== sysctl_old_kernel
) && !(oid
->oid_kind
& CTLFLAG_KERN
))
924 /* Most likely only root can write */
925 if (!(oid
->oid_kind
& CTLFLAG_ANYBODY
) &&
926 req
->newptr
&& req
->p
&&
927 (error
= suser(req
->p
->p_ucred
, &req
->p
->p_acflag
)))
930 if (!oid
->oid_handler
) {
935 if ((oid
->oid_kind
& CTLTYPE
) == CTLTYPE_NODE
) {
936 i
= (oid
->oid_handler
) (oid
,
937 name
+ indx
, namelen
- indx
,
940 i
= (oid
->oid_handler
) (oid
,
941 oid
->oid_arg1
, oid
->oid_arg2
,
948 #ifndef _SYS_SYSPROTO_H_
960 /* __sysctl(struct proc *p, struct sysctl_args *uap) */
961 new_sysctl(struct proc
*p
, struct sysctl_args
*uap
)
963 int error
, i
, name
[CTL_MAXNAME
];
966 if (uap
->namelen
> CTL_MAXNAME
|| uap
->namelen
< 2)
969 error
= copyin(CAST_USER_ADDR_T(uap
->name
), &name
, uap
->namelen
* sizeof(int));
973 error
= userland_sysctl(p
, name
, uap
->namelen
,
974 CAST_USER_ADDR_T(uap
->old
), uap
->oldlenp
, 0,
975 CAST_USER_ADDR_T(uap
->new), uap
->newlen
, &j
);
976 if (error
&& error
!= ENOMEM
)
979 i
= copyout(&j
, CAST_USER_ADDR_T(uap
->oldlenp
), sizeof(j
));
987 * This is used from various compatibility syscalls too. That's why name
988 * must be in kernel space.
991 userland_sysctl(struct proc
*p
, int *name
, u_int namelen
, user_addr_t oldp
,
992 size_t *oldlenp
, int inkernel
, user_addr_t newp
, size_t newlen
,
996 struct sysctl_req req
, req2
;
998 bzero(&req
, sizeof req
);
1004 req
.oldlen
= *oldlenp
;
1006 error
= copyin(CAST_USER_ADDR_T(oldlenp
), &req
.oldlen
, sizeof(*oldlenp
));
1017 req
.newlen
= newlen
;
1021 req
.oldfunc
= sysctl_old_user
;
1022 req
.newfunc
= sysctl_new_user
;
1027 error
= sysctl_root(0, name
, namelen
, &req2
);
1028 } while (error
== EAGAIN
);
1032 if (error
&& error
!= ENOMEM
)
1036 if (req
.oldptr
&& req
.oldidx
> req
.oldlen
)
1037 *retval
= req
.oldlen
;
1039 *retval
= req
.oldidx
;
1044 /* Non-standard BSDI extension - only present on their 4.3 net-2 releases */
1045 #define KINFO_BSDI_SYSINFO (101<<8)
1048 * Kernel versions of the userland sysctl helper functions.
1050 * These allow sysctl to be used in the same fashion in both
1051 * userland and the kernel.
1053 * Note that some sysctl handlers use copyin/copyout, which
1054 * may not work correctly.
1058 sysctl(int *name
, u_int namelen
, void *oldp
, size_t *oldlenp
, void *newp
, size_t newlen
)
1061 return(kernel_sysctl(current_proc(), name
, namelen
, oldp
, oldlenp
, newp
, newlen
));
1065 sysctlnametomib(const char *name
, int *mibp
, size_t *sizep
)
1070 /* magic service node */
1074 /* look up OID for name */
1075 *sizep
*= sizeof(int);
1076 error
= sysctl(oid
, 2, mibp
, sizep
, (void *)name
, strlen(name
));
1077 *sizep
/= sizeof(int);
1082 sysctlbyname(const char *name
, void *oldp
, size_t *oldlenp
, void *newp
, size_t newlen
)
1084 int oid
[CTL_MAXNAME
+ 2];
1088 /* look up the OID */
1089 oidlen
= CTL_MAXNAME
;
1090 error
= sysctlnametomib(name
, oid
, &oidlen
);
1092 /* now use the OID */
1094 error
= sysctl(oid
, oidlen
, oldp
, oldlenp
, newp
, newlen
);