2 * Copyright (c) 2004 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>
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(buf
,sizeof(buf
),"%d",*name
);
316 error
= SYSCTL_OUT(req
, ".", 1);
318 error
= SYSCTL_OUT(req
, buf
, strlen(buf
));
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 p
= _MALLOC(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
, 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
)
744 if (i
> req
->oldlen
- req
->oldidx
)
745 i
= req
->oldlen
- req
->oldidx
;
747 bcopy((void*)p
, (char *)req
->oldptr
+ req
->oldidx
, i
);
750 if (req
->oldptr
&& i
!= l
)
756 sysctl_new_kernel(struct sysctl_req
*req
, void *p
, size_t l
)
760 if (req
->newlen
- req
->newidx
< l
)
762 bcopy((char *)req
->newptr
+ req
->newidx
, p
, l
);
768 kernel_sysctl(struct proc
*p
, int *name
, u_int namelen
, void *old
, size_t *oldlenp
, void *new, size_t newlen
)
771 struct sysctl_req req
;
777 bzero(&req
, sizeof req
);
780 req
.oldlen
= *oldlenp
;
787 req
.oldfunc
= sysctl_old_kernel
;
788 req
.newfunc
= sysctl_new_kernel
;
792 * Locking. Tree traversal always begins with the kernel funnel held.
794 fnl
= spl_kernel_funnel();
796 /* XXX this should probably be done in a general way */
797 while (memlock
.sl_lock
) {
799 (void) tsleep((caddr_t
)&memlock
, PRIBIO
+1, "sysctl", 0);
804 /* make the request */
805 error
= sysctl_root(0, name
, namelen
, &req
);
807 /* unlock memory if required */
809 vsunlock(req
.oldptr
, req
.oldlen
, B_WRITE
);
813 if (memlock
.sl_want
) {
815 wakeup((caddr_t
)&memlock
);
821 splx_kernel_funnel(fnl
);
823 if (error
&& error
!= ENOMEM
)
827 *oldlenp
= req
.oldidx
;
833 * Transfer function to/from user space.
836 sysctl_old_user(struct sysctl_req
*req
, const void *p
, size_t l
)
842 if (req
->oldlen
- req
->oldidx
< l
)
845 if (i
> req
->oldlen
- req
->oldidx
)
846 i
= req
->oldlen
- req
->oldidx
;
848 error
= copyout((void*)p
, (char *)req
->oldptr
+ req
->oldidx
,
854 if (req
->oldptr
&& i
< l
)
860 sysctl_new_user(struct sysctl_req
*req
, void *p
, size_t l
)
866 if (req
->newlen
- req
->newidx
< l
)
868 error
= copyin((char *)req
->newptr
+ req
->newidx
, p
, l
);
874 * Traverse our tree, and find the right node, execute whatever it points
875 * at, and return the resulting error code.
879 sysctl_root SYSCTL_HANDLER_ARGS
881 int *name
= (int *) arg1
;
882 u_int namelen
= arg2
;
884 struct sysctl_oid
*oid
;
885 struct sysctl_oid_list
*lsp
= &sysctl__children
;
888 oid
= SLIST_FIRST(lsp
);
891 while (oid
&& indx
< CTL_MAXNAME
) {
892 if (oid
->oid_number
== name
[indx
]) {
894 if (oid
->oid_kind
& CTLFLAG_NOLOCK
)
896 if ((oid
->oid_kind
& CTLTYPE
) == CTLTYPE_NODE
) {
897 if (oid
->oid_handler
)
901 lsp
= (struct sysctl_oid_list
*)oid
->oid_arg1
;
902 oid
= SLIST_FIRST(lsp
);
909 oid
= SLIST_NEXT(oid
, oid_link
);
914 /* If writing isn't allowed */
915 if (req
->newptr
&& (!(oid
->oid_kind
& CTLFLAG_WR
) ||
916 ((oid
->oid_kind
& CTLFLAG_SECURE
) && securelevel
> 0))) {
921 * If we're inside the kernel, the OID must be marked as kernel-valid.
922 * XXX This mechanism for testing is bad.
924 if ((req
->oldfunc
== sysctl_old_kernel
) && !(oid
->oid_kind
& CTLFLAG_KERN
))
927 /* Most likely only root can write */
928 if (!(oid
->oid_kind
& CTLFLAG_ANYBODY
) &&
929 req
->newptr
&& req
->p
&&
930 (error
= suser(req
->p
->p_ucred
, &req
->p
->p_acflag
)))
933 if (!oid
->oid_handler
) {
938 * Switch to the NETWORK funnel for CTL_NET and KERN_IPC sysctls
941 if (((name
[0] == CTL_NET
) || ((name
[0] == CTL_KERN
) &&
942 (name
[1] == KERN_IPC
))))
943 thread_funnel_switch(KERNEL_FUNNEL
, NETWORK_FUNNEL
);
945 if ((oid
->oid_kind
& CTLTYPE
) == CTLTYPE_NODE
) {
946 i
= (oid
->oid_handler
) (oid
,
947 name
+ indx
, namelen
- indx
,
950 i
= (oid
->oid_handler
) (oid
,
951 oid
->oid_arg1
, oid
->oid_arg2
,
956 * Switch back to the KERNEL funnel, if necessary
959 if (((name
[0] == CTL_NET
) || ((name
[0] == CTL_KERN
) &&
960 (name
[1] == KERN_IPC
))))
961 thread_funnel_switch(NETWORK_FUNNEL
, KERNEL_FUNNEL
);
966 #ifndef _SYS_SYSPROTO_H_
978 /* __sysctl(struct proc *p, struct sysctl_args *uap) */
979 new_sysctl(struct proc
*p
, struct sysctl_args
*uap
)
981 int error
, i
, name
[CTL_MAXNAME
];
984 if (uap
->namelen
> CTL_MAXNAME
|| uap
->namelen
< 2)
987 error
= copyin(uap
->name
, &name
, uap
->namelen
* sizeof(int));
991 error
= userland_sysctl(p
, name
, uap
->namelen
,
992 uap
->old
, uap
->oldlenp
, 0,
993 uap
->new, uap
->newlen
, &j
);
994 if (error
&& error
!= ENOMEM
)
997 i
= copyout(&j
, uap
->oldlenp
, sizeof(j
));
1005 * This is used from various compatibility syscalls too. That's why name
1006 * must be in kernel space.
1009 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
)
1012 struct sysctl_req req
, req2
;
1014 bzero(&req
, sizeof req
);
1020 req
.oldlen
= *oldlenp
;
1022 error
= copyin(oldlenp
, &req
.oldlen
, sizeof(*oldlenp
));
1033 req
.newlen
= newlen
;
1037 req
.oldfunc
= sysctl_old_user
;
1038 req
.newfunc
= sysctl_new_user
;
1043 error
= sysctl_root(0, name
, namelen
, &req2
);
1044 } while (error
== EAGAIN
);
1048 if (error
&& error
!= ENOMEM
)
1052 if (req
.oldptr
&& req
.oldidx
> req
.oldlen
)
1053 *retval
= req
.oldlen
;
1055 *retval
= req
.oldidx
;
1060 /* Non-standard BSDI extension - only present on their 4.3 net-2 releases */
1061 #define KINFO_BSDI_SYSINFO (101<<8)
1064 * Kernel versions of the userland sysctl helper functions.
1066 * These allow sysctl to be used in the same fashion in both
1067 * userland and the kernel.
1069 * Note that some sysctl handlers use copyin/copyout, which
1070 * may not work correctly.
1074 sysctl(int *name
, u_int namelen
, void *oldp
, size_t *oldlenp
, void *newp
, size_t newlen
)
1077 return(kernel_sysctl(current_proc(), name
, namelen
, oldp
, oldlenp
, newp
, newlen
));
1081 sysctlnametomib(const char *name
, int *mibp
, size_t *sizep
)
1086 /* magic service node */
1090 /* look up OID for name */
1091 *sizep
*= sizeof(int);
1092 error
= sysctl(oid
, 2, mibp
, sizep
, (void *)name
, strlen(name
));
1093 *sizep
/= sizeof(int);
1098 sysctlbyname(const char *name
, void *oldp
, size_t *oldlenp
, void *newp
, size_t newlen
)
1100 int oid
[CTL_MAXNAME
+ 2];
1104 /* look up the OID */
1105 oidlen
= CTL_MAXNAME
;
1106 error
= sysctlnametomib(name
, oid
, &oidlen
);
1108 /* now use the OID */
1110 error
= sysctl(oid
, oidlen
, oldp
, oldlenp
, newp
, newlen
);