1 /** $MirOS: src/sys/kern/kern_sysctl.c,v 1.18 2010/09/19 18:55:40 tg Exp $ */
2 /* $NetBSD: kern_sysctl.c,v 1.146 2003/09/28 13:24:48 dsl Exp $ */
3 /* $OpenBSD: kern_sysctl.c,v 1.126 2005/06/04 05:10:40 tedu Exp $ */
4 /* $NetBSD: kern_sysctl.c,v 1.17 1996/05/20 17:49:05 mrg Exp $ */
5
6 /*-
7 * Copyright (c) 2006, 2007
8 * Thorsten “mirabilos” Glaser <tg@mirbsd.de>
9 * Copyright (c) 1982, 1986, 1989, 1993
10 * The Regents of the University of California. All rights reserved.
11 *
12 * This code is derived from software contributed to Berkeley by
13 * Mike Karels at Berkeley Software Design, Inc.
14 *
15 * Redistribution and use in source and binary forms, with or without
16 * modification, are permitted provided that the following conditions
17 * are met:
18 * 1. Redistributions of source code must retain the above copyright
19 * notice, this list of conditions and the following disclaimer.
20 * 2. Redistributions in binary form must reproduce the above copyright
21 * notice, this list of conditions and the following disclaimer in the
22 * documentation and/or other materials provided with the distribution.
23 * 3. Neither the name of the University nor the names of its contributors
24 * may be used to endorse or promote products derived from this software
25 * without specific prior written permission.
26 *
27 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
28 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
29 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
30 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
31 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
32 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
33 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
34 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
35 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
36 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
37 * SUCH DAMAGE.
38 *
39 * @(#)kern_sysctl.c 8.4 (Berkeley) 4/14/94
40 */
41
42 /*
43 * sysctl system call.
44 */
45
46 #include <sys/param.h>
47 #include <sys/systm.h>
48 #include <sys/kernel.h>
49 #include <sys/malloc.h>
50 #include <sys/proc.h>
51 #include <sys/resourcevar.h>
52 #include <sys/file.h>
53 #include <sys/vnode.h>
54 #include <sys/unistd.h>
55 #include <sys/buf.h>
56 #include <sys/ioctl.h>
57 #include <sys/tty.h>
58 #include <sys/disklabel.h>
59 #include <sys/disk.h>
60 #include <uvm/uvm_extern.h>
61 #include <sys/sysctl.h>
62 #include <sys/msgbuf.h>
63 #include <sys/dkstat.h>
64 #include <sys/vmmeter.h>
65 #include <sys/namei.h>
66 #include <sys/exec.h>
67 #include <sys/mbuf.h>
68 #include <sys/sensors.h>
69 #include <sys/conf.h>
70 #ifdef __HAVE_TIMECOUNTER
71 #include <sys/timetc.h>
72 #endif
73 #ifdef __HAVE_EVCOUNT
74 #include <sys/evcount.h>
75 #endif
76
77 #include <sys/mount.h>
78 #include <sys/syscallargs.h>
79 #include <dev/rndvar.h>
80
81 #ifdef DDB
82 #include <ddb/db_var.h>
83 #endif
84
85 #ifdef SYSVMSG
86 #include <sys/msg.h>
87 #endif
88 #ifdef SYSVSEM
89 #include <sys/sem.h>
90 #endif
91 #ifdef SYSVSHM
92 #include <sys/shm.h>
93 #endif
94
95 #define PTRTOINT64(_x) ((u_int64_t)(u_long)(_x))
96
97 extern struct forkstat forkstat;
98 extern struct nchstats nchstats;
99 extern int nselcoll, fscale;
100 extern struct disklist_head disklist;
101 extern fixpt_t ccpu;
102 extern long numvnodes;
103
104 extern void nmbclust_update(void);
105
106 int sysctl_diskinit(int, struct proc *);
107 int sysctl_proc_args(int *, u_int, void *, size_t *, struct proc *);
108 int sysctl_intrcnt(int *, u_int, void *, size_t *);
109 int sysctl_sensors(int *, u_int, void *, size_t *, void *, size_t);
110 int sysctl_emul(int *, u_int, void *, size_t *, void *, size_t);
111
112 int (*cpu_cpuspeed)(int *);
113 int (*cpu_setperf)(int);
114 static int do_cpu_setperf(int);
115 int perflevel = 100;
116
117 extern char root_devname[];
118
119 /*
120 * Lock to avoid too many processes vslocking a large amount of memory
121 * at the same time.
122 */
123 struct lock sysctl_lock, sysctl_disklock;
124
125 #if defined(KMEMSTATS) || defined(DIAGNOSTIC) || defined(FFS_SOFTUPDATES)
126 struct lock sysctl_kmemlock;
127 #endif
128
129 const char machine_arch[] = MACHINE_ARCH;
130
131 void sysctl_init_values(void);
132
133 static int
do_cpu_setperf(int newspeed)134 do_cpu_setperf(int newspeed)
135 {
136 int rv = EOPNOTSUPP;
137 if (cpu_setperf) {
138 rv = cpu_setperf(newspeed);
139 if (!rv)
140 __do_calibrate_cyclecounter(&rv);
141 }
142 return (rv);
143 }
144
145 void
sysctl_init()146 sysctl_init()
147 {
148 sysctl_init_values();
149
150 lockinit(&sysctl_lock, PLOCK|PCATCH, "sysctl", 0, 0);
151 lockinit(&sysctl_disklock, PLOCK|PCATCH, "sysctl_disklock", 0, 0);
152
153 #if defined(KMEMSTATS) || defined(DIAGNOSTIC) || defined(FFS_SOFTUPDATES)
154 lockinit(&sysctl_kmemlock, PLOCK|PCATCH, "sysctl_kmemlock", 0, 0);
155 #endif
156 }
157
158 int
sys___sysctl(p,v,retval)159 sys___sysctl(p, v, retval)
160 struct proc *p;
161 void *v;
162 register_t *retval;
163 {
164 register struct sys___sysctl_args /* {
165 syscallarg(int *) name;
166 syscallarg(u_int) namelen;
167 syscallarg(void *) old;
168 syscallarg(size_t *) oldlenp;
169 syscallarg(void *) new;
170 syscallarg(size_t) newlen;
171 } */ *uap = v;
172 int error, dolock = 1, canwrite = 0;
173 size_t savelen = 0, oldlen = 0;
174 sysctlfn *fn;
175 int name[CTL_MAXNAME];
176
177 /*
178 * all top-level sysctl names are non-terminal
179 */
180 if (SCARG(uap, namelen) > CTL_MAXNAME || SCARG(uap, namelen) < 2)
181 return (EINVAL);
182 error = copyin(SCARG(uap, name), name,
183 SCARG(uap, namelen) * sizeof(int));
184 if (error)
185 return (error);
186
187 switch (name[0]) {
188 case CTL_KERN:
189 fn = kern_sysctl;
190 if (name[1] == KERN_VNODE) /* XXX */
191 dolock = 0;
192 if (name[1] == KERN_ARND) /* non-root write access */
193 canwrite = 1;
194 break;
195 case CTL_HW:
196 fn = hw_sysctl;
197 break;
198 case CTL_VM:
199 fn = uvm_sysctl;
200 break;
201 case CTL_NET:
202 fn = net_sysctl;
203 break;
204 case CTL_FS:
205 fn = fs_sysctl;
206 break;
207 case CTL_VFS:
208 fn = vfs_sysctl;
209 break;
210 case CTL_MACHDEP:
211 fn = cpu_sysctl;
212 break;
213 #ifdef DEBUG
214 case CTL_DEBUG:
215 fn = debug_sysctl;
216 break;
217 #endif
218 #ifdef DDB
219 case CTL_DDB:
220 fn = ddb_sysctl;
221 break;
222 #endif
223 default:
224 return (EOPNOTSUPP);
225 }
226
227 if (SCARG(uap, new) != NULL && !canwrite &&
228 (error = suser(p, 0)))
229 return (error);
230
231 if (SCARG(uap, oldlenp) &&
232 (error = copyin(SCARG(uap, oldlenp), &oldlen, sizeof(oldlen))))
233 return (error);
234 if (SCARG(uap, old) != NULL) {
235 if ((error = lockmgr(&sysctl_lock, LK_EXCLUSIVE, NULL, p)) != 0)
236 return (error);
237 if (dolock) {
238 error = uvm_vslock(p, SCARG(uap, old), oldlen,
239 VM_PROT_READ|VM_PROT_WRITE);
240 if (error) {
241 lockmgr(&sysctl_lock, LK_RELEASE, NULL, p);
242 return (error);
243 }
244 }
245 savelen = oldlen;
246 }
247 error = (*fn)(&name[1], SCARG(uap, namelen) - 1, SCARG(uap, old),
248 &oldlen, SCARG(uap, new), SCARG(uap, newlen), p);
249 if (SCARG(uap, old) != NULL) {
250 if (dolock)
251 uvm_vsunlock(p, SCARG(uap, old), savelen);
252 lockmgr(&sysctl_lock, LK_RELEASE, NULL, p);
253 }
254 if (error)
255 return (error);
256 if (SCARG(uap, oldlenp))
257 error = copyout(&oldlen, SCARG(uap, oldlenp), sizeof(oldlen));
258 return (error);
259 }
260
261 /*
262 * Attributes stored in the kernel.
263 */
264 char hostname[MAXHOSTNAMELEN];
265 int hostnamelen;
266 char domainname[1] = "";
267 int domainnamelen;
268 long hostid;
269 char *disknames = NULL;
270 struct diskstats *diskstats = NULL;
271 #ifdef INSECURE
272 int securelevel = -1;
273 #else
274 int securelevel;
275 #endif
276 int allowpsa = 1, allowpse = 1;
277 #define MAXEMULUNAMELEN 65
278 char emul_uname[MAXEMULUNAMELEN];
279
280 /*
281 * kernel related system variables.
282 */
283 int
kern_sysctl(name,namelen,oldp,oldlenp,newp,newlen,p)284 kern_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p)
285 int *name;
286 u_int namelen;
287 void *oldp;
288 size_t *oldlenp;
289 void *newp;
290 size_t newlen;
291 struct proc *p;
292 {
293 int error, level, inthostid, stackgap;
294 extern int somaxconn, sominconn;
295 extern int usermount, nosuidcoredump;
296 extern long cp_time[CPUSTATES];
297 extern int stackgap_random;
298 #ifdef CRYPTO
299 extern int usercrypto;
300 extern int userasymcrypto;
301 extern int cryptodevallowsoft;
302 #endif
303
304 /* all sysctl names at this level are terminal except a ton of them */
305 if (namelen != 1) {
306 switch (name[0]) {
307 case KERN_PROC:
308 case KERN_PROC2:
309 case KERN_MALLOCSTATS:
310 case KERN_TTY:
311 case KERN_POOL:
312 case KERN_PROC_ARGS:
313 case KERN_SYSVIPC_INFO:
314 case KERN_SEMINFO:
315 case KERN_SHMINFO:
316 case KERN_INTRCNT:
317 case KERN_WATCHDOG:
318 case KERN_EMUL:
319 #ifdef __HAVE_EVCOUNT
320 case KERN_EVCOUNT:
321 #endif
322 #ifdef __HAVE_TIMECOUNTER
323 case KERN_TIMECOUNTER:
324 #endif
325 break;
326 default:
327 return (ENOTDIR); /* overloaded */
328 }
329 }
330
331 switch (name[0]) {
332 case KERN_OSTYPE:
333 return (sysctl_rdstring(oldp, oldlenp, newp, ostype));
334 case KERN_OSRELEASE:
335 return (sysctl_rdstring(oldp, oldlenp, newp, osrelease));
336 case KERN_OSPATCHLEVEL:
337 return (sysctl_rdstring(oldp, oldlenp, newp, ospatchlevel));
338 case KERN_OSREV:
339 return (sysctl_rdint(oldp, oldlenp, newp, MirBSD));
340 case KERN_OSVERSION:
341 return (sysctl_rdstring(oldp, oldlenp, newp, osversion));
342 case KERN_VERSION:
343 return (sysctl_rdstring(oldp, oldlenp, newp, version));
344 case KERN_MAXVNODES:
345 return(sysctl_int(oldp, oldlenp, newp, newlen, &desiredvnodes));
346 case KERN_MAXPROC:
347 return (sysctl_int(oldp, oldlenp, newp, newlen, &maxproc));
348 case KERN_MAXFILES:
349 return (sysctl_int(oldp, oldlenp, newp, newlen, &maxfiles));
350 case KERN_NFILES:
351 return (sysctl_rdint(oldp, oldlenp, newp, nfiles));
352 case KERN_TTYCOUNT:
353 return (sysctl_rdint(oldp, oldlenp, newp, tty_count));
354 case KERN_NUMVNODES:
355 return (sysctl_rdint(oldp, oldlenp, newp, numvnodes));
356 case KERN_ARGMAX:
357 return (sysctl_rdint(oldp, oldlenp, newp, ARG_MAX));
358 case KERN_NSELCOLL:
359 return (sysctl_rdint(oldp, oldlenp, newp, nselcoll));
360 case KERN_SECURELVL:
361 level = securelevel;
362 if ((error = sysctl_int(oldp, oldlenp, newp, newlen, &level)) ||
363 newp == NULL)
364 return (error);
365 if ((securelevel > 0 || level < -1) &&
366 level < securelevel && p->p_pid != 1)
367 return (EPERM);
368 securelevel = level;
369 return (0);
370 case KERN_HOSTNAME:
371 error = sysctl_tstring(oldp, oldlenp, newp, newlen,
372 hostname, sizeof(hostname));
373 if (newp && !error)
374 hostnamelen = newlen;
375 return (error);
376 case KERN_DOMAINNAME:
377 error = sysctl_rdstring(oldp, oldlenp, newp, domainname);
378 return (error);
379 case KERN_HOSTID:
380 inthostid = hostid; /* XXX assumes sizeof long <= sizeof int */
381 error = sysctl_int(oldp, oldlenp, newp, newlen, &inthostid);
382 hostid = inthostid;
383 return (error);
384 case KERN_CLOCKRATE:
385 return (sysctl_clockrate(oldp, oldlenp));
386 case KERN_BOOTTIME:
387 return (sysctl_rdstruct(oldp, oldlenp, newp, &boottime,
388 sizeof(struct timeval)));
389 case KERN_VNODE:
390 return (sysctl_vnode(oldp, oldlenp, p));
391 case KERN_PROC:
392 case KERN_PROC2:
393 return (sysctl_doproc(name, namelen, oldp, oldlenp));
394 case KERN_PROC_ARGS:
395 return (sysctl_proc_args(name + 1, namelen - 1, oldp, oldlenp,
396 p));
397 case KERN_FILE:
398 return (sysctl_file(oldp, oldlenp));
399 case KERN_MBSTAT:
400 return (sysctl_rdstruct(oldp, oldlenp, newp, &mbstat,
401 sizeof(mbstat)));
402 case KERN_POSIX1:
403 return (sysctl_rdint(oldp, oldlenp, newp, _POSIX_VERSION));
404 case KERN_NGROUPS:
405 return (sysctl_rdint(oldp, oldlenp, newp, NGROUPS_MAX));
406 case KERN_JOB_CONTROL:
407 return (sysctl_rdint(oldp, oldlenp, newp, 1));
408 case KERN_SAVED_IDS:
409 #ifdef _POSIX_SAVED_IDS
410 return (sysctl_rdint(oldp, oldlenp, newp, 1));
411 #else
412 return (sysctl_rdint(oldp, oldlenp, newp, 0));
413 #endif
414 case KERN_MAXPARTITIONS:
415 return (sysctl_rdint(oldp, oldlenp, newp, MAXPARTITIONS));
416 case KERN_RAWPARTITION:
417 return (sysctl_rdint(oldp, oldlenp, newp, RAW_PART));
418 case KERN_SOMAXCONN:
419 return (sysctl_int(oldp, oldlenp, newp, newlen, &somaxconn));
420 case KERN_SOMINCONN:
421 return (sysctl_int(oldp, oldlenp, newp, newlen, &sominconn));
422 case KERN_USERMOUNT:
423 return (sysctl_int(oldp, oldlenp, newp, newlen, &usermount));
424 case KERN_RND:
425 return (sysctl_rdstruct(oldp, oldlenp, newp, &rndstats,
426 sizeof(rndstats)));
427 case KERN_ARND: {
428 size_t n, o = 0;
429 /* typical userspace writes are 256 bytes */
430 uint8_t buf[256];
431
432 if (newp) while (newlen) {
433 n = min(newlen, sizeof(buf));
434 if ((error = copyin(newp + o, buf, n)))
435 return (error);
436 rnd_lopool_add(buf, n);
437 o += n;
438 newlen -= n;
439 }
440
441 if (oldp) {
442 newlen = *oldlenp;
443 o = 0;
444 while (newlen) {
445 n = min(newlen, sizeof(buf));
446 arc4random_buf(buf, n);
447 if ((error = copyout(buf, oldp + o, n)))
448 return (error);
449 o += n;
450 newlen -= n;
451 }
452 }
453 return (0);
454 }
455 case KERN_NOSUIDCOREDUMP:
456 return (sysctl_int(oldp, oldlenp, newp, newlen, &nosuidcoredump));
457 case KERN_FSYNC:
458 return (sysctl_rdint(oldp, oldlenp, newp, 1));
459 case KERN_SYSVMSG:
460 #ifdef SYSVMSG
461 return (sysctl_rdint(oldp, oldlenp, newp, 1));
462 #else
463 return (sysctl_rdint(oldp, oldlenp, newp, 0));
464 #endif
465 case KERN_SYSVSEM:
466 #ifdef SYSVSEM
467 return (sysctl_rdint(oldp, oldlenp, newp, 1));
468 #else
469 return (sysctl_rdint(oldp, oldlenp, newp, 0));
470 #endif
471 case KERN_SYSVSHM:
472 #ifdef SYSVSHM
473 return (sysctl_rdint(oldp, oldlenp, newp, 1));
474 #else
475 return (sysctl_rdint(oldp, oldlenp, newp, 0));
476 #endif
477 case KERN_MSGBUFSIZE:
478 /*
479 * deal with cases where the message buffer has
480 * become corrupted.
481 */
482 if (!msgbufp || msgbufp->msg_magic != MSG_MAGIC)
483 return (ENXIO);
484 return (sysctl_rdint(oldp, oldlenp, newp, msgbufp->msg_bufs));
485 case KERN_MSGBUF:
486 /* see note above */
487 if (!msgbufp || msgbufp->msg_magic != MSG_MAGIC)
488 return (ENXIO);
489 return (sysctl_rdstruct(oldp, oldlenp, newp, msgbufp,
490 msgbufp->msg_bufs + offsetof(struct msgbuf, msg_bufc)));
491 case KERN_MALLOCSTATS:
492 return (sysctl_malloc(name + 1, namelen - 1, oldp, oldlenp,
493 newp, newlen, p));
494 case KERN_CPTIME:
495 #ifdef __HAVE_CPUINFO
496 {
497 CPU_INFO_ITERATOR cii;
498 struct cpu_info *ci;
499 int i;
500
501 bzero(cp_time, sizeof(cp_time));
502
503 for (CPU_INFO_FOREACH(cii, ci)) {
504 for (i = 0; i < CPUSTATES; i++)
505 cp_time[i] += ci->ci_schedstate.spc_cp_time[i];
506 }
507 }
508 #endif
509 return (sysctl_rdstruct(oldp, oldlenp, newp, &cp_time,
510 sizeof(cp_time)));
511 case KERN_NCHSTATS:
512 return (sysctl_rdstruct(oldp, oldlenp, newp, &nchstats,
513 sizeof(struct nchstats)));
514 case KERN_FORKSTAT:
515 return (sysctl_rdstruct(oldp, oldlenp, newp, &forkstat,
516 sizeof(struct forkstat)));
517 case KERN_TTY:
518 return (sysctl_tty(name + 1, namelen - 1, oldp, oldlenp,
519 newp, newlen));
520 case KERN_FSCALE:
521 return (sysctl_rdint(oldp, oldlenp, newp, fscale));
522 case KERN_CCPU:
523 return (sysctl_rdint(oldp, oldlenp, newp, ccpu));
524 case KERN_NPROCS:
525 return (sysctl_rdint(oldp, oldlenp, newp, nprocs));
526 case KERN_POOL:
527 return (sysctl_dopool(name + 1, namelen - 1, oldp, oldlenp));
528 case KERN_STACKGAPRANDOM:
529 stackgap = stackgap_random;
530 error = sysctl_int(oldp, oldlenp, newp, newlen, &stackgap);
531 if (error)
532 return (error);
533 /*
534 * Safety harness.
535 */
536 if ((stackgap < ALIGNBYTES && stackgap != 0) ||
537 !powerof2(stackgap) || stackgap >= MAXSSIZ)
538 return (EINVAL);
539 stackgap_random = stackgap;
540 return (0);
541 #if defined(SYSVMSG) || defined(SYSVSEM) || defined(SYSVSHM)
542 case KERN_SYSVIPC_INFO:
543 return (sysctl_sysvipc(name + 1, namelen - 1, oldp, oldlenp));
544 #endif
545 #ifdef CRYPTO
546 case KERN_USERCRYPTO:
547 return (sysctl_int(oldp, oldlenp, newp, newlen, &usercrypto));
548 case KERN_USERASYMCRYPTO:
549 return (sysctl_int(oldp, oldlenp, newp, newlen,
550 &userasymcrypto));
551 case KERN_CRYPTODEVALLOWSOFT:
552 return (sysctl_int(oldp, oldlenp, newp, newlen,
553 &cryptodevallowsoft));
554 #endif
555 case KERN_SPLASSERT:
556 return (sysctl_int(oldp, oldlenp, newp, newlen,
557 &splassert_ctl));
558 #ifdef SYSVSEM
559 case KERN_SEMINFO:
560 return (sysctl_sysvsem(name + 1, namelen - 1, oldp, oldlenp,
561 newp, newlen));
562 #endif
563 #ifdef SYSVSHM
564 case KERN_SHMINFO:
565 return (sysctl_sysvshm(name + 1, namelen - 1, oldp, oldlenp,
566 newp, newlen));
567 #endif
568 case KERN_INTRCNT:
569 return (sysctl_intrcnt(name + 1, namelen - 1, oldp, oldlenp));
570 #ifndef SMALL_KERNEL
571 case KERN_WATCHDOG:
572 return (sysctl_wdog(name + 1, namelen - 1, oldp, oldlenp,
573 newp, newlen));
574 #endif
575 case KERN_ALLOWPSA:
576 return sysctl_int(oldp, oldlenp, newp, newlen,
577 &allowpsa);
578 case KERN_ALLOWPSE:
579 return sysctl_int(oldp, oldlenp, newp, newlen,
580 &allowpse);
581 case KERN_EMUL:
582 return (sysctl_emul(name + 1, namelen - 1, oldp, oldlenp,
583 newp, newlen));
584 case KERN_ROOT_DEVICE:
585 return sysctl_rdstring(oldp, oldlenp, newp,
586 root_devname);
587 case KERN_ROOT_PARTITION:
588 return sysctl_rdint(oldp, oldlenp, newp, DISKPART(rootdev));
589 case KERN_MAXCLUSTERS:
590 error = sysctl_int(oldp, oldlenp, newp, newlen, &nmbclust);
591 if (!error)
592 nmbclust_update();
593 return (error);
594 case KERN_EMULUNAME:
595 error = sysctl_tstring(oldp, oldlenp, newp, newlen,
596 emul_uname, MAXEMULUNAMELEN);
597 return (error);
598 #ifdef __HAVE_EVCOUNT
599 case KERN_EVCOUNT:
600 return (evcount_sysctl(name + 1, namelen - 1, oldp, oldlenp,
601 newp, newlen));
602 #endif
603 #ifdef __HAVE_TIMECOUNTER
604 case KERN_TIMECOUNTER:
605 return (sysctl_tc(name + 1, namelen - 1, oldp, oldlenp,
606 newp, newlen));
607 #endif
608 default:
609 return (EOPNOTSUPP);
610 }
611 /* NOTREACHED */
612 }
613
614 /*
615 * hardware related system variables.
616 */
617 int
hw_sysctl(name,namelen,oldp,oldlenp,newp,newlen,p)618 hw_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p)
619 int *name;
620 u_int namelen;
621 void *oldp;
622 size_t *oldlenp;
623 void *newp;
624 size_t newlen;
625 struct proc *p;
626 {
627 extern char machine[], cpu_model[];
628 int err;
629 int cpuspeed;
630
631 /* all sysctl names at this level except sensors are terminal */
632 if (name[0] != HW_SENSORS && namelen != 1)
633 return (ENOTDIR); /* overloaded */
634
635 switch (name[0]) {
636 case HW_MACHINE:
637 return (sysctl_rdstring(oldp, oldlenp, newp, machine));
638 case HW_MODEL:
639 return (sysctl_rdstring(oldp, oldlenp, newp, cpu_model));
640 case HW_NCPU:
641 return (sysctl_rdint(oldp, oldlenp, newp, 1)); /* XXX */
642 case HW_BYTEORDER:
643 return (sysctl_rdint(oldp, oldlenp, newp, BYTE_ORDER));
644 case HW_PHYSMEM:
645 return (sysctl_rdint(oldp, oldlenp, newp, ctob(physmem)));
646 case HW_USERMEM:
647 return (sysctl_rdint(oldp, oldlenp, newp,
648 ctob(physmem - uvmexp.wired)));
649 case HW_PAGESIZE:
650 return (sysctl_rdint(oldp, oldlenp, newp, PAGE_SIZE));
651 case HW_DISKNAMES:
652 err = sysctl_diskinit(0, p);
653 if (err)
654 return err;
655 if (disknames)
656 return (sysctl_rdstring(oldp, oldlenp, newp,
657 disknames));
658 else
659 return (sysctl_rdstring(oldp, oldlenp, newp, ""));
660 case HW_DISKSTATS:
661 err = sysctl_diskinit(1, p);
662 if (err)
663 return err;
664 return (sysctl_rdstruct(oldp, oldlenp, newp, diskstats,
665 disk_count * sizeof(struct diskstats)));
666 case HW_DISKCOUNT:
667 return (sysctl_rdint(oldp, oldlenp, newp, disk_count));
668 case HW_SENSORS:
669 return (sysctl_sensors(name + 1, namelen - 1, oldp, oldlenp,
670 newp, newlen));
671 case HW_CPUSPEED:
672 if (!cpu_cpuspeed)
673 return (EOPNOTSUPP);
674 err = cpu_cpuspeed(&cpuspeed);
675 if (err)
676 return err;
677 return (sysctl_rdint(oldp, oldlenp, newp, cpuspeed));
678 case HW_SETPERF:
679 if (!cpu_setperf)
680 return (EOPNOTSUPP);
681 err = sysctl_int(oldp, oldlenp, newp, newlen, &perflevel);
682 if (err)
683 return err;
684 if (perflevel > 100)
685 perflevel = 100;
686 if (perflevel < 0)
687 perflevel = 0;
688 if (newp)
689 return (do_cpu_setperf(perflevel));
690 else
691 return (0);
692 case HW_MACHINE_ARCH:
693 return (sysctl_rdstring(oldp, oldlenp, newp, machine_arch));
694 default:
695 return (EOPNOTSUPP);
696 }
697 /* NOTREACHED */
698 }
699
700 #ifdef DEBUG
701 /*
702 * Debugging related system variables.
703 */
704 extern struct ctldebug debug0, debug1;
705 struct ctldebug debug2, debug3, debug4;
706 struct ctldebug debug5, debug6, debug7, debug8, debug9;
707 struct ctldebug debug10, debug11, debug12, debug13, debug14;
708 struct ctldebug debug15, debug16, debug17, debug18, debug19;
709 static struct ctldebug *debugvars[CTL_DEBUG_MAXID] = {
710 &debug0, &debug1, &debug2, &debug3, &debug4,
711 &debug5, &debug6, &debug7, &debug8, &debug9,
712 &debug10, &debug11, &debug12, &debug13, &debug14,
713 &debug15, &debug16, &debug17, &debug18, &debug19,
714 };
715 int
debug_sysctl(name,namelen,oldp,oldlenp,newp,newlen,p)716 debug_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p)
717 int *name;
718 u_int namelen;
719 void *oldp;
720 size_t *oldlenp;
721 void *newp;
722 size_t newlen;
723 struct proc *p;
724 {
725 struct ctldebug *cdp;
726
727 /* all sysctl names at this level are name and field */
728 if (namelen != 2)
729 return (ENOTDIR); /* overloaded */
730 cdp = debugvars[name[0]];
731 if (cdp->debugname == 0)
732 return (EOPNOTSUPP);
733 switch (name[1]) {
734 case CTL_DEBUG_NAME:
735 return (sysctl_rdstring(oldp, oldlenp, newp, cdp->debugname));
736 case CTL_DEBUG_VALUE:
737 return (sysctl_int(oldp, oldlenp, newp, newlen, cdp->debugvar));
738 default:
739 return (EOPNOTSUPP);
740 }
741 /* NOTREACHED */
742 }
743 #endif /* DEBUG */
744
745 /*
746 * Validate parameters and get old / set new parameters
747 * for an integer-valued sysctl function.
748 */
749 int
sysctl_int(oldp,oldlenp,newp,newlen,valp)750 sysctl_int(oldp, oldlenp, newp, newlen, valp)
751 void *oldp;
752 size_t *oldlenp;
753 void *newp;
754 size_t newlen;
755 int *valp;
756 {
757 int error = 0;
758
759 if (oldp && *oldlenp < sizeof(int))
760 return (ENOMEM);
761 if (newp && newlen != sizeof(int))
762 return (EINVAL);
763 *oldlenp = sizeof(int);
764 if (oldp)
765 error = copyout(valp, oldp, sizeof(int));
766 if (error == 0 && newp)
767 error = copyin(newp, valp, sizeof(int));
768 return (error);
769 }
770
771 /*
772 * As above, but read-only.
773 */
774 int
sysctl_rdint(oldp,oldlenp,newp,val)775 sysctl_rdint(oldp, oldlenp, newp, val)
776 void *oldp;
777 size_t *oldlenp;
778 void *newp;
779 int val;
780 {
781 int error = 0;
782
783 if (oldp && *oldlenp < sizeof(int))
784 return (ENOMEM);
785 if (newp)
786 return (EPERM);
787 *oldlenp = sizeof(int);
788 if (oldp)
789 error = copyout((caddr_t)&val, oldp, sizeof(int));
790 return (error);
791 }
792
793 /*
794 * Array of integer values.
795 */
796 int
sysctl_int_arr(valpp,name,namelen,oldp,oldlenp,newp,newlen)797 sysctl_int_arr(valpp, name, namelen, oldp, oldlenp, newp, newlen)
798 int **valpp;
799 int *name;
800 u_int namelen;
801 void *oldp;
802 size_t *oldlenp;
803 void *newp;
804 size_t newlen;
805 {
806 if (namelen > 1)
807 return (ENOTDIR);
808 if (name[0] < 0 || valpp[name[0]] == NULL)
809 return (EOPNOTSUPP);
810 return (sysctl_int(oldp, oldlenp, newp, newlen, valpp[name[0]]));
811 }
812
813 /*
814 * Validate parameters and get old / set new parameters
815 * for an integer-valued sysctl function.
816 */
817 int
sysctl_quad(oldp,oldlenp,newp,newlen,valp)818 sysctl_quad(oldp, oldlenp, newp, newlen, valp)
819 void *oldp;
820 size_t *oldlenp;
821 void *newp;
822 size_t newlen;
823 int64_t *valp;
824 {
825 int error = 0;
826
827 if (oldp && *oldlenp < sizeof(int64_t))
828 return (ENOMEM);
829 if (newp && newlen != sizeof(int64_t))
830 return (EINVAL);
831 *oldlenp = sizeof(int64_t);
832 if (oldp)
833 error = copyout(valp, oldp, sizeof(int64_t));
834 if (error == 0 && newp)
835 error = copyin(newp, valp, sizeof(int64_t));
836 return (error);
837 }
838
839 /*
840 * As above, but read-only.
841 */
842 int
sysctl_rdquad(oldp,oldlenp,newp,val)843 sysctl_rdquad(oldp, oldlenp, newp, val)
844 void *oldp;
845 size_t *oldlenp;
846 void *newp;
847 int64_t val;
848 {
849 int error = 0;
850
851 if (oldp && *oldlenp < sizeof(int64_t))
852 return (ENOMEM);
853 if (newp)
854 return (EPERM);
855 *oldlenp = sizeof(int64_t);
856 if (oldp)
857 error = copyout((caddr_t)&val, oldp, sizeof(int64_t));
858 return (error);
859 }
860
861 /*
862 * Validate parameters and get old / set new parameters
863 * for a string-valued sysctl function.
864 */
865 int
sysctl_string(oldp,oldlenp,newp,newlen,str,maxlen)866 sysctl_string(oldp, oldlenp, newp, newlen, str, maxlen)
867 void *oldp;
868 size_t *oldlenp;
869 void *newp;
870 size_t newlen;
871 char *str;
872 int maxlen;
873 {
874 return sysctl__string(oldp, oldlenp, newp, newlen, str, maxlen, 0);
875 }
876
877 int
sysctl_tstring(oldp,oldlenp,newp,newlen,str,maxlen)878 sysctl_tstring(oldp, oldlenp, newp, newlen, str, maxlen)
879 void *oldp;
880 size_t *oldlenp;
881 void *newp;
882 size_t newlen;
883 char *str;
884 int maxlen;
885 {
886 return sysctl__string(oldp, oldlenp, newp, newlen, str, maxlen, 1);
887 }
888
889 int
sysctl__string(oldp,oldlenp,newp,newlen,str,maxlen,trunc)890 sysctl__string(oldp, oldlenp, newp, newlen, str, maxlen, trunc)
891 void *oldp;
892 size_t *oldlenp;
893 void *newp;
894 size_t newlen;
895 char *str;
896 int maxlen;
897 int trunc;
898 {
899 int len, error = 0;
900 char c;
901
902 len = strlen(str) + 1;
903 if (oldp && *oldlenp < len) {
904 if (trunc == 0 || *oldlenp == 0)
905 return (ENOMEM);
906 }
907 if (newp && newlen >= maxlen)
908 return (EINVAL);
909 if (oldp) {
910 if (trunc && *oldlenp < len) {
911 /* save & zap NUL terminator while copying */
912 c = str[*oldlenp-1];
913 str[*oldlenp-1] = '\0';
914 error = copyout(str, oldp, *oldlenp);
915 str[*oldlenp-1] = c;
916 } else {
917 *oldlenp = len;
918 error = copyout(str, oldp, len);
919 }
920 }
921 if (error == 0 && newp) {
922 error = copyin(newp, str, newlen);
923 str[newlen] = 0;
924 }
925 return (error);
926 }
927
928 /*
929 * As above, but read-only.
930 */
931 int
sysctl_rdstring(oldp,oldlenp,newp,str)932 sysctl_rdstring(oldp, oldlenp, newp, str)
933 void *oldp;
934 size_t *oldlenp;
935 void *newp;
936 const char *str;
937 {
938 int len, error = 0;
939
940 len = strlen(str) + 1;
941 if (oldp && *oldlenp < len)
942 return (ENOMEM);
943 if (newp)
944 return (EPERM);
945 *oldlenp = len;
946 if (oldp)
947 error = copyout(str, oldp, len);
948 return (error);
949 }
950
951 /*
952 * Validate parameters and get old / set new parameters
953 * for a structure oriented sysctl function.
954 */
955 int
sysctl_struct(oldp,oldlenp,newp,newlen,sp,len)956 sysctl_struct(oldp, oldlenp, newp, newlen, sp, len)
957 void *oldp;
958 size_t *oldlenp;
959 void *newp;
960 size_t newlen;
961 void *sp;
962 int len;
963 {
964 int error = 0;
965
966 if (oldp && *oldlenp < len)
967 return (ENOMEM);
968 if (newp && newlen > len)
969 return (EINVAL);
970 if (oldp) {
971 *oldlenp = len;
972 error = copyout(sp, oldp, len);
973 }
974 if (error == 0 && newp)
975 error = copyin(newp, sp, len);
976 return (error);
977 }
978
979 /*
980 * Validate parameters and get old parameters
981 * for a structure oriented sysctl function.
982 */
983 int
sysctl_rdstruct(oldp,oldlenp,newp,sp,len)984 sysctl_rdstruct(oldp, oldlenp, newp, sp, len)
985 void *oldp;
986 size_t *oldlenp;
987 void *newp;
988 const void *sp;
989 int len;
990 {
991 int error = 0;
992
993 if (oldp && *oldlenp < len)
994 return (ENOMEM);
995 if (newp)
996 return (EPERM);
997 *oldlenp = len;
998 if (oldp)
999 error = copyout(sp, oldp, len);
1000 return (error);
1001 }
1002
1003 /*
1004 * Get file structures.
1005 */
1006 int
sysctl_file(where,sizep)1007 sysctl_file(where, sizep)
1008 char *where;
1009 size_t *sizep;
1010 {
1011 int buflen, error;
1012 struct file *fp;
1013 char *start = where;
1014
1015 buflen = *sizep;
1016 if (where == NULL) {
1017 /*
1018 * overestimate by 10 files
1019 */
1020 *sizep = sizeof(filehead) + (nfiles + 10) * sizeof(struct file);
1021 return (0);
1022 }
1023
1024 /*
1025 * first copyout filehead
1026 */
1027 if (buflen < sizeof(filehead)) {
1028 *sizep = 0;
1029 return (0);
1030 }
1031 error = copyout((caddr_t)&filehead, where, sizeof(filehead));
1032 if (error)
1033 return (error);
1034 buflen -= sizeof(filehead);
1035 where += sizeof(filehead);
1036
1037 /*
1038 * followed by an array of file structures
1039 */
1040 LIST_FOREACH(fp, &filehead, f_list) {
1041 if (buflen < sizeof(struct file)) {
1042 *sizep = where - start;
1043 return (ENOMEM);
1044 }
1045 error = copyout((caddr_t)fp, where, sizeof (struct file));
1046 if (error)
1047 return (error);
1048 buflen -= sizeof(struct file);
1049 where += sizeof(struct file);
1050 }
1051 *sizep = where - start;
1052 return (0);
1053 }
1054
1055 /*
1056 * try over estimating by 5 procs
1057 */
1058 #define KERN_PROCSLOP (5 * sizeof (struct kinfo_proc))
1059
1060 int
sysctl_doproc(name,namelen,where,sizep)1061 sysctl_doproc(name, namelen, where, sizep)
1062 int *name;
1063 u_int namelen;
1064 char *where;
1065 size_t *sizep;
1066 {
1067 struct kinfo_proc2 kproc2;
1068 struct eproc eproc;
1069 struct proc *p;
1070 char *dp;
1071 int arg, buflen, doingzomb, elem_size, elem_count;
1072 int error, needed, type, op;
1073
1074 dp = where;
1075 buflen = where != NULL ? *sizep : 0;
1076 needed = error = 0;
1077 type = name[0];
1078
1079 if (type == KERN_PROC) {
1080 if (namelen != 3 && !(namelen == 2 &&
1081 (name[1] == KERN_PROC_ALL || name[1] == KERN_PROC_KTHREAD)))
1082 return (EINVAL);
1083 op = name[1];
1084 arg = op == KERN_PROC_ALL ? 0 : name[2];
1085 elem_size = elem_count = 0;
1086 } else /* if (type == KERN_PROC2) */ {
1087 if (namelen != 5 || name[3] < 0 || name[4] < 0)
1088 return (EINVAL);
1089 op = name[1];
1090 arg = name[2];
1091 elem_size = name[3];
1092 elem_count = name[4];
1093 }
1094 p = LIST_FIRST(&allproc);
1095 doingzomb = 0;
1096 again:
1097 for (; p != 0; p = LIST_NEXT(p, p_list)) {
1098 /*
1099 * Skip embryonic processes.
1100 */
1101 if (p->p_stat == SIDL)
1102 continue;
1103 /*
1104 * Skip processes with different real uid
1105 */
1106 if ((!allowpsa) &&
1107 (curproc->p_cred->p_ruid != p->p_cred->p_ruid) &&
1108 (curproc->p_cred->p_rgid))
1109 continue;
1110
1111 /*
1112 * TODO - make more efficient (see notes below).
1113 */
1114 switch (op) {
1115
1116 case KERN_PROC_PID:
1117 /* could do this with just a lookup */
1118 if (p->p_pid != (pid_t)arg)
1119 continue;
1120 break;
1121
1122 case KERN_PROC_PGRP:
1123 /* could do this by traversing pgrp */
1124 if (p->p_pgrp->pg_id != (pid_t)arg)
1125 continue;
1126 break;
1127
1128 case KERN_PROC_SESSION:
1129 if (p->p_session->s_leader == NULL ||
1130 p->p_session->s_leader->p_pid != (pid_t)arg)
1131 continue;
1132 break;
1133
1134 case KERN_PROC_TTY:
1135 if ((p->p_flag & P_CONTROLT) == 0 ||
1136 p->p_session->s_ttyp == NULL ||
1137 p->p_session->s_ttyp->t_dev != (dev_t)arg)
1138 continue;
1139 break;
1140
1141 case KERN_PROC_UID:
1142 if (p->p_ucred->cr_uid != (uid_t)arg)
1143 continue;
1144 break;
1145
1146 case KERN_PROC_RUID:
1147 if (p->p_cred->p_ruid != (uid_t)arg)
1148 continue;
1149 break;
1150
1151 case KERN_PROC_ALL:
1152 if (p->p_flag & P_SYSTEM)
1153 continue;
1154 break;
1155 case KERN_PROC_KTHREAD:
1156 /* no filtering */
1157 break;
1158 default:
1159 return (EINVAL);
1160 }
1161 if (type == KERN_PROC) {
1162 if (buflen >= sizeof(struct kinfo_proc)) {
1163 fill_eproc(p, &eproc);
1164 error = copyout((caddr_t)p,
1165 &((struct kinfo_proc *)dp)->kp_proc,
1166 sizeof(struct proc));
1167 if (error)
1168 return (error);
1169 error = copyout((caddr_t)&eproc,
1170 &((struct kinfo_proc *)dp)->kp_eproc,
1171 sizeof(eproc));
1172 if (error)
1173 return (error);
1174 dp += sizeof(struct kinfo_proc);
1175 buflen -= sizeof(struct kinfo_proc);
1176 }
1177 needed += sizeof(struct kinfo_proc);
1178 } else /* if (type == KERN_PROC2) */ {
1179 if (buflen >= elem_size && elem_count > 0) {
1180 fill_kproc2(p, &kproc2);
1181 /*
1182 * Copy out elem_size, but not larger than
1183 * the size of a struct kinfo_proc2.
1184 */
1185 error = copyout(&kproc2, dp,
1186 min(sizeof(kproc2), elem_size));
1187 if (error)
1188 return (error);
1189 dp += elem_size;
1190 buflen -= elem_size;
1191 elem_count--;
1192 }
1193 needed += elem_size;
1194 }
1195 }
1196 if (doingzomb == 0) {
1197 p = LIST_FIRST(&zombproc);
1198 doingzomb++;
1199 goto again;
1200 }
1201 if (where != NULL) {
1202 *sizep = dp - where;
1203 if (needed > *sizep)
1204 return (ENOMEM);
1205 } else {
1206 needed += KERN_PROCSLOP;
1207 *sizep = needed;
1208 }
1209 return (0);
1210 }
1211
1212 /*
1213 * Fill in an eproc structure for the specified process.
1214 */
1215 void
fill_eproc(struct proc * p,struct eproc * ep)1216 fill_eproc(struct proc *p, struct eproc *ep)
1217 {
1218 struct tty *tp;
1219
1220 ep->e_paddr = p;
1221 ep->e_sess = p->p_pgrp->pg_session;
1222 ep->e_pcred = *p->p_cred;
1223 ep->e_ucred = *p->p_ucred;
1224 if (p->p_stat == SIDL || P_ZOMBIE(p)) {
1225 ep->e_vm.vm_rssize = 0;
1226 ep->e_vm.vm_tsize = 0;
1227 ep->e_vm.vm_dsize = 0;
1228 ep->e_vm.vm_ssize = 0;
1229 bzero(&ep->e_pstats, sizeof(ep->e_pstats));
1230 ep->e_pstats_valid = 0;
1231 } else {
1232 struct vmspace *vm = p->p_vmspace;
1233
1234 PHOLD(p); /* need for pstats */
1235 ep->e_vm.vm_rssize = vm_resident_count(vm);
1236 ep->e_vm.vm_tsize = vm->vm_tsize;
1237 ep->e_vm.vm_dsize = vm->vm_dsize;
1238 ep->e_vm.vm_ssize = vm->vm_ssize;
1239 ep->e_pstats = *p->p_stats;
1240 ep->e_pstats_valid = 1;
1241 PRELE(p);
1242 }
1243 if (p->p_pptr)
1244 ep->e_ppid = p->p_pptr->p_pid;
1245 else
1246 ep->e_ppid = 0;
1247 ep->e_pgid = p->p_pgrp->pg_id;
1248 ep->e_jobc = p->p_pgrp->pg_jobc;
1249 if ((p->p_flag & P_CONTROLT) &&
1250 (tp = ep->e_sess->s_ttyp)) {
1251 ep->e_tdev = tp->t_dev;
1252 ep->e_tpgid = tp->t_pgrp ? tp->t_pgrp->pg_id : NO_PID;
1253 ep->e_tsess = tp->t_session;
1254 } else
1255 ep->e_tdev = NODEV;
1256 ep->e_flag = ep->e_sess->s_ttyvp ? EPROC_CTTY : 0;
1257 if (SESS_LEADER(p))
1258 ep->e_flag |= EPROC_SLEADER;
1259 strncpy(ep->e_wmesg, p->p_wmesg ? p->p_wmesg : "", WMESGLEN);
1260 ep->e_wmesg[WMESGLEN] = '\0';
1261 ep->e_xsize = ep->e_xrssize = 0;
1262 ep->e_xccount = ep->e_xswrss = 0;
1263 strncpy(ep->e_login, ep->e_sess->s_login, MAXLOGNAME-1);
1264 ep->e_login[MAXLOGNAME-1] = '\0';
1265 strncpy(ep->e_emul, p->p_emul->e_name, EMULNAMELEN);
1266 ep->e_emul[EMULNAMELEN] = '\0';
1267 ep->e_maxrss = p->p_rlimit ? p->p_rlimit[RLIMIT_RSS].rlim_cur : 0;
1268 }
1269
1270 /*
1271 * Fill in a kproc2 structure for the specified process.
1272 */
1273 void
fill_kproc2(struct proc * p,struct kinfo_proc2 * ki)1274 fill_kproc2(struct proc *p, struct kinfo_proc2 *ki)
1275 {
1276 struct tty *tp;
1277 struct timeval ut, st;
1278
1279 bzero(ki, sizeof(*ki));
1280
1281 ki->p_paddr = PTRTOINT64(p);
1282 ki->p_fd = PTRTOINT64(p->p_fd);
1283 ki->p_stats = PTRTOINT64(p->p_stats);
1284 ki->p_limit = PTRTOINT64(p->p_limit);
1285 ki->p_vmspace = PTRTOINT64(p->p_vmspace);
1286 ki->p_sigacts = PTRTOINT64(p->p_sigacts);
1287 ki->p_sess = PTRTOINT64(p->p_session);
1288 ki->p_tsess = 0; /* may be changed if controlling tty below */
1289 ki->p_ru = PTRTOINT64(p->p_ru);
1290
1291 ki->p_eflag = 0;
1292 ki->p_exitsig = p->p_exitsig;
1293 ki->p_flag = p->p_flag;
1294
1295 ki->p_pid = p->p_pid;
1296 if (p->p_pptr)
1297 ki->p_ppid = p->p_pptr->p_pid;
1298 else
1299 ki->p_ppid = 0;
1300 if (p->p_session->s_leader)
1301 ki->p_sid = p->p_session->s_leader->p_pid;
1302 else
1303 ki->p_sid = 0;
1304 ki->p__pgid = p->p_pgrp->pg_id;
1305
1306 ki->p_tpgid = -1; /* may be changed if controlling tty below */
1307
1308 ki->p_uid = p->p_ucred->cr_uid;
1309 ki->p_ruid = p->p_cred->p_ruid;
1310 ki->p_gid = p->p_ucred->cr_gid;
1311 ki->p_rgid = p->p_cred->p_rgid;
1312 ki->p_svuid = p->p_cred->p_svuid;
1313 ki->p_svgid = p->p_cred->p_svgid;
1314
1315 memcpy(ki->p_groups, p->p_cred->pc_ucred->cr_groups,
1316 min(sizeof(ki->p_groups), sizeof(p->p_cred->pc_ucred->cr_groups)));
1317 ki->p_ngroups = p->p_cred->pc_ucred->cr_ngroups;
1318
1319 ki->p_jobc = p->p_pgrp->pg_jobc;
1320 if ((p->p_flag & P_CONTROLT) && (tp = p->p_session->s_ttyp)) {
1321 ki->p_tdev = tp->t_dev;
1322 ki->p_tpgid = tp->t_pgrp ? tp->t_pgrp->pg_id : -1;
1323 ki->p_tsess = PTRTOINT64(tp->t_session);
1324 } else {
1325 ki->p_tdev = NODEV;
1326 }
1327
1328 ki->p_estcpu = p->p_estcpu;
1329 ki->p_rtime_sec = p->p_rtime.tv_sec;
1330 ki->p_rtime_usec = p->p_rtime.tv_usec;
1331 ki->p_cpticks = p->p_cpticks;
1332 ki->p_pctcpu = p->p_pctcpu;
1333
1334 ki->p_uticks = p->p_uticks;
1335 ki->p_sticks = p->p_sticks;
1336 ki->p_iticks = p->p_iticks;
1337
1338 ki->p_tracep = PTRTOINT64(p->p_tracep);
1339 ki->p_traceflag = p->p_traceflag;
1340
1341 ki->p_siglist = p->p_siglist;
1342 ki->p_sigmask = p->p_sigmask;
1343 ki->p_sigignore = p->p_sigignore;
1344 ki->p_sigcatch = p->p_sigcatch;
1345
1346 ki->p_stat = p->p_stat;
1347 ki->p_nice = p->p_nice;
1348
1349 ki->p_xstat = p->p_xstat;
1350 ki->p_acflag = p->p_acflag;
1351
1352 strlcpy(ki->p_emul, p->p_emul->e_name, sizeof(ki->p_emul));
1353 strlcpy(ki->p_comm, p->p_comm, sizeof(ki->p_comm));
1354 strncpy(ki->p_login, p->p_session->s_login,
1355 min(sizeof(ki->p_login) - 1, sizeof(p->p_session->s_login)));
1356
1357 if (p->p_stat == SIDL || P_ZOMBIE(p)) {
1358 ki->p_vm_rssize = 0;
1359 ki->p_vm_tsize = 0;
1360 ki->p_vm_dsize = 0;
1361 ki->p_vm_ssize = 0;
1362 } else {
1363 struct vmspace *vm = p->p_vmspace;
1364
1365 ki->p_vm_rssize = vm_resident_count(vm);
1366 ki->p_vm_tsize = vm->vm_tsize;
1367 ki->p_vm_dsize = vm->vm_dsize;
1368 ki->p_vm_ssize = vm->vm_ssize;
1369
1370 ki->p_forw = PTRTOINT64(p->p_forw);
1371 ki->p_back = PTRTOINT64(p->p_back);
1372 ki->p_addr = PTRTOINT64(p->p_addr);
1373 ki->p_stat = p->p_stat;
1374 ki->p_swtime = p->p_swtime;
1375 ki->p_slptime = p->p_slptime;
1376 #ifdef __HAVE_CPUINFO
1377 ki->p_schedflags = 0;
1378 #else
1379 ki->p_schedflags = p->p_schedflags;
1380 #endif
1381 ki->p_holdcnt = p->p_holdcnt;
1382 ki->p_priority = p->p_priority;
1383 ki->p_usrpri = p->p_usrpri;
1384 if (p->p_wmesg)
1385 strlcpy(ki->p_wmesg, p->p_wmesg, sizeof(ki->p_wmesg));
1386 ki->p_wchan = PTRTOINT64(p->p_wchan);
1387
1388 }
1389
1390 if (p->p_session->s_ttyvp)
1391 ki->p_eflag |= EPROC_CTTY;
1392 if (SESS_LEADER(p))
1393 ki->p_eflag |= EPROC_SLEADER;
1394 if (p->p_rlimit)
1395 ki->p_rlim_rss_cur = p->p_rlimit[RLIMIT_RSS].rlim_cur;
1396
1397 /* XXX Is this double check necessary? */
1398 if (P_ZOMBIE(p)) {
1399 ki->p_uvalid = 0;
1400 } else {
1401 ki->p_uvalid = 1;
1402
1403 PHOLD(p); /* need for pstats */
1404 ki->p_ustart_sec = p->p_stats->p_start.tv_sec;
1405 ki->p_ustart_usec = p->p_stats->p_start.tv_usec;
1406
1407 calcru(p, &ut, &st, 0);
1408 ki->p_uutime_sec = ut.tv_sec;
1409 ki->p_uutime_usec = ut.tv_usec;
1410 ki->p_ustime_sec = st.tv_sec;
1411 ki->p_ustime_usec = st.tv_usec;
1412
1413 ki->p_uru_maxrss = p->p_stats->p_ru.ru_maxrss;
1414 ki->p_uru_ixrss = p->p_stats->p_ru.ru_ixrss;
1415 ki->p_uru_idrss = p->p_stats->p_ru.ru_idrss;
1416 ki->p_uru_isrss = p->p_stats->p_ru.ru_isrss;
1417 ki->p_uru_minflt = p->p_stats->p_ru.ru_minflt;
1418 ki->p_uru_majflt = p->p_stats->p_ru.ru_majflt;
1419 ki->p_uru_nswap = p->p_stats->p_ru.ru_nswap;
1420 ki->p_uru_inblock = p->p_stats->p_ru.ru_inblock;
1421 ki->p_uru_oublock = p->p_stats->p_ru.ru_oublock;
1422 ki->p_uru_msgsnd = p->p_stats->p_ru.ru_msgsnd;
1423 ki->p_uru_msgrcv = p->p_stats->p_ru.ru_msgrcv;
1424 ki->p_uru_nsignals = p->p_stats->p_ru.ru_nsignals;
1425 ki->p_uru_nvcsw = p->p_stats->p_ru.ru_nvcsw;
1426 ki->p_uru_nivcsw = p->p_stats->p_ru.ru_nivcsw;
1427
1428 timeradd(&p->p_stats->p_cru.ru_utime,
1429 &p->p_stats->p_cru.ru_stime, &ut);
1430 ki->p_uctime_sec = ut.tv_sec;
1431 ki->p_uctime_usec = ut.tv_usec;
1432 PRELE(p);
1433 }
1434 }
1435
1436 int
sysctl_proc_args(int * name,u_int namelen,void * oldp,size_t * oldlenp,struct proc * cp)1437 sysctl_proc_args(int *name, u_int namelen, void *oldp, size_t *oldlenp,
1438 struct proc *cp)
1439 {
1440 struct proc *vp, *cur = curproc;
1441 pid_t pid;
1442 int op;
1443 struct ps_strings pss;
1444 struct iovec iov;
1445 struct uio uio;
1446 int error;
1447 size_t limit;
1448 int cnt;
1449 char **rargv, **vargv; /* reader vs. victim */
1450 char *rarg, *varg;
1451 char *buf;
1452
1453 if (namelen > 2)
1454 return (ENOTDIR);
1455 if (namelen < 2)
1456 return (EINVAL);
1457
1458 pid = name[0];
1459 op = name[1];
1460
1461 switch (op) {
1462 case KERN_PROC_ARGV:
1463 case KERN_PROC_NARGV:
1464 case KERN_PROC_ENV:
1465 case KERN_PROC_NENV:
1466 break;
1467 default:
1468 return (EOPNOTSUPP);
1469 }
1470
1471 if ((vp = pfind(pid)) == NULL)
1472 return (ESRCH);
1473
1474 if ((!allowpse) &&
1475 (cur->p_cred->p_ruid != vp->p_cred->p_ruid) &&
1476 (cur->p_cred->p_rgid))
1477 return (EPERM);
1478
1479 if (oldp == NULL) {
1480 if (op == KERN_PROC_NARGV || op == KERN_PROC_NENV)
1481 *oldlenp = sizeof(int);
1482 else
1483 *oldlenp = ARG_MAX; /* XXX XXX XXX */
1484 return (0);
1485 }
1486
1487 if (P_ZOMBIE(vp) || (vp->p_flag & P_SYSTEM))
1488 return (EINVAL);
1489
1490 /* Exiting - don't bother, it will be gone soon anyway */
1491 if ((vp->p_flag & P_WEXIT))
1492 return (ESRCH);
1493
1494 /* Execing - danger. */
1495 if ((vp->p_flag & P_INEXEC))
1496 return (EBUSY);
1497
1498 vp->p_vmspace->vm_refcnt++; /* XXX */
1499 buf = malloc(PAGE_SIZE, M_TEMP, M_WAITOK);
1500
1501 iov.iov_base = &pss;
1502 iov.iov_len = sizeof(pss);
1503 uio.uio_iov = &iov;
1504 uio.uio_iovcnt = 1;
1505 uio.uio_offset = (off_t)PS_STRINGS;
1506 uio.uio_resid = sizeof(pss);
1507 uio.uio_segflg = UIO_SYSSPACE;
1508 uio.uio_rw = UIO_READ;
1509 uio.uio_procp = cp;
1510
1511 if ((error = uvm_io(&vp->p_vmspace->vm_map, &uio)) != 0)
1512 goto out;
1513
1514 if (op == KERN_PROC_NARGV) {
1515 error = sysctl_rdint(oldp, oldlenp, NULL, pss.ps_nargvstr);
1516 goto out;
1517 }
1518 if (op == KERN_PROC_NENV) {
1519 error = sysctl_rdint(oldp, oldlenp, NULL, pss.ps_nenvstr);
1520 goto out;
1521 }
1522
1523 if (op == KERN_PROC_ARGV) {
1524 cnt = pss.ps_nargvstr;
1525 vargv = pss.ps_argvstr;
1526 } else {
1527 cnt = pss.ps_nenvstr;
1528 vargv = pss.ps_envstr;
1529 }
1530
1531 /* -1 to have space for a terminating NUL */
1532 limit = *oldlenp - 1;
1533 *oldlenp = 0;
1534
1535 rargv = oldp;
1536
1537 /*
1538 * *oldlenp - number of bytes copied out into readers buffer.
1539 * limit - maximal number of bytes allowed into readers buffer.
1540 * rarg - pointer into readers buffer where next arg will be stored.
1541 * rargv - pointer into readers buffer where the next rarg pointer
1542 * will be stored.
1543 * vargv - pointer into victim address space where the next argument
1544 * will be read.
1545 */
1546
1547 /* space for cnt pointers and a NULL */
1548 rarg = (char *)(rargv + cnt + 1);
1549 *oldlenp += (cnt + 1) * sizeof(char **);
1550
1551 while (cnt > 0 && *oldlenp < limit) {
1552 size_t len, vstrlen;
1553
1554 /* Write to readers argv */
1555 if ((error = copyout(&rarg, rargv, sizeof(rarg))) != 0)
1556 goto out;
1557
1558 /* read the victim argv */
1559 iov.iov_base = &varg;
1560 iov.iov_len = sizeof(varg);
1561 uio.uio_iov = &iov;
1562 uio.uio_iovcnt = 1;
1563 uio.uio_offset = (off_t)(vaddr_t)vargv;
1564 uio.uio_resid = sizeof(varg);
1565 uio.uio_segflg = UIO_SYSSPACE;
1566 uio.uio_rw = UIO_READ;
1567 uio.uio_procp = cp;
1568 if ((error = uvm_io(&vp->p_vmspace->vm_map, &uio)) != 0)
1569 goto out;
1570
1571 if (varg == NULL)
1572 break;
1573
1574 /*
1575 * read the victim arg. We must jump through hoops to avoid
1576 * crossing a page boundary too much and returning an error.
1577 */
1578 more:
1579 len = PAGE_SIZE - (((vaddr_t)varg) & PAGE_MASK);
1580 /* leave space for the terminating NUL */
1581 iov.iov_base = buf;
1582 iov.iov_len = len;
1583 uio.uio_iov = &iov;
1584 uio.uio_iovcnt = 1;
1585 uio.uio_offset = (off_t)(vaddr_t)varg;
1586 uio.uio_resid = len;
1587 uio.uio_segflg = UIO_SYSSPACE;
1588 uio.uio_rw = UIO_READ;
1589 uio.uio_procp = cp;
1590 if ((error = uvm_io(&vp->p_vmspace->vm_map, &uio)) != 0)
1591 goto out;
1592
1593 for (vstrlen = 0; vstrlen < len; vstrlen++) {
1594 if (buf[vstrlen] == '\0')
1595 break;
1596 }
1597
1598 /* Don't overflow readers buffer. */
1599 if (*oldlenp + vstrlen + 1 >= limit) {
1600 error = ENOMEM;
1601 goto out;
1602 }
1603
1604 if ((error = copyout(buf, rarg, vstrlen)) != 0)
1605 goto out;
1606
1607 *oldlenp += vstrlen;
1608 rarg += vstrlen;
1609
1610 /* The string didn't end in this page? */
1611 if (vstrlen == len) {
1612 varg += vstrlen;
1613 goto more;
1614 }
1615
1616 /* End of string. Terminate it with a NUL */
1617 buf[0] = '\0';
1618 if ((error = copyout(buf, rarg, 1)) != 0)
1619 goto out;
1620 *oldlenp += 1;
1621 rarg += 1;
1622
1623 vargv++;
1624 rargv++;
1625 cnt--;
1626 }
1627
1628 if (*oldlenp >= limit) {
1629 error = ENOMEM;
1630 goto out;
1631 }
1632
1633 /* Write the terminating null */
1634 rarg = NULL;
1635 error = copyout(&rarg, rargv, sizeof(rarg));
1636
1637 out:
1638 uvmspace_free(vp->p_vmspace);
1639 free(buf, M_TEMP);
1640 return (error);
1641 }
1642
1643 /*
1644 * Initialize disknames/diskstats for export by sysctl. If update is set,
1645 * then we simply update the disk statistics information.
1646 */
1647 int
sysctl_diskinit(update,p)1648 sysctl_diskinit(update, p)
1649 int update;
1650 struct proc *p;
1651 {
1652 struct diskstats *sdk;
1653 struct disk *dk;
1654 int i, tlen, l;
1655
1656 if ((i = lockmgr(&sysctl_disklock, LK_EXCLUSIVE, NULL, p)) != 0)
1657 return i;
1658
1659 if (disk_change) {
1660 for (dk = TAILQ_FIRST(&disklist), tlen = 0; dk;
1661 dk = TAILQ_NEXT(dk, dk_link))
1662 tlen += strlen(dk->dk_name) + 1;
1663 tlen++;
1664
1665 if (disknames)
1666 free(disknames, M_SYSCTL);
1667 if (diskstats)
1668 free(diskstats, M_SYSCTL);
1669 diskstats = NULL;
1670 disknames = NULL;
1671 diskstats = malloc(disk_count * sizeof(struct diskstats),
1672 M_SYSCTL, M_WAITOK);
1673 disknames = malloc(tlen, M_SYSCTL, M_WAITOK);
1674 disknames[0] = '\0';
1675
1676 for (dk = TAILQ_FIRST(&disklist), i = 0, l = 0; dk;
1677 dk = TAILQ_NEXT(dk, dk_link), i++) {
1678 snprintf(disknames + l, tlen - l, "%s,",
1679 dk->dk_name ? dk->dk_name : "");
1680 l += strlen(disknames + l);
1681 sdk = diskstats + i;
1682 strlcpy(sdk->ds_name, dk->dk_name,
1683 sizeof(sdk->ds_name));
1684 sdk->ds_busy = dk->dk_busy;
1685 sdk->ds_rxfer = dk->dk_rxfer;
1686 sdk->ds_wxfer = dk->dk_wxfer;
1687 sdk->ds_seek = dk->dk_seek;
1688 sdk->ds_rbytes = dk->dk_rbytes;
1689 sdk->ds_wbytes = dk->dk_wbytes;
1690 sdk->ds_attachtime = dk->dk_attachtime;
1691 sdk->ds_timestamp = dk->dk_timestamp;
1692 sdk->ds_time = dk->dk_time;
1693 }
1694
1695 /* Eliminate trailing comma */
1696 if (l != 0)
1697 disknames[l - 1] = '\0';
1698 disk_change = 0;
1699 } else if (update) {
1700 /* Just update, number of drives hasn't changed */
1701 for (dk = TAILQ_FIRST(&disklist), i = 0; dk;
1702 dk = TAILQ_NEXT(dk, dk_link), i++) {
1703 sdk = diskstats + i;
1704 strlcpy(sdk->ds_name, dk->dk_name,
1705 sizeof(sdk->ds_name));
1706 sdk->ds_busy = dk->dk_busy;
1707 sdk->ds_rxfer = dk->dk_rxfer;
1708 sdk->ds_wxfer = dk->dk_wxfer;
1709 sdk->ds_seek = dk->dk_seek;
1710 sdk->ds_rbytes = dk->dk_rbytes;
1711 sdk->ds_wbytes = dk->dk_wbytes;
1712 sdk->ds_attachtime = dk->dk_attachtime;
1713 sdk->ds_timestamp = dk->dk_timestamp;
1714 sdk->ds_time = dk->dk_time;
1715 }
1716 }
1717 lockmgr(&sysctl_disklock, LK_RELEASE, NULL, p);
1718 return 0;
1719 }
1720
1721 #if defined(SYSVMSG) || defined(SYSVSEM) || defined(SYSVSHM)
1722 int
sysctl_sysvipc(name,namelen,where,sizep)1723 sysctl_sysvipc(name, namelen, where, sizep)
1724 int *name;
1725 u_int namelen;
1726 void *where;
1727 size_t *sizep;
1728 {
1729 #ifdef SYSVMSG
1730 struct msg_sysctl_info *msgsi = NULL;
1731 #endif
1732 #ifdef SYSVSEM
1733 struct sem_sysctl_info *semsi = NULL;
1734 #endif
1735 #ifdef SYSVSHM
1736 struct shm_sysctl_info *shmsi = NULL;
1737 #endif
1738 size_t infosize, dssize, tsize, buflen;
1739 int i, nds, error, ret;
1740 void *buf;
1741
1742 if (namelen != 1)
1743 return (EINVAL);
1744
1745 buflen = *sizep;
1746
1747 switch (*name) {
1748 case KERN_SYSVIPC_MSG_INFO:
1749 #ifdef SYSVMSG
1750 infosize = sizeof(msgsi->msginfo);
1751 nds = msginfo.msgmni;
1752 dssize = sizeof(msgsi->msgids[0]);
1753 break;
1754 #else
1755 return (EOPNOTSUPP);
1756 #endif
1757 case KERN_SYSVIPC_SEM_INFO:
1758 #ifdef SYSVSEM
1759 infosize = sizeof(semsi->seminfo);
1760 nds = seminfo.semmni;
1761 dssize = sizeof(semsi->semids[0]);
1762 break;
1763 #else
1764 return (EOPNOTSUPP);
1765 #endif
1766 case KERN_SYSVIPC_SHM_INFO:
1767 #ifdef SYSVSHM
1768 infosize = sizeof(shmsi->shminfo);
1769 nds = shminfo.shmmni;
1770 dssize = sizeof(shmsi->shmids[0]);
1771 break;
1772 #else
1773 return (EOPNOTSUPP);
1774 #endif
1775 default:
1776 return (EINVAL);
1777 }
1778 tsize = infosize + (nds * dssize);
1779
1780 /* Return just the total size required. */
1781 if (where == NULL) {
1782 *sizep = tsize;
1783 return (0);
1784 }
1785
1786 /* Not enough room for even the info struct. */
1787 if (buflen < infosize) {
1788 *sizep = 0;
1789 return (ENOMEM);
1790 }
1791 buf = malloc(min(tsize, buflen), M_TEMP, M_WAITOK);
1792 bzero(buf, min(tsize, buflen));
1793
1794 switch (*name) {
1795 #ifdef SYSVMSG
1796 case KERN_SYSVIPC_MSG_INFO:
1797 msgsi = (struct msg_sysctl_info *)buf;
1798 msgsi->msginfo = msginfo;
1799 break;
1800 #endif
1801 #ifdef SYSVSEM
1802 case KERN_SYSVIPC_SEM_INFO:
1803 semsi = (struct sem_sysctl_info *)buf;
1804 semsi->seminfo = seminfo;
1805 break;
1806 #endif
1807 #ifdef SYSVSHM
1808 case KERN_SYSVIPC_SHM_INFO:
1809 shmsi = (struct shm_sysctl_info *)buf;
1810 shmsi->shminfo = shminfo;
1811 break;
1812 #endif
1813 }
1814 buflen -= infosize;
1815
1816 ret = 0;
1817 if (buflen > 0) {
1818 /* Fill in the IPC data structures. */
1819 for (i = 0; i < nds; i++) {
1820 if (buflen < dssize) {
1821 ret = ENOMEM;
1822 break;
1823 }
1824 switch (*name) {
1825 #ifdef SYSVMSG
1826 case KERN_SYSVIPC_MSG_INFO:
1827 bcopy(&msqids[i], &msgsi->msgids[i], dssize);
1828 break;
1829 #endif
1830 #ifdef SYSVSEM
1831 case KERN_SYSVIPC_SEM_INFO:
1832 if (sema[i] != NULL)
1833 bcopy(sema[i], &semsi->semids[i],
1834 dssize);
1835 else
1836 bzero(&semsi->semids[i], dssize);
1837 break;
1838 #endif
1839 #ifdef SYSVSHM
1840 case KERN_SYSVIPC_SHM_INFO:
1841 if (shmsegs[i] != NULL)
1842 bcopy(shmsegs[i], &shmsi->shmids[i],
1843 dssize);
1844 else
1845 bzero(&shmsi->shmids[i], dssize);
1846 break;
1847 #endif
1848 }
1849 buflen -= dssize;
1850 }
1851 }
1852 *sizep -= buflen;
1853 error = copyout(buf, where, *sizep);
1854 free(buf, M_TEMP);
1855 /* If copyout succeeded, use return code set earlier. */
1856 return (error ? error : ret);
1857 }
1858 #endif /* SYSVMSG || SYSVSEM || SYSVSHM */
1859
1860 int
sysctl_intrcnt(int * name,u_int namelen,void * oldp,size_t * oldlenp)1861 sysctl_intrcnt(int *name, u_int namelen, void *oldp, size_t *oldlenp)
1862 {
1863 #ifdef __HAVE_EVCOUNT
1864 return (evcount_sysctl(name, namelen, oldp, oldlenp, NULL, 0));
1865 #else
1866 extern int intrcnt[], eintrcnt[];
1867 extern char intrnames[], eintrnames[];
1868 char *intrname;
1869 int nintr, i;
1870
1871 nintr = (off_t)(eintrcnt - intrcnt);
1872
1873 if (name[0] != KERN_INTRCNT_NUM) {
1874 if (namelen != 2)
1875 return (ENOTDIR);
1876 if (name[1] < 0 || name[1] >= nintr)
1877 return (EINVAL);
1878 i = name[1];
1879 }
1880
1881 switch (name[0]) {
1882 case KERN_INTRCNT_NUM:
1883 return (sysctl_rdint(oldp, oldlenp, NULL, nintr));
1884 break;
1885 case KERN_INTRCNT_CNT:
1886 return (sysctl_rdquad(oldp, oldlenp, NULL, intrcnt[i]));
1887 case KERN_INTRCNT_NAME:
1888 intrname = intrnames;
1889 while (i > 0) {
1890 intrname += strlen(intrname) + 1;
1891 i--;
1892 if (intrname > eintrnames)
1893 return (EINVAL);
1894 }
1895 return (sysctl_rdstring(oldp, oldlenp, NULL, intrname));
1896 default:
1897 return (EOPNOTSUPP);
1898 }
1899 #endif
1900 }
1901
1902 int nsensors = 0;
1903 struct sensors_head sensors = SLIST_HEAD_INITIALIZER(&sensors);
1904
1905 int
sysctl_sensors(int * name,u_int namelen,void * oldp,size_t * oldlenp,void * newp,size_t newlen)1906 sysctl_sensors(int *name, u_int namelen, void *oldp, size_t *oldlenp,
1907 void *newp, size_t newlen)
1908 {
1909 struct sensor *s = NULL;
1910 int num;
1911
1912 if (namelen != 1)
1913 return (ENOTDIR);
1914
1915 num = name[0];
1916 if (num < 0 || num >= nsensors)
1917 return (ENXIO);
1918
1919 SLIST_FOREACH(s, &sensors, list)
1920 if (s->num == num)
1921 break;
1922
1923 return (sysctl_rdstruct(oldp, oldlenp, newp, s, sizeof(struct sensor)));
1924 }
1925
1926 int
sysctl_emul(int * name,u_int namelen,void * oldp,size_t * oldlenp,void * newp,size_t newlen)1927 sysctl_emul(int *name, u_int namelen, void *oldp, size_t *oldlenp,
1928 void *newp, size_t newlen)
1929 {
1930 int enabled, error;
1931 struct emul *e;
1932
1933 if (name[0] == KERN_EMUL_NUM) {
1934 if (namelen != 1)
1935 return (ENOTDIR);
1936 return (sysctl_rdint(oldp, oldlenp, newp, nexecs));
1937 }
1938
1939 if (namelen != 2)
1940 return (ENOTDIR);
1941 if (name[0] > nexecs || name[0] < 0)
1942 return (EINVAL);
1943 e = execsw[name[0] - 1].es_emul;
1944 if (e == NULL)
1945 return (EINVAL);
1946
1947 switch (name[1]) {
1948 case KERN_EMUL_NAME:
1949 return (sysctl_rdstring(oldp, oldlenp, newp, e->e_name));
1950 case KERN_EMUL_ENABLED:
1951 enabled = (e->e_flags & EMUL_ENABLED);
1952 error = sysctl_int(oldp, oldlenp, newp, newlen,
1953 &enabled);
1954 e->e_flags = (enabled & EMUL_ENABLED);
1955 return (error);
1956 default:
1957 return (EINVAL);
1958 }
1959 }
1960
1961 /* should be last because of declarations */
1962 void
sysctl_init_values(void)1963 sysctl_init_values(void)
1964 {
1965 strlcpy(emul_uname, ostype, MAXEMULUNAMELEN);
1966 }
1967