sysctl.c revision 1.56
1/*	$OpenBSD: sysctl.c,v 1.56 2001/01/04 06:07:22 angelos 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.56 2001/01/04 06:07:22 angelos 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 <sys/malloc.h>
58#include <vm/vm_param.h>
59#include <machine/cpu.h>
60#include <net/route.h>
61
62#include <netinet/in.h>
63#include <netinet/in_systm.h>
64#include <netinet/ip.h>
65#include <netinet/in_pcb.h>
66#include <netinet/ip_icmp.h>
67#include <netinet/ip_ipip.h>
68#include <netinet/ip_ether.h>
69#include <netinet/ip_ah.h>
70#include <netinet/ip_esp.h>
71#include <netinet/icmp_var.h>
72#include <netinet/ip_var.h>
73#include <netinet/udp.h>
74#include <netinet/udp_var.h>
75#include <netinet/tcp.h>
76#include <netinet/tcp_timer.h>
77#include <netinet/tcp_var.h>
78#include <netinet/ip_gre.h>
79
80#ifdef INET6
81#include <netinet/ip6.h>
82#include <netinet/icmp6.h>
83#include <netinet6/ip6_var.h>
84#include <netinet6/pim6_var.h>
85#endif
86
87#ifdef UVM
88#include <uvm/uvm_swap_encrypt.h>
89#endif
90
91#include <ufs/ufs/quota.h>
92#include <ufs/ufs/inode.h>
93#include <ufs/ffs/fs.h>
94#include <ufs/ffs/ffs_extern.h>
95
96#include <nfs/rpcv2.h>
97#include <nfs/nfsproto.h>
98#include <nfs/nfs.h>
99
100#include <netipx/ipx.h>
101#include <netipx/ipx_var.h>
102#include <netipx/spx_var.h>
103#include <ddb/db_var.h>
104#include <dev/rndvar.h>
105
106#include <err.h>
107#include <errno.h>
108#include <stdio.h>
109#include <stdlib.h>
110#include <string.h>
111#include <ctype.h>
112
113#ifdef CPU_BIOS
114#include <machine/biosvar.h>
115#endif
116
117struct ctlname topname[] = CTL_NAMES;
118struct ctlname kernname[] = CTL_KERN_NAMES;
119struct ctlname vmname[] = CTL_VM_NAMES;
120struct ctlname fsname[] = CTL_FS_NAMES;
121struct ctlname netname[] = CTL_NET_NAMES;
122struct ctlname hwname[] = CTL_HW_NAMES;
123struct ctlname username[] = CTL_USER_NAMES;
124struct ctlname debugname[CTL_DEBUG_MAXID];
125struct ctlname kernmallocname[] = CTL_KERN_MALLOC_NAMES;
126struct ctlname kernbucketname[] = CTL_KERN_MALLOC_BUCKET_NAMES;
127struct ctlname *vfsname;
128#ifdef CTL_MACHDEP_NAMES
129struct ctlname machdepname[] = CTL_MACHDEP_NAMES;
130#endif
131struct ctlname ddbname[] = CTL_DDB_NAMES;
132char names[BUFSIZ];
133int lastused;
134
135struct list {
136	struct	ctlname *list;
137	int	size;
138};
139struct list toplist = { topname, CTL_MAXID };
140struct list secondlevel[] = {
141	{ 0, 0 },			/* CTL_UNSPEC */
142	{ kernname, KERN_MAXID },	/* CTL_KERN */
143	{ vmname, VM_MAXID },		/* CTL_VM */
144	{ fsname, FS_MAXID },		/* CTL_FS */
145	{ netname, NET_MAXID },		/* CTL_NET */
146	{ 0, CTL_DEBUG_MAXID },		/* CTL_DEBUG */
147	{ hwname, HW_MAXID },		/* CTL_HW */
148#ifdef CTL_MACHDEP_NAMES
149	{ machdepname, CPU_MAXID },	/* CTL_MACHDEP */
150#else
151	{ 0, 0 },			/* CTL_MACHDEP */
152#endif
153	{ username, USER_MAXID },	/* CTL_USER_NAMES */
154	{ ddbname, DBCTL_MAXID },	/* CTL_DDB_NAMES */
155	{ 0, 0 },			/* CTL_VFS */
156};
157
158int	Aflag, aflag, nflag, wflag;
159
160/*
161 * Variables requiring special processing.
162 */
163#define	CLOCK		0x00000001
164#define	BOOTTIME	0x00000002
165#define	CHRDEV		0x00000004
166#define	BLKDEV		0x00000008
167#define	RNDSTATS	0x00000010
168#define	BADDYNAMIC	0x00000020
169#define	BIOSGEO		0x00000040
170#define	BIOSDEV		0x00000080
171#define	MAJ2DEV		0x00000100
172#define	UNSIGNED	0x00000200
173
174/* prototypes */
175void debuginit __P((void));
176void listall __P((char *, struct list *));
177void parse __P((char *, int));
178void parse_baddynamic __P((int *, size_t, char *, void **, size_t *, int, int));
179void usage __P((void));
180int findname __P((char *, char *, char **, struct list *));
181int sysctl_inet __P((char *, char **, int *, int, int *));
182#ifdef INET6
183int sysctl_inet6 __P((char *, char **, int *, int, int *));
184#endif
185int sysctl_ipx __P((char *, char **, int *, int, int *));
186int sysctl_fs __P((char *, char **, int *, int, int *));
187static int sysctl_vfs __P((char *, char **, int[], int, int *));
188static int sysctl_vfsgen __P((char *, char **, int[], int, int *));
189int sysctl_bios __P((char *, char **, int *, int, int *));
190int sysctl_swpenc __P((char *, char **, int *, int, int *));
191void vfsinit __P((void));
192
193int
194main(argc, argv)
195	int argc;
196	char *argv[];
197{
198	int ch, lvl1;
199
200	while ((ch = getopt(argc, argv, "Aanw")) != -1) {
201		switch (ch) {
202
203		case 'A':
204			Aflag = 1;
205			break;
206
207		case 'a':
208			aflag = 1;
209			break;
210
211		case 'n':
212			nflag = 1;
213			break;
214
215		case 'w':
216			wflag = 1;
217			break;
218
219		default:
220			usage();
221		}
222	}
223	argc -= optind;
224	argv += optind;
225
226	if (argc == 0 && (Aflag || aflag)) {
227		debuginit();
228		vfsinit();
229		for (lvl1 = 1; lvl1 < CTL_MAXID; lvl1++)
230			listall(topname[lvl1].ctl_name, &secondlevel[lvl1]);
231		exit(0);
232	}
233	if (argc == 0)
234		usage();
235	for (; *argv != NULL; ++argv)
236		parse(*argv, 1);
237	exit(0);
238}
239
240/*
241 * List all variables known to the system.
242 */
243void
244listall(prefix, lp)
245	char *prefix;
246	struct list *lp;
247{
248	int lvl2;
249	char *cp, name[BUFSIZ];
250
251	if (lp->list == NULL)
252		return;
253	(void)strlcpy(name, prefix, BUFSIZ);
254	cp = &name[strlen(name)];
255	*cp++ = '.';
256	for (lvl2 = 0; lvl2 < lp->size; lvl2++) {
257		if (lp->list[lvl2].ctl_name == NULL)
258			continue;
259		(void)strcpy(cp, lp->list[lvl2].ctl_name);
260		parse(name, Aflag);
261	}
262}
263
264/*
265 * Parse a name into a MIB entry.
266 * Lookup and print out the MIB entry if it exists.
267 * Set a new value if requested.
268 */
269void
270parse(string, flags)
271	char *string;
272	int flags;
273{
274	int indx, type, state, intval, len;
275	size_t size, newsize = 0;
276	int special = 0;
277	void *newval = 0;
278	quad_t quadval;
279	struct list *lp;
280	int mib[CTL_MAXNAME];
281	char *cp, *bufp, buf[BUFSIZ];
282
283	(void)strlcpy(buf, string, sizeof(buf));
284	bufp = buf;
285	if ((cp = strchr(string, '=')) != NULL) {
286		if (!wflag)
287			errx(2, "must specify -w to set variables");
288		*strchr(buf, '=') = '\0';
289		*cp++ = '\0';
290		while (isspace(*cp))
291			cp++;
292		newval = cp;
293		newsize = strlen(cp);
294	}
295	if ((indx = findname(string, "top", &bufp, &toplist)) == -1)
296		return;
297	mib[0] = indx;
298	if (indx == CTL_VFS)
299		vfsinit();
300	if (indx == CTL_DEBUG)
301		debuginit();
302	lp = &secondlevel[indx];
303	if (lp->list == 0) {
304		warnx("%s: class is not implemented", topname[indx].ctl_name);
305		return;
306	}
307	if (bufp == NULL) {
308		listall(topname[indx].ctl_name, lp);
309		return;
310	}
311	if ((indx = findname(string, "second", &bufp, lp)) == -1)
312		return;
313	mib[1] = indx;
314	type = lp->list[indx].ctl_type;
315	len = 2;
316	switch (mib[0]) {
317
318	case CTL_KERN:
319		switch (mib[1]) {
320		case KERN_PROF:
321			mib[2] = GPROF_STATE;
322			size = sizeof(state);
323			if (sysctl(mib, 3, &state, &size, NULL, 0) == -1) {
324				if (flags == 0)
325					return;
326				if (!nflag)
327					(void)printf("%s: ", string);
328				(void)puts("kernel is not compiled for profiling");
329				return;
330			}
331			if (!nflag)
332				(void)printf("%s = %s\n", string,
333				    state == GMON_PROF_OFF ? "off" : "running");
334			return;
335		case KERN_MALLOCSTATS:
336			len = sysctl_malloc(string, &bufp, mib, flags, &type);
337			if (len < 0)
338				return;
339			newsize = 0;
340			break;
341		case KERN_VNODE:
342		case KERN_FILE:
343			if (flags == 0)
344				return;
345			warnx("use pstat to view %s information", string);
346			return;
347		case KERN_PROC:
348			if (flags == 0)
349				return;
350			warnx("use ps to view %s information", string);
351			return;
352		case KERN_NTPTIME:
353			if (flags == 0)
354				return;
355			warnx("use xntpdc to view %s information", string);
356			return;
357		case KERN_CLOCKRATE:
358			special |= CLOCK;
359			break;
360		case KERN_BOOTTIME:
361			special |= BOOTTIME;
362			break;
363		case KERN_RND:
364			special |= RNDSTATS;
365			break;
366		case KERN_HOSTID:
367		case KERN_ARND:
368			special |= UNSIGNED;
369			break;
370		}
371		break;
372
373	case CTL_HW:
374		break;
375
376	case CTL_VM:
377		if (mib[1] == VM_LOADAVG) {
378			double loads[3];
379
380			getloadavg(loads, 3);
381			if (!nflag)
382				(void)printf("%s = ", string);
383			(void)printf("%.2f %.2f %.2f\n", loads[0],
384			    loads[1], loads[2]);
385			return;
386		} else if (mib[1] == VM_PSSTRINGS) {
387			struct _ps_strings _ps;
388
389			size = sizeof(_ps);
390			if (sysctl(mib, 2, &_ps, &size, NULL, 0) == -1) {
391				if (flags == 0)
392					return;
393				if (!nflag)
394					(void)printf("%s: ", string);
395				(void)puts("can't find ps strings");
396				return;
397			}
398			if (!nflag)
399				(void)printf("%s = ", string);
400			(void)printf("%p\n", _ps.val);
401			return;
402		}
403#ifdef UVM
404		else if (mib[1] == VM_SWAPENCRYPT) {
405			len = sysctl_swpenc(string, &bufp, mib, flags, &type);
406			if (len < 0)
407				return;
408
409			break;
410		}
411#endif
412		if (flags == 0)
413			return;
414		warnx("use vmstat or systat to view %s information", string);
415		return;
416
417		break;
418
419	case CTL_NET:
420		if (mib[1] == PF_INET) {
421			len = sysctl_inet(string, &bufp, mib, flags, &type);
422			if (len < 0)
423				return;
424
425			if ((mib[2] == IPPROTO_TCP &&
426			     mib[3] == TCPCTL_BADDYNAMIC) ||
427			    (mib[2] == IPPROTO_UDP &&
428			     mib[3] == UDPCTL_BADDYNAMIC)) {
429
430				special |= BADDYNAMIC;
431
432				if (newval != NULL)
433					parse_baddynamic(mib, len, string,
434					    &newval, &newsize, flags, nflag);
435			}
436			break;
437		}
438#ifdef INET6
439		if (mib[1] == PF_INET6) {
440			len = sysctl_inet6(string, &bufp, mib, flags, &type);
441			if (len < 0)
442				return;
443
444			break;
445		}
446#endif
447		if (mib[1] == PF_IPX) {
448			len = sysctl_ipx(string, &bufp, mib, flags, &type);
449			if (len >= 0)
450				break;
451			return;
452		}
453		if (flags == 0)
454			return;
455		warnx("use netstat to view %s information", string);
456		return;
457
458	case CTL_DEBUG:
459		mib[2] = CTL_DEBUG_VALUE;
460		len = 3;
461		break;
462
463	case CTL_MACHDEP:
464#ifdef CPU_CONSDEV
465		if (mib[1] == CPU_CONSDEV)
466			special |= CHRDEV;
467#endif
468#ifdef CPU_BLK2CHR
469		if (mib[1] == CPU_BLK2CHR) {
470			if (bufp == NULL)
471				return;
472			mib[2] = makedev(atoi(bufp),0);
473			bufp = NULL;
474			len = 3;
475			special |= CHRDEV;
476			break;
477		}
478#endif
479#ifdef CPU_CHR2BLK
480		if (mib[1] == CPU_CHR2BLK) {
481			if (bufp == NULL)
482				return;
483			mib[2] = makedev(atoi(bufp),0);
484			bufp = NULL;
485			len = 3;
486			special |= BLKDEV;
487			break;
488		}
489#endif
490#ifdef CPU_BIOS
491		if (mib[1] == CPU_BIOS) {
492			len = sysctl_bios(string, &bufp, mib, flags, &type);
493			if (len < 0)
494				return;
495			if (mib[2] == BIOS_DEV)
496				special |= BIOSDEV;
497			if (mib[2] == BIOS_DISKINFO)
498				special |= BIOSGEO;
499			break;
500		}
501#endif
502		break;
503
504	case CTL_FS:
505		len = sysctl_fs(string, &bufp, mib, flags, &type);
506		if (len >= 0)
507			break;
508		return;
509
510	case CTL_VFS:
511		if (mib[1])
512			len = sysctl_vfs(string, &bufp, mib, flags, &type);
513		else
514			len = sysctl_vfsgen(string, &bufp, mib, flags, &type);
515		if (len >= 0) {
516			if (type == CTLTYPE_STRUCT) {
517				if (flags)
518					warnx("use nfsstat to view %s information",
519					    MOUNT_NFS);
520				return;
521			} else
522				break;
523		}
524		return;
525
526	case CTL_USER:
527	case CTL_DDB:
528		break;
529
530	default:
531		warnx("illegal top level value: %d", mib[0]);
532		return;
533
534	}
535	if (bufp) {
536		warnx("name %s in %s is unknown", bufp, string);
537		return;
538	}
539	if (newsize > 0) {
540		switch (type) {
541		case CTLTYPE_INT:
542			errno = 0;
543			if (special & UNSIGNED)
544				intval = strtoul(newval, &cp, 10);
545			else
546				intval = strtol(newval, &cp, 10);
547			if (*cp != '\0') {
548				warnx("%s: illegal value: %s", string,
549				    (char *)newval);
550				return;
551			}
552			if (errno == ERANGE) {
553				warnx("%s: value %s out of range", string,
554				    (char *)newval);
555				return;
556			}
557			newval = &intval;
558			newsize = sizeof(intval);
559			break;
560
561		case CTLTYPE_QUAD:
562			(void)sscanf(newval, "%qd", &quadval);
563			newval = &quadval;
564			newsize = sizeof(quadval);
565			break;
566		}
567	}
568	size = BUFSIZ;
569	if (sysctl(mib, len, buf, &size, newsize ? newval : 0, newsize) == -1) {
570		if (flags == 0)
571			return;
572		switch (errno) {
573		case EOPNOTSUPP:
574			warnx("%s: value is not available", string);
575			return;
576		case ENOTDIR:
577			warnx("%s: specification is incomplete", string);
578			return;
579		case ENOMEM:
580			warnx("%s: type is unknown to this program", string);
581			return;
582		case ENXIO:
583			if (special & BIOSGEO)
584				return;
585		default:
586			warn("%s", string);
587			return;
588		}
589	}
590	if (special & CLOCK) {
591		struct clockinfo *clkp = (struct clockinfo *)buf;
592
593		if (!nflag)
594			(void)printf("%s = ", string);
595		(void)printf(
596		    "tick = %d, tickadj = %d, hz = %d, profhz = %d, stathz = %d\n",
597		    clkp->tick, clkp->tickadj, clkp->hz, clkp->profhz, clkp->stathz);
598		return;
599	}
600	if (special & BOOTTIME) {
601		struct timeval *btp = (struct timeval *)buf;
602		time_t boottime;
603
604		if (!nflag) {
605			boottime = btp->tv_sec;
606			(void)printf("%s = %s", string, ctime(&boottime));
607		} else
608			(void)printf("%ld\n", btp->tv_sec);
609		return;
610	}
611	if (special & BLKDEV) {
612		dev_t dev = *(dev_t *)buf;
613
614		if (!nflag)
615			(void)printf("%s = %s\n", string,
616			    devname(dev, S_IFBLK));
617		else
618			(void)printf("0x%x\n", dev);
619		return;
620	}
621	if (special & CHRDEV) {
622		dev_t dev = *(dev_t *)buf;
623
624		if (!nflag)
625			(void)printf("%s = %s\n", string,
626			    devname(dev, S_IFCHR));
627		else
628			(void)printf("0x%x\n", dev);
629		return;
630	}
631#ifdef CPU_BIOS
632	if (special & BIOSGEO) {
633		bios_diskinfo_t *pdi = (bios_diskinfo_t *)buf;
634
635		if (!nflag)
636			(void)printf("%s = ", string);
637		(void)printf("bootdev = 0x%x, "
638			     "cylinders = %u, heads = %u, sectors = %u\n",
639			     pdi->bsd_dev, pdi->bios_cylinders, pdi->bios_heads,
640			     pdi->bios_sectors);
641		return;
642	}
643	if (special & BIOSDEV) {
644		int dev = *(int*)buf;
645
646		if (!nflag)
647			(void)printf("%s = ", string);
648		(void) printf("0x%02x\n", dev);
649		return;
650	}
651#endif
652	if (special & UNSIGNED) {
653		if (newsize == 0) {
654			if (!nflag)
655				(void)printf("%s = ", string);
656			(void)printf("%u\n", *(u_int *)buf);
657		} else {
658			if (!nflag)
659				(void)printf("%s: %u -> ", string,
660				    *(u_int *)buf);
661			(void)printf("%u\n", *(u_int *)newval);
662		}
663		return;
664	}
665	if (special & RNDSTATS) {
666		struct rndstats *rndstats = (struct rndstats *)buf;
667		int i;
668
669		if (!nflag)
670			(void)printf("%s = ", string);
671		(void)printf(
672		"%qu %qu %qu %qu %qu %qu %qu %qu %qu %qu %qu %qu %qu %qu %qu %qu",
673		    rndstats->rnd_total,
674		    rndstats->rnd_used, rndstats->rnd_reads,
675		    rndstats->arc4_reads, rndstats->arc4_nstirs,
676		    rndstats->arc4_stirs,
677		    rndstats->rnd_pad[0],
678		    rndstats->rnd_pad[1],
679		    rndstats->rnd_pad[2],
680		    rndstats->rnd_pad[3],
681		    rndstats->rnd_pad[4],
682		    rndstats->rnd_waits,
683		    rndstats->rnd_enqs, rndstats->rnd_deqs,
684		    rndstats->rnd_drops, rndstats->rnd_drople);
685		for (i = 0; i < sizeof(rndstats->rnd_ed)/sizeof(rndstats->rnd_ed[0]); i++)
686			(void)printf(" %qu", rndstats->rnd_ed[i]);
687		for (i = 0; i < sizeof(rndstats->rnd_sc)/sizeof(rndstats->rnd_sc[0]); i++)
688			(void)printf(" %qu", rndstats->rnd_sc[i]);
689		for (i = 0; i < sizeof(rndstats->rnd_sb)/sizeof(rndstats->rnd_sb[0]); i++)
690			(void)printf(" %qu", rndstats->rnd_sb[i]);
691		printf("\n");
692		return;
693	}
694	if (special & BADDYNAMIC) {
695		in_port_t port, lastport;
696		u_int32_t *baddynamic = (u_int32_t *)buf;
697
698		if (!nflag)
699			(void)printf("%s%s", string, newsize ? ": " : " = ");
700		lastport = 0;
701		for (port = IPPORT_RESERVED/2; port < IPPORT_RESERVED; port++)
702			if (DP_ISSET(baddynamic, port)) {
703				(void)printf("%s%hd", lastport ? "," : "",
704				    port);
705				lastport = port;
706			}
707		if (newsize != 0) {
708			if (!nflag)
709				fputs(" -> ", stdout);
710			baddynamic = (u_int32_t *)newval;
711			lastport = 0;
712			for (port = IPPORT_RESERVED/2; port < IPPORT_RESERVED;
713			    port++)
714				if (DP_ISSET(baddynamic, port)) {
715					(void)printf("%s%hd",
716					    lastport ? "," : "", port);
717					lastport = port;
718				}
719		}
720		(void)putchar('\n');
721		return;
722	}
723	switch (type) {
724	case CTLTYPE_INT:
725		if (newsize == 0) {
726			if (!nflag)
727				(void)printf("%s = ", string);
728			(void)printf("%d\n", *(int *)buf);
729		} else {
730			if (!nflag)
731				(void)printf("%s: %d -> ", string,
732				    *(int *)buf);
733			(void)printf("%d\n", *(int *)newval);
734		}
735		return;
736
737	case CTLTYPE_STRING:
738		if (newsize == 0) {
739			if (!nflag)
740				(void)printf("%s = ", string);
741			(void)puts(buf);
742		} else {
743			if (!nflag)
744				(void)printf("%s: %s -> ", string, buf);
745			(void)puts((char *)newval);
746		}
747		return;
748
749	case CTLTYPE_QUAD:
750		if (newsize == 0) {
751			if (!nflag)
752				(void)printf("%s = ", string);
753			(void)printf("%qd\n", *(quad_t *)buf);
754		} else {
755			if (!nflag)
756				(void)printf("%s: %qd -> ", string,
757				    *(quad_t *)buf);
758			(void)printf("%qd\n", *(quad_t *)newval);
759		}
760		return;
761
762	case CTLTYPE_STRUCT:
763		warnx("%s: unknown structure returned", string);
764		return;
765
766	default:
767	case CTLTYPE_NODE:
768		warnx("%s: unknown type returned", string);
769		return;
770	}
771}
772
773void
774parse_baddynamic(mib, len, string, newvalp, newsizep, flags, nflag)
775	int mib[];
776	size_t len;
777	char *string;
778	void **newvalp;
779	size_t *newsizep;
780	int flags;
781	int nflag;
782{
783	static u_int32_t newbaddynamic[DP_MAPSIZE];
784	in_port_t port;
785	size_t size;
786	char action, *cp;
787
788	if (strchr((char *)*newvalp, '+') || strchr((char *)*newvalp, '-')) {
789		size = sizeof(newbaddynamic);
790		if (sysctl(mib, len, newbaddynamic, &size, 0, 0) == -1) {
791			if (flags == 0)
792				return;
793			if (!nflag)
794				(void)printf("%s: ", string);
795			(void)puts("kernel does contain bad dynamic port tables");
796			return;
797		}
798
799		while (*newvalp && (cp = strsep((char **)newvalp, ", \t")) && *cp) {
800			if (*cp != '+' && *cp != '-')
801				errx(1, "cannot mix +/- with full list");
802			action = *cp++;
803			port = atoi(cp);
804			if (port < IPPORT_RESERVED/2 || port >= IPPORT_RESERVED)
805				errx(1, "invalid port, range is %d to %d",
806				    IPPORT_RESERVED/2, IPPORT_RESERVED-1);
807			if (action == '+')
808				DP_SET(newbaddynamic, port);
809			else
810				DP_CLR(newbaddynamic, port);
811		}
812	} else {
813		(void)memset((void *)newbaddynamic, 0, sizeof(newbaddynamic));
814		while (*newvalp && (cp = strsep((char **)newvalp, ", \t")) && *cp) {
815			port = atoi(cp);
816			if (port < IPPORT_RESERVED/2 || port >= IPPORT_RESERVED)
817				errx(1, "invalid port, range is %d to %d",
818				    IPPORT_RESERVED/2, IPPORT_RESERVED-1);
819			DP_SET(newbaddynamic, port);
820		}
821	}
822
823	*newvalp = (void *)newbaddynamic;
824	*newsizep = sizeof(newbaddynamic);
825}
826
827/*
828 * Initialize the set of debugging names
829 */
830void
831debuginit()
832{
833	int mib[3], loc, i;
834	size_t size;
835
836	if (secondlevel[CTL_DEBUG].list != 0)
837		return;
838	secondlevel[CTL_DEBUG].list = debugname;
839	mib[0] = CTL_DEBUG;
840	mib[2] = CTL_DEBUG_NAME;
841	for (loc = lastused, i = 0; i < CTL_DEBUG_MAXID; i++) {
842		mib[1] = i;
843		size = BUFSIZ - loc;
844		if (sysctl(mib, 3, &names[loc], &size, NULL, 0) == -1)
845			continue;
846		debugname[i].ctl_name = &names[loc];
847		debugname[i].ctl_type = CTLTYPE_INT;
848		loc += size;
849	}
850	lastused = loc;
851}
852
853struct ctlname vfsgennames[] = CTL_VFSGENCTL_NAMES;
854struct ctlname ffsname[] = FFS_NAMES;
855struct ctlname nfsname[] = FS_NFS_NAMES;
856struct list *vfsvars;
857int *vfs_typenums;
858
859/*
860 * Initialize the set of filesystem names
861 */
862void
863vfsinit()
864{
865	int mib[4], maxtypenum, cnt, loc, size;
866	struct vfsconf vfc;
867	size_t buflen;
868
869	if (secondlevel[CTL_VFS].list != 0)
870		return;
871	mib[0] = CTL_VFS;
872	mib[1] = VFS_GENERIC;
873	mib[2] = VFS_MAXTYPENUM;
874	buflen = 4;
875	if (sysctl(mib, 3, &maxtypenum, &buflen, (void *)0, (size_t)0) < 0)
876		return;
877	maxtypenum++;	/* + generic */
878	if ((vfs_typenums = malloc(maxtypenum * sizeof(int))) == NULL)
879		return;
880	memset(vfs_typenums, 0, maxtypenum * sizeof(int));
881	if ((vfsvars = malloc(maxtypenum * sizeof(*vfsvars))) == NULL) {
882		free(vfs_typenums);
883		return;
884	}
885	memset(vfsvars, 0, maxtypenum * sizeof(*vfsvars));
886	if ((vfsname = malloc(maxtypenum * sizeof(*vfsname))) == NULL) {
887		free(vfs_typenums);
888		free(vfsvars);
889		return;
890	}
891	memset(vfsname, 0, maxtypenum * sizeof(*vfsname));
892	mib[2] = VFS_CONF;
893	buflen = sizeof vfc;
894	for (loc = lastused, cnt = 1; cnt < maxtypenum; cnt++) {
895		mib[3] = cnt - 1;
896		if (sysctl(mib, 4, &vfc, &buflen, (void *)0, (size_t)0) < 0) {
897			if (errno == EOPNOTSUPP)
898				continue;
899			warn("vfsinit");
900			free(vfsname);
901			return;
902		}
903		if (!strcmp(vfc.vfc_name, MOUNT_FFS)) {
904			vfsvars[cnt].list = ffsname;
905			vfsvars[cnt].size = FFS_MAXID;
906		}
907		if (!strcmp(vfc.vfc_name, MOUNT_NFS)) {
908			vfsvars[cnt].list = nfsname;
909			vfsvars[cnt].size = NFS_MAXID;
910		}
911		vfs_typenums[cnt] = vfc.vfc_typenum;
912		strcat(&names[loc], vfc.vfc_name);
913		vfsname[cnt].ctl_name = &names[loc];
914		vfsname[cnt].ctl_type = CTLTYPE_NODE;
915		size = strlen(vfc.vfc_name) + 1;
916		loc += size;
917	}
918	lastused = loc;
919
920	vfsname[0].ctl_name = "mounts";
921	vfsname[0].ctl_type = CTLTYPE_NODE;
922	vfsvars[0].list = vfsname + 1;
923	vfsvars[0].size = maxtypenum - 1;
924
925	secondlevel[CTL_VFS].list = vfsname;
926	secondlevel[CTL_VFS].size = maxtypenum;
927	return;
928}
929
930int
931sysctl_vfsgen(string, bufpp, mib, flags, typep)
932	char *string;
933	char **bufpp;
934	int mib[];
935	int flags;
936	int *typep;
937{
938	int indx;
939	size_t size;
940	struct vfsconf vfc;
941
942	if (*bufpp == NULL) {
943		listall(string, vfsvars);
944		return (-1);
945	}
946
947	if ((indx = findname(string, "third", bufpp, vfsvars)) == -1)
948		return (-1);
949
950	mib[1] = VFS_GENERIC;
951	mib[2] = VFS_CONF;
952	mib[3] = indx;
953	size = sizeof vfc;
954	if (sysctl(mib, 4, &vfc, &size, (void *)0, (size_t)0) < 0) {
955		if (errno != EOPNOTSUPP)
956			warn("vfs print");
957		return -1;
958	}
959	if (flags == 0 && vfc.vfc_refcount == 0)
960		return -1;
961	if (!nflag)
962		fprintf(stdout, "%s has %d mounted instance%s\n",
963		    string, vfc.vfc_refcount,
964		    vfc.vfc_refcount != 1 ? "s" : "");
965	else
966		fprintf(stdout, "%d\n", vfc.vfc_refcount);
967
968	return -1;
969}
970
971int
972sysctl_vfs(string, bufpp, mib, flags, typep)
973	char *string;
974	char **bufpp;
975	int mib[];
976	int flags;
977	int *typep;
978{
979	struct list *lp = &vfsvars[mib[1]];
980	int indx;
981
982	if (lp->list == NULL) {
983		if (flags)
984			warnx("No variables defined for file system %s", string);
985		return(-1);
986	}
987	if (*bufpp == NULL) {
988		listall(string, lp);
989		return (-1);
990	}
991	if ((indx = findname(string, "third", bufpp, lp)) == -1)
992		return (-1);
993
994	mib[1] = vfs_typenums[mib[1]];
995	mib[2] = indx;
996	*typep = lp->list[indx].ctl_type;
997	return (3);
998}
999
1000struct ctlname posixname[] = CTL_FS_POSIX_NAMES;
1001struct list fslist = { posixname, FS_POSIX_MAXID };
1002
1003/*
1004 * handle file system requests
1005 */
1006int
1007sysctl_fs(string, bufpp, mib, flags, typep)
1008	char *string;
1009	char **bufpp;
1010	int mib[];
1011	int flags;
1012	int *typep;
1013{
1014	int indx;
1015
1016	if (*bufpp == NULL) {
1017		listall(string, &fslist);
1018		return(-1);
1019	}
1020	if ((indx = findname(string, "third", bufpp, &fslist)) == -1)
1021		return(-1);
1022	mib[2] = indx;
1023	*typep = fslist.list[indx].ctl_type;
1024	return(3);
1025}
1026
1027#ifdef CPU_BIOS
1028struct ctlname biosname[] = CTL_BIOS_NAMES;
1029struct list bioslist = { biosname, BIOS_MAXID };
1030
1031/*
1032 * handle BIOS requests
1033 */
1034int
1035sysctl_bios(string, bufpp, mib, flags, typep)
1036	char *string;
1037	char **bufpp;
1038	int mib[];
1039	int flags;
1040	int *typep;
1041{
1042	char *name;
1043	int indx;
1044
1045	if (*bufpp == NULL) {
1046		listall(string, &bioslist);
1047		return(-1);
1048	}
1049	if ((indx = findname(string, "third", bufpp, &bioslist)) == -1)
1050		return(-1);
1051	mib[2] = indx;
1052	if (indx == BIOS_DISKINFO) {
1053		if (*bufpp == NULL) {
1054			char name[BUFSIZ];
1055
1056			/* scan all the bios devices */
1057			for (indx = 0; indx < 256; indx++) {
1058				snprintf(name, sizeof(name), "%s.%u",
1059					 string, indx);
1060				parse(name, 1);
1061			}
1062			return(-1);
1063		}
1064		if ((name = strsep(bufpp, ".")) == NULL) {
1065			warnx("%s: incomplete specification", string);
1066			return(-1);
1067		}
1068		mib[3] = atoi(name);
1069		*typep = CTLTYPE_STRUCT;
1070		return(4);
1071	} else {
1072		*typep = bioslist.list[indx].ctl_type;
1073		return(3);
1074	}
1075}
1076#endif
1077
1078#ifdef UVM
1079struct ctlname swpencname[] = CTL_SWPENC_NAMES;
1080struct list swpenclist = { swpencname, SWPENC_MAXID };
1081
1082/*
1083 * handle swap encrypt requests
1084 */
1085int
1086sysctl_swpenc(string, bufpp, mib, flags, typep)
1087	char *string;
1088	char **bufpp;
1089	int mib[];
1090	int flags;
1091	int *typep;
1092{
1093	char *name;
1094	int indx;
1095
1096	if (*bufpp == NULL) {
1097		listall(string, &swpenclist);
1098		return(-1);
1099	}
1100	if ((indx = findname(string, "third", bufpp, &swpenclist)) == -1)
1101		return(-1);
1102	mib[2] = indx;
1103	*typep = swpenclist.list[indx].ctl_type;
1104	return(3);
1105}
1106#endif
1107
1108struct ctlname inetname[] = CTL_IPPROTO_NAMES;
1109struct ctlname ipname[] = IPCTL_NAMES;
1110struct ctlname icmpname[] = ICMPCTL_NAMES;
1111struct ctlname ipipname[] = IPIPCTL_NAMES;
1112struct ctlname tcpname[] = TCPCTL_NAMES;
1113struct ctlname udpname[] = UDPCTL_NAMES;
1114struct ctlname espname[] = ESPCTL_NAMES;
1115struct ctlname ahname[] = AHCTL_NAMES;
1116struct ctlname etheripname[] = ETHERIPCTL_NAMES;
1117struct ctlname grename[] = GRECTL_NAMES;
1118struct ctlname mobileipname[] = MOBILEIPCTL_NAMES;
1119struct list inetlist = { inetname, IPPROTO_MAXID };
1120struct list inetvars[] = {
1121	{ ipname, IPCTL_MAXID },	/* ip */
1122	{ icmpname, ICMPCTL_MAXID },	/* icmp */
1123	{ 0, 0 },			/* igmp */
1124	{ 0, 0 },			/* ggmp */
1125	{ ipipname, IPIPCTL_MAXID },	/* ipencap */
1126	{ 0, 0 },
1127	{ tcpname, TCPCTL_MAXID },	/* tcp */
1128	{ 0, 0 },
1129	{ 0, 0 },			/* egp */
1130	{ 0, 0 },
1131	{ 0, 0 },
1132	{ 0, 0 },
1133	{ 0, 0 },			/* pup */
1134	{ 0, 0 },
1135	{ 0, 0 },
1136	{ 0, 0 },
1137	{ 0, 0 },
1138	{ udpname, UDPCTL_MAXID },	/* udp */
1139	{ 0, 0 },
1140	{ 0, 0 },
1141	{ 0, 0 },
1142	{ 0, 0 },
1143	{ 0, 0 },
1144	{ 0, 0 },
1145	{ 0, 0 },
1146	{ 0, 0 },
1147	{ 0, 0 },
1148	{ 0, 0 },
1149	{ 0, 0 },
1150	{ 0, 0 },
1151	{ 0, 0 },
1152	{ 0, 0 },
1153	{ 0, 0 },
1154	{ 0, 0 },
1155	{ 0, 0 },
1156	{ 0, 0 },
1157	{ 0, 0 },
1158	{ 0, 0 },
1159	{ 0, 0 },
1160	{ 0, 0 },
1161	{ 0, 0 },
1162	{ 0, 0 },
1163	{ 0, 0 },
1164	{ 0, 0 },
1165	{ 0, 0 },
1166	{ 0, 0 },
1167	{ 0, 0 },
1168	{ grename, GRECTL_MAXID }, /* GRE */
1169	{ 0, 0 },
1170	{ 0, 0 },
1171	{ espname, ESPCTL_MAXID },	/* esp */
1172	{ ahname, AHCTL_MAXID },	/* ah */
1173	{ 0, 0 },
1174	{ 0, 0 },
1175	{ 0, 0 },
1176	{ mobileipname, MOBILEIPCTL_MAXID }, /* mobileip */
1177	{ 0, 0 },
1178	{ 0, 0 },
1179	{ 0, 0 },
1180	{ 0, 0 },
1181	{ 0, 0 },
1182	{ 0, 0 },
1183	{ 0, 0 },
1184	{ 0, 0 },
1185	{ 0, 0 },
1186	{ 0, 0 },
1187	{ 0, 0 },
1188	{ 0, 0 },
1189	{ 0, 0 },
1190	{ 0, 0 },
1191	{ 0, 0 },
1192	{ 0, 0 },
1193	{ 0, 0 },
1194	{ 0, 0 },
1195	{ 0, 0 },
1196	{ 0, 0 },
1197	{ 0, 0 },
1198	{ 0, 0 },
1199	{ 0, 0 },
1200	{ 0, 0 },
1201	{ 0, 0 },
1202	{ 0, 0 },
1203	{ 0, 0 },
1204	{ 0, 0 },
1205	{ 0, 0 },
1206	{ 0, 0 },
1207	{ 0, 0 },
1208	{ 0, 0 },
1209	{ 0, 0 },
1210	{ 0, 0 },
1211	{ 0, 0 },
1212	{ 0, 0 },
1213	{ 0, 0 },
1214	{ 0, 0 },
1215	{ 0, 0 },
1216	{ 0, 0 },
1217	{ 0, 0 },
1218	{ etheripname, ETHERIPCTL_MAXID },
1219};
1220
1221struct list kernmalloclist = { kernmallocname, KERN_MALLOC_MAXID };
1222struct list kernbucketlist = { kernbucketname, KERN_MALLOC_BUCKET_MAXID };
1223
1224/*
1225 * handle malloc statistics
1226 */
1227int
1228sysctl_malloc(string, bufpp, mib, flags, typep)
1229	char *string;
1230	char **bufpp;
1231	int mib[];
1232	int flags;
1233	int *typep;
1234{
1235	int indx, size, stor, i;
1236	char *name, bufp[BUFSIZ], *buf;
1237        struct list lp;
1238
1239	if (*bufpp == NULL) {
1240		listall(string, &kernmalloclist);
1241		return(-1);
1242	}
1243	if ((indx = findname(string, "third", bufpp, &kernmalloclist)) == -1)
1244	        return (-1);
1245	mib[2] = indx;
1246	if (mib[2] == KERN_MALLOC_BUCKET) {
1247	        if ((name = strsep(bufpp, ".")) == NULL) {
1248		        size = BUFSIZ;
1249			stor = mib[2];
1250			mib[2] = KERN_MALLOC_BUCKETS;
1251			buf = bufp;
1252			if (sysctl(mib, 3, buf, &size, NULL, 0) < 0)
1253			        return(-1);
1254			mib[2] = stor;
1255			for (stor = 0, i = 0; i < size; i++)
1256			        if (buf[i] == ',')
1257				        stor++;
1258			lp.list = calloc(stor + 2, sizeof(struct ctlname));
1259			if (lp.list == NULL)
1260			        return(-1);
1261			lp.size = stor + 2;
1262			for (i = 1;
1263			     (lp.list[i].ctl_name = strsep(&buf, ",")) != NULL;
1264			     i++) {
1265			        lp.list[i].ctl_type = CTLTYPE_QUAD;
1266			}
1267			lp.list[i].ctl_name = buf;
1268			lp.list[i].ctl_type = CTLTYPE_QUAD;
1269			listall(string, &lp);
1270			free(lp.list);
1271			return(-1);
1272		}
1273		mib[3] = atoi(name);
1274		if (*bufpp == NULL) {
1275		        listall(string, &kernbucketlist);
1276			return(-1);
1277		}
1278		if ((indx = findname(string, "fifth", bufpp,
1279				     &kernbucketlist)) == -1)
1280		        return (-1);
1281		mib[4] = indx;
1282		*typep = CTLTYPE_QUAD;
1283		return(5);
1284	} else {
1285	        *typep = CTLTYPE_STRING;
1286	        return(3);
1287	}
1288}
1289
1290/*
1291 * handle internet requests
1292 */
1293int
1294sysctl_inet(string, bufpp, mib, flags, typep)
1295	char *string;
1296	char **bufpp;
1297	int mib[];
1298	int flags;
1299	int *typep;
1300{
1301	struct list *lp;
1302	int indx;
1303
1304	if (*bufpp == NULL) {
1305		listall(string, &inetlist);
1306		return(-1);
1307	}
1308	if ((indx = findname(string, "third", bufpp, &inetlist)) == -1)
1309		return(-1);
1310	mib[2] = indx;
1311	if (indx < IPPROTO_MAXID && inetvars[indx].list != NULL)
1312		lp = &inetvars[indx];
1313	else if (!flags)
1314		return(-1);
1315	else {
1316		warnx("%s: no variables defined for this protocol", string);
1317		return(-1);
1318	}
1319	if (*bufpp == NULL) {
1320		listall(string, lp);
1321		return(-1);
1322	}
1323	if ((indx = findname(string, "fourth", bufpp, lp)) == -1)
1324		return(-1);
1325	mib[3] = indx;
1326	*typep = lp->list[indx].ctl_type;
1327	return(4);
1328}
1329
1330#ifdef INET6
1331struct ctlname inet6name[] = CTL_IPV6PROTO_NAMES;
1332struct ctlname ip6name[] = IPV6CTL_NAMES;
1333struct ctlname icmp6name[] = ICMPV6CTL_NAMES;
1334struct ctlname pim6name[] = PIM6CTL_NAMES;
1335struct list inet6list = { inet6name, IPV6PROTO_MAXID };
1336struct list inet6vars[] = {
1337/*0*/	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
1338	{ 0, 0 },
1339	{ 0, 0 },
1340	{ 0, 0 },
1341	{ 0, 0 },
1342	{ 0, 0 },
1343/*10*/	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
1344	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
1345/*20*/	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
1346	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
1347/*30*/	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
1348	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
1349/*40*/	{ 0, 0 },
1350	{ ip6name, IPV6CTL_MAXID },	/* ipv6 */
1351	{ 0, 0 },
1352	{ 0, 0 },
1353	{ 0, 0 },
1354	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
1355/*50*/	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
1356	{ 0, 0 },
1357	{ 0, 0 },
1358	{ 0, 0 },
1359	{ icmp6name, ICMPV6CTL_MAXID },	/* icmp6 */
1360	{ 0, 0 },
1361/*60*/	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
1362	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
1363/*70*/	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
1364	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
1365/*80*/	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
1366	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
1367/*90*/	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
1368	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
1369/*100*/	{ 0, 0 },
1370	{ 0, 0 },
1371	{ 0, 0 },
1372	{ pim6name, PIM6CTL_MAXID },	/* pim6 */
1373};
1374
1375/*
1376 * handle internet6 requests
1377 */
1378int
1379sysctl_inet6(string, bufpp, mib, flags, typep)
1380	char *string;
1381	char **bufpp;
1382	int mib[];
1383	int flags;
1384	int *typep;
1385{
1386	struct list *lp;
1387	int indx;
1388
1389	if (*bufpp == NULL) {
1390		listall(string, &inet6list);
1391		return(-1);
1392	}
1393	if ((indx = findname(string, "third", bufpp, &inet6list)) == -1)
1394		return(-1);
1395	mib[2] = indx;
1396	if (indx < IPV6PROTO_MAXID && inet6vars[indx].list != NULL)
1397		lp = &inet6vars[indx];
1398	else if (!flags)
1399		return(-1);
1400	else {
1401		warnx("%s: no variables defined for this protocol", string);
1402		return(-1);
1403	}
1404	if (*bufpp == NULL) {
1405		listall(string, lp);
1406		return(-1);
1407	}
1408	if ((indx = findname(string, "fourth", bufpp, lp)) == -1)
1409		return(-1);
1410	mib[3] = indx;
1411	*typep = lp->list[indx].ctl_type;
1412	return(4);
1413}
1414#endif
1415
1416struct ctlname ipxname[] = CTL_IPXPROTO_NAMES;
1417struct ctlname ipxpname[] = IPXCTL_NAMES;
1418struct ctlname spxpname[] = SPXCTL_NAMES;
1419struct list ipxlist = { ipxname, IPXCTL_MAXID };
1420struct list ipxvars[] = {
1421	{ ipxpname, IPXCTL_MAXID },	/* ipx */
1422	{ 0, 0 },
1423	{ 0, 0 },
1424	{ 0, 0 },
1425	{ 0, 0 },
1426	{ spxpname, SPXCTL_MAXID },
1427};
1428
1429/*
1430 * Handle internet requests
1431 */
1432int
1433sysctl_ipx(string, bufpp, mib, flags, typep)
1434	char *string;
1435	char **bufpp;
1436	int mib[];
1437	int flags;
1438	int *typep;
1439{
1440	struct list *lp;
1441	int indx;
1442
1443	if (*bufpp == NULL) {
1444		listall(string, &ipxlist);
1445		return(-1);
1446	}
1447	if ((indx = findname(string, "third", bufpp, &ipxlist)) == -1)
1448		return(-1);
1449	mib[2] = indx;
1450	if (indx <= IPXPROTO_SPX && ipxvars[indx].list != NULL)
1451		lp = &ipxvars[indx];
1452	else if (!flags)
1453		return(-1);
1454	else {
1455		warnx("%s: no variables defined for this protocol", string);
1456		return(-1);
1457	}
1458	if (*bufpp == NULL) {
1459		listall(string, lp);
1460		return(-1);
1461	}
1462	if ((indx = findname(string, "fourth", bufpp, lp)) == -1)
1463		return(-1);
1464	mib[3] = indx;
1465	*typep = lp->list[indx].ctl_type;
1466	return(4);
1467}
1468
1469/*
1470 * Scan a list of names searching for a particular name.
1471 */
1472int
1473findname(string, level, bufp, namelist)
1474	char *string;
1475	char *level;
1476	char **bufp;
1477	struct list *namelist;
1478{
1479	char *name;
1480	int i;
1481
1482	if (namelist->list == 0 || (name = strsep(bufp, ".")) == NULL) {
1483		warnx("%s: incomplete specification", string);
1484		return(-1);
1485	}
1486	for (i = 0; i < namelist->size; i++)
1487		if (namelist->list[i].ctl_name != NULL &&
1488		    strcmp(name, namelist->list[i].ctl_name) == 0)
1489			break;
1490	if (i == namelist->size) {
1491		warnx("%s level name %s in %s is invalid", level, name, string);
1492		return(-1);
1493	}
1494	return(i);
1495}
1496
1497void
1498usage()
1499{
1500
1501	(void)fprintf(stderr, "usage:\t%s\n\t%s\n\t%s\n\t%s\n",
1502	    "sysctl [-n] variable ...", "sysctl [-n] -w variable=value ...",
1503	    "sysctl [-n] -a", "sysctl [-n] -A");
1504	exit(1);
1505}
1506