1 /**	$MirOS: src/sbin/sysctl/sysctl.c,v 1.6 2011/10/28 20:35:47 tg Exp $ */
2 /*	$OpenBSD: sysctl.c,v 1.123 2005/07/20 16:56:12 miod Exp $	*/
3 /*	$NetBSD: sysctl.c,v 1.9 1995/09/30 07:12:50 thorpej Exp $	*/
4 
5 /*
6  * Copyright (c) 2011
7  *	Thorsten Glaser <tg@mirbsd.org>
8  * Copyright (c) 1993
9  *	The Regents of the University of California.  All rights reserved.
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 
36 #include <sys/param.h>
37 #include <sys/mount.h>
38 #include <sys/stat.h>
39 #include <sys/sem.h>
40 #include <sys/shm.h>
41 #include <sys/sysctl.h>
42 #include <sys/socket.h>
43 #include <sys/malloc.h>
44 #include <sys/dkstat.h>
45 #include <sys/uio.h>
46 #include <sys/tty.h>
47 #include <sys/namei.h>
48 #include <sys/sensors.h>
49 #include <machine/cpu.h>
50 #include <net/route.h>
51 #include <net/if.h>
52 
53 #include <netinet/in.h>
54 #include <netinet/in_systm.h>
55 #include <netinet/ip.h>
56 #include <netinet/in_pcb.h>
57 #include <netinet/ip_icmp.h>
58 #include <netinet/ip_ipip.h>
59 #include <netinet/ip_ether.h>
60 #include <netinet/ip_ah.h>
61 #include <netinet/ip_esp.h>
62 #include <netinet/icmp_var.h>
63 #include <netinet/ip_var.h>
64 #include <netinet/udp.h>
65 #include <netinet/udp_var.h>
66 #include <netinet/tcp.h>
67 #include <netinet/tcp_timer.h>
68 #include <netinet/tcp_var.h>
69 #include <netinet/ip_gre.h>
70 #include <netinet/ip_ipcomp.h>
71 #include <netinet/ip_carp.h>
72 
73 #ifdef INET6
74 #include <netinet/ip6.h>
75 #include <netinet/icmp6.h>
76 #include <netinet6/ip6_var.h>
77 #include <netinet6/pim6_var.h>
78 #endif
79 
80 #include <sys/vmmeter.h>
81 #include <uvm/uvm_swap_encrypt.h>
82 
83 #include <ufs/ufs/quota.h>
84 #include <ufs/ufs/inode.h>
85 #include <ufs/ffs/fs.h>
86 #include <ufs/ffs/ffs_extern.h>
87 
88 #include <nfs/rpcv2.h>
89 #include <nfs/nfsproto.h>
90 #include <nfs/nfs.h>
91 
92 #include <netipx/ipx.h>
93 #include <netipx/ipx_var.h>
94 #include <netipx/spx_var.h>
95 #include <ddb/db_var.h>
96 #include <dev/rndvar.h>
97 
98 #include <err.h>
99 #include <errno.h>
100 #include <stdio.h>
101 #include <stdlib.h>
102 #include <string.h>
103 #include <ctype.h>
104 #include <unistd.h>
105 
106 #ifdef CPU_BIOS
107 #include <machine/biosvar.h>
108 #endif
109 
110 __COPYRIGHT("@(#) Copyright (c) 1993\n\
111 	The Regents of the University of California.  All rights reserved.\n");
112 __SCCSID("@(#)sysctl.c	8.5 (Berkeley) 5/9/95");
113 __RCSID("$MirOS: src/sbin/sysctl/sysctl.c,v 1.6 2011/10/28 20:35:47 tg Exp $");
114 
115 struct ctlname topname[] = CTL_NAMES;
116 struct ctlname kernname[] = CTL_KERN_NAMES;
117 struct ctlname vmname[] = CTL_VM_NAMES;
118 struct ctlname fsname[] = CTL_FS_NAMES;
119 struct ctlname netname[] = CTL_NET_NAMES;
120 struct ctlname hwname[] = CTL_HW_NAMES;
121 struct ctlname username[] = CTL_USER_NAMES;
122 struct ctlname debugname[CTL_DEBUG_MAXID];
123 struct ctlname kernmallocname[] = CTL_KERN_MALLOC_NAMES;
124 struct ctlname forkstatname[] = CTL_KERN_FORKSTAT_NAMES;
125 struct ctlname nchstatsname[] = CTL_KERN_NCHSTATS_NAMES;
126 struct ctlname ttysname[] = CTL_KERN_TTY_NAMES;
127 struct ctlname semname[] = CTL_KERN_SEMINFO_NAMES;
128 struct ctlname shmname[] = CTL_KERN_SHMINFO_NAMES;
129 struct ctlname watchdogname[] = CTL_KERN_WATCHDOG_NAMES;
130 #ifdef CTL_KERN_TIMECOUNTER_NAMES
131 struct ctlname tcname[] = CTL_KERN_TIMECOUNTER_NAMES;
132 #endif
133 struct ctlname *vfsname;
134 #ifdef CTL_MACHDEP_NAMES
135 struct ctlname machdepname[] = CTL_MACHDEP_NAMES;
136 #endif
137 struct ctlname ddbname[] = CTL_DDB_NAMES;
138 char names[BUFSIZ];
139 int lastused;
140 
141 struct list {
142 	struct	ctlname *list;
143 	int	size;
144 };
145 struct list toplist = { topname, CTL_MAXID };
146 struct list secondlevel[] = {
147 	{ 0, 0 },			/* CTL_UNSPEC */
148 	{ kernname, KERN_MAXID },	/* CTL_KERN */
149 	{ vmname, VM_MAXID },		/* CTL_VM */
150 	{ fsname, FS_MAXID },		/* CTL_FS */
151 	{ netname, NET_MAXID },		/* CTL_NET */
152 	{ 0, CTL_DEBUG_MAXID },		/* CTL_DEBUG */
153 	{ hwname, HW_MAXID },		/* CTL_HW */
154 #ifdef CTL_MACHDEP_NAMES
155 	{ machdepname, CPU_MAXID },	/* CTL_MACHDEP */
156 #else
157 	{ 0, 0 },			/* CTL_MACHDEP */
158 #endif
159 	{ username, USER_MAXID },	/* CTL_USER_NAMES */
160 	{ ddbname, DBCTL_MAXID },	/* CTL_DDB_NAMES */
161 	{ 0, 0 },			/* CTL_VFS */
162 };
163 
164 int	Aflag, aflag, nflag, qflag;
165 
166 /*
167  * Variables requiring special processing.
168  */
169 #define	CLOCK		0x00000001
170 #define	BOOTTIME	0x00000002
171 #define	CHRDEV		0x00000004
172 #define	BLKDEV		0x00000008
173 #define	RNDSTATS	0x00000010
174 #define	BADDYNAMIC	0x00000020
175 #define	BIOSGEO		0x00000040
176 #define	BIOSDEV		0x00000080
177 #define	MAJ2DEV		0x00000100
178 #define	UNSIGNED	0x00000200
179 #define	KMEMBUCKETS	0x00000400
180 #define	LONGARRAY	0x00000800
181 #define	KMEMSTATS	0x00001000
182 #define	SENSORS		0x00002000
183 #define	ZTSSCALE	0x00004000
184 
185 /* prototypes */
186 void debuginit(void);
187 void listall(char *, struct list *);
188 void parse(char *, int);
189 void parse_baddynamic(int *, size_t, char *, void **, size_t *, int, int);
190 void usage(void);
191 int findname(char *, char *, char **, struct list *);
192 int sysctl_inet(char *, char **, int *, int, int *);
193 #ifdef INET6
194 int sysctl_inet6(char *, char **, int *, int, int *);
195 #endif
196 int sysctl_bpf(char *, char **, int *, int, int *);
197 int sysctl_ipx(char *, char **, int *, int, int *);
198 int sysctl_fs(char *, char **, int *, int, int *);
199 static int sysctl_vfs(char *, char **, int[], int, int *);
200 static int sysctl_vfsgen(char *, char **, int[], int, int *);
201 int sysctl_bios(char *, char **, int *, int, int *);
202 int sysctl_swpenc(char *, char **, int *, int, int *);
203 int sysctl_forkstat(char *, char **, int *, int, int *);
204 int sysctl_tty(char *, char **, int *, int, int *);
205 int sysctl_nchstats(char *, char **, int *, int, int *);
206 int sysctl_malloc(char *, char **, int *, int, int *);
207 int sysctl_seminfo(char *, char **, int *, int, int *);
208 int sysctl_shminfo(char *, char **, int *, int, int *);
209 int sysctl_watchdog(char *, char **, int *, int, int *);
210 int sysctl_tc(char *, char **, int *, int, int *);
211 int sysctl_sensors(char *, char **, int *, int, int *);
212 int sysctl_emul(char *, char *, int);
213 #ifdef CPU_CHIPSET
214 int sysctl_chipset(char *, char **, int *, int, int *);
215 #endif
216 void vfsinit(void);
217 
218 char *equ = "=";
219 
220 int
main(int argc,char * argv[])221 main(int argc, char *argv[])
222 {
223 	int ch, lvl1;
224 
225 	while ((ch = getopt(argc, argv, "Aanqw")) != -1) {
226 		switch (ch) {
227 
228 		case 'A':
229 			Aflag = 1;
230 			break;
231 
232 		case 'a':
233 			aflag = 1;
234 			break;
235 
236 		case 'n':
237 			nflag = 1;
238 			break;
239 
240 		case 'q':
241 			qflag = 1;
242 			break;
243 
244 		case 'w':
245 			/* flag no longer needed; var=value implies write */
246 			break;
247 
248 		default:
249 			usage();
250 		}
251 	}
252 	argc -= optind;
253 	argv += optind;
254 
255 	if (argc == 0 && (Aflag || aflag)) {
256 		debuginit();
257 		vfsinit();
258 		for (lvl1 = 1; lvl1 < CTL_MAXID; lvl1++)
259 			listall(topname[lvl1].ctl_name, &secondlevel[lvl1]);
260 		return (0);
261 	}
262 	if (argc == 0)
263 		usage();
264 	for (; *argv != NULL; ++argv)
265 		parse(*argv, 1);
266 	return (0);
267 }
268 
269 /*
270  * List all variables known to the system.
271  */
272 void
listall(char * prefix,struct list * lp)273 listall(char *prefix, struct list *lp)
274 {
275 	char *cp, name[BUFSIZ];
276 	int lvl2, len;
277 
278 	if (lp->list == NULL)
279 		return;
280 	if ((len = strlcpy(name, prefix, sizeof(name))) >= sizeof(name))
281 		errx(1, "%s: name too long", prefix);
282 	cp = name + len++;
283 	*cp++ = '.';
284 	for (lvl2 = 0; lvl2 < lp->size; lvl2++) {
285 		if (lp->list[lvl2].ctl_name == NULL)
286 			continue;
287 		if (strlcpy(cp, lp->list[lvl2].ctl_name,
288 		    sizeof(name) - len) >= sizeof(name) - len)
289 			warn("%s: name too long", lp->list[lvl2].ctl_name);
290 		parse(name, Aflag);
291 	}
292 }
293 
294 /*
295  * Parse a name into a MIB entry.
296  * Lookup and print out the MIB entry if it exists.
297  * Set a new value if requested.
298  */
299 void
parse(char * string,int flags)300 parse(char *string, int flags)
301 {
302 	int indx, type, state, intval, len;
303 	size_t size, newsize = 0;
304 	int lal = 0, special = 0;
305 	void *newval = 0;
306 	int64_t quadval;
307 	struct list *lp;
308 	int mib[CTL_MAXNAME];
309 	char *cp, *bufp, buf[BUFSIZ];
310 #ifdef CPU_ZTSSCALE
311 	struct ztsscale {
312 		int ts_minx;
313 		int ts_maxx;
314 		int ts_miny;
315 		int ts_maxy;
316 	} tsbuf;
317 #endif
318 
319 	(void)strlcpy(buf, string, sizeof(buf));
320 	bufp = buf;
321 	if ((cp = strchr(string, '=')) != NULL) {
322 		*strchr(buf, '=') = '\0';
323 		*cp++ = '\0';
324 		while (isspace(*cp))
325 			cp++;
326 		newval = cp;
327 		newsize = strlen(cp);
328 	}
329 	if ((indx = findname(string, "top", &bufp, &toplist)) == -1)
330 		return;
331 	mib[0] = indx;
332 	if (indx == CTL_VFS)
333 		vfsinit();
334 	if (indx == CTL_DEBUG)
335 		debuginit();
336 	lp = &secondlevel[indx];
337 	if (lp->list == 0) {
338 		warnx("%s: class is not implemented", topname[indx].ctl_name);
339 		return;
340 	}
341 	if (bufp == NULL) {
342 		listall(topname[indx].ctl_name, lp);
343 		return;
344 	}
345 	if ((indx = findname(string, "second", &bufp, lp)) == -1)
346 		return;
347 	mib[1] = indx;
348 	type = lp->list[indx].ctl_type;
349 	len = 2;
350 	switch (mib[0]) {
351 
352 	case CTL_KERN:
353 		switch (mib[1]) {
354 		case KERN_FORKSTAT:
355 			sysctl_forkstat(string, &bufp, mib, flags, &type);
356 			return;
357 		case KERN_TTY:
358 			len = sysctl_tty(string, &bufp, mib, flags, &type);
359 			if (len < 0)
360 				return;
361 			break;
362 		case KERN_NCHSTATS:
363 			sysctl_nchstats(string, &bufp, mib, flags, &type);
364 			return;
365 		case KERN_MALLOCSTATS:
366 			len = sysctl_malloc(string, &bufp, mib, flags, &type);
367 			if (len < 0)
368 				return;
369 			if (mib[2] == KERN_MALLOC_BUCKET)
370 				special |= KMEMBUCKETS;
371 			if (mib[2] == KERN_MALLOC_KMEMSTATS)
372 				special |= KMEMSTATS;
373 			newsize = 0;
374 			break;
375 		case KERN_MBSTAT:
376 			if (flags == 0)
377 				return;
378 			warnx("use netstat to view %s", string);
379 			return;
380 		case KERN_MSGBUF:
381 			if (flags == 0)
382 				return;
383 			warnx("use dmesg to view %s", string);
384 			return;
385 		case KERN_VNODE:
386 		case KERN_FILE:
387 			if (flags == 0)
388 				return;
389 			warnx("use pstat to view %s information", string);
390 			return;
391 		case KERN_PROC:
392 		case KERN_PROC2:
393 			if (flags == 0)
394 				return;
395 			warnx("use ps to view %s information", string);
396 			return;
397 		case KERN_CLOCKRATE:
398 			special |= CLOCK;
399 			break;
400 		case KERN_BOOTTIME:
401 			special |= BOOTTIME;
402 			break;
403 		case KERN_RND:
404 			special |= RNDSTATS;
405 			break;
406 		case KERN_HOSTID:
407 		case KERN_ARND:
408 			special |= UNSIGNED;
409 			break;
410 		case KERN_CPTIME:
411 			special |= LONGARRAY;
412 			lal = CPUSTATES;
413 			break;
414 		case KERN_SEMINFO:
415 			len = sysctl_seminfo(string, &bufp, mib, flags, &type);
416 			if (len < 0)
417 				return;
418 			break;
419 		case KERN_SHMINFO:
420 			len = sysctl_shminfo(string, &bufp, mib, flags, &type);
421 			if (len < 0)
422 				return;
423 			break;
424 		case KERN_WATCHDOG:
425 			len = sysctl_watchdog(string, &bufp, mib, flags,
426 			    &type);
427 			if (len < 0)
428 				return;
429 			break;
430 #ifdef KERN_TIMECOUNTER
431 		case KERN_TIMECOUNTER:
432 			len = sysctl_tc(string, &bufp, mib, flags,
433 			    &type);
434 			if (len < 0)
435 				return;
436 			break;
437 #endif
438 		case KERN_EMUL:
439 			sysctl_emul(string, newval, flags);
440 			return;
441 		}
442 		break;
443 
444 	case CTL_HW:
445 		switch (mib[1]) {
446 		case HW_DISKSTATS:
447 			/*
448 			 * Only complain if someone asks explicitly for this,
449 			 * otherwise "fail" silently.
450 			 */
451 			if (flags)
452 				warnx("use vmstat to view %s information",
453 				    string);
454 			return;
455 		case HW_SENSORS:
456 			special |= SENSORS;
457 			len = sysctl_sensors(string, &bufp, mib, flags, &type);
458 			if (len < 0)
459 				return;
460 			break;
461 		}
462 		break;
463 
464 	case CTL_VM:
465 		if (mib[1] == VM_LOADAVG) {
466 			double loads[3];
467 
468 			getloadavg(loads, 3);
469 			if (!nflag)
470 				(void)printf("%s%s", string, equ);
471 			(void)printf("%.2f %.2f %.2f\n", loads[0],
472 			    loads[1], loads[2]);
473 			return;
474 		} else if (mib[1] == VM_PSSTRINGS) {
475 			struct _ps_strings _ps;
476 
477 			size = sizeof(_ps);
478 			if (sysctl(mib, 2, &_ps, &size, NULL, 0) == -1) {
479 				if (flags == 0)
480 					return;
481 				if (!nflag)
482 					(void)printf("%s: ", string);
483 				(void)puts("can't find ps strings");
484 				return;
485 			}
486 			if (!nflag)
487 				(void)printf("%s%s", string, equ);
488 			(void)printf("%p\n", _ps.val);
489 			return;
490 		} else if (mib[1] == VM_SWAPENCRYPT) {
491 			len = sysctl_swpenc(string, &bufp, mib, flags, &type);
492 			if (len < 0)
493 				return;
494 
495 			break;
496 		} else if (mib[1] == VM_NKMEMPAGES ||
497 		    mib[1] == VM_ANONMIN ||
498 		    mib[1] == VM_VTEXTMIN ||
499 		    mib[1] == VM_VNODEMIN) {
500 			break;
501 		} else if (mib[1] == VM_METER) {
502 			struct vmtotal vmm;
503 			unsigned pgszK;
504 
505 			pgszK = getpagesize() / 1024;
506 			if (pgszK * 1024 != getpagesize()) {
507 				(void)puts("pagesize not KiB");
508 				return;
509 			}
510 #define pgtok(v) ((unsigned)(v) * pgszK)
511 			size = sizeof(vmm);
512 			if (sysctl(mib, 2, &vmm, &size, NULL, 0) == -1) {
513 				if (flags == 0)
514 					return;
515 				if (!nflag)
516 					(void)printf("%s: ", string);
517 				(void)puts("can't find vm meter");
518 				return;
519 			}
520 			if (!nflag)
521 				(void)printf("%s%s", string, equ);
522 			(void)printf("{ proc: runq=%u dskwait=%u pgwait=%u "
523 			    "sleep=%u swp=%u | KiB: free=%u act/tot vm=%u/%u "
524 			    "rm=%u/%u shm vm=%u/%u rm=%u/%u }\n",
525 			    (unsigned)vmm.t_rq, (unsigned)vmm.t_dw,
526 			    (unsigned)vmm.t_pw, (unsigned)vmm.t_sl,
527 			    (unsigned)vmm.t_sw, pgtok(vmm.t_free),
528 			    pgtok(vmm.t_avm), pgtok(vmm.t_vm),
529 			    pgtok(vmm.t_arm), pgtok(vmm.t_rm),
530 			    pgtok(vmm.t_avmshr), pgtok(vmm.t_vmshr),
531 			    pgtok(vmm.t_armshr), pgtok(vmm.t_rmshr));
532 #undef pgtok
533 			return;
534 		}
535 		if (flags == 0)
536 			return;
537 		warnx("use vmstat or systat to view %s information", string);
538 		return;
539 
540 		break;
541 
542 	case CTL_NET:
543 		if (mib[1] == PF_INET) {
544 			len = sysctl_inet(string, &bufp, mib, flags, &type);
545 			if (len < 0)
546 				return;
547 
548 			if ((mib[2] == IPPROTO_TCP &&
549 			    mib[3] == TCPCTL_BADDYNAMIC) ||
550 			    (mib[2] == IPPROTO_UDP &&
551 			    mib[3] == UDPCTL_BADDYNAMIC)) {
552 
553 				special |= BADDYNAMIC;
554 
555 				if (newval != NULL)
556 					parse_baddynamic(mib, len, string,
557 					    &newval, &newsize, flags, nflag);
558 			}
559 			break;
560 		}
561 #ifdef INET6
562 		if (mib[1] == PF_INET6) {
563 			len = sysctl_inet6(string, &bufp, mib, flags, &type);
564 			if (len < 0)
565 				return;
566 
567 			break;
568 		}
569 #endif
570 		if (mib[1] == PF_IPX) {
571 			len = sysctl_ipx(string, &bufp, mib, flags, &type);
572 			if (len >= 0)
573 				break;
574 			return;
575 		}
576 		if (mib[1] == PF_BPF) {
577 			len = sysctl_bpf(string, &bufp, mib, flags, &type);
578 			if (len < 0)
579 				return;
580 			break;
581 		}
582 		if (flags == 0)
583 			return;
584 		warnx("use netstat to view %s information", string);
585 		return;
586 
587 	case CTL_DEBUG:
588 		mib[2] = CTL_DEBUG_VALUE;
589 		len = 3;
590 		break;
591 
592 	case CTL_MACHDEP:
593 #ifdef CPU_CONSDEV
594 		if (mib[1] == CPU_CONSDEV)
595 			special |= CHRDEV;
596 #endif
597 #ifdef CPU_BLK2CHR
598 		if (mib[1] == CPU_BLK2CHR) {
599 			if (bufp == NULL)
600 				return;
601 			mib[2] = makedev(atoi(bufp),0);
602 			bufp = NULL;
603 			len = 3;
604 			special |= CHRDEV;
605 			break;
606 		}
607 #endif
608 #ifdef CPU_CHR2BLK
609 		if (mib[1] == CPU_CHR2BLK) {
610 			if (bufp == NULL)
611 				return;
612 			mib[2] = makedev(atoi(bufp),0);
613 			bufp = NULL;
614 			len = 3;
615 			special |= BLKDEV;
616 			break;
617 		}
618 #endif
619 #ifdef CPU_BIOS
620 		if (mib[1] == CPU_BIOS) {
621 			len = sysctl_bios(string, &bufp, mib, flags, &type);
622 			if (len < 0)
623 				return;
624 			if (mib[2] == BIOS_DEV)
625 				special |= BIOSDEV;
626 			if (mib[2] == BIOS_DISKINFO)
627 				special |= BIOSGEO;
628 			break;
629 		}
630 #endif
631 #ifdef CPU_CHIPSET
632 		if (mib[1] == CPU_CHIPSET) {
633 			len = sysctl_chipset(string, &bufp, mib, flags, &type);
634 			if (len < 0)
635 				return;
636 			break;
637 		}
638 #endif
639 #ifdef CPU_ZTSSCALE
640 		if (mib[1] == CPU_ZTSSCALE) {
641 			special |= ZTSSCALE;
642 			if (newsize > 0) {
643 				const char *errstr = 0;
644 
645 				/* Unspecified values default to 0. */
646 				bzero(&tsbuf, sizeof tsbuf);
647 				newval = (void *)strtok(newval, ",");
648 				if (newval != NULL) {
649 					tsbuf.ts_minx = (int)strtonum(newval,
650 					    0, 32768, &errstr);
651 					newval = (void *)strtok(NULL, ",");
652 				}
653 				if (!errstr && newval != NULL) {
654 					tsbuf.ts_maxx = (int)strtonum(newval,
655 					    0, 32768, &errstr);
656 					newval = (void *)strtok(NULL, ",");
657 				}
658 				if (!errstr && newval != NULL) {
659 					tsbuf.ts_miny = (int)strtonum(newval,
660 					    0, 32768, &errstr);
661 					newval = (void *)strtok(NULL, ",");
662 				}
663 				if (!errstr && newval != NULL) {
664 					tsbuf.ts_maxy = (int)strtonum(newval,
665 					    0, 32768, &errstr);
666 					newval = (void *)strtok(NULL, ",");
667 				}
668 				if (errstr)
669 					errx(1, "calibration value is %s",
670 					    errstr);
671 				if (newval != NULL)
672 					errx(1, "too many calibration values");
673 				newval = &tsbuf;
674 				newsize = sizeof(tsbuf);
675 			}
676 			break;
677 		}
678 #endif
679 		break;
680 
681 	case CTL_FS:
682 		len = sysctl_fs(string, &bufp, mib, flags, &type);
683 		if (len >= 0)
684 			break;
685 		return;
686 
687 	case CTL_VFS:
688 		if (mib[1])
689 			len = sysctl_vfs(string, &bufp, mib, flags, &type);
690 		else
691 			len = sysctl_vfsgen(string, &bufp, mib, flags, &type);
692 		if (len >= 0) {
693 			if (type == CTLTYPE_STRUCT) {
694 				if (flags)
695 					warnx("use nfsstat to view %s information",
696 					    MOUNT_NFS);
697 				return;
698 			} else
699 				break;
700 		}
701 		return;
702 
703 	case CTL_USER:
704 	case CTL_DDB:
705 		break;
706 
707 	default:
708 		warnx("illegal top level value: %d", mib[0]);
709 		return;
710 
711 	}
712 	if (bufp) {
713 		warnx("name %s in %s is unknown", bufp, string);
714 		return;
715 	}
716 	if (newsize > 0) {
717 		switch (type) {
718 		case CTLTYPE_INT:
719 			errno = 0;
720 			if (special & UNSIGNED)
721 				intval = strtoul(newval, &cp, 10);
722 			else
723 				intval = strtol(newval, &cp, 10);
724 			if (*cp != '\0') {
725 				warnx("%s: illegal value: %s", string,
726 				    (char *)newval);
727 				return;
728 			}
729 			if (errno == ERANGE) {
730 				warnx("%s: value %s out of range", string,
731 				    (char *)newval);
732 				return;
733 			}
734 			newval = &intval;
735 			newsize = sizeof(intval);
736 			break;
737 
738 		case CTLTYPE_QUAD:
739 			/* XXX - assumes sizeof(long long) == sizeof(quad_t) */
740 			(void)sscanf(newval, "%lld", (long long *)&quadval);
741 			newval = &quadval;
742 			newsize = sizeof(quadval);
743 			break;
744 		}
745 	}
746 	size = BUFSIZ;
747 	if (sysctl(mib, len, buf, &size, newval, newsize) == -1) {
748 		if (flags == 0)
749 			return;
750 		switch (errno) {
751 		case EOPNOTSUPP:
752 			warnx("%s: value is not available", string);
753 			return;
754 		case ENOTDIR:
755 			warnx("%s: specification is incomplete", string);
756 			return;
757 		case ENOMEM:
758 			warnx("%s: type is unknown to this program", string);
759 			return;
760 		case ENXIO:
761 			if (special & BIOSGEO)
762 				return;
763 		default:
764 			warn("%s", string);
765 			return;
766 		}
767 	}
768 	if (special & KMEMBUCKETS) {
769 		struct kmembuckets *kb = (struct kmembuckets *)buf;
770 		if (!nflag)
771 			(void)printf("%s%s", string, equ);
772 		printf("(");
773 		printf("calls = %llu ", (long long)kb->kb_calls);
774 		printf("total_allocated = %llu ", (long long)kb->kb_total);
775 		printf("total_free = %lld ", (long long)kb->kb_totalfree);
776 		printf("elements = %lld ", (long long)kb->kb_elmpercl);
777 		printf("high watermark = %lld ", (long long)kb->kb_highwat);
778 		printf("could_free = %lld", (long long)kb->kb_couldfree);
779 		printf(")\n");
780 		return;
781 	}
782 	if (special & KMEMSTATS) {
783 		struct kmemstats *km = (struct kmemstats *)buf;
784 		int j, first = 1;
785 
786 		if (!nflag)
787 			(void)printf("%s%s", string, equ);
788 		(void)printf("(inuse = %ld, calls = %ld, memuse = %ldK, "
789 		    "limblocks = %d, mapblocks = %d, maxused = %ldK, "
790 		    "limit = %ldK, spare = %ld, sizes = (",
791 		    km->ks_inuse, km->ks_calls,
792 		    (km->ks_memuse + 1023) / 1024, km->ks_limblocks,
793 		    km->ks_mapblocks, (km->ks_maxused + 1023) / 1024,
794 		    (km->ks_limit + 1023) / 1024, km->ks_spare);
795 		for (j = 1 << MINBUCKET; j < 1 << (MINBUCKET + 16); j <<= 1) {
796 			if ((km->ks_size & j ) == 0)
797 				continue;
798 			if (first)
799 				(void)printf("%d", j);
800 			else
801 				(void)printf(",%d", j);
802 			first = 0;
803 		}
804 		if (first)
805 			(void)printf("none");
806 		(void)printf("))\n");
807 		return;
808 	}
809 	if (special & CLOCK) {
810 		struct clockinfo *clkp = (struct clockinfo *)buf;
811 
812 		if (!nflag)
813 			(void)printf("%s%s", string, equ);
814 		(void)printf(
815 		    "tick = %d, tickadj = %d, hz = %d, profhz = %d, stathz = %d\n",
816 		    clkp->tick, clkp->tickadj, clkp->hz, clkp->profhz, clkp->stathz);
817 		return;
818 	}
819 	if (special & BOOTTIME) {
820 		struct timeval *btp = (struct timeval *)buf;
821 		time_t boottime;
822 
823 		if (!nflag) {
824 			boottime = btp->tv_sec;
825 			(void)printf("%s%s%s", string, equ, ctime(&boottime));
826 		} else
827 			(void)printf("%lld\n", (int64_t)(btp->tv_sec));
828 		return;
829 	}
830 	if (special & BLKDEV) {
831 		dev_t dev = *(dev_t *)buf;
832 
833 		if (!nflag)
834 			(void)printf("%s%s%s\n", string, equ,
835 			    devname(dev, S_IFBLK));
836 		else
837 			(void)printf("0x%x\n", dev);
838 		return;
839 	}
840 	if (special & CHRDEV) {
841 		dev_t dev = *(dev_t *)buf;
842 
843 		if (!nflag)
844 			(void)printf("%s%s%s\n", string, equ,
845 			    devname(dev, S_IFCHR));
846 		else
847 			(void)printf("0x%x\n", dev);
848 		return;
849 	}
850 #ifdef CPU_BIOS
851 	if (special & BIOSGEO) {
852 		bios_diskinfo_t *pdi = (bios_diskinfo_t *)buf;
853 
854 		if (!nflag)
855 			(void)printf("%s%s", string, equ);
856 		(void)printf("bootdev = 0x%x, "
857 		    "cylinders = %u, heads = %u, sectors = %u\n",
858 		    pdi->bsd_dev, pdi->bios_cylinders,
859 		    pdi->bios_heads, pdi->bios_sectors);
860 		return;
861 	}
862 	if (special & BIOSDEV) {
863 		int dev = *(int*)buf;
864 
865 		if (!nflag)
866 			(void)printf("%s%s", string, equ);
867 		(void) printf("0x%02x\n", dev);
868 		return;
869 	}
870 #endif
871 	if (special & UNSIGNED) {
872 		if (newsize == 0) {
873 			if (!nflag)
874 				(void)printf("%s%s", string, equ);
875 			(void)printf("%u\n", *(u_int *)buf);
876 		} else {
877 			if (!qflag) {
878 				if (!nflag)
879 					(void)printf("%s: %u -> ", string,
880 					    *(u_int *)buf);
881 				(void)printf("%u\n", *(u_int *)newval);
882 			}
883 		}
884 		return;
885 	}
886 	if (special & RNDSTATS) {
887 		quad_t *rndstats = (quad_t *)buf;
888 		int i;
889 
890 		if (!nflag)
891 			(void)printf("%s%s", string, equ);
892 		for (i = 0; i < sizeof(struct rndstats) / sizeof(quad_t); ++i)
893 			printf(i ? " %llu" : "%llu", rndstats[i]);
894 		printf("\n");
895 		return;
896 	}
897 	if (special & BADDYNAMIC) {
898 		in_port_t port, lastport;
899 		u_int32_t *baddynamic = (u_int32_t *)buf;
900 
901 		if (!qflag) {
902 			if (!nflag)
903 				(void)printf("%s%s", string,
904 				    newsize ? ": " : equ);
905 			lastport = 0;
906 			for (port = IPPORT_RESERVED/2; port < IPPORT_RESERVED;
907 			    port++)
908 				if (DP_ISSET(baddynamic, port)) {
909 					(void)printf("%s%hd",
910 					    lastport ? "," : "", port);
911 					lastport = port;
912 				}
913 			if (newsize != 0) {
914 				if (!nflag)
915 					fputs(" -> ", stdout);
916 				baddynamic = (u_int32_t *)newval;
917 				lastport = 0;
918 				for (port = IPPORT_RESERVED/2;
919 				    port < IPPORT_RESERVED; port++)
920 					if (DP_ISSET(baddynamic, port)) {
921 						(void)printf("%s%hd",
922 						    lastport ? "," : "", port);
923 						lastport = port;
924 					}
925 			}
926 			(void)putchar('\n');
927 		}
928 		return;
929 	}
930 	if (special & LONGARRAY) {
931 		long *la = (long *)buf;
932 		if (!nflag)
933 			printf("%s%s", string, equ);
934 		while (lal--)
935 			printf("%ld%s", *la++, lal? ",":"");
936 		putchar('\n');
937 		return;
938 	}
939 	if (special & SENSORS) {
940 		struct sensor *s = (struct sensor *)buf;
941 
942 		if (size > 0 && (s->flags & SENSOR_FINVALID) == 0) {
943 			if (!nflag)
944 				printf("%s%s", string, equ);
945 			printf("%s, %s, ", s->device, s->desc);
946 			switch (s->type) {
947 			case SENSOR_TEMP:
948 				printf("temp, %.2f degC / %.2f degF",
949 				    (s->value - 273150000) / 1000000.0,
950 				    (s->value - 273150000) / 1000000.0 * 9 / 5 +
951 				    32);
952 				break;
953 			case SENSOR_FANRPM:
954 				printf("fanrpm, %lld RPM", s->value);
955 				break;
956 			case SENSOR_VOLTS_DC:
957 				printf("volts_dc, %.2f V",
958 				    s->value / 1000000.0);
959 				break;
960 			default:
961 				printf("unknown");
962 			}
963 			printf("\n");
964 		}
965 		return;
966 	}
967 #ifdef CPU_ZTSSCALE
968 	if (special & ZTSSCALE) {
969 		struct ztsscale *tsp;
970 
971 		if (newsize == 0) {
972 			if (!nflag)
973 				(void)printf("%s%s", string, equ);
974 			tsp = (struct ztsscale *)buf;
975 			(void)printf("%d,%d,%d,%d\n", tsp->ts_minx,
976 			    tsp->ts_maxx, tsp->ts_miny, tsp->ts_maxy);
977 		} else {
978 			if (!qflag) {
979 				if (!nflag) {
980 					tsp = (struct ztsscale *)buf;
981 					(void)printf("%s: %d,%d,%d,%d -> ",
982 					    string, tsp->ts_minx, tsp->ts_maxx,
983 					    tsp->ts_miny, tsp->ts_maxy);
984 				}
985 				tsp = (struct ztsscale *)newval;
986 				(void)printf("%d,%d,%d,%d\n", tsp->ts_minx,
987 				    tsp->ts_maxx, tsp->ts_miny, tsp->ts_maxy);
988 			}
989 		}
990 		return;
991 	}
992 #endif
993 	switch (type) {
994 	case CTLTYPE_INT:
995 		if (newsize == 0) {
996 			if (!nflag)
997 				(void)printf("%s%s", string, equ);
998 			(void)printf("%d\n", *(int *)buf);
999 		} else {
1000 			if (!qflag) {
1001 				if (!nflag)
1002 					(void)printf("%s: %d -> ", string,
1003 					    *(int *)buf);
1004 				(void)printf("%d\n", *(int *)newval);
1005 			}
1006 		}
1007 		return;
1008 
1009 	case CTLTYPE_STRING:
1010 		if (newval == NULL) {
1011 			if (!nflag)
1012 				(void)printf("%s%s", string, equ);
1013 			(void)puts(buf);
1014 		} else {
1015 			if (!qflag) {
1016 				if (!nflag)
1017 					(void)printf("%s: %s -> ", string, buf);
1018 				(void)puts((char *)newval);
1019 			}
1020 		}
1021 		return;
1022 
1023 	case CTLTYPE_QUAD:
1024 		if (newsize == 0) {
1025 			long long tmp = *(quad_t *)buf;
1026 
1027 			if (!nflag)
1028 				(void)printf("%s%s", string, equ);
1029 			(void)printf("%lld\n", tmp);
1030 		} else {
1031 			long long tmp = *(quad_t *)buf;
1032 
1033 			if (!qflag) {
1034 				if (!nflag)
1035 					(void)printf("%s: %lld -> ",
1036 					    string, tmp);
1037 				tmp = *(quad_t *)newval;
1038 				(void)printf("%qd\n", tmp);
1039 			}
1040 		}
1041 		return;
1042 
1043 	case CTLTYPE_STRUCT:
1044 		warnx("%s: unknown structure returned", string);
1045 		return;
1046 
1047 	default:
1048 	case CTLTYPE_NODE:
1049 		warnx("%s: unknown type returned", string);
1050 		return;
1051 	}
1052 }
1053 
1054 void
parse_baddynamic(int mib[],size_t len,char * string,void ** newvalp,size_t * newsizep,int flags,int nflag)1055 parse_baddynamic(int mib[], size_t len, char *string, void **newvalp,
1056     size_t *newsizep, int flags, int nflag)
1057 {
1058 	static u_int32_t newbaddynamic[DP_MAPSIZE];
1059 	in_port_t port;
1060 	size_t size;
1061 	char action, *cp;
1062 
1063 	if (strchr((char *)*newvalp, '+') || strchr((char *)*newvalp, '-')) {
1064 		size = sizeof(newbaddynamic);
1065 		if (sysctl(mib, len, newbaddynamic, &size, 0, 0) == -1) {
1066 			if (flags == 0)
1067 				return;
1068 			if (!nflag)
1069 				(void)printf("%s: ", string);
1070 			(void)puts("kernel does contain bad dynamic port tables");
1071 			return;
1072 		}
1073 
1074 		while (*newvalp && (cp = strsep((char **)newvalp, ", \t")) && *cp) {
1075 			if (*cp != '+' && *cp != '-')
1076 				errx(1, "cannot mix +/- with full list");
1077 			action = *cp++;
1078 			port = atoi(cp);
1079 			if (port < IPPORT_RESERVED/2 || port >= IPPORT_RESERVED)
1080 				errx(1, "invalid port, range is %d to %d",
1081 				    IPPORT_RESERVED/2, IPPORT_RESERVED-1);
1082 			if (action == '+')
1083 				DP_SET(newbaddynamic, port);
1084 			else
1085 				DP_CLR(newbaddynamic, port);
1086 		}
1087 	} else {
1088 		(void)memset((void *)newbaddynamic, 0, sizeof(newbaddynamic));
1089 		while (*newvalp && (cp = strsep((char **)newvalp, ", \t")) && *cp) {
1090 			port = atoi(cp);
1091 			if (port < IPPORT_RESERVED/2 || port >= IPPORT_RESERVED)
1092 				errx(1, "invalid port, range is %d to %d",
1093 				    IPPORT_RESERVED/2, IPPORT_RESERVED-1);
1094 			DP_SET(newbaddynamic, port);
1095 		}
1096 	}
1097 
1098 	*newvalp = (void *)newbaddynamic;
1099 	*newsizep = sizeof(newbaddynamic);
1100 }
1101 
1102 /*
1103  * Initialize the set of debugging names
1104  */
1105 void
debuginit(void)1106 debuginit(void)
1107 {
1108 	int mib[3], loc, i;
1109 	size_t size;
1110 
1111 	if (secondlevel[CTL_DEBUG].list != 0)
1112 		return;
1113 	secondlevel[CTL_DEBUG].list = debugname;
1114 	mib[0] = CTL_DEBUG;
1115 	mib[2] = CTL_DEBUG_NAME;
1116 	for (loc = lastused, i = 0; i < CTL_DEBUG_MAXID; i++) {
1117 		mib[1] = i;
1118 		size = BUFSIZ - loc;
1119 		if (sysctl(mib, 3, &names[loc], &size, NULL, 0) == -1)
1120 			continue;
1121 		debugname[i].ctl_name = &names[loc];
1122 		debugname[i].ctl_type = CTLTYPE_INT;
1123 		loc += size;
1124 	}
1125 	lastused = loc;
1126 }
1127 
1128 struct ctlname vfsgennames[] = CTL_VFSGENCTL_NAMES;
1129 struct ctlname ffsname[] = FFS_NAMES;
1130 struct ctlname nfsname[] = FS_NFS_NAMES;
1131 struct list *vfsvars;
1132 int *vfs_typenums;
1133 
1134 /*
1135  * Initialize the set of filesystem names
1136  */
1137 void
vfsinit(void)1138 vfsinit(void)
1139 {
1140 	int mib[4], maxtypenum, cnt, loc, size;
1141 	struct vfsconf vfc;
1142 	size_t buflen;
1143 
1144 	if (secondlevel[CTL_VFS].list != 0)
1145 		return;
1146 	mib[0] = CTL_VFS;
1147 	mib[1] = VFS_GENERIC;
1148 	mib[2] = VFS_MAXTYPENUM;
1149 	buflen = 4;
1150 	if (sysctl(mib, 3, &maxtypenum, &buflen, (void *)0, (size_t)0) < 0)
1151 		return;
1152 	maxtypenum++;	/* + generic */
1153 	if ((vfs_typenums = malloc(maxtypenum * sizeof(int))) == NULL)
1154 		return;
1155 	memset(vfs_typenums, 0, maxtypenum * sizeof(int));
1156 	if ((vfsvars = malloc(maxtypenum * sizeof(*vfsvars))) == NULL) {
1157 		free(vfs_typenums);
1158 		return;
1159 	}
1160 	memset(vfsvars, 0, maxtypenum * sizeof(*vfsvars));
1161 	if ((vfsname = malloc(maxtypenum * sizeof(*vfsname))) == NULL) {
1162 		free(vfs_typenums);
1163 		free(vfsvars);
1164 		return;
1165 	}
1166 	memset(vfsname, 0, maxtypenum * sizeof(*vfsname));
1167 	mib[2] = VFS_CONF;
1168 	buflen = sizeof vfc;
1169 	for (loc = lastused, cnt = 1; cnt < maxtypenum; cnt++) {
1170 		mib[3] = cnt - 1;
1171 		if (sysctl(mib, 4, &vfc, &buflen, (void *)0, (size_t)0) < 0) {
1172 			if (errno == EOPNOTSUPP)
1173 				continue;
1174 			warn("vfsinit");
1175 			free(vfsname);
1176 			return;
1177 		}
1178 		if (!strcmp(vfc.vfc_name, MOUNT_FFS)) {
1179 			vfsvars[cnt].list = ffsname;
1180 			vfsvars[cnt].size = FFS_MAXID;
1181 		}
1182 		if (!strcmp(vfc.vfc_name, MOUNT_NFS)) {
1183 			vfsvars[cnt].list = nfsname;
1184 			vfsvars[cnt].size = NFS_MAXID;
1185 		}
1186 		vfs_typenums[cnt] = vfc.vfc_typenum;
1187 		strlcat(&names[loc], vfc.vfc_name, sizeof names - loc);
1188 		vfsname[cnt].ctl_name = &names[loc];
1189 		vfsname[cnt].ctl_type = CTLTYPE_NODE;
1190 		size = strlen(vfc.vfc_name) + 1;
1191 		loc += size;
1192 	}
1193 	lastused = loc;
1194 
1195 	vfsname[0].ctl_name = "mounts";
1196 	vfsname[0].ctl_type = CTLTYPE_NODE;
1197 	vfsvars[0].list = vfsname + 1;
1198 	vfsvars[0].size = maxtypenum - 1;
1199 
1200 	secondlevel[CTL_VFS].list = vfsname;
1201 	secondlevel[CTL_VFS].size = maxtypenum;
1202 	return;
1203 }
1204 
1205 int
sysctl_vfsgen(char * string,char ** bufpp,int mib[],int flags,int * typep)1206 sysctl_vfsgen(char *string, char **bufpp, int mib[], int flags, int *typep)
1207 {
1208 	int indx;
1209 	size_t size;
1210 	struct vfsconf vfc;
1211 
1212 	if (*bufpp == NULL) {
1213 		listall(string, vfsvars);
1214 		return (-1);
1215 	}
1216 
1217 	if ((indx = findname(string, "third", bufpp, vfsvars)) == -1)
1218 		return (-1);
1219 
1220 	mib[1] = VFS_GENERIC;
1221 	mib[2] = VFS_CONF;
1222 	mib[3] = indx;
1223 	size = sizeof vfc;
1224 	if (sysctl(mib, 4, &vfc, &size, (void *)0, (size_t)0) < 0) {
1225 		if (errno != EOPNOTSUPP)
1226 			warn("vfs print");
1227 		return -1;
1228 	}
1229 	if (flags == 0 && vfc.vfc_refcount == 0)
1230 		return -1;
1231 	if (!nflag)
1232 		fprintf(stdout, "%s has %d mounted instance%s\n",
1233 		    string, vfc.vfc_refcount,
1234 		    vfc.vfc_refcount != 1 ? "s" : "");
1235 	else
1236 		fprintf(stdout, "%d\n", vfc.vfc_refcount);
1237 
1238 	return -1;
1239 }
1240 
1241 int
sysctl_vfs(char * string,char ** bufpp,int mib[],int flags,int * typep)1242 sysctl_vfs(char *string, char **bufpp, int mib[], int flags, int *typep)
1243 {
1244 	struct list *lp = &vfsvars[mib[1]];
1245 	int indx;
1246 
1247 	if (lp->list == NULL) {
1248 		if (flags)
1249 			warnx("No variables defined for file system %s", string);
1250 		return (-1);
1251 	}
1252 	if (*bufpp == NULL) {
1253 		listall(string, lp);
1254 		return (-1);
1255 	}
1256 	if ((indx = findname(string, "third", bufpp, lp)) == -1)
1257 		return (-1);
1258 
1259 	mib[1] = vfs_typenums[mib[1]];
1260 	mib[2] = indx;
1261 	*typep = lp->list[indx].ctl_type;
1262 	return (3);
1263 }
1264 
1265 struct ctlname posixname[] = CTL_FS_POSIX_NAMES;
1266 struct list fslist = { posixname, FS_POSIX_MAXID };
1267 
1268 /*
1269  * handle file system requests
1270  */
1271 int
sysctl_fs(char * string,char ** bufpp,int mib[],int flags,int * typep)1272 sysctl_fs(char *string, char **bufpp, int mib[], int flags, int *typep)
1273 {
1274 	int indx;
1275 
1276 	if (*bufpp == NULL) {
1277 		listall(string, &fslist);
1278 		return (-1);
1279 	}
1280 	if ((indx = findname(string, "third", bufpp, &fslist)) == -1)
1281 		return (-1);
1282 	mib[2] = indx;
1283 	*typep = fslist.list[indx].ctl_type;
1284 	return (3);
1285 }
1286 
1287 #ifdef CPU_BIOS
1288 struct ctlname biosname[] = CTL_BIOS_NAMES;
1289 struct list bioslist = { biosname, BIOS_MAXID };
1290 
1291 /*
1292  * handle BIOS requests
1293  */
1294 int
sysctl_bios(char * string,char ** bufpp,int mib[],int flags,int * typep)1295 sysctl_bios(char *string, char **bufpp, int mib[], int flags, int *typep)
1296 {
1297 	char *name;
1298 	int indx;
1299 
1300 	if (*bufpp == NULL) {
1301 		listall(string, &bioslist);
1302 		return (-1);
1303 	}
1304 	if ((indx = findname(string, "third", bufpp, &bioslist)) == -1)
1305 		return (-1);
1306 	mib[2] = indx;
1307 	if (indx == BIOS_DISKINFO) {
1308 		if (*bufpp == NULL) {
1309 			char name[BUFSIZ];
1310 
1311 			/* scan all the bios devices */
1312 			for (indx = 0; indx < 256; indx++) {
1313 				snprintf(name, sizeof(name), "%s.%u",
1314 				    string, indx);
1315 				parse(name, 1);
1316 			}
1317 			return (-1);
1318 		}
1319 		if ((name = strsep(bufpp, ".")) == NULL) {
1320 			warnx("%s: incomplete specification", string);
1321 			return (-1);
1322 		}
1323 		mib[3] = atoi(name);
1324 		*typep = CTLTYPE_STRUCT;
1325 		return (4);
1326 	} else {
1327 		*typep = bioslist.list[indx].ctl_type;
1328 		return (3);
1329 	}
1330 }
1331 #endif
1332 
1333 struct ctlname swpencname[] = CTL_SWPENC_NAMES;
1334 struct list swpenclist = { swpencname, SWPENC_MAXID };
1335 
1336 /*
1337  * handle swap encrypt requests
1338  */
1339 int
sysctl_swpenc(char * string,char ** bufpp,int mib[],int flags,int * typep)1340 sysctl_swpenc(char *string, char **bufpp, int mib[], int flags, int *typep)
1341 {
1342 	int indx;
1343 
1344 	if (*bufpp == NULL) {
1345 		listall(string, &swpenclist);
1346 		return (-1);
1347 	}
1348 	if ((indx = findname(string, "third", bufpp, &swpenclist)) == -1)
1349 		return (-1);
1350 	mib[2] = indx;
1351 	*typep = swpenclist.list[indx].ctl_type;
1352 	return (3);
1353 }
1354 
1355 struct ctlname inetname[] = CTL_IPPROTO_NAMES;
1356 struct ctlname ipname[] = IPCTL_NAMES;
1357 struct ctlname icmpname[] = ICMPCTL_NAMES;
1358 struct ctlname ipipname[] = IPIPCTL_NAMES;
1359 struct ctlname tcpname[] = TCPCTL_NAMES;
1360 struct ctlname udpname[] = UDPCTL_NAMES;
1361 struct ctlname espname[] = ESPCTL_NAMES;
1362 struct ctlname ahname[] = AHCTL_NAMES;
1363 struct ctlname etheripname[] = ETHERIPCTL_NAMES;
1364 struct ctlname grename[] = GRECTL_NAMES;
1365 struct ctlname mobileipname[] = MOBILEIPCTL_NAMES;
1366 struct ctlname ipcompname[] = IPCOMPCTL_NAMES;
1367 struct ctlname carpname[] = CARPCTL_NAMES;
1368 struct ctlname bpfname[] = CTL_NET_BPF_NAMES;
1369 struct ctlname ifqname[] = CTL_IFQ_NAMES;
1370 struct list inetlist = { inetname, IPPROTO_MAXID };
1371 struct list inetvars[] = {
1372 	{ ipname, IPCTL_MAXID },	/* ip */
1373 	{ icmpname, ICMPCTL_MAXID },	/* icmp */
1374 	{ 0, 0 },			/* igmp */
1375 	{ 0, 0 },			/* ggmp */
1376 	{ ipipname, IPIPCTL_MAXID },	/* ipencap */
1377 	{ 0, 0 },
1378 	{ tcpname, TCPCTL_MAXID },	/* tcp */
1379 	{ 0, 0 },
1380 	{ 0, 0 },			/* egp */
1381 	{ 0, 0 },
1382 	{ 0, 0 },
1383 	{ 0, 0 },
1384 	{ 0, 0 },			/* pup */
1385 	{ 0, 0 },
1386 	{ 0, 0 },
1387 	{ 0, 0 },
1388 	{ 0, 0 },
1389 	{ udpname, UDPCTL_MAXID },	/* udp */
1390 	{ 0, 0 },
1391 	{ 0, 0 },
1392 	{ 0, 0 },
1393 	{ 0, 0 },
1394 	{ 0, 0 },
1395 	{ 0, 0 },
1396 	{ 0, 0 },
1397 	{ 0, 0 },
1398 	{ 0, 0 },
1399 	{ 0, 0 },
1400 	{ 0, 0 },
1401 	{ 0, 0 },
1402 	{ 0, 0 },
1403 	{ 0, 0 },
1404 	{ 0, 0 },
1405 	{ 0, 0 },
1406 	{ 0, 0 },
1407 	{ 0, 0 },
1408 	{ 0, 0 },
1409 	{ 0, 0 },
1410 	{ 0, 0 },
1411 	{ 0, 0 },
1412 	{ 0, 0 },
1413 	{ 0, 0 },
1414 	{ 0, 0 },
1415 	{ 0, 0 },
1416 	{ 0, 0 },
1417 	{ 0, 0 },
1418 	{ 0, 0 },
1419 	{ grename, GRECTL_MAXID }, /* GRE */
1420 	{ 0, 0 },
1421 	{ 0, 0 },
1422 	{ espname, ESPCTL_MAXID },	/* esp */
1423 	{ ahname, AHCTL_MAXID },	/* ah */
1424 	{ 0, 0 },
1425 	{ 0, 0 },
1426 	{ 0, 0 },
1427 	{ mobileipname, MOBILEIPCTL_MAXID }, /* mobileip */
1428 	{ 0, 0 },
1429 	{ 0, 0 },
1430 	{ 0, 0 },
1431 	{ 0, 0 },
1432 	{ 0, 0 },
1433 	{ 0, 0 },
1434 	{ 0, 0 },
1435 	{ 0, 0 },
1436 	{ 0, 0 },
1437 	{ 0, 0 },
1438 	{ 0, 0 },
1439 	{ 0, 0 },
1440 	{ 0, 0 },
1441 	{ 0, 0 },
1442 	{ 0, 0 },
1443 	{ 0, 0 },
1444 	{ 0, 0 },
1445 	{ 0, 0 },
1446 	{ 0, 0 },
1447 	{ 0, 0 },
1448 	{ 0, 0 },
1449 	{ 0, 0 },
1450 	{ 0, 0 },
1451 	{ 0, 0 },
1452 	{ 0, 0 },
1453 	{ 0, 0 },
1454 	{ 0, 0 },
1455 	{ 0, 0 },
1456 	{ 0, 0 },
1457 	{ 0, 0 },
1458 	{ 0, 0 },
1459 	{ 0, 0 },
1460 	{ 0, 0 },
1461 	{ 0, 0 },
1462 	{ 0, 0 },
1463 	{ 0, 0 },
1464 	{ 0, 0 },
1465 	{ 0, 0 },
1466 	{ 0, 0 },
1467 	{ 0, 0 },
1468 	{ 0, 0 },
1469 	{ etheripname, ETHERIPCTL_MAXID },
1470 	{ 0, 0 },
1471 	{ 0, 0 },
1472 	{ 0, 0 },
1473 	{ 0, 0 },
1474 	{ 0, 0 },
1475 	{ 0, 0 },
1476 	{ 0, 0 },
1477 	{ 0, 0 },
1478 	{ 0, 0 },
1479 	{ 0, 0 },
1480 	{ ipcompname, IPCOMPCTL_MAXID },
1481 	{ 0, 0 },
1482 	{ 0, 0 },
1483 	{ 0, 0 },
1484 	{ carpname, CARPCTL_MAXID },
1485 };
1486 struct list bpflist = { bpfname, NET_BPF_MAXID };
1487 struct list ifqlist = { ifqname, IFQCTL_MAXID };
1488 
1489 struct list kernmalloclist = { kernmallocname, KERN_MALLOC_MAXID };
1490 struct list forkstatlist = { forkstatname, KERN_FORKSTAT_MAXID };
1491 struct list nchstatslist = { nchstatsname, KERN_NCHSTATS_MAXID };
1492 struct list ttylist = { ttysname, KERN_TTY_MAXID };
1493 struct list semlist = { semname, KERN_SEMINFO_MAXID };
1494 struct list shmlist = { shmname, KERN_SHMINFO_MAXID };
1495 struct list watchdoglist = { watchdogname, KERN_WATCHDOG_MAXID };
1496 #ifdef KERN_TIMECOUNTER_MAXID
1497 struct list tclist = { tcname, KERN_TIMECOUNTER_MAXID };
1498 #endif
1499 
1500 /*
1501  * handle vfs namei cache statistics
1502  */
1503 int
sysctl_nchstats(char * string,char ** bufpp,int mib[],int flags,int * typep)1504 sysctl_nchstats(char *string, char **bufpp, int mib[], int flags, int *typep)
1505 {
1506 	static struct nchstats nch;
1507 	int indx;
1508 	size_t size;
1509 	static int keepvalue = 0;
1510 
1511 	if (*bufpp == NULL) {
1512 		bzero(&nch, sizeof(struct nchstats));
1513 		listall(string, &nchstatslist);
1514 		return (-1);
1515 	}
1516 	if ((indx = findname(string, "third", bufpp, &nchstatslist)) == -1)
1517 		return (-1);
1518 	mib[2] = indx;
1519 	if (*bufpp != NULL) {
1520 		warnx("fourth level name in %s is invalid", string);
1521 		return (-1);
1522 	}
1523 	if (keepvalue == 0) {
1524 		size = sizeof(struct nchstats);
1525 		if (sysctl(mib, 2, &nch, &size, NULL, 0) < 0)
1526 			return (-1);
1527 		keepvalue = 1;
1528 	}
1529 	if (!nflag)
1530 		(void)printf("%s%s", string, equ);
1531 	switch (indx) {
1532 	case KERN_NCHSTATS_GOODHITS:
1533 		(void)printf("%ld\n", nch.ncs_goodhits);
1534 		break;
1535 	case KERN_NCHSTATS_NEGHITS:
1536 		(void)printf("%ld\n", nch.ncs_neghits);
1537 		break;
1538 	case KERN_NCHSTATS_BADHITS:
1539 		(void)printf("%ld\n", nch.ncs_badhits);
1540 		break;
1541 	case KERN_NCHSTATS_FALSEHITS:
1542 		(void)printf("%ld\n", nch.ncs_falsehits);
1543 		break;
1544 	case KERN_NCHSTATS_MISS:
1545 		(void)printf("%ld\n", nch.ncs_miss);
1546 		break;
1547 	case KERN_NCHSTATS_LONG:
1548 		(void)printf("%ld\n", nch.ncs_long);
1549 		break;
1550 	case KERN_NCHSTATS_PASS2:
1551 		(void)printf("%ld\n", nch.ncs_pass2);
1552 		break;
1553 	case KERN_NCHSTATS_2PASSES:
1554 		(void)printf("%ld\n", nch.ncs_2passes);
1555 		break;
1556 	case KERN_NCHSTATS_REVHITS:
1557 		(void)printf("%ld\n", nch.ncs_revhits);
1558 		break;
1559 	case KERN_NCHSTATS_REVMISS:
1560 		(void)printf("%ld\n", nch.ncs_revmiss);
1561 		break;
1562 	}
1563 	return (-1);
1564 }
1565 
1566 /*
1567  * handle tty statistics
1568  */
1569 int
sysctl_tty(char * string,char ** bufpp,int mib[],int flags,int * typep)1570 sysctl_tty(char *string, char **bufpp, int mib[], int flags, int *typep)
1571 {
1572 	int indx;
1573 
1574 	if (*bufpp == NULL) {
1575 		listall(string, &ttylist);
1576 		return (-1);
1577 	}
1578 	if ((indx = findname(string, "third", bufpp, &ttylist)) == -1)
1579 		return (-1);
1580 	mib[2] = indx;
1581 
1582 	if ((*typep = ttylist.list[indx].ctl_type) == CTLTYPE_STRUCT) {
1583 		if (flags)
1584 			warnx("use pstat -t to view %s information",
1585 			    string);
1586 		return (-1);
1587 	}
1588 	return (3);
1589 }
1590 
1591 /*
1592  * handle fork statistics
1593  */
1594 int
sysctl_forkstat(char * string,char ** bufpp,int mib[],int flags,int * typep)1595 sysctl_forkstat(char *string, char **bufpp, int mib[], int flags, int *typep)
1596 {
1597 	static struct forkstat fks;
1598 	static int keepvalue = 0;
1599 	int indx;
1600 	size_t size;
1601 
1602 	if (*bufpp == NULL) {
1603 		bzero(&fks, sizeof(struct forkstat));
1604 		listall(string, &forkstatlist);
1605 		return (-1);
1606 	}
1607 	if ((indx = findname(string, "third", bufpp, &forkstatlist)) == -1)
1608 		return (-1);
1609 	if (*bufpp != NULL) {
1610 		warnx("fourth level name in %s is invalid", string);
1611 		return (-1);
1612 	}
1613 	if (keepvalue == 0) {
1614 		size = sizeof(struct forkstat);
1615 		if (sysctl(mib, 2, &fks, &size, NULL, 0) < 0)
1616 			return (-1);
1617 		keepvalue = 1;
1618 	}
1619 	if (!nflag)
1620 		(void)printf("%s%s", string, equ);
1621 	switch (indx)	{
1622 	case KERN_FORKSTAT_FORK:
1623 		(void)printf("%d\n", fks.cntfork);
1624 		break;
1625 	case KERN_FORKSTAT_VFORK:
1626 		(void)printf("%d\n", fks.cntvfork);
1627 		break;
1628 	case KERN_FORKSTAT_RFORK:
1629 		(void)printf("%d\n", fks.cntrfork);
1630 		break;
1631 	case KERN_FORKSTAT_KTHREAD:
1632 		(void)printf("%d\n", fks.cntkthread);
1633 		break;
1634 	case KERN_FORKSTAT_SIZFORK:
1635 		(void)printf("%d\n", fks.sizfork);
1636 		break;
1637 	case KERN_FORKSTAT_SIZVFORK:
1638 		(void)printf("%d\n", fks.sizvfork);
1639 		break;
1640 	case KERN_FORKSTAT_SIZRFORK:
1641 		(void)printf("%d\n", fks.sizrfork);
1642 		break;
1643 	case KERN_FORKSTAT_SIZKTHREAD:
1644 		(void)printf("%d\n", fks.sizkthread);
1645 		break;
1646 	}
1647 	return (-1);
1648 }
1649 
1650 /*
1651  * handle malloc statistics
1652  */
1653 int
sysctl_malloc(char * string,char ** bufpp,int mib[],int flags,int * typep)1654 sysctl_malloc(char *string, char **bufpp, int mib[], int flags, int *typep)
1655 {
1656 	int indx, stor, i;
1657 	char *name, bufp[BUFSIZ], *buf, *ptr;
1658 	struct list lp;
1659 	size_t size;
1660 
1661 	if (*bufpp == NULL) {
1662 		listall(string, &kernmalloclist);
1663 		return (-1);
1664 	}
1665 	if ((indx = findname(string, "third", bufpp, &kernmalloclist)) == -1)
1666 		return (-1);
1667 	mib[2] = indx;
1668 	if (mib[2] == KERN_MALLOC_BUCKET) {
1669 		if ((name = strsep(bufpp, ".")) == NULL) {
1670 			size = BUFSIZ;
1671 			stor = mib[2];
1672 			mib[2] = KERN_MALLOC_BUCKETS;
1673 			buf = bufp;
1674 			if (sysctl(mib, 3, buf, &size, NULL, 0) < 0)
1675 				return (-1);
1676 			mib[2] = stor;
1677 			for (stor = 0, i = 0; i < size; i++)
1678 				if (buf[i] == ',')
1679 					stor++;
1680 			lp.list = calloc(stor + 2, sizeof(struct ctlname));
1681 			if (lp.list == NULL)
1682 				return (-1);
1683 			lp.size = stor + 2;
1684 			for (i = 1;
1685 			    (lp.list[i].ctl_name = strsep(&buf, ",")) != NULL;
1686 			    i++) {
1687 				lp.list[i].ctl_type = CTLTYPE_STRUCT;
1688 			}
1689 			lp.list[i].ctl_name = buf;
1690 			lp.list[i].ctl_type = CTLTYPE_STRUCT;
1691 			listall(string, &lp);
1692 			free(lp.list);
1693 			return (-1);
1694 		}
1695 		mib[3] = atoi(name);
1696 		return (4);
1697 	} else if (mib[2] == KERN_MALLOC_BUCKETS) {
1698 		*typep = CTLTYPE_STRING;
1699 		return (3);
1700 	} else if (mib[2] == KERN_MALLOC_KMEMSTATS) {
1701 		size = BUFSIZ;
1702 		stor = mib[2];
1703 		mib[2] = KERN_MALLOC_KMEMNAMES;
1704 		buf = bufp;
1705 		if (sysctl(mib, 3, buf, &size, NULL, 0) < 0)
1706 			return (-1);
1707 		mib[2] = stor;
1708 		if ((name = strsep(bufpp, ".")) == NULL) {
1709 			for (stor = 0, i = 0; i < size; i++)
1710 				if (buf[i] == ',')
1711 					stor++;
1712 			lp.list = calloc(stor + 2, sizeof(struct ctlname));
1713 			if (lp.list == NULL)
1714 				return (-1);
1715 			lp.size = stor + 2;
1716 			for (i = 1;
1717 			    (lp.list[i].ctl_name = strsep(&buf, ",")) != NULL; i++) {
1718 				if (lp.list[i].ctl_name[0] == '\0') {
1719 					i--;
1720 					continue;
1721 				}
1722 				lp.list[i].ctl_type = CTLTYPE_STRUCT;
1723 			}
1724 			lp.list[i].ctl_name = buf;
1725 			lp.list[i].ctl_type = CTLTYPE_STRUCT;
1726 			listall(string, &lp);
1727 			free(lp.list);
1728 			return (-1);
1729 		}
1730 		ptr = strstr(buf, name);
1731  tryagain:
1732 		if (ptr == NULL) {
1733 			warnx("fourth level name %s in %s is invalid", name,
1734 			    string);
1735 			return (-1);
1736 		}
1737 		if ((*(ptr + strlen(name)) != ',') &&
1738 		    (*(ptr + strlen(name)) != '\0')) {
1739 			ptr = strstr(ptr + 1, name); /* retry */
1740 			goto tryagain;
1741 		}
1742 		if ((ptr != buf) && (*(ptr - 1) != ',')) {
1743 			ptr = strstr(ptr + 1, name); /* retry */
1744 			goto tryagain;
1745 		}
1746 		for (i = 0, stor = 0; buf + i < ptr; i++)
1747 			if (buf[i] == ',')
1748 				stor++;
1749 		mib[3] = stor;
1750 		return (4);
1751 	} else if (mib[2] == KERN_MALLOC_KMEMNAMES) {
1752 		*typep = CTLTYPE_STRING;
1753 		return (3);
1754 	}
1755 	return (-1);
1756 }
1757 
1758 #ifdef CPU_CHIPSET
1759 /*
1760  * handle machdep.chipset requests
1761  */
1762 struct ctlname chipsetname[] = CTL_CHIPSET_NAMES;
1763 struct list chipsetlist = { chipsetname, CPU_CHIPSET_MAXID };
1764 
1765 int
sysctl_chipset(char * string,char ** bufpp,int mib[],int flags,int * typep)1766 sysctl_chipset(char *string, char **bufpp, int mib[], int flags, int *typep)
1767 {
1768 	int indx, bwx;
1769 	static void *q;
1770 	size_t len;
1771 	char *p;
1772 
1773 	if (*bufpp == NULL) {
1774 		listall(string, &chipsetlist);
1775 		return (-1);
1776 	}
1777 	if ((indx = findname(string, "third", bufpp, &chipsetlist)) == -1)
1778 		return (-1);
1779 	mib[2] = indx;
1780 	if (!nflag)
1781 		printf("%s%s", string, equ);
1782 	switch(mib[2]) {
1783 	case CPU_CHIPSET_MEM:
1784 	case CPU_CHIPSET_DENSE:
1785 	case CPU_CHIPSET_PORTS:
1786 	case CPU_CHIPSET_HAE_MASK:
1787 		len = sizeof(void *);
1788 		if (sysctl(mib, 3, &q, &len, NULL, 0) < 0)
1789 			return (-1);
1790 		printf("%p\n", q);
1791 		break;
1792 	case CPU_CHIPSET_BWX:
1793 		len = sizeof(int);
1794 		if (sysctl(mib, 3, &bwx, &len, NULL, 0) < 0)
1795 			return (-1);
1796 		printf("%d\n", bwx);
1797 		break;
1798 	case CPU_CHIPSET_TYPE:
1799 		if (sysctl(mib, 3, NULL, &len, NULL, 0) < 0)
1800 			return (-1);
1801 		p = malloc(len + 1);
1802 		if (p == NULL)
1803 			return (-1);
1804 		if (sysctl(mib, 3, p, &len, NULL, 0) < 0)
1805 			return (-1);
1806 		p[len] = '\0';
1807 		printf("%s\n", p);
1808 		break;
1809 	}
1810 	return (-1);
1811 }
1812 #endif
1813 /*
1814  * handle internet requests
1815  */
1816 int
sysctl_inet(char * string,char ** bufpp,int mib[],int flags,int * typep)1817 sysctl_inet(char *string, char **bufpp, int mib[], int flags, int *typep)
1818 {
1819 	struct list *lp;
1820 	int indx;
1821 
1822 	if (*bufpp == NULL) {
1823 		listall(string, &inetlist);
1824 		return (-1);
1825 	}
1826 	if ((indx = findname(string, "third", bufpp, &inetlist)) == -1)
1827 		return (-1);
1828 	mib[2] = indx;
1829 	if (indx < IPPROTO_MAXID && inetvars[indx].list != NULL)
1830 		lp = &inetvars[indx];
1831 	else if (!flags)
1832 		return (-1);
1833 	else {
1834 		warnx("%s: no variables defined for this protocol", string);
1835 		return (-1);
1836 	}
1837 	if (*bufpp == NULL) {
1838 		listall(string, lp);
1839 		return (-1);
1840 	}
1841 	if ((indx = findname(string, "fourth", bufpp, lp)) == -1)
1842 		return (-1);
1843 	mib[3] = indx;
1844 	*typep = lp->list[indx].ctl_type;
1845 	if (*typep == CTLTYPE_NODE) {
1846 		int tindx;
1847 
1848 		if (*bufpp == 0) {
1849 			listall(string, &ifqlist);
1850 			return(-1);
1851 		}
1852 		lp = &ifqlist;
1853 		if ((tindx = findname(string, "fifth", bufpp, lp)) == -1)
1854 			return (-1);
1855 		mib[4] = tindx;
1856 		*typep = lp->list[tindx].ctl_type;
1857 		return(5);
1858 	}
1859 	return (4);
1860 }
1861 
1862 #ifdef INET6
1863 struct ctlname inet6name[] = CTL_IPV6PROTO_NAMES;
1864 struct ctlname ip6name[] = IPV6CTL_NAMES;
1865 struct ctlname icmp6name[] = ICMPV6CTL_NAMES;
1866 struct ctlname pim6name[] = PIM6CTL_NAMES;
1867 struct list inet6list = { inet6name, IPV6PROTO_MAXID };
1868 struct list inet6vars[] = {
1869 /*0*/	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
1870 	{ 0, 0 },
1871 	{ 0, 0 },
1872 	{ 0, 0 },
1873 	{ 0, 0 },
1874 	{ 0, 0 },
1875 /*10*/	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
1876 	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
1877 /*20*/	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
1878 	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
1879 /*30*/	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
1880 	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
1881 /*40*/	{ 0, 0 },
1882 	{ ip6name, IPV6CTL_MAXID },	/* ipv6 */
1883 	{ 0, 0 },
1884 	{ 0, 0 },
1885 	{ 0, 0 },
1886 	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
1887 /*50*/	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
1888 	{ 0, 0 },
1889 	{ 0, 0 },
1890 	{ 0, 0 },
1891 	{ icmp6name, ICMPV6CTL_MAXID },	/* icmp6 */
1892 	{ 0, 0 },
1893 /*60*/	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
1894 	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
1895 /*70*/	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
1896 	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
1897 /*80*/	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
1898 	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
1899 /*90*/	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
1900 	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
1901 /*100*/	{ 0, 0 },
1902 	{ 0, 0 },
1903 	{ 0, 0 },
1904 	{ pim6name, PIM6CTL_MAXID },	/* pim6 */
1905 };
1906 
1907 /*
1908  * handle internet6 requests
1909  */
1910 int
sysctl_inet6(char * string,char ** bufpp,int mib[],int flags,int * typep)1911 sysctl_inet6(char *string, char **bufpp, int mib[], int flags, int *typep)
1912 {
1913 	struct list *lp;
1914 	int indx;
1915 
1916 	if (*bufpp == NULL) {
1917 		listall(string, &inet6list);
1918 		return (-1);
1919 	}
1920 	if ((indx = findname(string, "third", bufpp, &inet6list)) == -1)
1921 		return (-1);
1922 	mib[2] = indx;
1923 	if (indx < IPV6PROTO_MAXID && inet6vars[indx].list != NULL)
1924 		lp = &inet6vars[indx];
1925 	else if (!flags)
1926 		return (-1);
1927 	else {
1928 		warnx("%s: no variables defined for this protocol", string);
1929 		return (-1);
1930 	}
1931 	if (*bufpp == NULL) {
1932 		listall(string, lp);
1933 		return (-1);
1934 	}
1935 	if ((indx = findname(string, "fourth", bufpp, lp)) == -1)
1936 		return (-1);
1937 	mib[3] = indx;
1938 	*typep = lp->list[indx].ctl_type;
1939 	return (4);
1940 }
1941 #endif
1942 
1943 struct ctlname ipxname[] = CTL_IPXPROTO_NAMES;
1944 struct ctlname ipxpname[] = IPXCTL_NAMES;
1945 struct ctlname spxpname[] = SPXCTL_NAMES;
1946 struct list ipxlist = { ipxname, IPXCTL_MAXID };
1947 struct list ipxvars[] = {
1948 	{ ipxpname, IPXCTL_MAXID },	/* ipx */
1949 	{ 0, 0 },
1950 	{ 0, 0 },
1951 	{ 0, 0 },
1952 	{ 0, 0 },
1953 	{ spxpname, SPXCTL_MAXID },
1954 };
1955 
1956 /*
1957  * Handle internet requests
1958  */
1959 int
sysctl_ipx(char * string,char ** bufpp,int mib[],int flags,int * typep)1960 sysctl_ipx(char *string, char **bufpp, int mib[], int flags, int *typep)
1961 {
1962 	struct list *lp;
1963 	int indx;
1964 
1965 	if (*bufpp == NULL) {
1966 		listall(string, &ipxlist);
1967 		return (-1);
1968 	}
1969 	if ((indx = findname(string, "third", bufpp, &ipxlist)) == -1)
1970 		return (-1);
1971 	mib[2] = indx;
1972 	if (indx <= IPXPROTO_SPX && ipxvars[indx].list != NULL)
1973 		lp = &ipxvars[indx];
1974 	else if (!flags)
1975 		return (-1);
1976 	else {
1977 		warnx("%s: no variables defined for this protocol", string);
1978 		return (-1);
1979 	}
1980 	if (*bufpp == NULL) {
1981 		listall(string, lp);
1982 		return (-1);
1983 	}
1984 	if ((indx = findname(string, "fourth", bufpp, lp)) == -1)
1985 		return (-1);
1986 	mib[3] = indx;
1987 	*typep = lp->list[indx].ctl_type;
1988 	return (4);
1989 }
1990 
1991 /* handle bpf requests */
1992 int
sysctl_bpf(char * string,char ** bufpp,int mib[],int flags,int * typep)1993 sysctl_bpf(char *string, char **bufpp, int mib[], int flags, int *typep)
1994 {
1995 	int indx;
1996 
1997 	if (*bufpp == NULL) {
1998 		listall(string, &bpflist);
1999 		return (-1);
2000 	}
2001 	if ((indx = findname(string, "third", bufpp, &bpflist)) == -1)
2002 		return (-1);
2003 	mib[2] = indx;
2004 	*typep = CTLTYPE_INT;
2005 	return (3);
2006 }
2007 
2008 /*
2009  * Handle SysV semaphore info requests
2010  */
2011 int
sysctl_seminfo(string,bufpp,mib,flags,typep)2012 sysctl_seminfo(string, bufpp, mib, flags, typep)
2013 	char *string;
2014 	char **bufpp;
2015 	int mib[];
2016 	int flags;
2017 	int *typep;
2018 {
2019 	int indx;
2020 
2021 	if (*bufpp == NULL) {
2022 		listall(string, &semlist);
2023 		return (-1);
2024 	}
2025 	if ((indx = findname(string, "third", bufpp, &semlist)) == -1)
2026 		return (-1);
2027 	mib[2] = indx;
2028 	*typep = CTLTYPE_INT;
2029 	return (3);
2030 }
2031 
2032 /*
2033  * Handle SysV shared memory info requests
2034  */
2035 int
sysctl_shminfo(string,bufpp,mib,flags,typep)2036 sysctl_shminfo(string, bufpp, mib, flags, typep)
2037 	char *string;
2038 	char **bufpp;
2039 	int mib[];
2040 	int flags;
2041 	int *typep;
2042 {
2043 	int indx;
2044 
2045 	if (*bufpp == NULL) {
2046 		listall(string, &shmlist);
2047 		return (-1);
2048 	}
2049 	if ((indx = findname(string, "third", bufpp, &shmlist)) == -1)
2050 		return (-1);
2051 	mib[2] = indx;
2052 	*typep = CTLTYPE_INT;
2053 	return (3);
2054 }
2055 
2056 /*
2057  * Handle watchdog support
2058  */
2059 int
sysctl_watchdog(char * string,char ** bufpp,int mib[],int flags,int * typep)2060 sysctl_watchdog(char *string, char **bufpp, int mib[], int flags,
2061     int *typep)
2062 {
2063 	int indx;
2064 
2065 	if (*bufpp == NULL) {
2066 		listall(string, &watchdoglist);
2067 		return (-1);
2068 	}
2069 	if ((indx = findname(string, "third", bufpp, &watchdoglist)) == -1)
2070 		return (-1);
2071 	mib[2] = indx;
2072 	*typep = watchdoglist.list[indx].ctl_type;
2073 	return (3);
2074 }
2075 
2076 #ifdef KERN_TIMECOUNTER_MAXID
2077 /*
2078  * Handle timecounter support
2079  */
2080 int
sysctl_tc(char * string,char ** bufpp,int mib[],int flags,int * typep)2081 sysctl_tc(char *string, char **bufpp, int mib[], int flags,
2082     int *typep)
2083 {
2084 	int indx;
2085 
2086 	if (*bufpp == NULL) {
2087 		listall(string, &tclist);
2088 		return (-1);
2089 	}
2090 	if ((indx = findname(string, "third", bufpp, &tclist)) == -1)
2091 		return (-1);
2092 	mib[2] = indx;
2093 	*typep = tclist.list[indx].ctl_type;
2094 	return (3);
2095 }
2096 #endif
2097 
2098 /*
2099  * Handle hardware monitoring sensors support
2100  */
2101 int
sysctl_sensors(char * string,char ** bufpp,int mib[],int flags,int * typep)2102 sysctl_sensors(char *string, char **bufpp, int mib[], int flags, int *typep)
2103 {
2104 	char *name;
2105 	int indx;
2106 
2107 	if (*bufpp == NULL) {
2108 		char buf[BUFSIZ];
2109 
2110 		/* scan all sensors */
2111 		for (indx = 0; indx < 256; indx++) {
2112 			snprintf(buf, sizeof(buf), "%s.%u", string, indx);
2113 			parse(buf, 0);
2114 		}
2115 		return (-1);
2116 	}
2117 	if ((name = strsep(bufpp, ".")) == NULL) {
2118 		warnx("%s: incomplete specification", string);
2119 		return (-1);
2120 	}
2121 	mib[2] = atoi(name);
2122 	*typep = CTLTYPE_STRUCT;
2123 	return (3);
2124 }
2125 
2126 struct emulname {
2127 	char *name;
2128 	int index;
2129 } *emul_names;
2130 int	emul_num, nemuls;
2131 int	emul_init(void);
2132 
2133 int
sysctl_emul(char * string,char * newval,int flags)2134 sysctl_emul(char *string, char *newval, int flags)
2135 {
2136 	int mib[4], enabled, i, old, print, found = 0;
2137 	char *head, *target;
2138 	size_t len;
2139 
2140 	if (emul_init() == -1) {
2141 		warnx("emul_init: out of memory");
2142 		return (1);
2143 	}
2144 
2145 	mib[0] = CTL_KERN;
2146 	mib[1] = KERN_EMUL;
2147 	mib[3] = KERN_EMUL_ENABLED;
2148 	head = "kern.emul.";
2149 
2150 	if (aflag || strcmp(string, "kern.emul") == 0) {
2151 		if (newval) {
2152 			warnx("%s: specification is incomplete", string);
2153 			return (1);
2154 		}
2155 		if (nflag)
2156 			printf("%d\n", nemuls);
2157 		else
2158 			printf("%snemuls%s%d\n", head, equ, nemuls);
2159 		for (i = 0; i < emul_num; i++) {
2160 			if (emul_names[i].name == NULL)
2161 				break;
2162 			if (i > 0 && strcmp(emul_names[i].name,
2163 			    emul_names[i-1].name) == 0)
2164 				continue;
2165 			mib[2] = emul_names[i].index;
2166 			len = sizeof(int);
2167 			if (sysctl(mib, 4, &enabled, &len, NULL, 0) == -1) {
2168 				warn("%s", string);
2169 				continue;
2170 			}
2171 			if (nflag)
2172 				printf("%d\n", enabled);
2173 			else
2174 				printf("%s%s%s%d\n", head, emul_names[i].name,
2175 				    equ, enabled);
2176 		}
2177 		return (0);
2178 	}
2179 	/* User specified a third level name */
2180 	target = strrchr(string, '.');
2181 	target++;
2182 	if (strcmp(target, "nemuls") == 0) {
2183 		if (newval) {
2184 			warnx("Operation not permitted");
2185 			return (1);
2186 		}
2187 		if (nflag)
2188 			printf("%d\n", nemuls);
2189 		else
2190 			printf("%snemuls = %d\n", head, nemuls);
2191 		return (0);
2192 	}
2193 	print = 1;
2194 	for (i = 0; i < emul_num; i++) {
2195 		if (!emul_names[i].name || (strcmp(target, emul_names[i].name)))
2196 			continue;
2197 		found = 1;
2198 		mib[2] = emul_names[i].index;
2199 		len = sizeof(int);
2200 		if (newval) {
2201 			enabled = atoi(newval);
2202 			if (sysctl(mib, 4, &old, &len, &enabled, len) == -1) {
2203 				warn("%s", string);
2204 				print = 0;
2205 				continue;
2206 			}
2207 			if (print) {
2208 				if (nflag)
2209 					printf("%d\n", enabled);
2210 				else
2211 					printf("%s%s: %d -> %d\n", head,
2212 					    target, old, enabled);
2213 			}
2214 		} else {
2215 			if (sysctl(mib, 4, &enabled, &len, NULL, 0) == -1) {
2216 				warn("%s", string);
2217 				continue;
2218 			}
2219 			if (print) {
2220 				if (nflag)
2221 					printf("%d\n", enabled);
2222 				else
2223 					printf("%s%s = %d\n", head, target,
2224 					    enabled);
2225 			}
2226 		}
2227 		print = 0;
2228 	}
2229 	if (!found)
2230 		warnx("third level name %s in kern.emul is invalid",
2231 		    string);
2232 	return (0);
2233 
2234 
2235 }
2236 
2237 int
emulcmp(const void * m,const void * n)2238 emulcmp(const void *m, const void *n)
2239 {
2240 	const struct emulname *a = m, *b = n;
2241 
2242 	if (!a || !a->name)
2243 		return 1;
2244 	if (!b || !b->name)
2245 		return -1;
2246 	return (strcmp(a->name, b->name));
2247 }
2248 
2249 int
emul_init(void)2250 emul_init(void)
2251 {
2252 	static int done;
2253 	char string[16];
2254 	int mib[4], i;
2255 	size_t len;
2256 
2257 	if (done)
2258 		return (0);
2259 	done = 1;
2260 
2261 	mib[0] = CTL_KERN;
2262 	mib[1] = KERN_EMUL;
2263 	mib[2] = KERN_EMUL_NUM;
2264 	len = sizeof(int);
2265 	if (sysctl(mib, 3, &emul_num, &len, NULL, 0) == -1)
2266 		return (-1);
2267 
2268 	emul_names = calloc(emul_num, sizeof(*emul_names));
2269 	if (emul_names == NULL)
2270 		return (-1);
2271 
2272 	nemuls = emul_num;
2273 	for (i = 0; i < emul_num; i++) {
2274 		emul_names[i].index = mib[2] = i + 1;
2275 		mib[3] = KERN_EMUL_NAME;
2276 		len = sizeof(string);
2277 		if (sysctl(mib, 4, string, &len, NULL, 0) == -1)
2278 			continue;
2279 		if (strcmp(string, "native") == 0)
2280 			continue;
2281 		emul_names[i].name = strdup(string);
2282 		if (emul_names[i].name == NULL) {
2283 			free(emul_names);
2284 			return (-1);
2285 		}
2286 	}
2287 	qsort(emul_names, nemuls, sizeof(*emul_names), emulcmp);
2288 	for (i = 0; i < emul_num; i++) {
2289 		if (!emul_names[i].name || (i > 0 &&
2290 		    strcmp(emul_names[i].name, emul_names[i - 1].name) == 0)) {
2291 
2292 			nemuls--;
2293 		}
2294 	}
2295 	return (0);
2296 }
2297 
2298 /*
2299  * Scan a list of names searching for a particular name.
2300  */
2301 int
findname(char * string,char * level,char ** bufp,struct list * namelist)2302 findname(char *string, char *level, char **bufp, struct list *namelist)
2303 {
2304 	char *name;
2305 	int i;
2306 
2307 	if (namelist->list == 0 || (name = strsep(bufp, ".")) == NULL) {
2308 		warnx("%s: incomplete specification", string);
2309 		return (-1);
2310 	}
2311 	for (i = 0; i < namelist->size; i++)
2312 		if (namelist->list[i].ctl_name != NULL &&
2313 		    strcmp(name, namelist->list[i].ctl_name) == 0)
2314 			break;
2315 	if (i == namelist->size) {
2316 		warnx("%s level name %s in %s is invalid", level, name, string);
2317 		return (-1);
2318 	}
2319 	return (i);
2320 }
2321 
2322 void
usage(void)2323 usage(void)
2324 {
2325 
2326 	(void)fprintf(stderr, "usage:\t%s\n\t%s\n\t%s\n",
2327 	    "sysctl [-n] variable ...", "sysctl [-nqw] variable=value ...",
2328 	    "sysctl [-n] -Aa");
2329 	exit(1);
2330 }
2331