netbsd32_sysctl.c revision 1.9 1 /* $NetBSD: netbsd32_sysctl.c,v 1.9 2003/06/29 13:35:40 martin Exp $ */
2
3 /*
4 * Copyright (c) 1998, 2001 Matthew R. Green
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
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.
15 * 3. The name of the author may not be used to endorse or promote products
16 * derived from this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
23 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
25 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
26 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 * SUCH DAMAGE.
29 */
30
31 #include <sys/cdefs.h>
32 __KERNEL_RCSID(0, "$NetBSD: netbsd32_sysctl.c,v 1.9 2003/06/29 13:35:40 martin Exp $");
33
34 #if defined(_KERNEL_OPT)
35 #include "opt_ddb.h"
36 #endif
37
38 #include <sys/param.h>
39 #include <sys/systm.h>
40 #include <sys/kernel.h>
41 #include <sys/malloc.h>
42 #include <sys/mount.h>
43 #include <sys/stat.h>
44 #include <sys/time.h>
45 #include <sys/vnode.h>
46 #include <sys/sa.h>
47 #include <sys/syscallargs.h>
48 #include <sys/proc.h>
49 #define __SYSCTL_PRIVATE
50 #include <sys/sysctl.h>
51
52 #include <uvm/uvm_extern.h>
53
54 #include <compat/netbsd32/netbsd32.h>
55 #include <compat/netbsd32/netbsd32_syscall.h>
56 #include <compat/netbsd32/netbsd32_syscallargs.h>
57 #include <compat/netbsd32/netbsd32_conv.h>
58
59 #if defined(DDB)
60 #include <ddb/ddbvar.h>
61 #endif
62
63 int uvm_sysctl32(int *, u_int, void *, size_t *, void *, size_t, struct lwp *);
64 int kern_sysctl32(int *, u_int, void *, size_t *, void *, size_t, struct lwp *);
65 int hw_sysctl32(int *, u_int, void *, size_t *, void *, size_t, struct lwp *);
66
67 /*
68 * uvm_sysctl32: sysctl hook into UVM system, handling special 32-bit
69 * sensitive calls.
70 */
71 int
72 uvm_sysctl32(name, namelen, oldp, oldlenp, newp, newlen, l)
73 int *name;
74 u_int namelen;
75 void *oldp;
76 size_t *oldlenp;
77 void *newp;
78 size_t newlen;
79 struct lwp *l;
80 {
81 struct netbsd32_loadavg av32;
82
83 /* all sysctl names at this level are terminal */
84 if (namelen != 1)
85 return (ENOTDIR); /* overloaded */
86
87 switch (name[0]) {
88 case VM_LOADAVG:
89 netbsd32_from_loadavg(&av32, &averunnable);
90 return (sysctl_rdstruct(oldp, oldlenp, newp, &av32,
91 sizeof(av32)));
92
93 default:
94 return (EOPNOTSUPP);
95 }
96 /* NOTREACHED */
97 }
98
99 /*
100 * kern_sysctl32: sysctl hook into KERN system, handling special 32-bit
101 * sensitive calls.
102 */
103 int
104 kern_sysctl32(name, namelen, oldp, oldlenp, newp, newlen, l)
105 int *name;
106 u_int namelen;
107 void *oldp;
108 size_t *oldlenp;
109 void *newp;
110 size_t newlen;
111 struct lwp *l;
112 {
113 struct netbsd32_timeval bt32;
114
115 /* All sysctl names at this level, except for a few, are terminal. */
116 switch (name[0]) {
117 #if 0
118 case KERN_PROC:
119 case KERN_PROC2:
120 case KERN_PROF:
121 case KERN_MBUF:
122 case KERN_PROC_ARGS:
123 case KERN_SYSVIPC_INFO:
124 /* Not terminal. */
125 break;
126 #endif
127 default:
128 if (namelen != 1)
129 return (ENOTDIR); /* overloaded */
130 }
131
132 switch (name[0]) {
133 case KERN_BOOTTIME:
134 netbsd32_from_timeval(&boottime, &bt32);
135 return (sysctl_rdstruct(oldp, oldlenp, newp, &bt32,
136 sizeof(struct netbsd32_timeval)));
137
138 default:
139 return (EOPNOTSUPP);
140 }
141 /* NOTREACHED */
142 }
143
144 /*
145 * hardware related system variables.
146 */
147 int
148 hw_sysctl32(int *name, u_int namelen, void *oldp, size_t *oldlenp,
149 void *newp, size_t newlen, struct lwp *l)
150 {
151 extern char machine_arch32[];
152
153 switch (name[0]) {
154 case HW_MACHINE_ARCH:
155 return (sysctl_rdstring(oldp, oldlenp, newp, machine_arch32));
156 default:
157 return (EOPNOTSUPP);
158 }
159 /* NOTREACHED */
160 }
161
162 int
163 netbsd32___sysctl(l, v, retval)
164 struct lwp *l;
165 void *v;
166 register_t *retval;
167 {
168 struct netbsd32___sysctl_args /* {
169 syscallarg(netbsd32_intp) name;
170 syscallarg(u_int) namelen;
171 syscallarg(netbsd32_voidp) old;
172 syscallarg(netbsd32_size_tp) oldlenp;
173 syscallarg(netbsd32_voidp) new;
174 syscallarg(netbsd32_size_t) newlen;
175 } */ *uap = v;
176 int error;
177 netbsd32_size_t savelen = 0;
178 size_t oldlen = 0;
179 sysctlfn *fn;
180 struct proc *p = l->l_proc;
181 int name[CTL_MAXNAME];
182
183 /*
184 * Some of these sysctl functions do their own copyin/copyout.
185 * We need to disable or emulate the ones that need their
186 * arguments converted.
187 */
188
189 if (SCARG(uap, new) != NULL &&
190 (error = suser(p->p_ucred, &p->p_acflag)))
191 return (error);
192 /*
193 * all top-level sysctl names are non-terminal
194 */
195 if (SCARG(uap, namelen) > CTL_MAXNAME || SCARG(uap, namelen) < 2)
196 return (EINVAL);
197 error = copyin((caddr_t)NETBSD32PTR64(SCARG(uap, name)), &name,
198 SCARG(uap, namelen) * sizeof(int));
199 if (error)
200 return (error);
201
202 switch (name[0]) {
203 case CTL_KERN:
204 switch (name[1]) {
205 #if 0
206 case KERN_FILE:
207 case KERN_NTPTIME:
208 case KERN_SYSVIPC_INFO:
209 #endif
210 case KERN_BOOTTIME:
211 fn = kern_sysctl32;
212 break;
213 default:
214 fn = kern_sysctl;
215 break;
216 }
217 break;
218 case CTL_HW:
219 switch (name[1]) {
220 case HW_MACHINE_ARCH:
221 fn = hw_sysctl32;
222 break;
223 default:
224 fn = hw_sysctl;
225 break;
226 }
227 break;
228 case CTL_VM:
229 switch (name[1]) {
230 case VM_LOADAVG:
231 fn = uvm_sysctl32; /* need to convert a `long' */
232 break;
233 default:
234 fn = uvm_sysctl;
235 break;
236 }
237 break;
238 case CTL_NET:
239 fn = net_sysctl;
240 break;
241 case CTL_VFS:
242 fn = vfs_sysctl;
243 break;
244 case CTL_MACHDEP:
245 fn = cpu_sysctl;
246 break;
247 #ifdef DEBUG
248 case CTL_DEBUG:
249 fn = debug_sysctl;
250 break;
251 #endif
252 #ifdef DDB
253 case CTL_DDB:
254 fn = ddb_sysctl;
255 break;
256 #endif
257 case CTL_PROC:
258 fn = proc_sysctl;
259 break;
260 default:
261 return (EOPNOTSUPP);
262 }
263
264 /*
265 * XXX Hey, we wire `old', but what about `new'?
266 */
267
268 if (SCARG(uap, oldlenp) &&
269 (error = copyin((caddr_t)NETBSD32PTR64(SCARG(uap, oldlenp)),
270 &savelen, sizeof(savelen))))
271 return (error);
272 if (SCARG(uap, old) != NULL) {
273 error = lockmgr(&sysctl_memlock, LK_EXCLUSIVE, NULL);
274 if (error)
275 return (error);
276 error = uvm_vslock(p, (void *)(vaddr_t)SCARG(uap, old), savelen,
277 VM_PROT_WRITE);
278 if (error) {
279 (void) lockmgr(&sysctl_memlock, LK_RELEASE, NULL);
280 return error;
281 }
282 oldlen = savelen;
283 }
284 error = (*fn)(name + 1, SCARG(uap, namelen) - 1,
285 (void *)NETBSD32PTR64(SCARG(uap, old)), &oldlen,
286 (void *)NETBSD32PTR64(SCARG(uap, new)), SCARG(uap, newlen), l);
287 if (SCARG(uap, old) != NULL) {
288 uvm_vsunlock(p, (void *)NETBSD32PTR64(SCARG(uap, old)),
289 savelen);
290 (void) lockmgr(&sysctl_memlock, LK_RELEASE, NULL);
291 }
292 savelen = oldlen;
293 if (error)
294 return (error);
295 if (SCARG(uap, oldlenp))
296 error = copyout(&savelen,
297 (caddr_t)NETBSD32PTR64(SCARG(uap, oldlenp)),
298 sizeof(savelen));
299 return (error);
300 }
301