1 /* $NetBSD: freebsd_sysctl.c,v 1.14 2008/04/28 20:23:41 martin Exp $ */
4 * Copyright (c) 2005 The NetBSD Foundation, Inc.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
16 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
17 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
18 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 * POSSIBILITY OF SUCH DAMAGE.
30 * FreeBSD compatibility module. Try to deal with various FreeBSD sysctl calls.
33 #include <sys/cdefs.h>
34 __KERNEL_RCSID(0, "$NetBSD: freebsd_sysctl.c,v 1.14 2008/04/28 20:23:41 martin Exp $");
36 #include <sys/param.h>
37 #include <sys/systm.h>
39 #include <sys/mount.h>
40 #include <sys/signal.h>
41 #include <sys/signalvar.h>
42 #include <sys/malloc.h>
44 #include <sys/sysctl.h>
45 #include <sys/ktrace.h>
47 #include <sys/syscallargs.h>
49 #include <compat/freebsd/freebsd_syscallargs.h>
50 #include <compat/common/compat_util.h>
51 #include <compat/freebsd/freebsd_rtprio.h>
52 #include <compat/freebsd/freebsd_timex.h>
53 #include <compat/freebsd/freebsd_signal.h>
54 #include <compat/freebsd/freebsd_mman.h>
55 #include <compat/freebsd/freebsd_sysctl.h>
57 static int freebsd_sysctl_name2oid(char *, int *, int *);
59 static struct sysctllog
*freebsd_clog
;
62 freebsd_sysctl_init(void)
65 sysctl_createv(&freebsd_clog
, 0, NULL
, NULL
,
67 CTLTYPE_NODE
, "kern", NULL
,
70 sysctl_createv(&freebsd_clog
, 0, NULL
, NULL
,
71 CTLFLAG_PERMANENT
|CTLFLAG_IMMEDIATE
,
72 CTLTYPE_INT
, "osreldate",
73 SYSCTL_DESCR("Operating system revision"),
74 NULL
, __NetBSD_Version__
, NULL
, 0,
75 CTL_KERN
, CTL_CREATE
, CTL_EOL
);
79 freebsd_sysctl_fini(void)
82 sysctl_teardown(&freebsd_clog
);
86 freebsd_sys_sysctl(struct lwp
*l
, const struct freebsd_sys_sysctl_args
*uap
, register_t
*retval
)
89 syscallarg(int *) name;
90 syscallarg(u_int) namelen;
91 syscallarg(void *) old;
92 syscallarg(size_t *) oldlenp;
93 syscallarg(void *) new;
94 syscallarg(size_t) newlen;
97 int name
[CTL_MAXNAME
];
98 size_t newlen
, *oldlenp
;
102 namelen
= SCARG(uap
, namelen
);
104 if ((namelen
> CTL_MAXNAME
) || (namelen
< 1))
107 if ((error
= copyin(SCARG(uap
, name
), name
,
108 namelen
* sizeof(*name
))) != 0)
111 if (namelen
> 0 && name
[0] != 0)
112 return(sys___sysctl(l
, (const void *)uap
, retval
));
114 ktrmib(name
, namelen
);
117 * FreeBSD sysctl uses an undocumented set of special OIDs in it's
118 * sysctl MIB whose tree is rooted at oid 0. These OIDs are
119 * interpretted by their sysctl to implement functions that NetBSD
120 * performs in libc, such as sysctlgetmibinfo.
122 * From the FreeBSD kern_sysctl.c, these OIDs are:
123 * {0,0} printf the entire MIB-tree.
124 * {0,1,...} return the name of the "..." OID.
125 * {0,2,...} return the next OID.
126 * {0,3} return the OID of the name in "new"
127 * {0,4,...} return the kind & format info for the "..." OID.
128 * {0,5,...} return the description the "..." OID.
130 * Only implement {0,3} for now.
133 if (namelen
< 2 || namelen
> CTL_MAXNAME
)
138 int oid
[CTL_MAXNAME
];
139 u_int oidlen
= CTL_MAXNAME
;
141 new = SCARG(uap
, new);
142 newlen
= SCARG(uap
, newlen
);
143 if (new == NULL
|| newlen
< 1 ||
144 newlen
> (SYSCTL_NAMELEN
* CTL_MAXNAME
))
147 old
= SCARG(uap
, old
);
148 oldlenp
= SCARG(uap
, oldlenp
);
149 if (old
== NULL
|| oldlenp
== NULL
|| *oldlenp
< sizeof(int))
153 (char *) malloc(newlen
+ 1, M_TEMP
, M_WAITOK
)) == NULL
)
156 if ((error
= copyinstr(new, locnew
, newlen
+ 1, NULL
))) {
157 free(locnew
, M_TEMP
);
161 ktrmibio(-1, UIO_WRITE
, new, newlen
+ 1, error
);
162 sysctl_lock(new != NULL
);
163 error
= freebsd_sysctl_name2oid(locnew
, oid
, &oidlen
);
165 free(locnew
, M_TEMP
);
169 oidlen
*= sizeof(int);
170 error
= copyout(oid
, SCARG(uap
, old
),
171 MIN(oidlen
, *SCARG(uap
, oldlenp
)));
174 ktrmibio(-1, UIO_READ
, SCARG(uap
, old
),
175 MIN(oidlen
, *SCARG(uap
, oldlenp
)), 0);
177 error
= copyout(&oidlen
, SCARG(uap
, oldlenp
), sizeof(u_int
));
186 freebsd_sysctl_name2oid(char *name
, int *oid
, int *oidlen
)
190 struct sysctlnode
*node
, *pnode
;
192 pnode
= &sysctl_root
;
193 node
= sysctl_root
.sysctl_child
;
195 if ((dot
= strchr(name
, (int)'.')) != NULL
)
199 while (*name
!= '\0' && node
!= NULL
) {
200 for (ci
= 0; ci
< pnode
->sysctl_clen
; ci
++) {
201 if (strcmp(name
, node
[ci
].sysctl_name
) == 0) {
202 oid
[oi
++] = node
[ci
].sysctl_num
;
203 if ((name
= dot
) == NULL
) {
207 if ((dot
= strchr(name
, (int)'.')) != NULL
)
210 if (SYSCTL_TYPE(node
[ci
].sysctl_flags
) !=
215 node
= pnode
->sysctl_child
;
220 /* no more nodes, it must not exist */