sysctl.c revision 1.43
1/*	$OpenBSD: sysctl.c,v 1.43 1999/12/10 10:12:56 itojun Exp $	*/
2/*	$NetBSD: sysctl.c,v 1.9 1995/09/30 07:12:50 thorpej Exp $	*/
3
4/*
5 * Copyright (c) 1993
6 *	The Regents of the University of California.  All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 *    notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 *    notice, this list of conditions and the following disclaimer in the
15 *    documentation and/or other materials provided with the distribution.
16 * 3. All advertising materials mentioning features or use of this software
17 *    must display the following acknowledgement:
18 *	This product includes software developed by the University of
19 *	California, Berkeley and its contributors.
20 * 4. Neither the name of the University nor the names of its contributors
21 *    may be used to endorse or promote products derived from this software
22 *    without specific prior written permission.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 * SUCH DAMAGE.
35 */
36
37#ifndef lint
38static char copyright[] =
39"@(#) Copyright (c) 1993\n\
40	The Regents of the University of California.  All rights reserved.\n";
41#endif /* not lint */
42
43#ifndef lint
44#if 0
45static char sccsid[] = "@(#)sysctl.c	8.5 (Berkeley) 5/9/95";
46#else
47static char *rcsid = "$OpenBSD: sysctl.c,v 1.43 1999/12/10 10:12:56 itojun Exp $";
48#endif
49#endif /* not lint */
50
51#include <sys/param.h>
52#include <sys/gmon.h>
53#include <sys/mount.h>
54#include <sys/stat.h>
55#include <sys/sysctl.h>
56#include <sys/socket.h>
57#include <vm/vm_param.h>
58#include <machine/cpu.h>
59#include <net/route.h>
60
61#include <netinet/in.h>
62#include <netinet/in_systm.h>
63#include <netinet/ip.h>
64#include <netinet/in_pcb.h>
65#include <netinet/ip_icmp.h>
66#include <netinet/ip_ip4.h>
67#include <netinet/ip_ether.h>
68#include <netinet/ip_ah.h>
69#include <netinet/ip_esp.h>
70#include <netinet/icmp_var.h>
71#include <netinet/ip_var.h>
72#include <netinet/udp.h>
73#include <netinet/udp_var.h>
74#include <netinet/tcp.h>
75#include <netinet/tcp_timer.h>
76#include <netinet/tcp_var.h>
77
78#ifdef INET6
79#include <netinet6/ip6.h>
80#include <netinet6/icmp6.h>
81#include <netinet6/ip6_var.h>
82#include <netinet6/pim6_var.h>
83#endif
84
85#include <netipx/ipx.h>
86#include <netipx/ipx_var.h>
87#include <netipx/spx_var.h>
88#include <ddb/db_var.h>
89#include <dev/rndvar.h>
90
91#include <err.h>
92#include <errno.h>
93#include <stdio.h>
94#include <stdlib.h>
95#include <string.h>
96#include <ctype.h>
97
98#ifdef CPU_BIOS
99#include <machine/biosvar.h>
100#endif
101
102struct ctlname topname[] = CTL_NAMES;
103struct ctlname kernname[] = CTL_KERN_NAMES;
104struct ctlname vmname[] = CTL_VM_NAMES;
105struct ctlname fsname[] = CTL_FS_NAMES;
106struct ctlname netname[] = CTL_NET_NAMES;
107struct ctlname hwname[] = CTL_HW_NAMES;
108struct ctlname username[] = CTL_USER_NAMES;
109struct ctlname debugname[CTL_DEBUG_MAXID];
110struct ctlname *vfsname;
111#ifdef CTL_MACHDEP_NAMES
112struct ctlname machdepname[] = CTL_MACHDEP_NAMES;
113#endif
114struct ctlname ddbname[] = CTL_DDB_NAMES;
115char names[BUFSIZ];
116int lastused;
117
118struct list {
119	struct	ctlname *list;
120	int	size;
121};
122struct list toplist = { topname, CTL_MAXID };
123struct list secondlevel[] = {
124	{ 0, 0 },			/* CTL_UNSPEC */
125	{ kernname, KERN_MAXID },	/* CTL_KERN */
126	{ vmname, VM_MAXID },		/* CTL_VM */
127	{ fsname, FS_MAXID },		/* CTL_FS */
128	{ netname, NET_MAXID },		/* CTL_NET */
129	{ 0, CTL_DEBUG_MAXID },		/* CTL_DEBUG */
130	{ hwname, HW_MAXID },		/* CTL_HW */
131#ifdef CTL_MACHDEP_NAMES
132	{ machdepname, CPU_MAXID },	/* CTL_MACHDEP */
133#else
134	{ 0, 0 },			/* CTL_MACHDEP */
135#endif
136	{ username, USER_MAXID },	/* CTL_USER_NAMES */
137	{ ddbname, DBCTL_MAXID },	/* CTL_DDB_NAMES */
138	{ 0, 0 },			/* CTL_VFS */
139};
140
141int	Aflag, aflag, nflag, wflag;
142
143/*
144 * Variables requiring special processing.
145 */
146#define	CLOCK		0x00000001
147#define	BOOTTIME	0x00000002
148#define	CHRDEV		0x00000004
149#define	BLKDEV		0x00000008
150#define	RNDSTATS	0x00000010
151#define	BADDYNAMIC	0x00000020
152#define	BIOSGEO		0x00000040
153#define	BIOSDEV		0x00000080
154#define	MAJ2DEV		0x00000100
155#define	UNSIGNED	0x00000200
156
157/* prototypes */
158void debuginit __P((void));
159void listall __P((char *, struct list *));
160void parse __P((char *, int));
161void parse_baddynamic __P((int *, size_t, char *, void **, size_t *, int, int));
162void usage __P((void));
163int findname __P((char *, char *, char **, struct list *));
164int sysctl_inet __P((char *, char **, int *, int, int *));
165#ifdef INET6
166int sysctl_inet6 __P((char *, char **, int *, int, int *));
167#endif
168int sysctl_ipx __P((char *, char **, int *, int, int *));
169int sysctl_fs __P((char *, char **, int *, int, int *));
170int sysctl_bios __P((char *, char **, int *, int, int *));
171void vfsinit __P((void));
172
173int
174main(argc, argv)
175	int argc;
176	char *argv[];
177{
178	int ch, lvl1;
179
180	while ((ch = getopt(argc, argv, "Aanw")) != -1) {
181		switch (ch) {
182
183		case 'A':
184			Aflag = 1;
185			break;
186
187		case 'a':
188			aflag = 1;
189			break;
190
191		case 'n':
192			nflag = 1;
193			break;
194
195		case 'w':
196			wflag = 1;
197			break;
198
199		default:
200			usage();
201		}
202	}
203	argc -= optind;
204	argv += optind;
205
206	if (argc == 0 && (Aflag || aflag)) {
207		debuginit();
208		vfsinit();
209		for (lvl1 = 1; lvl1 < CTL_MAXID; lvl1++)
210			listall(topname[lvl1].ctl_name, &secondlevel[lvl1]);
211		exit(0);
212	}
213	if (argc == 0)
214		usage();
215	for (; *argv != NULL; ++argv)
216		parse(*argv, 1);
217	exit(0);
218}
219
220/*
221 * List all variables known to the system.
222 */
223void
224listall(prefix, lp)
225	char *prefix;
226	struct list *lp;
227{
228	int lvl2;
229	char *cp, name[BUFSIZ];
230
231	if (lp->list == NULL)
232		return;
233	(void)strncpy(name, prefix, BUFSIZ-1);
234	name[BUFSIZ-1] = '\0';
235	cp = &name[strlen(name)];
236	*cp++ = '.';
237	for (lvl2 = 0; lvl2 < lp->size; lvl2++) {
238		if (lp->list[lvl2].ctl_name == NULL)
239			continue;
240		(void)strcpy(cp, lp->list[lvl2].ctl_name);
241		parse(name, Aflag);
242	}
243}
244
245/*
246 * Parse a name into a MIB entry.
247 * Lookup and print out the MIB entry if it exists.
248 * Set a new value if requested.
249 */
250void
251parse(string, flags)
252	char *string;
253	int flags;
254{
255	int indx, type, state, intval;
256	size_t size, len,  newsize = 0;
257	int special = 0;
258	void *newval = 0;
259	quad_t quadval;
260	struct list *lp;
261	struct vfsconf vfc;
262	int mib[CTL_MAXNAME];
263	char *cp, *bufp, buf[BUFSIZ];
264
265	(void)strncpy(buf, string, sizeof(buf) - 1);
266	buf[sizeof(buf) - 1] = '\0';
267	bufp = buf;
268	if ((cp = strchr(string, '=')) != NULL) {
269		if (!wflag)
270			errx(2, "must specify -w to set variables");
271		*strchr(buf, '=') = '\0';
272		*cp++ = '\0';
273		while (isspace(*cp))
274			cp++;
275		newval = cp;
276		newsize = strlen(cp);
277	}
278	if ((indx = findname(string, "top", &bufp, &toplist)) == -1)
279		return;
280	mib[0] = indx;
281	if (indx == CTL_VFS)
282		vfsinit();
283	if (indx == CTL_DEBUG)
284		debuginit();
285	lp = &secondlevel[indx];
286	if (lp->list == 0) {
287		warnx("%s: class is not implemented", topname[indx].ctl_name);
288		return;
289	}
290	if (bufp == NULL) {
291		listall(topname[indx].ctl_name, lp);
292		return;
293	}
294	if ((indx = findname(string, "second", &bufp, lp)) == -1)
295		return;
296	mib[1] = indx;
297	type = lp->list[indx].ctl_type;
298	len = 2;
299	switch (mib[0]) {
300
301	case CTL_KERN:
302		switch (mib[1]) {
303		case KERN_PROF:
304			mib[2] = GPROF_STATE;
305			size = sizeof(state);
306			if (sysctl(mib, 3, &state, &size, NULL, 0) == -1) {
307				if (flags == 0)
308					return;
309				if (!nflag)
310					(void)printf("%s: ", string);
311				(void)puts("kernel is not compiled for profiling");
312				return;
313			}
314			if (!nflag)
315				(void)printf("%s = %s\n", string,
316				    state == GMON_PROF_OFF ? "off" : "running");
317			return;
318		case KERN_VNODE:
319		case KERN_FILE:
320			if (flags == 0)
321				return;
322			warnx("use pstat to view %s information", string);
323			return;
324		case KERN_PROC:
325			if (flags == 0)
326				return;
327			warnx("use ps to view %s information", string);
328			return;
329		case KERN_NTPTIME:
330			if (flags == 0)
331				return;
332			warnx("use xntpdc to view %s information", string);
333			return;
334		case KERN_CLOCKRATE:
335			special |= CLOCK;
336			break;
337		case KERN_BOOTTIME:
338			special |= BOOTTIME;
339			break;
340		case KERN_RND:
341			special |= RNDSTATS;
342			break;
343		case KERN_HOSTID:
344		case KERN_ARND:
345			special |= UNSIGNED;
346			break;
347		}
348		break;
349
350	case CTL_HW:
351		break;
352
353	case CTL_VM:
354		if (mib[1] == VM_LOADAVG) {
355			double loads[3];
356
357			getloadavg(loads, 3);
358			if (!nflag)
359				(void)printf("%s = ", string);
360			(void)printf("%.2f %.2f %.2f\n", loads[0],
361			    loads[1], loads[2]);
362			return;
363		} else if (mib[1] == VM_PSSTRINGS) {
364			struct _ps_strings _ps;
365
366			len = sizeof(_ps);
367			if (sysctl(mib, 2, &_ps, &len, NULL, 0) == -1) {
368				if (flags == 0)
369					return;
370				if (!nflag)
371					(void)printf("%s: ", string);
372				(void)puts("can't find ps strings");
373				return;
374			}
375			if (!nflag)
376				(void)printf("%s = ", string);
377			(void)printf("%p\n", _ps.val);
378			return;
379		}
380		if (flags == 0)
381			return;
382		warnx("use vmstat or systat to view %s information", string);
383		return;
384
385	case CTL_NET:
386		if (mib[1] == PF_INET) {
387			len = sysctl_inet(string, &bufp, mib, flags, &type);
388			if (len < 0)
389				return;
390
391			if ((mib[2] == IPPROTO_TCP &&
392			     mib[3] == TCPCTL_BADDYNAMIC) ||
393			    (mib[2] == IPPROTO_UDP &&
394			     mib[3] == UDPCTL_BADDYNAMIC)) {
395
396				special |= BADDYNAMIC;
397
398				if (newval != NULL)
399					parse_baddynamic(mib, len, string,
400					    &newval, &newsize, flags, nflag);
401			}
402			break;
403		}
404#ifdef INET6
405		if (mib[1] == PF_INET6) {
406			len = sysctl_inet6(string, &bufp, mib, flags, &type);
407			if (len < 0)
408				return;
409
410			break;
411		}
412#endif
413		if (mib[1] == PF_IPX) {
414			len = sysctl_ipx(string, &bufp, mib, flags, &type);
415			if (len >= 0)
416				break;
417			return;
418		}
419		if (flags == 0)
420			return;
421		warnx("use netstat to view %s information", string);
422		return;
423
424	case CTL_DEBUG:
425		mib[2] = CTL_DEBUG_VALUE;
426		len = 3;
427		break;
428
429	case CTL_MACHDEP:
430#ifdef CPU_CONSDEV
431		if (mib[1] == CPU_CONSDEV)
432			special |= CHRDEV;
433#endif
434#ifdef CPU_BLK2CHR
435		if (mib[1] == CPU_BLK2CHR) {
436			if (bufp == NULL)
437				return;
438			mib[2] = makedev(atoi(bufp),0);
439			bufp = NULL;
440			len = 3;
441			special |= CHRDEV;
442			break;
443		}
444#endif
445#ifdef CPU_CHR2BLK
446		if (mib[1] == CPU_CHR2BLK) {
447			if (bufp == NULL)
448				return;
449			mib[2] = makedev(atoi(bufp),0);
450			bufp = NULL;
451			len = 3;
452			special |= BLKDEV;
453			break;
454		}
455#endif
456#ifdef CPU_BIOS
457		if (mib[1] == CPU_BIOS) {
458			len = sysctl_bios(string, &bufp, mib, flags, &type);
459			if (len < 0)
460				return;
461			if (mib[2] == BIOS_DEV)
462				special |= BIOSDEV;
463			if (mib[2] == BIOS_DISKINFO)
464				special |= BIOSGEO;
465			break;
466		}
467#endif
468		break;
469
470	case CTL_FS:
471		len = sysctl_fs(string, &bufp, mib, flags, &type);
472		if (len >= 0)
473			break;
474		return;
475
476	case CTL_VFS:
477		mib[3] = mib[1];
478		mib[1] = VFS_GENERIC;
479		mib[2] = VFS_CONF;
480		len = 4;
481		size = sizeof vfc;
482		if (sysctl(mib, 4, &vfc, &size, (void *)0, (size_t)0) < 0) {
483			if (errno != EOPNOTSUPP)
484				perror("vfs print");
485			return;
486		}
487		if (flags == 0 && vfc.vfc_refcount == 0)
488			return;
489		if (!nflag)
490			fprintf(stdout, "%s has %d mounted instance%s\n",
491			    string, vfc.vfc_refcount,
492			    vfc.vfc_refcount != 1 ? "s" : "");
493		else
494			fprintf(stdout, "%d\n", vfc.vfc_refcount);
495		return;
496
497	case CTL_USER:
498	case CTL_DDB:
499		break;
500
501	default:
502		warnx("illegal top level value: %d", mib[0]);
503		return;
504
505	}
506	if (bufp) {
507		warnx("name %s in %s is unknown", bufp, string);
508		return;
509	}
510	if (newsize > 0) {
511		switch (type) {
512		case CTLTYPE_INT:
513			errno = 0;
514			if (special & UNSIGNED)
515				intval = strtoul(newval, &cp, 10);
516			else
517				intval = strtol(newval, &cp, 10);
518			if (*cp != '\0') {
519				warnx("%s: illegal value: %s", string,
520				    (char *)newval);
521				return;
522			}
523			if (errno == ERANGE) {
524				warnx("%s: value %s out of range", string,
525				    (char *)newval);
526				return;
527			}
528			newval = &intval;
529			newsize = sizeof(intval);
530			break;
531
532		case CTLTYPE_QUAD:
533			(void)sscanf(newval, "%qd", &quadval);
534			newval = &quadval;
535			newsize = sizeof(quadval);
536			break;
537		}
538	}
539	size = BUFSIZ;
540	if (sysctl(mib, len, buf, &size, newsize ? newval : 0, newsize) == -1) {
541		if (flags == 0)
542			return;
543		switch (errno) {
544		case EOPNOTSUPP:
545			warnx("%s: value is not available", string);
546			return;
547		case ENOTDIR:
548			warnx("%s: specification is incomplete", string);
549			return;
550		case ENOMEM:
551			warnx("%s: type is unknown to this program", string);
552			return;
553		case ENXIO:
554			if (special & BIOSGEO)
555				return;
556		default:
557			warn(string);
558			return;
559		}
560	}
561	if (special & CLOCK) {
562		struct clockinfo *clkp = (struct clockinfo *)buf;
563
564		if (!nflag)
565			(void)printf("%s = ", string);
566		(void)printf(
567		    "tick = %d, tickadj = %d, hz = %d, profhz = %d, stathz = %d\n",
568		    clkp->tick, clkp->tickadj, clkp->hz, clkp->profhz, clkp->stathz);
569		return;
570	}
571	if (special & BOOTTIME) {
572		struct timeval *btp = (struct timeval *)buf;
573		time_t boottime;
574
575		if (!nflag) {
576			boottime = btp->tv_sec;
577			(void)printf("%s = %s", string, ctime(&boottime));
578		} else
579			(void)printf("%ld\n", btp->tv_sec);
580		return;
581	}
582	if (special & BLKDEV) {
583		dev_t dev = *(dev_t *)buf;
584
585		if (!nflag)
586			(void)printf("%s = %s\n", string,
587			    devname(dev, S_IFBLK));
588		else
589			(void)printf("0x%x\n", dev);
590		return;
591	}
592	if (special & CHRDEV) {
593		dev_t dev = *(dev_t *)buf;
594
595		if (!nflag)
596			(void)printf("%s = %s\n", string,
597			    devname(dev, S_IFCHR));
598		else
599			(void)printf("0x%x\n", dev);
600		return;
601	}
602#ifdef CPU_BIOS
603	if (special & BIOSGEO) {
604		bios_diskinfo_t *pdi = (bios_diskinfo_t *)buf;
605
606		if (!nflag)
607			(void)printf("%s = ", string);
608		(void)printf("bootdev = 0x%x, "
609			     "cylinders = %u, heads = %u, sectors = %u\n",
610			     pdi->bsd_dev, pdi->bios_cylinders, pdi->bios_heads,
611			     pdi->bios_sectors);
612		return;
613	}
614	if (special & BIOSDEV) {
615		int dev = *(int*)buf;
616
617		if (!nflag)
618			(void)printf("%s = ", string);
619		(void) printf("0x%02x\n", dev);
620		return;
621	}
622#endif
623	if (special & UNSIGNED) {
624		if (newsize == 0) {
625			if (!nflag)
626				(void)printf("%s = ", string);
627			(void)printf("%u\n", *(u_int *)buf);
628		} else {
629			if (!nflag)
630				(void)printf("%s: %u -> ", string,
631				    *(u_int *)buf);
632			(void)printf("%u\n", *(u_int *)newval);
633		}
634		return;
635	}
636	if (special & RNDSTATS) {
637		struct rndstats *rndstats = (struct rndstats *)buf;
638
639		if (!nflag)
640			(void)printf("%s = ", string);
641		(void)printf(
642		    "%u %u %u %u %u %u %u %u %u %u %u %u %u %u %u %u\n",
643		    rndstats->rnd_total, rndstats->rnd_used,
644		    rndstats->arc4_reads, rndstats->rnd_timer,
645		    rndstats->rnd_mouse, rndstats->rnd_tty,
646		    rndstats->rnd_disk, rndstats->rnd_net,
647		    rndstats->rnd_reads, rndstats->rnd_waits,
648		    rndstats->rnd_enqs, rndstats->rnd_deqs,
649		    rndstats->rnd_drops, rndstats->rnd_drople,
650		    rndstats->rnd_asleep, rndstats->rnd_queued);
651		return;
652	}
653	if (special & BADDYNAMIC) {
654		in_port_t port, lastport;
655		u_int32_t *baddynamic = (u_int32_t *)buf;
656
657		if (!nflag)
658			(void)printf("%s%s", string, newsize ? ": " : " = ");
659		lastport = 0;
660		for (port = IPPORT_RESERVED/2; port < IPPORT_RESERVED; port++)
661			if (DP_ISSET(baddynamic, port)) {
662				(void)printf("%s%hd", lastport ? "," : "",
663				    port);
664				lastport = port;
665			}
666		if (newsize != 0) {
667			if (!nflag)
668				fputs(" -> ", stdout);
669			baddynamic = (u_int32_t *)newval;
670			lastport = 0;
671			for (port = IPPORT_RESERVED/2; port < IPPORT_RESERVED;
672			    port++)
673				if (DP_ISSET(baddynamic, port)) {
674					(void)printf("%s%hd",
675					    lastport ? "," : "", port);
676					lastport = port;
677				}
678		}
679		(void)putchar('\n');
680		return;
681	}
682	switch (type) {
683	case CTLTYPE_INT:
684		if (newsize == 0) {
685			if (!nflag)
686				(void)printf("%s = ", string);
687			(void)printf("%d\n", *(int *)buf);
688		} else {
689			if (!nflag)
690				(void)printf("%s: %d -> ", string,
691				    *(int *)buf);
692			(void)printf("%d\n", *(int *)newval);
693		}
694		return;
695
696	case CTLTYPE_STRING:
697		if (newsize == 0) {
698			if (!nflag)
699				(void)printf("%s = ", string);
700			(void)puts(buf);
701		} else {
702			if (!nflag)
703				(void)printf("%s: %s -> ", string, buf);
704			(void)puts((char *)newval);
705		}
706		return;
707
708	case CTLTYPE_QUAD:
709		if (newsize == 0) {
710			if (!nflag)
711				(void)printf("%s = ", string);
712			(void)printf("%qd\n", *(quad_t *)buf);
713		} else {
714			if (!nflag)
715				(void)printf("%s: %qd -> ", string,
716				    *(quad_t *)buf);
717			(void)printf("%qd\n", *(quad_t *)newval);
718		}
719		return;
720
721	case CTLTYPE_STRUCT:
722		warnx("%s: unknown structure returned", string);
723		return;
724
725	default:
726	case CTLTYPE_NODE:
727		warnx("%s: unknown type returned", string);
728		return;
729	}
730}
731
732void
733parse_baddynamic(mib, len, string, newvalp, newsizep, flags, nflag)
734	int mib[];
735	size_t len;
736	char *string;
737	void **newvalp;
738	size_t *newsizep;
739	int flags;
740	int nflag;
741{
742	static u_int32_t newbaddynamic[DP_MAPSIZE];
743	in_port_t port;
744	size_t size;
745	char action, *cp;
746
747	if (strchr((char *)*newvalp, '+') || strchr((char *)*newvalp, '-')) {
748		size = sizeof(newbaddynamic);
749		if (sysctl(mib, len, newbaddynamic, &size, 0, 0) == -1) {
750			if (flags == 0)
751				return;
752			if (!nflag)
753				(void)printf("%s: ", string);
754			(void)puts("kernel does contain bad dynamic port tables");
755			return;
756		}
757
758		while (*newvalp && (cp = strsep((char **)newvalp, ", \t")) && *cp) {
759			if (*cp != '+' && *cp != '-')
760				errx(1, "cannot mix +/- with full list");
761			action = *cp++;
762			port = atoi(cp);
763			if (port < IPPORT_RESERVED/2 || port >= IPPORT_RESERVED)
764				errx(1, "invalid port, range is %d to %d",
765				    IPPORT_RESERVED/2, IPPORT_RESERVED-1);
766			if (action == '+')
767				DP_SET(newbaddynamic, port);
768			else
769				DP_CLR(newbaddynamic, port);
770		}
771	} else {
772		(void)memset((void *)newbaddynamic, 0, sizeof(newbaddynamic));
773		while (*newvalp && (cp = strsep((char **)newvalp, ", \t")) && *cp) {
774			port = atoi(cp);
775			if (port < IPPORT_RESERVED/2 || port >= IPPORT_RESERVED)
776				errx(1, "invalid port, range is %d to %d",
777				    IPPORT_RESERVED/2, IPPORT_RESERVED-1);
778			DP_SET(newbaddynamic, port);
779		}
780	}
781
782	*newvalp = (void *)newbaddynamic;
783	*newsizep = sizeof(newbaddynamic);
784}
785
786/*
787 * Initialize the set of debugging names
788 */
789void
790debuginit()
791{
792	int mib[3], loc, i;
793	size_t size;
794
795	if (secondlevel[CTL_DEBUG].list != 0)
796		return;
797	secondlevel[CTL_DEBUG].list = debugname;
798	mib[0] = CTL_DEBUG;
799	mib[2] = CTL_DEBUG_NAME;
800	for (loc = lastused, i = 0; i < CTL_DEBUG_MAXID; i++) {
801		mib[1] = i;
802		size = BUFSIZ - loc;
803		if (sysctl(mib, 3, &names[loc], &size, NULL, 0) == -1)
804			continue;
805		debugname[i].ctl_name = &names[loc];
806		debugname[i].ctl_type = CTLTYPE_INT;
807		loc += size;
808	}
809	lastused = loc;
810}
811
812/*
813 * Initialize the set of filesystem names
814 */
815void
816vfsinit()
817{
818	int mib[4], maxtypenum, cnt, loc, size;
819	struct vfsconf vfc;
820	size_t buflen;
821
822	if (secondlevel[CTL_VFS].list != 0)
823		return;
824	mib[0] = CTL_VFS;
825	mib[1] = VFS_GENERIC;
826	mib[2] = VFS_MAXTYPENUM;
827	buflen = 4;
828	if (sysctl(mib, 3, &maxtypenum, &buflen, (void *)0, (size_t)0) < 0)
829		return;
830	if ((vfsname = malloc(maxtypenum * sizeof(*vfsname))) == 0)
831		return;
832	memset(vfsname, 0, maxtypenum * sizeof(*vfsname));
833	mib[2] = VFS_CONF;
834	buflen = sizeof vfc;
835	for (loc = lastused, cnt = 0; cnt < maxtypenum; cnt++) {
836		mib[3] = cnt;
837		if (sysctl(mib, 4, &vfc, &buflen, (void *)0, (size_t)0) < 0) {
838			if (errno == EOPNOTSUPP)
839				continue;
840			perror("vfsinit");
841			free(vfsname);
842			return;
843		}
844		strcat(&names[loc], vfc.vfc_name);
845		vfsname[cnt].ctl_name = &names[loc];
846		vfsname[cnt].ctl_type = CTLTYPE_INT;
847		size = strlen(vfc.vfc_name) + 1;
848		loc += size;
849	}
850	lastused = loc;
851	secondlevel[CTL_VFS].list = vfsname;
852	secondlevel[CTL_VFS].size = maxtypenum;
853	return;
854}
855
856struct ctlname posixname[] = CTL_FS_POSIX_NAMES;
857struct list fslist = { posixname, FS_POSIX_MAXID };
858
859/*
860 * handle file system requests
861 */
862int
863sysctl_fs(string, bufpp, mib, flags, typep)
864	char *string;
865	char **bufpp;
866	int mib[];
867	int flags;
868	int *typep;
869{
870	int indx;
871
872	if (*bufpp == NULL) {
873		listall(string, &fslist);
874		return(-1);
875	}
876	if ((indx = findname(string, "third", bufpp, &fslist)) == -1)
877		return(-1);
878	mib[2] = indx;
879	*typep = fslist.list[indx].ctl_type;
880	return(3);
881}
882
883#ifdef CPU_BIOS
884struct ctlname biosname[] = CTL_BIOS_NAMES;
885struct list bioslist = { biosname, BIOS_MAXID };
886
887/*
888 * handle BIOS requests
889 */
890int
891sysctl_bios(string, bufpp, mib, flags, typep)
892	char *string;
893	char **bufpp;
894	int mib[];
895	int flags;
896	int *typep;
897{
898	char *name;
899	int indx;
900
901	if (*bufpp == NULL) {
902		listall(string, &bioslist);
903		return(-1);
904	}
905	if ((indx = findname(string, "third", bufpp, &bioslist)) == -1)
906		return(-1);
907	mib[2] = indx;
908	if (indx == BIOS_DISKINFO) {
909		if (*bufpp == NULL) {
910			char name[BUFSIZ];
911
912			/* scan all the bios devices */
913			for (indx = 0; indx < 256; indx++) {
914				snprintf(name, sizeof(name), "%s.%u",
915					 string, indx);
916				parse(name, 1);
917			}
918			return(-1);
919		}
920		if ((name = strsep(bufpp, ".")) == NULL) {
921			warnx("%s: incomplete specification", string);
922			return(-1);
923		}
924		mib[3] = atoi(name);
925		*typep = CTLTYPE_STRUCT;
926		return 4;
927	} else {
928		*typep = bioslist.list[indx].ctl_type;
929		return(3);
930	}
931}
932#endif
933
934struct ctlname inetname[] = CTL_IPPROTO_NAMES;
935struct ctlname ipname[] = IPCTL_NAMES;
936struct ctlname icmpname[] = ICMPCTL_NAMES;
937struct ctlname ip4name[] = IP4CTL_NAMES;
938struct ctlname tcpname[] = TCPCTL_NAMES;
939struct ctlname udpname[] = UDPCTL_NAMES;
940struct ctlname espname[] = ESPCTL_NAMES;
941struct ctlname ahname[] = AHCTL_NAMES;
942struct ctlname etheripname[] = ETHERIPCTL_NAMES;
943struct list inetlist = { inetname, IPPROTO_MAXID };
944struct list inetvars[] = {
945	{ ipname, IPCTL_MAXID },	/* ip */
946	{ icmpname, ICMPCTL_MAXID },	/* icmp */
947	{ 0, 0 },			/* igmp */
948	{ 0, 0 },			/* ggmp */
949	{ ip4name, IP4CTL_MAXID },	/* ipencap */
950	{ 0, 0 },
951	{ tcpname, TCPCTL_MAXID },	/* tcp */
952	{ 0, 0 },
953	{ 0, 0 },			/* egp */
954	{ 0, 0 },
955	{ 0, 0 },
956	{ 0, 0 },
957	{ 0, 0 },			/* pup */
958	{ 0, 0 },
959	{ 0, 0 },
960	{ 0, 0 },
961	{ 0, 0 },
962	{ udpname, UDPCTL_MAXID },	/* udp */
963	{ 0, 0 },
964	{ 0, 0 },
965	{ 0, 0 },
966	{ 0, 0 },
967	{ 0, 0 },
968	{ 0, 0 },
969	{ 0, 0 },
970	{ 0, 0 },
971	{ 0, 0 },
972	{ 0, 0 },
973	{ 0, 0 },
974	{ 0, 0 },
975	{ 0, 0 },
976	{ 0, 0 },
977	{ 0, 0 },
978	{ 0, 0 },
979	{ 0, 0 },
980	{ 0, 0 },
981	{ 0, 0 },
982	{ 0, 0 },
983	{ 0, 0 },
984	{ 0, 0 },
985	{ 0, 0 },
986	{ 0, 0 },
987	{ 0, 0 },
988	{ 0, 0 },
989	{ 0, 0 },
990	{ 0, 0 },
991	{ 0, 0 },
992	{ 0, 0 },
993	{ 0, 0 },
994	{ 0, 0 },
995	{ espname, ESPCTL_MAXID },	/* esp */
996	{ ahname, AHCTL_MAXID },	/* ah */
997	{ 0, 0 },
998	{ 0, 0 },
999	{ 0, 0 },
1000	{ 0, 0 },
1001	{ 0, 0 },
1002	{ 0, 0 },
1003	{ 0, 0 },
1004	{ 0, 0 },
1005	{ 0, 0 },
1006	{ 0, 0 },
1007	{ 0, 0 },
1008	{ 0, 0 },
1009	{ 0, 0 },
1010	{ 0, 0 },
1011	{ 0, 0 },
1012	{ 0, 0 },
1013	{ 0, 0 },
1014	{ 0, 0 },
1015	{ 0, 0 },
1016	{ 0, 0 },
1017	{ 0, 0 },
1018	{ 0, 0 },
1019	{ 0, 0 },
1020	{ 0, 0 },
1021	{ 0, 0 },
1022	{ 0, 0 },
1023	{ 0, 0 },
1024	{ 0, 0 },
1025	{ 0, 0 },
1026	{ 0, 0 },
1027	{ 0, 0 },
1028	{ 0, 0 },
1029	{ 0, 0 },
1030	{ 0, 0 },
1031	{ 0, 0 },
1032	{ 0, 0 },
1033	{ 0, 0 },
1034	{ 0, 0 },
1035	{ 0, 0 },
1036	{ 0, 0 },
1037	{ 0, 0 },
1038	{ 0, 0 },
1039	{ 0, 0 },
1040	{ 0, 0 },
1041	{ 0, 0 },
1042	{ etheripname, ETHERIPCTL_MAXID },
1043};
1044
1045/*
1046 * handle internet requests
1047 */
1048int
1049sysctl_inet(string, bufpp, mib, flags, typep)
1050	char *string;
1051	char **bufpp;
1052	int mib[];
1053	int flags;
1054	int *typep;
1055{
1056	struct list *lp;
1057	int indx;
1058
1059	if (*bufpp == NULL) {
1060		listall(string, &inetlist);
1061		return(-1);
1062	}
1063	if ((indx = findname(string, "third", bufpp, &inetlist)) == -1)
1064		return(-1);
1065	mib[2] = indx;
1066	if (indx < IPPROTO_MAXID && inetvars[indx].list != NULL)
1067		lp = &inetvars[indx];
1068	else if (!flags)
1069		return(-1);
1070	else {
1071		warnx("%s: no variables defined for this protocol", string);
1072		return(-1);
1073	}
1074	if (*bufpp == NULL) {
1075		listall(string, lp);
1076		return(-1);
1077	}
1078	if ((indx = findname(string, "fourth", bufpp, lp)) == -1)
1079		return(-1);
1080	mib[3] = indx;
1081	*typep = lp->list[indx].ctl_type;
1082	return(4);
1083}
1084
1085#ifdef INET6
1086struct ctlname inet6name[] = CTL_IPV6PROTO_NAMES;
1087struct ctlname ip6name[] = IPV6CTL_NAMES;
1088struct ctlname icmp6name[] = ICMPV6CTL_NAMES;
1089struct ctlname pim6name[] = PIMCTL_NAMES;
1090struct list inet6list = { inet6name, IPV6PROTO_MAXID };
1091struct list inet6vars[] = {
1092/*0*/	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
1093	{ 0, 0 },
1094	{ 0, 0 },
1095	{ 0, 0 },
1096	{ 0, 0 },
1097	{ 0, 0 },
1098/*10*/	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
1099	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
1100/*20*/	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
1101	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
1102/*30*/	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
1103	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
1104/*40*/	{ 0, 0 },
1105	{ ip6name, IPV6CTL_MAXID },	/* ipv6 */
1106	{ 0, 0 },
1107	{ 0, 0 },
1108	{ 0, 0 },
1109	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
1110/*50*/	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
1111	{ 0, 0 },
1112	{ 0, 0 },
1113	{ 0, 0 },
1114	{ icmp6name, ICMPV6CTL_MAXID },	/* icmp6 */
1115	{ 0, 0 },
1116/*60*/	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
1117	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
1118/*70*/	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
1119	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
1120/*80*/	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
1121	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
1122/*90*/	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
1123	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
1124/*100*/	{ 0, 0 },
1125	{ 0, 0 },
1126	{ 0, 0 },
1127	{ pim6name, PIMCTL_MAXID },	/* pim6 */
1128};
1129
1130/*
1131 * handle internet6 requests
1132 */
1133int
1134sysctl_inet6(string, bufpp, mib, flags, typep)
1135	char *string;
1136	char **bufpp;
1137	int mib[];
1138	int flags;
1139	int *typep;
1140{
1141	struct list *lp;
1142	int indx;
1143
1144	if (*bufpp == NULL) {
1145		listall(string, &inet6list);
1146		return(-1);
1147	}
1148	if ((indx = findname(string, "third", bufpp, &inet6list)) == -1)
1149		return(-1);
1150	mib[2] = indx;
1151	if (indx < IPV6PROTO_MAXID && inet6vars[indx].list != NULL)
1152		lp = &inet6vars[indx];
1153	else if (!flags)
1154		return(-1);
1155	else {
1156		warnx("%s: no variables defined for this protocol", string);
1157		return(-1);
1158	}
1159	if (*bufpp == NULL) {
1160		listall(string, lp);
1161		return(-1);
1162	}
1163	if ((indx = findname(string, "fourth", bufpp, lp)) == -1)
1164		return(-1);
1165	mib[3] = indx;
1166	*typep = lp->list[indx].ctl_type;
1167	return(4);
1168}
1169#endif
1170
1171struct ctlname ipxname[] = CTL_IPXPROTO_NAMES;
1172struct ctlname ipxpname[] = IPXCTL_NAMES;
1173struct ctlname spxpname[] = SPXCTL_NAMES;
1174struct list ipxlist = { ipxname, IPXCTL_MAXID };
1175struct list ipxvars[] = {
1176	{ ipxpname, IPXCTL_MAXID },	/* ipx */
1177	{ 0, 0 },
1178	{ 0, 0 },
1179	{ 0, 0 },
1180	{ 0, 0 },
1181	{ spxpname, SPXCTL_MAXID },
1182};
1183
1184/*
1185 * Handle internet requests
1186 */
1187int
1188sysctl_ipx(string, bufpp, mib, flags, typep)
1189	char *string;
1190	char **bufpp;
1191	int mib[];
1192	int flags;
1193	int *typep;
1194{
1195	struct list *lp;
1196	int indx;
1197
1198	if (*bufpp == NULL) {
1199		listall(string, &ipxlist);
1200		return(-1);
1201	}
1202	if ((indx = findname(string, "third", bufpp, &ipxlist)) == -1)
1203		return(-1);
1204	mib[2] = indx;
1205	if (indx <= IPXPROTO_SPX && ipxvars[indx].list != NULL)
1206		lp = &ipxvars[indx];
1207	else if (!flags)
1208		return(-1);
1209	else {
1210		warnx("%s: no variables defined for this protocol", string);
1211		return(-1);
1212	}
1213	if (*bufpp == NULL) {
1214		listall(string, lp);
1215		return(-1);
1216	}
1217	if ((indx = findname(string, "fourth", bufpp, lp)) == -1)
1218		return(-1);
1219	mib[3] = indx;
1220	*typep = lp->list[indx].ctl_type;
1221	return(4);
1222}
1223
1224/*
1225 * Scan a list of names searching for a particular name.
1226 */
1227int
1228findname(string, level, bufp, namelist)
1229	char *string;
1230	char *level;
1231	char **bufp;
1232	struct list *namelist;
1233{
1234	char *name;
1235	int i;
1236
1237	if (namelist->list == 0 || (name = strsep(bufp, ".")) == NULL) {
1238		warnx("%s: incomplete specification", string);
1239		return(-1);
1240	}
1241	for (i = 0; i < namelist->size; i++)
1242		if (namelist->list[i].ctl_name != NULL &&
1243		    strcmp(name, namelist->list[i].ctl_name) == 0)
1244			break;
1245	if (i == namelist->size) {
1246		warnx("%s level name %s in %s is invalid", level, name, string);
1247		return(-1);
1248	}
1249	return(i);
1250}
1251
1252void
1253usage()
1254{
1255
1256	(void)fprintf(stderr, "usage:\t%s\n\t%s\n\t%s\n\t%s\n",
1257	    "sysctl [-n] variable ...", "sysctl [-n] -w variable=value ...",
1258	    "sysctl [-n] -a", "sysctl [-n] -A");
1259	exit(1);
1260}
1261