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