xref: /openbsd-src/sys/kern/kern_sysctl.c (revision db3296cf5c1dd9058ceecc3a29fe4aaa0bd26000)
1 /*	$OpenBSD: kern_sysctl.c,v 1.83 2003/06/10 21:50:26 mickey Exp $	*/
2 /*	$NetBSD: kern_sysctl.c,v 1.17 1996/05/20 17:49:05 mrg Exp $	*/
3 
4 /*-
5  * Copyright (c) 1982, 1986, 1989, 1993
6  *	The Regents of the University of California.  All rights reserved.
7  *
8  * This code is derived from software contributed to Berkeley by
9  * Mike Karels at Berkeley Software Design, Inc.
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions
13  * are met:
14  * 1. Redistributions of source code must retain the above copyright
15  *    notice, this list of conditions and the following disclaimer.
16  * 2. Redistributions in binary form must reproduce the above copyright
17  *    notice, this list of conditions and the following disclaimer in the
18  *    documentation and/or other materials provided with the distribution.
19  * 3. Neither the name of the University nor the names of its contributors
20  *    may be used to endorse or promote products derived from this software
21  *    without specific prior written permission.
22  *
23  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33  * SUCH DAMAGE.
34  *
35  *	@(#)kern_sysctl.c	8.4 (Berkeley) 4/14/94
36  */
37 
38 /*
39  * sysctl system call.
40  */
41 
42 #include <sys/param.h>
43 #include <sys/systm.h>
44 #include <sys/kernel.h>
45 #include <sys/malloc.h>
46 #include <sys/proc.h>
47 #include <sys/resourcevar.h>
48 #include <sys/file.h>
49 #include <sys/vnode.h>
50 #include <sys/unistd.h>
51 #include <sys/buf.h>
52 #include <sys/ioctl.h>
53 #include <sys/tty.h>
54 #include <sys/disklabel.h>
55 #include <sys/disk.h>
56 #include <uvm/uvm_extern.h>
57 #include <sys/sysctl.h>
58 #include <sys/msgbuf.h>
59 #include <sys/dkstat.h>
60 #include <sys/vmmeter.h>
61 #include <sys/namei.h>
62 #include <sys/exec.h>
63 #include <sys/mbuf.h>
64 #include <sys/sensors.h>
65 
66 #include <sys/mount.h>
67 #include <sys/syscallargs.h>
68 #include <dev/rndvar.h>
69 
70 #ifdef DDB
71 #include <ddb/db_var.h>
72 #endif
73 
74 #ifdef SYSVMSG
75 #include <sys/msg.h>
76 #endif
77 #ifdef SYSVSEM
78 #include <sys/sem.h>
79 #endif
80 #ifdef SYSVSHM
81 #include <sys/shm.h>
82 #endif
83 
84 extern struct forkstat forkstat;
85 extern struct nchstats nchstats;
86 extern int nselcoll, fscale;
87 extern struct disklist_head disklist;
88 extern fixpt_t ccpu;
89 extern  long numvnodes;
90 
91 int sysctl_diskinit(int, struct proc *);
92 int sysctl_proc_args(int *, u_int, void *, size_t *, struct proc *);
93 int sysctl_intrcnt(int *, u_int, void *, size_t *);
94 int sysctl_sensors(int *, u_int, void *, size_t *, void *, size_t);
95 
96 /*
97  * Lock to avoid too many processes vslocking a large amount of memory
98  * at the same time.
99  */
100 struct lock sysctl_lock, sysctl_disklock;
101 
102 #if defined(KMEMSTATS) || defined(DIAGNOSTIC) || defined(FFS_SOFTUPDATES)
103 struct lock sysctl_kmemlock;
104 #endif
105 
106 void
107 sysctl_init()
108 {
109 	lockinit(&sysctl_lock, PLOCK|PCATCH, "sysctl", 0, 0);
110 	lockinit(&sysctl_disklock, PLOCK|PCATCH, "sysctl_disklock", 0, 0);
111 
112 #if defined(KMEMSTATS) || defined(DIAGNOSTIC) || defined(FFS_SOFTUPDATES)
113 	lockinit(&sysctl_kmemlock, PLOCK|PCATCH, "sysctl_kmemlock", 0, 0);
114 #endif
115 }
116 
117 int
118 sys___sysctl(p, v, retval)
119 	struct proc *p;
120 	void *v;
121 	register_t *retval;
122 {
123 	register struct sys___sysctl_args /* {
124 		syscallarg(int *) name;
125 		syscallarg(u_int) namelen;
126 		syscallarg(void *) old;
127 		syscallarg(size_t *) oldlenp;
128 		syscallarg(void *) new;
129 		syscallarg(size_t) newlen;
130 	} */ *uap = v;
131 	int error, dolock = 1;
132 	size_t savelen = 0, oldlen = 0;
133 	sysctlfn *fn;
134 	int name[CTL_MAXNAME];
135 
136 	if (SCARG(uap, new) != NULL &&
137 	    (error = suser(p->p_ucred, &p->p_acflag)))
138 		return (error);
139 	/*
140 	 * all top-level sysctl names are non-terminal
141 	 */
142 	if (SCARG(uap, namelen) > CTL_MAXNAME || SCARG(uap, namelen) < 2)
143 		return (EINVAL);
144 	error = copyin(SCARG(uap, name), name,
145 		       SCARG(uap, namelen) * sizeof(int));
146 	if (error)
147 		return (error);
148 
149 	switch (name[0]) {
150 	case CTL_KERN:
151 		fn = kern_sysctl;
152 		if (name[2] == KERN_VNODE)	/* XXX */
153 			dolock = 0;
154 		break;
155 	case CTL_HW:
156 		fn = hw_sysctl;
157 		break;
158 	case CTL_VM:
159 		fn = uvm_sysctl;
160 		break;
161 	case CTL_NET:
162 		fn = net_sysctl;
163 		break;
164 	case CTL_FS:
165 		fn = fs_sysctl;
166 		break;
167 	case CTL_VFS:
168 		fn = vfs_sysctl;
169 		break;
170 	case CTL_MACHDEP:
171 		fn = cpu_sysctl;
172 		break;
173 #ifdef DEBUG
174 	case CTL_DEBUG:
175 		fn = debug_sysctl;
176 		break;
177 #endif
178 #ifdef DDB
179 	case CTL_DDB:
180 		fn = ddb_sysctl;
181 		break;
182 #endif
183 	default:
184 		return (EOPNOTSUPP);
185 	}
186 
187 	if (SCARG(uap, oldlenp) &&
188 	    (error = copyin(SCARG(uap, oldlenp), &oldlen, sizeof(oldlen))))
189 		return (error);
190 	if (SCARG(uap, old) != NULL) {
191 		if ((error = lockmgr(&sysctl_lock, LK_EXCLUSIVE, NULL, p)) != 0)
192 			return (error);
193 		if (dolock) {
194 			error = uvm_vslock(p, SCARG(uap, old), oldlen,
195 			    VM_PROT_READ|VM_PROT_WRITE);
196 			if (error) {
197 				lockmgr(&sysctl_lock, LK_RELEASE, NULL, p);
198 				return (error);
199 			}
200 		}
201 		savelen = oldlen;
202 	}
203 	error = (*fn)(&name[1], SCARG(uap, namelen) - 1, SCARG(uap, old),
204 	    &oldlen, SCARG(uap, new), SCARG(uap, newlen), p);
205 	if (SCARG(uap, old) != NULL) {
206 		if (dolock)
207 			uvm_vsunlock(p, SCARG(uap, old), savelen);
208 		lockmgr(&sysctl_lock, LK_RELEASE, NULL, p);
209 	}
210 	if (error)
211 		return (error);
212 	if (SCARG(uap, oldlenp))
213 		error = copyout(&oldlen, SCARG(uap, oldlenp), sizeof(oldlen));
214 	return (error);
215 }
216 
217 /*
218  * Attributes stored in the kernel.
219  */
220 char hostname[MAXHOSTNAMELEN];
221 int hostnamelen;
222 char domainname[MAXHOSTNAMELEN];
223 int domainnamelen;
224 long hostid;
225 char *disknames = NULL;
226 struct diskstats *diskstats = NULL;
227 #ifdef INSECURE
228 int securelevel = -1;
229 #else
230 int securelevel;
231 #endif
232 
233 /*
234  * kernel related system variables.
235  */
236 int
237 kern_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p)
238 	int *name;
239 	u_int namelen;
240 	void *oldp;
241 	size_t *oldlenp;
242 	void *newp;
243 	size_t newlen;
244 	struct proc *p;
245 {
246 	int error, level, inthostid, oldsgap;
247 	extern int somaxconn, sominconn;
248 	extern int usermount, nosuidcoredump;
249 	extern long cp_time[CPUSTATES];
250 	extern int stackgap_random;
251 #ifdef CRYPTO
252 	extern int usercrypto;
253 	extern int userasymcrypto;
254 	extern int cryptodevallowsoft;
255 #endif
256 
257 	/* all sysctl names at this level are terminal except a ton of them */
258 	if (namelen != 1) {
259 		switch (name[0]) {
260 		case KERN_PROC:
261 		case KERN_PROF:
262 		case KERN_MALLOCSTATS:
263 		case KERN_TTY:
264 		case KERN_POOL:
265 		case KERN_PROC_ARGS:
266 		case KERN_SYSVIPC_INFO:
267 		case KERN_SEMINFO:
268 		case KERN_SHMINFO:
269 		case KERN_INTRCNT:
270 		case KERN_WATCHDOG:
271 			break;
272 		default:
273 			return (ENOTDIR);	/* overloaded */
274 		}
275 	}
276 
277 	switch (name[0]) {
278 	case KERN_OSTYPE:
279 		return (sysctl_rdstring(oldp, oldlenp, newp, ostype));
280 	case KERN_OSRELEASE:
281 		return (sysctl_rdstring(oldp, oldlenp, newp, osrelease));
282 	case KERN_OSREV:
283 		return (sysctl_rdint(oldp, oldlenp, newp, OpenBSD));
284 	case KERN_OSVERSION:
285 		return (sysctl_rdstring(oldp, oldlenp, newp, osversion));
286 	case KERN_VERSION:
287 		return (sysctl_rdstring(oldp, oldlenp, newp, version));
288 	case KERN_MAXVNODES:
289 		return(sysctl_int(oldp, oldlenp, newp, newlen, &desiredvnodes));
290 	case KERN_MAXPROC:
291 		return (sysctl_int(oldp, oldlenp, newp, newlen, &maxproc));
292 	case KERN_MAXFILES:
293 		return (sysctl_int(oldp, oldlenp, newp, newlen, &maxfiles));
294 	case KERN_NFILES:
295 		return (sysctl_rdint(oldp, oldlenp, newp, nfiles));
296 	case KERN_TTYCOUNT:
297 		return (sysctl_rdint(oldp, oldlenp, newp, tty_count));
298 	case KERN_NUMVNODES:
299 		return (sysctl_rdint(oldp, oldlenp, newp, numvnodes));
300 	case KERN_ARGMAX:
301 		return (sysctl_rdint(oldp, oldlenp, newp, ARG_MAX));
302 	case KERN_NSELCOLL:
303 		return (sysctl_rdint(oldp, oldlenp, newp, nselcoll));
304 	case KERN_SECURELVL:
305 		level = securelevel;
306 		if ((error = sysctl_int(oldp, oldlenp, newp, newlen, &level)) ||
307 		    newp == NULL)
308 			return (error);
309 		if ((securelevel > 0 || level < -1)
310 		    && level < securelevel && p->p_pid != 1)
311 			return (EPERM);
312 		securelevel = level;
313 		return (0);
314 	case KERN_HOSTNAME:
315 		error = sysctl_tstring(oldp, oldlenp, newp, newlen,
316 		    hostname, sizeof(hostname));
317 		if (newp && !error)
318 			hostnamelen = newlen;
319 		return (error);
320 	case KERN_DOMAINNAME:
321 		error = sysctl_tstring(oldp, oldlenp, newp, newlen,
322 		    domainname, sizeof(domainname));
323 		if (newp && !error)
324 			domainnamelen = newlen;
325 		return (error);
326 	case KERN_HOSTID:
327 		inthostid = hostid;  /* XXX assumes sizeof long <= sizeof int */
328 		error =  sysctl_int(oldp, oldlenp, newp, newlen, &inthostid);
329 		hostid = inthostid;
330 		return (error);
331 	case KERN_CLOCKRATE:
332 		return (sysctl_clockrate(oldp, oldlenp));
333 	case KERN_BOOTTIME:
334 		return (sysctl_rdstruct(oldp, oldlenp, newp, &boottime,
335 		    sizeof(struct timeval)));
336 	case KERN_VNODE:
337 		return (sysctl_vnode(oldp, oldlenp, p));
338 	case KERN_PROC:
339 		return (sysctl_doproc(name + 1, namelen - 1, oldp, oldlenp));
340 	case KERN_PROC_ARGS:
341 		return (sysctl_proc_args(name + 1, namelen - 1, oldp, oldlenp,
342 		     p));
343 	case KERN_FILE:
344 		return (sysctl_file(oldp, oldlenp));
345 	case KERN_MBSTAT:
346 		return (sysctl_rdstruct(oldp, oldlenp, newp, &mbstat,
347 		    sizeof(mbstat)));
348 #ifdef GPROF
349 	case KERN_PROF:
350 		return (sysctl_doprof(name + 1, namelen - 1, oldp, oldlenp,
351 		    newp, newlen));
352 #endif
353 	case KERN_POSIX1:
354 		return (sysctl_rdint(oldp, oldlenp, newp, _POSIX_VERSION));
355 	case KERN_NGROUPS:
356 		return (sysctl_rdint(oldp, oldlenp, newp, NGROUPS_MAX));
357 	case KERN_JOB_CONTROL:
358 		return (sysctl_rdint(oldp, oldlenp, newp, 1));
359 	case KERN_SAVED_IDS:
360 #ifdef _POSIX_SAVED_IDS
361 		return (sysctl_rdint(oldp, oldlenp, newp, 1));
362 #else
363 		return (sysctl_rdint(oldp, oldlenp, newp, 0));
364 #endif
365 	case KERN_MAXPARTITIONS:
366 		return (sysctl_rdint(oldp, oldlenp, newp, MAXPARTITIONS));
367 	case KERN_RAWPARTITION:
368 		return (sysctl_rdint(oldp, oldlenp, newp, RAW_PART));
369 	case KERN_SOMAXCONN:
370 		return (sysctl_int(oldp, oldlenp, newp, newlen, &somaxconn));
371 	case KERN_SOMINCONN:
372 		return (sysctl_int(oldp, oldlenp, newp, newlen, &sominconn));
373 	case KERN_USERMOUNT:
374 		return (sysctl_int(oldp, oldlenp, newp, newlen, &usermount));
375 	case KERN_RND:
376 		return (sysctl_rdstruct(oldp, oldlenp, newp, &rndstats,
377 		    sizeof(rndstats)));
378 	case KERN_ARND:
379 		return (sysctl_rdint(oldp, oldlenp, newp, arc4random()));
380 	case KERN_NOSUIDCOREDUMP:
381 		return (sysctl_int(oldp, oldlenp, newp, newlen, &nosuidcoredump));
382 	case KERN_FSYNC:
383 		return (sysctl_rdint(oldp, oldlenp, newp, 1));
384 	case KERN_SYSVMSG:
385 #ifdef SYSVMSG
386 		return (sysctl_rdint(oldp, oldlenp, newp, 1));
387 #else
388 		return (sysctl_rdint(oldp, oldlenp, newp, 0));
389 #endif
390 	case KERN_SYSVSEM:
391 #ifdef SYSVSEM
392 		return (sysctl_rdint(oldp, oldlenp, newp, 1));
393 #else
394 		return (sysctl_rdint(oldp, oldlenp, newp, 0));
395 #endif
396 	case KERN_SYSVSHM:
397 #ifdef SYSVSHM
398 		return (sysctl_rdint(oldp, oldlenp, newp, 1));
399 #else
400 		return (sysctl_rdint(oldp, oldlenp, newp, 0));
401 #endif
402 	case KERN_MSGBUFSIZE:
403 		/*
404 		 * deal with cases where the message buffer has
405 		 * become corrupted.
406 		 */
407 		if (!msgbufp || msgbufp->msg_magic != MSG_MAGIC)
408 			return (ENXIO);
409 		return (sysctl_rdint(oldp, oldlenp, newp, msgbufp->msg_bufs));
410 	case KERN_MSGBUF:
411 		/* see note above */
412 		if (!msgbufp || msgbufp->msg_magic != MSG_MAGIC)
413 			return (ENXIO);
414 		return (sysctl_rdstruct(oldp, oldlenp, newp, msgbufp,
415 		    msgbufp->msg_bufs + offsetof(struct msgbuf, msg_bufc)));
416 	case KERN_MALLOCSTATS:
417 		return (sysctl_malloc(name + 1, namelen - 1, oldp, oldlenp,
418 		    newp, newlen, p));
419 	case KERN_CPTIME:
420 		return (sysctl_rdstruct(oldp, oldlenp, newp, &cp_time,
421 		    sizeof(cp_time)));
422 	case KERN_NCHSTATS:
423 		return (sysctl_rdstruct(oldp, oldlenp, newp, &nchstats,
424 		    sizeof(struct nchstats)));
425 	case KERN_FORKSTAT:
426 		return (sysctl_rdstruct(oldp, oldlenp, newp, &forkstat,
427 		    sizeof(struct forkstat)));
428 	case KERN_TTY:
429 		return (sysctl_tty(name + 1, namelen - 1, oldp, oldlenp,
430 		    newp, newlen));
431 	case KERN_FSCALE:
432 		return (sysctl_rdint(oldp, oldlenp, newp, fscale));
433 	case KERN_CCPU:
434 		return (sysctl_rdint(oldp, oldlenp, newp, ccpu));
435 	case KERN_NPROCS:
436 		return (sysctl_rdint(oldp, oldlenp, newp, nprocs));
437 	case KERN_POOL:
438 		return (sysctl_dopool(name + 1, namelen - 1, oldp, oldlenp));
439 	case KERN_STACKGAPRANDOM:
440 		oldsgap = stackgap_random;
441 
442 		error = sysctl_int(oldp, oldlenp, newp, newlen, &stackgap_random);
443 		/*
444 		 * Safety harness.
445 		 */
446 		if ((stackgap_random < ALIGNBYTES && stackgap_random != 0) ||
447 		    !powerof2(stackgap_random) ||
448 		    stackgap_random > PAGE_SIZE * 2) {
449 			stackgap_random = oldsgap;
450 			return (EINVAL);
451 		}
452 		return (error);
453 #if defined(SYSVMSG) || defined(SYSVSEM) || defined(SYSVSHM)
454 	case KERN_SYSVIPC_INFO:
455 		return (sysctl_sysvipc(name + 1, namelen - 1, oldp, oldlenp));
456 #endif
457 #ifdef CRYPTO
458 	case KERN_USERCRYPTO:
459 		return (sysctl_int(oldp, oldlenp, newp, newlen, &usercrypto));
460 	case KERN_USERASYMCRYPTO:
461 		return (sysctl_int(oldp, oldlenp, newp, newlen,
462 			    &userasymcrypto));
463 	case KERN_CRYPTODEVALLOWSOFT:
464 		return (sysctl_int(oldp, oldlenp, newp, newlen,
465 			    &cryptodevallowsoft));
466 #endif
467 	case KERN_SPLASSERT:
468 		return (sysctl_int(oldp, oldlenp, newp, newlen,
469 		    &splassert_ctl));
470 #ifdef SYSVSEM
471 	case KERN_SEMINFO:
472 		return (sysctl_sysvsem(name + 1, namelen - 1, oldp, oldlenp,
473 		    newp, newlen));
474 #endif
475 #ifdef SYSVSHM
476 	case KERN_SHMINFO:
477 		return (sysctl_sysvshm(name + 1, namelen - 1, oldp, oldlenp,
478 		    newp, newlen));
479 #endif
480 	case KERN_INTRCNT:
481 		return (sysctl_intrcnt(name + 1, namelen - 1, oldp, oldlenp));
482 	case KERN_WATCHDOG:
483 		return (sysctl_wdog(name + 1, namelen - 1, oldp, oldlenp,
484 		    newp, newlen));
485 	default:
486 		return (EOPNOTSUPP);
487 	}
488 	/* NOTREACHED */
489 }
490 
491 /*
492  * hardware related system variables.
493  */
494 int
495 hw_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p)
496 	int *name;
497 	u_int namelen;
498 	void *oldp;
499 	size_t *oldlenp;
500 	void *newp;
501 	size_t newlen;
502 	struct proc *p;
503 {
504 	extern char machine[], cpu_model[];
505 	int err;
506 
507 	/* all sysctl names at this level except sensors are terminal */
508 	if (name[0] != HW_SENSORS && namelen != 1)
509 		return (ENOTDIR);		/* overloaded */
510 
511 	switch (name[0]) {
512 	case HW_MACHINE:
513 		return (sysctl_rdstring(oldp, oldlenp, newp, machine));
514 	case HW_MODEL:
515 		return (sysctl_rdstring(oldp, oldlenp, newp, cpu_model));
516 	case HW_NCPU:
517 		return (sysctl_rdint(oldp, oldlenp, newp, 1));	/* XXX */
518 	case HW_BYTEORDER:
519 		return (sysctl_rdint(oldp, oldlenp, newp, BYTE_ORDER));
520 	case HW_PHYSMEM:
521 		return (sysctl_rdint(oldp, oldlenp, newp, ctob(physmem)));
522 	case HW_USERMEM:
523 		return (sysctl_rdint(oldp, oldlenp, newp,
524 		    ctob(physmem - uvmexp.wired)));
525 	case HW_PAGESIZE:
526 		return (sysctl_rdint(oldp, oldlenp, newp, PAGE_SIZE));
527 	case HW_DISKNAMES:
528 		err = sysctl_diskinit(0, p);
529 		if (err)
530 			return err;
531 		if (disknames)
532 			return (sysctl_rdstring(oldp, oldlenp, newp,
533 			    disknames));
534 		else
535 			return (sysctl_rdstring(oldp, oldlenp, newp, ""));
536 	case HW_DISKSTATS:
537 		err = sysctl_diskinit(1, p);
538 		if (err)
539 			return err;
540 		return (sysctl_rdstruct(oldp, oldlenp, newp, diskstats,
541 		    disk_count * sizeof(struct diskstats)));
542 	case HW_DISKCOUNT:
543 		return (sysctl_rdint(oldp, oldlenp, newp, disk_count));
544 	case HW_SENSORS:
545 		return (sysctl_sensors(name + 1, namelen - 1, oldp, oldlenp,
546 		    newp, newlen));
547 	default:
548 		return (EOPNOTSUPP);
549 	}
550 	/* NOTREACHED */
551 }
552 
553 #ifdef DEBUG
554 /*
555  * Debugging related system variables.
556  */
557 extern struct ctldebug debug0, debug1;
558 struct ctldebug debug2, debug3, debug4;
559 struct ctldebug debug5, debug6, debug7, debug8, debug9;
560 struct ctldebug debug10, debug11, debug12, debug13, debug14;
561 struct ctldebug debug15, debug16, debug17, debug18, debug19;
562 static struct ctldebug *debugvars[CTL_DEBUG_MAXID] = {
563 	&debug0, &debug1, &debug2, &debug3, &debug4,
564 	&debug5, &debug6, &debug7, &debug8, &debug9,
565 	&debug10, &debug11, &debug12, &debug13, &debug14,
566 	&debug15, &debug16, &debug17, &debug18, &debug19,
567 };
568 int
569 debug_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p)
570 	int *name;
571 	u_int namelen;
572 	void *oldp;
573 	size_t *oldlenp;
574 	void *newp;
575 	size_t newlen;
576 	struct proc *p;
577 {
578 	struct ctldebug *cdp;
579 
580 	/* all sysctl names at this level are name and field */
581 	if (namelen != 2)
582 		return (ENOTDIR);		/* overloaded */
583 	cdp = debugvars[name[0]];
584 	if (cdp->debugname == 0)
585 		return (EOPNOTSUPP);
586 	switch (name[1]) {
587 	case CTL_DEBUG_NAME:
588 		return (sysctl_rdstring(oldp, oldlenp, newp, cdp->debugname));
589 	case CTL_DEBUG_VALUE:
590 		return (sysctl_int(oldp, oldlenp, newp, newlen, cdp->debugvar));
591 	default:
592 		return (EOPNOTSUPP);
593 	}
594 	/* NOTREACHED */
595 }
596 #endif /* DEBUG */
597 
598 /*
599  * Validate parameters and get old / set new parameters
600  * for an integer-valued sysctl function.
601  */
602 int
603 sysctl_int(oldp, oldlenp, newp, newlen, valp)
604 	void *oldp;
605 	size_t *oldlenp;
606 	void *newp;
607 	size_t newlen;
608 	int *valp;
609 {
610 	int error = 0;
611 
612 	if (oldp && *oldlenp < sizeof(int))
613 		return (ENOMEM);
614 	if (newp && newlen != sizeof(int))
615 		return (EINVAL);
616 	*oldlenp = sizeof(int);
617 	if (oldp)
618 		error = copyout(valp, oldp, sizeof(int));
619 	if (error == 0 && newp)
620 		error = copyin(newp, valp, sizeof(int));
621 	return (error);
622 }
623 
624 /*
625  * As above, but read-only.
626  */
627 int
628 sysctl_rdint(oldp, oldlenp, newp, val)
629 	void *oldp;
630 	size_t *oldlenp;
631 	void *newp;
632 	int val;
633 {
634 	int error = 0;
635 
636 	if (oldp && *oldlenp < sizeof(int))
637 		return (ENOMEM);
638 	if (newp)
639 		return (EPERM);
640 	*oldlenp = sizeof(int);
641 	if (oldp)
642 		error = copyout((caddr_t)&val, oldp, sizeof(int));
643 	return (error);
644 }
645 
646 /*
647  * Validate parameters and get old / set new parameters
648  * for an integer-valued sysctl function.
649  */
650 int
651 sysctl_quad(oldp, oldlenp, newp, newlen, valp)
652 	void *oldp;
653 	size_t *oldlenp;
654 	void *newp;
655 	size_t newlen;
656 	int64_t *valp;
657 {
658 	int error = 0;
659 
660 	if (oldp && *oldlenp < sizeof(int64_t))
661 		return (ENOMEM);
662 	if (newp && newlen != sizeof(int64_t))
663 		return (EINVAL);
664 	*oldlenp = sizeof(int64_t);
665 	if (oldp)
666 		error = copyout(valp, oldp, sizeof(int64_t));
667 	if (error == 0 && newp)
668 		error = copyin(newp, valp, sizeof(int64_t));
669 	return (error);
670 }
671 
672 /*
673  * As above, but read-only.
674  */
675 int
676 sysctl_rdquad(oldp, oldlenp, newp, val)
677 	void *oldp;
678 	size_t *oldlenp;
679 	void *newp;
680 	int64_t val;
681 {
682 	int error = 0;
683 
684 	if (oldp && *oldlenp < sizeof(int64_t))
685 		return (ENOMEM);
686 	if (newp)
687 		return (EPERM);
688 	*oldlenp = sizeof(int64_t);
689 	if (oldp)
690 		error = copyout((caddr_t)&val, oldp, sizeof(int64_t));
691 	return (error);
692 }
693 
694 /*
695  * Validate parameters and get old / set new parameters
696  * for a string-valued sysctl function.
697  */
698 int
699 sysctl_string(oldp, oldlenp, newp, newlen, str, maxlen)
700 	void *oldp;
701 	size_t *oldlenp;
702 	void *newp;
703 	size_t newlen;
704 	char *str;
705 	int maxlen;
706 {
707 	return sysctl__string(oldp, oldlenp, newp, newlen, str, maxlen, 0);
708 }
709 
710 int
711 sysctl_tstring(oldp, oldlenp, newp, newlen, str, maxlen)
712 	void *oldp;
713 	size_t *oldlenp;
714 	void *newp;
715 	size_t newlen;
716 	char *str;
717 	int maxlen;
718 {
719 	return sysctl__string(oldp, oldlenp, newp, newlen, str, maxlen, 1);
720 }
721 
722 int
723 sysctl__string(oldp, oldlenp, newp, newlen, str, maxlen, trunc)
724 	void *oldp;
725 	size_t *oldlenp;
726 	void *newp;
727 	size_t newlen;
728 	char *str;
729 	int maxlen;
730 	int trunc;
731 {
732 	int len, error = 0;
733 	char c;
734 
735 	len = strlen(str) + 1;
736 	if (oldp && *oldlenp < len) {
737 		if (trunc == 0 || *oldlenp == 0)
738 			return (ENOMEM);
739 	}
740 	if (newp && newlen >= maxlen)
741 		return (EINVAL);
742 	if (oldp) {
743 		if (trunc && *oldlenp < len) {
744 			/* save & zap NUL terminator while copying */
745 			c = str[*oldlenp-1];
746 			str[*oldlenp-1] = '\0';
747 			error = copyout(str, oldp, *oldlenp);
748 			str[*oldlenp-1] = c;
749 		} else {
750 			*oldlenp = len;
751 			error = copyout(str, oldp, len);
752 		}
753 	}
754 	if (error == 0 && newp) {
755 		error = copyin(newp, str, newlen);
756 		str[newlen] = 0;
757 	}
758 	return (error);
759 }
760 
761 /*
762  * As above, but read-only.
763  */
764 int
765 sysctl_rdstring(oldp, oldlenp, newp, str)
766 	void *oldp;
767 	size_t *oldlenp;
768 	void *newp;
769 	const char *str;
770 {
771 	int len, error = 0;
772 
773 	len = strlen(str) + 1;
774 	if (oldp && *oldlenp < len)
775 		return (ENOMEM);
776 	if (newp)
777 		return (EPERM);
778 	*oldlenp = len;
779 	if (oldp)
780 		error = copyout(str, oldp, len);
781 	return (error);
782 }
783 
784 /*
785  * Validate parameters and get old / set new parameters
786  * for a structure oriented sysctl function.
787  */
788 int
789 sysctl_struct(oldp, oldlenp, newp, newlen, sp, len)
790 	void *oldp;
791 	size_t *oldlenp;
792 	void *newp;
793 	size_t newlen;
794 	void *sp;
795 	int len;
796 {
797 	int error = 0;
798 
799 	if (oldp && *oldlenp < len)
800 		return (ENOMEM);
801 	if (newp && newlen > len)
802 		return (EINVAL);
803 	if (oldp) {
804 		*oldlenp = len;
805 		error = copyout(sp, oldp, len);
806 	}
807 	if (error == 0 && newp)
808 		error = copyin(newp, sp, len);
809 	return (error);
810 }
811 
812 /*
813  * Validate parameters and get old parameters
814  * for a structure oriented sysctl function.
815  */
816 int
817 sysctl_rdstruct(oldp, oldlenp, newp, sp, len)
818 	void *oldp;
819 	size_t *oldlenp;
820 	void *newp;
821 	const void *sp;
822 	int len;
823 {
824 	int error = 0;
825 
826 	if (oldp && *oldlenp < len)
827 		return (ENOMEM);
828 	if (newp)
829 		return (EPERM);
830 	*oldlenp = len;
831 	if (oldp)
832 		error = copyout(sp, oldp, len);
833 	return (error);
834 }
835 
836 /*
837  * Get file structures.
838  */
839 int
840 sysctl_file(where, sizep)
841 	char *where;
842 	size_t *sizep;
843 {
844 	int buflen, error;
845 	struct file *fp;
846 	char *start = where;
847 
848 	buflen = *sizep;
849 	if (where == NULL) {
850 		/*
851 		 * overestimate by 10 files
852 		 */
853 		*sizep = sizeof(filehead) + (nfiles + 10) * sizeof(struct file);
854 		return (0);
855 	}
856 
857 	/*
858 	 * first copyout filehead
859 	 */
860 	if (buflen < sizeof(filehead)) {
861 		*sizep = 0;
862 		return (0);
863 	}
864 	error = copyout((caddr_t)&filehead, where, sizeof(filehead));
865 	if (error)
866 		return (error);
867 	buflen -= sizeof(filehead);
868 	where += sizeof(filehead);
869 
870 	/*
871 	 * followed by an array of file structures
872 	 */
873 	LIST_FOREACH(fp, &filehead, f_list) {
874 		if (buflen < sizeof(struct file)) {
875 			*sizep = where - start;
876 			return (ENOMEM);
877 		}
878 		error = copyout((caddr_t)fp, where, sizeof (struct file));
879 		if (error)
880 			return (error);
881 		buflen -= sizeof(struct file);
882 		where += sizeof(struct file);
883 	}
884 	*sizep = where - start;
885 	return (0);
886 }
887 
888 /*
889  * try over estimating by 5 procs
890  */
891 #define KERN_PROCSLOP	(5 * sizeof (struct kinfo_proc))
892 
893 int
894 sysctl_doproc(name, namelen, where, sizep)
895 	int *name;
896 	u_int namelen;
897 	char *where;
898 	size_t *sizep;
899 {
900 	register struct proc *p;
901 	register struct kinfo_proc *dp = (struct kinfo_proc *)where;
902 	register int needed = 0;
903 	int buflen = where != NULL ? *sizep : 0;
904 	int doingzomb;
905 	struct eproc eproc;
906 	int error = 0;
907 
908 	if (namelen != 2 && !(namelen == 1 &&
909 	    (name[0] == KERN_PROC_ALL || name[0] == KERN_PROC_KTHREAD)))
910 		return (EINVAL);
911 	p = LIST_FIRST(&allproc);
912 	doingzomb = 0;
913 again:
914 	for (; p != 0; p = LIST_NEXT(p, p_list)) {
915 		/*
916 		 * Skip embryonic processes.
917 		 */
918 		if (p->p_stat == SIDL)
919 			continue;
920 		/*
921 		 * TODO - make more efficient (see notes below).
922 		 * do by session.
923 		 */
924 		switch (name[0]) {
925 
926 		case KERN_PROC_PID:
927 			/* could do this with just a lookup */
928 			if (p->p_pid != (pid_t)name[1])
929 				continue;
930 			break;
931 
932 		case KERN_PROC_PGRP:
933 			/* could do this by traversing pgrp */
934 			if (p->p_pgrp->pg_id != (pid_t)name[1])
935 				continue;
936 			break;
937 
938 		case KERN_PROC_TTY:
939 			if ((p->p_flag & P_CONTROLT) == 0 ||
940 			    p->p_session->s_ttyp == NULL ||
941 			    p->p_session->s_ttyp->t_dev != (dev_t)name[1])
942 				continue;
943 			break;
944 
945 		case KERN_PROC_UID:
946 			if (p->p_ucred->cr_uid != (uid_t)name[1])
947 				continue;
948 			break;
949 
950 		case KERN_PROC_RUID:
951 			if (p->p_cred->p_ruid != (uid_t)name[1])
952 				continue;
953 			break;
954 
955 		case KERN_PROC_ALL:
956 			if (p->p_flag & P_SYSTEM)
957 				continue;
958 			break;
959 		}
960 		if (buflen >= sizeof(struct kinfo_proc)) {
961 			fill_eproc(p, &eproc);
962 			error = copyout((caddr_t)p, &dp->kp_proc,
963 					sizeof(struct proc));
964 			if (error)
965 				return (error);
966 			error = copyout((caddr_t)&eproc, &dp->kp_eproc,
967 					sizeof(eproc));
968 			if (error)
969 				return (error);
970 			dp++;
971 			buflen -= sizeof(struct kinfo_proc);
972 		}
973 		needed += sizeof(struct kinfo_proc);
974 	}
975 	if (doingzomb == 0) {
976 		p = LIST_FIRST(&zombproc);
977 		doingzomb++;
978 		goto again;
979 	}
980 	if (where != NULL) {
981 		*sizep = (caddr_t)dp - where;
982 		if (needed > *sizep)
983 			return (ENOMEM);
984 	} else {
985 		needed += KERN_PROCSLOP;
986 		*sizep = needed;
987 	}
988 	return (0);
989 }
990 
991 /*
992  * Fill in an eproc structure for the specified process.
993  */
994 void
995 fill_eproc(struct proc *p, struct eproc *ep)
996 {
997 	struct tty *tp;
998 
999 	ep->e_paddr = p;
1000 	ep->e_sess = p->p_pgrp->pg_session;
1001 	ep->e_pcred = *p->p_cred;
1002 	ep->e_ucred = *p->p_ucred;
1003 	if (p->p_stat == SIDL || P_ZOMBIE(p)) {
1004 		ep->e_vm.vm_rssize = 0;
1005 		ep->e_vm.vm_tsize = 0;
1006 		ep->e_vm.vm_dsize = 0;
1007 		ep->e_vm.vm_ssize = 0;
1008 		bzero(&ep->e_pstats, sizeof(ep->e_pstats));
1009 		ep->e_pstats_valid = 0;
1010 	} else {
1011 		struct vmspace *vm = p->p_vmspace;
1012 
1013 		PHOLD(p);	/* need for pstats */
1014 		ep->e_vm.vm_rssize = vm_resident_count(vm);
1015 		ep->e_vm.vm_tsize = vm->vm_tsize;
1016 		ep->e_vm.vm_dsize = vm->vm_dsize;
1017 		ep->e_vm.vm_ssize = vm->vm_ssize;
1018 		ep->e_pstats = *p->p_stats;
1019 		ep->e_pstats_valid = 1;
1020 		PRELE(p);
1021 	}
1022 	if (p->p_pptr)
1023 		ep->e_ppid = p->p_pptr->p_pid;
1024 	else
1025 		ep->e_ppid = 0;
1026 	ep->e_pgid = p->p_pgrp->pg_id;
1027 	ep->e_jobc = p->p_pgrp->pg_jobc;
1028 	if ((p->p_flag & P_CONTROLT) &&
1029 	     (tp = ep->e_sess->s_ttyp)) {
1030 		ep->e_tdev = tp->t_dev;
1031 		ep->e_tpgid = tp->t_pgrp ? tp->t_pgrp->pg_id : NO_PID;
1032 		ep->e_tsess = tp->t_session;
1033 	} else
1034 		ep->e_tdev = NODEV;
1035 	ep->e_flag = ep->e_sess->s_ttyvp ? EPROC_CTTY : 0;
1036 	if (SESS_LEADER(p))
1037 		ep->e_flag |= EPROC_SLEADER;
1038 	strncpy(ep->e_wmesg, p->p_wmesg ? p->p_wmesg : "", WMESGLEN);
1039 	ep->e_wmesg[WMESGLEN] = '\0';
1040 	ep->e_xsize = ep->e_xrssize = 0;
1041 	ep->e_xccount = ep->e_xswrss = 0;
1042 	strncpy(ep->e_login, ep->e_sess->s_login, MAXLOGNAME-1);
1043 	ep->e_login[MAXLOGNAME-1] = '\0';
1044 	strncpy(ep->e_emul, p->p_emul->e_name, EMULNAMELEN);
1045 	ep->e_emul[EMULNAMELEN] = '\0';
1046 	ep->e_maxrss = p->p_rlimit ? p->p_rlimit[RLIMIT_RSS].rlim_cur : 0;
1047 }
1048 
1049 int
1050 sysctl_proc_args(int *name, u_int namelen, void *oldp, size_t *oldlenp,
1051     struct proc *cp)
1052 {
1053 	struct proc *vp;
1054 	pid_t pid;
1055 	int op;
1056 	struct ps_strings pss;
1057 	struct iovec iov;
1058 	struct uio uio;
1059 	int error;
1060 	size_t limit;
1061 	int cnt;
1062 	char **rargv, **vargv;		/* reader vs. victim */
1063 	char *rarg, *varg;
1064 	char *buf;
1065 
1066 	if (namelen > 2)
1067 		return (ENOTDIR);
1068 	if (namelen < 2)
1069 		return (EINVAL);
1070 
1071 	pid = name[0];
1072 	op = name[1];
1073 
1074 	switch (op) {
1075 	case KERN_PROC_ARGV:
1076 	case KERN_PROC_NARGV:
1077 	case KERN_PROC_ENV:
1078 	case KERN_PROC_NENV:
1079 		break;
1080 	default:
1081 		return (EOPNOTSUPP);
1082 	}
1083 
1084 	if ((vp = pfind(pid)) == NULL)
1085 		return (ESRCH);
1086 
1087 	if (P_ZOMBIE(vp) || (vp->p_flag & P_SYSTEM))
1088 		return (EINVAL);
1089 
1090 	/* Exiting - don't bother, it will be gone soon anyway */
1091 	if ((vp->p_flag & P_WEXIT))
1092 		return (ESRCH);
1093 
1094 	/* Execing - danger. */
1095 	if ((vp->p_flag & P_INEXEC))
1096 		return (EBUSY);
1097 
1098 	vp->p_vmspace->vm_refcnt++;	/* XXX */
1099 	buf = malloc(PAGE_SIZE, M_TEMP, M_WAITOK);
1100 
1101 	iov.iov_base = &pss;
1102 	iov.iov_len = sizeof(pss);
1103 	uio.uio_iov = &iov;
1104 	uio.uio_iovcnt = 1;
1105 	uio.uio_offset = (off_t)PS_STRINGS;
1106 	uio.uio_resid = sizeof(pss);
1107 	uio.uio_segflg = UIO_SYSSPACE;
1108 	uio.uio_rw = UIO_READ;
1109 	uio.uio_procp = cp;
1110 
1111 	if ((error = uvm_io(&vp->p_vmspace->vm_map, &uio)) != 0)
1112 		goto out;
1113 
1114 	if (op == KERN_PROC_NARGV) {
1115 		error = sysctl_rdint(oldp, oldlenp, NULL, pss.ps_nargvstr);
1116 		goto out;
1117 	}
1118 	if (op == KERN_PROC_NENV) {
1119 		error = sysctl_rdint(oldp, oldlenp, NULL, pss.ps_nenvstr);
1120 		goto out;
1121 	}
1122 
1123 	if (op == KERN_PROC_ARGV) {
1124 		cnt = pss.ps_nargvstr;
1125 		vargv = pss.ps_argvstr;
1126 	} else {
1127 		cnt = pss.ps_nenvstr;
1128 		vargv = pss.ps_envstr;
1129 	}
1130 
1131 	/* -1 to have space for a terminating NUL */
1132 	limit = *oldlenp - 1;
1133 	*oldlenp = 0;
1134 
1135 	if (limit > 8 * PAGE_SIZE) {
1136 		/* Don't allow a denial of service. */
1137 		error = E2BIG;
1138 		goto out;
1139 	}
1140 
1141 	rargv = oldp;
1142 
1143 	/*
1144 	 * *oldlenp - number of bytes copied out into readers buffer.
1145 	 * limit - maximal number of bytes allowed into readers buffer.
1146 	 * rarg - pointer into readers buffer where next arg will be stored.
1147 	 * rargv - pointer into readers buffer where the next rarg pointer
1148 	 *  will be stored.
1149 	 * vargv - pointer into victim address space where the next argument
1150 	 *  will be read.
1151 	 */
1152 
1153 	/* space for cnt pointers and a NULL */
1154 	rarg = (char *)(rargv + cnt + 1);
1155 	*oldlenp += (cnt + 1) * sizeof(char **);
1156 
1157 	while (cnt > 0 && *oldlenp < limit) {
1158 		size_t len, vstrlen;
1159 
1160 		/* Write to readers argv */
1161 		if ((error = copyout(&rarg, rargv, sizeof(rarg))) != 0)
1162 			goto out;
1163 
1164 		/* read the victim argv */
1165 		iov.iov_base = &varg;
1166 		iov.iov_len = sizeof(varg);
1167 		uio.uio_iov = &iov;
1168 		uio.uio_iovcnt = 1;
1169 		uio.uio_offset = (off_t)(vaddr_t)vargv;
1170 		uio.uio_resid = sizeof(varg);
1171 		uio.uio_segflg = UIO_SYSSPACE;
1172 		uio.uio_rw = UIO_READ;
1173 		uio.uio_procp = cp;
1174 		if ((error = uvm_io(&vp->p_vmspace->vm_map, &uio)) != 0)
1175 			goto out;
1176 
1177 		if (varg == NULL)
1178 			break;
1179 
1180 		/*
1181 		 * read the victim arg. We must jump through hoops to avoid
1182 		 * crossing a page boundary too much and returning an error.
1183 		 */
1184 more:
1185 		len = PAGE_SIZE - (((vaddr_t)varg) & PAGE_MASK);
1186 		/* leave space for the terminating NUL */
1187 		iov.iov_base = buf;
1188 		iov.iov_len = len;
1189 		uio.uio_iov = &iov;
1190 		uio.uio_iovcnt = 1;
1191 		uio.uio_offset = (off_t)(vaddr_t)varg;
1192 		uio.uio_resid = len;
1193 		uio.uio_segflg = UIO_SYSSPACE;
1194 		uio.uio_rw = UIO_READ;
1195 		uio.uio_procp = cp;
1196 		if ((error = uvm_io(&vp->p_vmspace->vm_map, &uio)) != 0)
1197 			goto out;
1198 
1199 		for (vstrlen = 0; vstrlen < len; vstrlen++) {
1200 			if (buf[vstrlen] == '\0')
1201 				break;
1202 		}
1203 
1204 		/* Don't overflow readers buffer. */
1205 		if (*oldlenp + vstrlen + 1 >= limit) {
1206 			error = ENOMEM;
1207 			goto out;
1208 		}
1209 
1210 		if ((error = copyout(buf, rarg, vstrlen)) != 0)
1211 			goto out;
1212 
1213 		*oldlenp += vstrlen;
1214 		rarg += vstrlen;
1215 
1216 		/* The string didn't end in this page? */
1217 		if (vstrlen == len) {
1218 			varg += vstrlen;
1219 			goto more;
1220 		}
1221 
1222 		/* End of string. Terminate it with a NUL */
1223 		buf[0] = '\0';
1224 		if ((error = copyout(buf, rarg, 1)) != 0)
1225 			goto out;
1226 		*oldlenp += 1;;
1227 		rarg += 1;
1228 
1229 		vargv++;
1230 		rargv++;
1231 		cnt--;
1232 	}
1233 
1234 	if (*oldlenp >= limit) {
1235 		error = ENOMEM;
1236 		goto out;
1237 	}
1238 
1239 	/* Write the terminating null */
1240 	rarg = NULL;
1241 	error = copyout(&rarg, rargv, sizeof(rarg));
1242 
1243 out:
1244 	uvmspace_free(vp->p_vmspace);
1245 	free(buf, M_TEMP);
1246 	return (error);
1247 }
1248 
1249 /*
1250  * Initialize disknames/diskstats for export by sysctl. If update is set,
1251  * then we simply update the disk statistics information.
1252  */
1253 int
1254 sysctl_diskinit(update, p)
1255 	int update;
1256 	struct proc *p;
1257 {
1258 	struct diskstats *sdk;
1259 	struct disk *dk;
1260 	int i, tlen, l;
1261 
1262 	if ((i = lockmgr(&sysctl_disklock, LK_EXCLUSIVE, NULL, p)) != 0)
1263 		return i;
1264 
1265 	if (disk_change) {
1266 		for (dk = TAILQ_FIRST(&disklist), tlen = 0; dk;
1267 		    dk = TAILQ_NEXT(dk, dk_link))
1268 			tlen += strlen(dk->dk_name) + 1;
1269 		tlen++;
1270 
1271 		if (disknames)
1272 			free(disknames, M_SYSCTL);
1273 		if (diskstats)
1274 			free(diskstats, M_SYSCTL);
1275 		diskstats = NULL;
1276 		disknames = NULL;
1277 		diskstats = malloc(disk_count * sizeof(struct diskstats),
1278 		    M_SYSCTL, M_WAITOK);
1279 		disknames = malloc(tlen, M_SYSCTL, M_WAITOK);
1280 		disknames[0] = '\0';
1281 
1282 		for (dk = TAILQ_FIRST(&disklist), i = 0, l = 0; dk;
1283 		    dk = TAILQ_NEXT(dk, dk_link), i++) {
1284 			snprintf(disknames + l, tlen - l, "%s,",
1285 			    dk->dk_name ? dk->dk_name : "");
1286 			l += strlen(disknames + l);
1287 			sdk = diskstats + i;
1288 			sdk->ds_busy = dk->dk_busy;
1289 			sdk->ds_xfer = dk->dk_xfer;
1290 			sdk->ds_seek = dk->dk_seek;
1291 			sdk->ds_bytes = dk->dk_bytes;
1292 			sdk->ds_attachtime = dk->dk_attachtime;
1293 			sdk->ds_timestamp = dk->dk_timestamp;
1294 			sdk->ds_time = dk->dk_time;
1295 		}
1296 
1297 		/* Eliminate trailing comma */
1298 		if (l != 0)
1299 			disknames[l - 1] = '\0';
1300 		disk_change = 0;
1301 	} else if (update) {
1302 		/* Just update, number of drives hasn't changed */
1303 		for (dk = TAILQ_FIRST(&disklist), i = 0; dk;
1304 		    dk = TAILQ_NEXT(dk, dk_link), i++) {
1305 			sdk = diskstats + i;
1306 			sdk->ds_busy = dk->dk_busy;
1307 			sdk->ds_xfer = dk->dk_xfer;
1308 			sdk->ds_seek = dk->dk_seek;
1309 			sdk->ds_bytes = dk->dk_bytes;
1310 			sdk->ds_attachtime = dk->dk_attachtime;
1311 			sdk->ds_timestamp = dk->dk_timestamp;
1312 			sdk->ds_time = dk->dk_time;
1313 		}
1314 	}
1315 	lockmgr(&sysctl_disklock, LK_RELEASE, NULL, p);
1316 	return 0;
1317 }
1318 
1319 #if defined(SYSVMSG) || defined(SYSVSEM) || defined(SYSVSHM)
1320 int
1321 sysctl_sysvipc(name, namelen, where, sizep)
1322 	int *name;
1323 	u_int namelen;
1324 	void *where;
1325 	size_t *sizep;
1326 {
1327 #ifdef SYSVMSG
1328 	struct msg_sysctl_info *msgsi;
1329 #endif
1330 #ifdef SYSVSEM
1331 	struct sem_sysctl_info *semsi;
1332 #endif
1333 #ifdef SYSVSHM
1334 	struct shm_sysctl_info *shmsi;
1335 #endif
1336 	size_t infosize, dssize, tsize, buflen;
1337 	int i, nds, error, ret;
1338 	void *buf;
1339 
1340 	if (namelen != 1)
1341 		return (EINVAL);
1342 
1343 	buflen = *sizep;
1344 
1345 	switch (*name) {
1346 	case KERN_SYSVIPC_MSG_INFO:
1347 #ifdef SYSVMSG
1348 		infosize = sizeof(msgsi->msginfo);
1349 		nds = msginfo.msgmni;
1350 		dssize = sizeof(msgsi->msgids[0]);
1351 		break;
1352 #else
1353 		return (EOPNOTSUPP);
1354 #endif
1355 	case KERN_SYSVIPC_SEM_INFO:
1356 #ifdef SYSVSEM
1357 		infosize = sizeof(semsi->seminfo);
1358 		nds = seminfo.semmni;
1359 		dssize = sizeof(semsi->semids[0]);
1360 		break;
1361 #else
1362 		return (EOPNOTSUPP);
1363 #endif
1364 	case KERN_SYSVIPC_SHM_INFO:
1365 #ifdef SYSVSHM
1366 		infosize = sizeof(shmsi->shminfo);
1367 		nds = shminfo.shmmni;
1368 		dssize = sizeof(shmsi->shmids[0]);
1369 		break;
1370 #else
1371 		return (EOPNOTSUPP);
1372 #endif
1373 	default:
1374 		return (EINVAL);
1375 	}
1376 	tsize = infosize + (nds * dssize);
1377 
1378 	/* Return just the total size required. */
1379 	if (where == NULL) {
1380 		*sizep = tsize;
1381 		return (0);
1382 	}
1383 
1384 	/* Not enough room for even the info struct. */
1385 	if (buflen < infosize) {
1386 		*sizep = 0;
1387 		return (ENOMEM);
1388 	}
1389 	buf = malloc(min(tsize, buflen), M_TEMP, M_WAITOK);
1390 	bzero(buf, min(tsize, buflen));
1391 
1392 	switch (*name) {
1393 #ifdef SYSVMSG
1394 	case KERN_SYSVIPC_MSG_INFO:
1395 		msgsi = (struct msg_sysctl_info *)buf;
1396 		msgsi->msginfo = msginfo;
1397 		break;
1398 #endif
1399 #ifdef SYSVSEM
1400 	case KERN_SYSVIPC_SEM_INFO:
1401 		semsi = (struct sem_sysctl_info *)buf;
1402 		semsi->seminfo = seminfo;
1403 		break;
1404 #endif
1405 #ifdef SYSVSHM
1406 	case KERN_SYSVIPC_SHM_INFO:
1407 		shmsi = (struct shm_sysctl_info *)buf;
1408 		shmsi->shminfo = shminfo;
1409 		break;
1410 #endif
1411 	}
1412 	buflen -= infosize;
1413 
1414 	ret = 0;
1415 	if (buflen > 0) {
1416 		/* Fill in the IPC data structures.  */
1417 		for (i = 0; i < nds; i++) {
1418 			if (buflen < dssize) {
1419 				ret = ENOMEM;
1420 				break;
1421 			}
1422 			switch (*name) {
1423 #ifdef SYSVMSG
1424 			case KERN_SYSVIPC_MSG_INFO:
1425 				bcopy(&msqids[i], &msgsi->msgids[i], dssize);
1426 				break;
1427 #endif
1428 #ifdef SYSVSEM
1429 			case KERN_SYSVIPC_SEM_INFO:
1430 				if (sema[i] != NULL)
1431 					bcopy(sema[i], &semsi->semids[i],
1432 					    dssize);
1433 				else
1434 					bzero(&semsi->semids[i], dssize);
1435 				break;
1436 #endif
1437 #ifdef SYSVSHM
1438 			case KERN_SYSVIPC_SHM_INFO:
1439 				if (shmsegs[i] != NULL)
1440 					bcopy(shmsegs[i], &shmsi->shmids[i],
1441 					    dssize);
1442 				else
1443 					bzero(&shmsi->shmids[i], dssize);
1444 				break;
1445 #endif
1446 			}
1447 			buflen -= dssize;
1448 		}
1449 	}
1450 	*sizep -= buflen;
1451 	error = copyout(buf, where, *sizep);
1452 	free(buf, M_TEMP);
1453 	/* If copyout succeeded, use return code set earlier. */
1454 	return (error ? error : ret);
1455 }
1456 #endif /* SYSVMSG || SYSVSEM || SYSVSHM */
1457 
1458 int
1459 sysctl_intrcnt(int *name, u_int namelen, void *oldp, size_t *oldlenp)
1460 {
1461 	extern int intrcnt[], eintrcnt[];
1462 	extern char intrnames[], eintrnames[];
1463 	char *intrname;
1464 	int nintr, i;
1465 
1466 	nintr = (off_t)(eintrcnt - intrcnt);
1467 
1468 	if (name[0] != KERN_INTRCNT_NUM) {
1469 		if (namelen != 2)
1470 			return (ENOTDIR);
1471 		if (name[1] < 0 || name[1] >= nintr)
1472 			return (EINVAL);
1473 		i = name[1];
1474 	}
1475 
1476 	switch (name[0]) {
1477 	case KERN_INTRCNT_NUM:
1478 		return (sysctl_rdint(oldp, oldlenp, NULL, nintr));
1479 		break;
1480 	case KERN_INTRCNT_CNT:
1481 		return (sysctl_rdint(oldp, oldlenp, NULL, intrcnt[i]));
1482 	case KERN_INTRCNT_NAME:
1483 		intrname = intrnames;
1484 		while (i > 0) {
1485 			intrname += strlen(intrname) + 1;
1486 			i--;
1487 			if (intrname > eintrnames)
1488 				return (EINVAL);
1489 		}
1490 		return (sysctl_rdstring(oldp, oldlenp, NULL, intrname));
1491 	default:
1492 		return (EOPNOTSUPP);
1493 	}
1494 }
1495 
1496 int nsensors = 0;
1497 struct sensors_head sensors = SLIST_HEAD_INITIALIZER(&sensors);
1498 
1499 int
1500 sysctl_sensors(int *name, u_int namelen, void *oldp, size_t *oldlenp,
1501     void *newp, size_t newlen)
1502 {
1503 	struct sensor *s = NULL;
1504 	int num;
1505 
1506 	if (namelen != 1)
1507 		return (ENOTDIR);
1508 
1509 	num = name[0];
1510 	if (num >= nsensors)
1511 		return (ENXIO);
1512 
1513 	SLIST_FOREACH(s, &sensors, list)
1514 		if (s->num == num)
1515 			break;
1516 
1517 	return (sysctl_rdstruct(oldp, oldlenp, newp, s, sizeof(struct sensor)));
1518 }
1519