sysctl.c revision 1.45 1 /* $NetBSD: sysctl.c,v 1.45 2001/02/19 22:56:23 cgd Exp $ */
2
3 /*
4 * Copyright (c) 1993
5 * The Regents of the University of California. All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software
16 * must display the following acknowledgement:
17 * This product includes software developed by the University of
18 * California, Berkeley and its contributors.
19 * 4. Neither the name of the University nor the names of its contributors
20 * may be used to endorse or promote products derived from this software
21 * without specific prior written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * SUCH DAMAGE.
34 */
35
36 #include <sys/cdefs.h>
37 #ifndef lint
38 __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
45 static char sccsid[] = "@(#)sysctl.c 8.1 (Berkeley) 6/6/93";
46 #else
47 __RCSID("$NetBSD: sysctl.c,v 1.45 2001/02/19 22:56:23 cgd Exp $");
48 #endif
49 #endif /* not lint */
50
51 #include <sys/param.h>
52 #include <sys/gmon.h>
53 #include <sys/stat.h>
54 #include <sys/sysctl.h>
55 #include <sys/socket.h>
56 #include <sys/mount.h>
57 #include <sys/mbuf.h>
58 #include <sys/resource.h>
59 #include <uvm/uvm_param.h>
60 #include <machine/cpu.h>
61
62 #include <ufs/ufs/dinode.h>
63 #include <ufs/ufs/dir.h>
64 #include <ufs/ffs/fs.h>
65 #include <ufs/ffs/ffs_extern.h>
66
67 #include <nfs/rpcv2.h>
68 #include <nfs/nfsproto.h>
69 #include <nfs/nfs.h>
70
71 #include <netinet/in.h>
72 #include <netinet/in_systm.h>
73 #include <netinet/ip.h>
74 #include <netinet/ip_icmp.h>
75 #include <netinet/icmp_var.h>
76 #include <netinet/ip_var.h>
77 #include <netinet/udp.h>
78 #include <netinet/udp_var.h>
79 #include <netinet/tcp.h>
80 #include <netinet/tcp_timer.h>
81 #include <netinet/tcp_var.h>
82
83 #ifdef INET6
84 #include <netinet/ip6.h>
85 #include <netinet/icmp6.h>
86 #include <netinet6/ip6_var.h>
87 #include <netinet6/udp6.h>
88 #include <netinet6/udp6_var.h>
89 #ifdef TCP6
90 #include <netinet6/tcp6.h>
91 #include <netinet6/tcp6_timer.h>
92 #include <netinet6/tcp6_var.h>
93 #endif
94 #include <netinet6/pim6_var.h>
95 #endif /* INET6 */
96
97 #ifdef IPSEC
98 #include <net/route.h>
99 #include <netinet6/ipsec.h>
100 #include <netkey/key_var.h>
101 #endif /* IPSEC */
102
103 #include <err.h>
104 #include <ctype.h>
105 #include <errno.h>
106 #include <stdio.h>
107 #include <stdlib.h>
108 #include <string.h>
109 #include <unistd.h>
110 #include <util.h>
111
112 struct ctlname topname[] = CTL_NAMES;
113 struct ctlname kernname[] = CTL_KERN_NAMES;
114 struct ctlname vmname[] = CTL_VM_NAMES;
115 struct ctlname vfsname[] = CTL_VFS_NAMES;
116 struct ctlname netname[] = CTL_NET_NAMES;
117 struct ctlname hwname[] = CTL_HW_NAMES;
118 struct ctlname username[] = CTL_USER_NAMES;
119 struct ctlname ddbname[] = CTL_DDB_NAMES;
120 struct ctlname debugname[CTL_DEBUG_MAXID];
121 #ifdef CTL_MACHDEP_NAMES
122 struct ctlname machdepname[] = CTL_MACHDEP_NAMES;
123 #endif
124 /* this one is dummy, it's used only for '-a' or '-A' */
125 struct ctlname procname[] = { {0, 0}, {"curproc", CTLTYPE_NODE} };
126
127 char names[BUFSIZ];
128
129 struct list {
130 struct ctlname *list;
131 int size;
132 };
133 struct list toplist = { topname, CTL_MAXID };
134 struct list secondlevel[] = {
135 { 0, 0 }, /* CTL_UNSPEC */
136 { kernname, KERN_MAXID }, /* CTL_KERN */
137 { vmname, VM_MAXID }, /* CTL_VM */
138 { vfsname, VFS_MAXID }, /* CTL_VFS */
139 { netname, NET_MAXID }, /* CTL_NET */
140 { 0, CTL_DEBUG_MAXID }, /* CTL_DEBUG */
141 { hwname, HW_MAXID }, /* CTL_HW */
142 #ifdef CTL_MACHDEP_NAMES
143 { machdepname, CPU_MAXID }, /* CTL_MACHDEP */
144 #else
145 { 0, 0 }, /* CTL_MACHDEP */
146 #endif
147 { username, USER_MAXID }, /* CTL_USER_NAMES */
148 { ddbname, DDBCTL_MAXID }, /* CTL_DDB_NAMES */
149 { procname, 2 }, /* dummy name */
150 { 0, 0},
151 };
152
153 int Aflag, aflag, nflag, wflag;
154
155 /*
156 * Variables requiring special processing.
157 */
158 #define CLOCK 0x00000001
159 #define BOOTTIME 0x00000002
160 #define CONSDEV 0x00000004
161 #define DISKINFO 0x00000008
162 #define CPTIME 0x00000010
163
164 /*
165 * A dummy type for limits, which requires special parsing
166 */
167 #define CTLTYPE_LIMIT ((~0x1) << 31)
168
169 int main __P((int, char *[]));
170
171 static void listall __P((const char *, struct list *));
172 static void parse __P((char *, int));
173 static void debuginit __P((void));
174 static int sysctl_inet __P((char *, char **, int[], int, int *));
175 #ifdef INET6
176 static int sysctl_inet6 __P((char *, char **, int[], int, int *));
177 #endif
178 #ifdef IPSEC
179 static int sysctl_key __P((char *, char **, int[], int, int *));
180 #endif
181 static int sysctl_vfs __P((char *, char **, int[], int, int *));
182 static int sysctl_vfsgen __P((char *, char **, int[], int, int *));
183 static int sysctl_mbuf __P((char *, char **, int[], int, int *));
184 static int sysctl_proc __P((char *, char **, int[], int, int *));
185 static int findname __P((char *, char *, char **, struct list *));
186 static void usage __P((void));
187
188 int
189 main(argc, argv)
190 int argc;
191 char *argv[];
192 {
193 char *fn = NULL;
194 int ch, lvl1;
195
196 while ((ch = getopt(argc, argv, "Aaf:nw")) != -1) {
197 switch (ch) {
198
199 case 'A':
200 Aflag = 1;
201 break;
202
203 case 'a':
204 aflag = 1;
205 break;
206
207 case 'f':
208 fn = optarg;
209 wflag = 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 (Aflag || aflag) {
228 debuginit();
229 for (lvl1 = 1; lvl1 < CTL_MAXID; lvl1++)
230 listall(topname[lvl1].ctl_name, &secondlevel[lvl1]);
231 return 0;
232 }
233
234 if (fn) {
235 FILE *fp;
236 char *l;
237
238 fp = fopen(fn, "r");
239 if (fp == NULL) {
240 err(1, "%s", fn);
241 } else {
242 for (; (l = fparseln(fp, NULL, NULL, NULL, 0)) != NULL;
243 free(l)) {
244 if (*l)
245 parse(l, 1);
246 }
247 fclose(fp);
248 }
249 } else {
250 if (argc == 0)
251 usage();
252 while (argc-- > 0)
253 parse(*argv++, 1);
254 }
255 return 0;
256 }
257
258 /*
259 * List all variables known to the system.
260 */
261 static void
262 listall(prefix, lp)
263 const char *prefix;
264 struct list *lp;
265 {
266 int lvl2;
267 char *cp, name[BUFSIZ];
268
269 if (lp->list == 0)
270 return;
271 strcpy(name, prefix);
272 cp = &name[strlen(name)];
273 *cp++ = '.';
274 for (lvl2 = 0; lvl2 < lp->size; lvl2++) {
275 if (lp->list[lvl2].ctl_name == 0)
276 continue;
277 strcpy(cp, lp->list[lvl2].ctl_name);
278 parse(name, Aflag);
279 }
280 }
281
282 /*
283 * Parse a name into a MIB entry.
284 * Lookup and print out the MIB entry if it exists.
285 * Set a new value if requested.
286 */
287 static void
288 parse(string, flags)
289 char *string;
290 int flags;
291 {
292 int indx, type, state, len;
293 int special = 0;
294 void *newval = 0;
295 int intval, newsize = 0;
296 quad_t quadval;
297 size_t size;
298 struct list *lp;
299 int mib[CTL_MAXNAME];
300 char *cp, *bufp, buf[BUFSIZ];
301
302 bufp = buf;
303 snprintf(buf, BUFSIZ, "%s", string);
304 if ((cp = strchr(string, '=')) != NULL) {
305 if (!wflag)
306 errx(2, "Must specify -w to set variables");
307 *strchr(buf, '=') = '\0';
308 *cp++ = '\0';
309 while (isspace((unsigned char) *cp))
310 cp++;
311 newval = cp;
312 newsize = strlen(cp);
313 }
314 if ((indx = findname(string, "top", &bufp, &toplist)) == -1)
315 return;
316 mib[0] = indx;
317 if (indx == CTL_DEBUG)
318 debuginit();
319 if (mib[0] == CTL_PROC) {
320 type = CTLTYPE_NODE;
321 len = 1;
322 } else {
323 lp = &secondlevel[indx];
324 if (lp->list == 0) {
325 warnx("Class `%s' is not implemented",
326 topname[indx].ctl_name);
327 return;
328 }
329 if (bufp == NULL) {
330 listall(topname[indx].ctl_name, lp);
331 return;
332 }
333 if ((indx = findname(string, "second", &bufp, lp)) == -1)
334 return;
335 mib[1] = indx;
336 type = lp->list[indx].ctl_type;
337 len = 2;
338 }
339 switch (mib[0]) {
340
341 case CTL_KERN:
342 switch (mib[1]) {
343 case KERN_PROF:
344 mib[2] = GPROF_STATE;
345 size = sizeof state;
346 if (sysctl(mib, 3, &state, &size, NULL, 0) < 0) {
347 if (flags == 0)
348 return;
349 if (!nflag)
350 printf("%s: ", string);
351 warnx("Kernel is not compiled for profiling");
352 return;
353 }
354 if (!nflag)
355 printf("%s: %s\n", string,
356 state == GMON_PROF_OFF ? "off" : "running");
357 return;
358 case KERN_VNODE:
359 case KERN_FILE:
360 if (flags == 0)
361 return;
362 warnx("Use pstat to view %s information", string);
363 return;
364 case KERN_PROC:
365 case KERN_PROC2:
366 case KERN_PROC_ARGS:
367 if (flags == 0)
368 return;
369 warnx("Use ps to view %s information", string);
370 return;
371 case KERN_CLOCKRATE:
372 special |= CLOCK;
373 break;
374 case KERN_BOOTTIME:
375 special |= BOOTTIME;
376 break;
377 case KERN_NTPTIME:
378 if (flags == 0)
379 return;
380 warnx("Use xntpdc -c kerninfo to view %s information",
381 string);
382 return;
383 case KERN_MBUF:
384 len = sysctl_mbuf(string, &bufp, mib, flags, &type);
385 if (len < 0)
386 return;
387 break;
388 case KERN_CP_TIME:
389 special |= CPTIME;
390 break;
391 case KERN_MSGBUF:
392 if (flags == 0)
393 return;
394 warnx("Use dmesg to view %s information", string);
395 return;
396 case KERN_CONSDEV:
397 special |= CONSDEV;
398 break;
399 }
400 break;
401
402 case CTL_HW:
403 break;
404
405 case CTL_VM:
406 if (mib[1] == VM_LOADAVG) {
407 double loads[3];
408
409 getloadavg(loads, 3);
410 if (!nflag)
411 printf("%s: ", string);
412 printf("%.2f %.2f %.2f\n", loads[0], loads[1],
413 loads[2]);
414 return;
415 }
416 if (mib[1] == VM_NKMEMPAGES) {
417 size_t nkmempages_len;
418 int nkmempages;
419
420 nkmempages_len = sizeof(nkmempages);
421
422 if (sysctl(mib, 2, &nkmempages, &nkmempages_len,
423 NULL, 0)) {
424 warn("unable to get %s", string);
425 return;
426 }
427 if (!nflag)
428 printf("%s: ", string);
429 printf("%d\n", nkmempages);
430 }
431 if (flags == 0)
432 return;
433 warnx("Use vmstat or systat to view %s information", string);
434 return;
435
436 case CTL_NET:
437 if (mib[1] == PF_INET) {
438 len = sysctl_inet(string, &bufp, mib, flags, &type);
439 if (len >= 0)
440 break;
441 return;
442 }
443 #ifdef INET6
444 else if (mib[1] == PF_INET6) {
445 len = sysctl_inet6(string, &bufp, mib, flags, &type);
446 if (len >= 0)
447 break;
448 return;
449 }
450 #endif /* INET6 */
451 #ifdef IPSEC
452 else if (mib[1] == PF_KEY) {
453 len = sysctl_key(string, &bufp, mib, flags, &type);
454 if (len >= 0)
455 break;
456 return;
457 }
458 #endif /* IPSEC */
459 if (flags == 0)
460 return;
461 warnx("Use netstat to view %s information", string);
462 return;
463
464 case CTL_DEBUG:
465 mib[2] = CTL_DEBUG_VALUE;
466 len = 3;
467 break;
468
469 case CTL_MACHDEP:
470 #ifdef CPU_CONSDEV
471 if (mib[1] == CPU_CONSDEV)
472 special |= CONSDEV;
473 #endif
474 #ifdef CPU_DISKINFO
475 if (mib[1] == CPU_DISKINFO)
476 special |= DISKINFO;
477 #endif
478 break;
479
480 case CTL_VFS:
481 if (mib[1] == VFS_GENERIC)
482 len = sysctl_vfsgen(string, &bufp, mib, flags, &type);
483 else
484 len = sysctl_vfs(string, &bufp, mib, flags, &type);
485 if (len < 0)
486 return;
487
488 /* XXX Special-case for NFS stats. */
489 if (mib[1] == 2 && mib[2] == NFS_NFSSTATS) {
490 if (flags == 0)
491 return;
492 warnx("Use nfsstat to view %s information", string);
493 return;
494 }
495 break;
496
497 case CTL_VENDOR:
498 case CTL_USER:
499 case CTL_DDB:
500 break;
501 case CTL_PROC:
502 len = sysctl_proc(string, &bufp, mib, flags, &type);
503 if (len < 0)
504 return;
505 break;
506 default:
507 warnx("Illegal top level value: %d", mib[0]);
508 return;
509
510 }
511 if (bufp) {
512 warnx("Name %s in %s is unknown", bufp, string);
513 return;
514 }
515 if (newsize > 0) {
516 switch (type) {
517 case CTLTYPE_INT:
518 intval = atoi(newval);
519 newval = &intval;
520 newsize = sizeof intval;
521 break;
522
523 case CTLTYPE_LIMIT:
524 if (strcmp(newval, "unlimited") == 0) {
525 quadval = RLIM_INFINITY;
526 newval = &quadval;
527 newsize = sizeof quadval;
528 break;
529 }
530 /* FALLTHROUGH */
531 case CTLTYPE_QUAD:
532 sscanf(newval, "%lld", (long long *)&quadval);
533 newval = &quadval;
534 newsize = sizeof quadval;
535 break;
536 }
537 }
538 size = BUFSIZ;
539 if (sysctl(mib, len, buf, &size, newsize ? newval : 0, newsize) == -1) {
540 if (flags == 0)
541 return;
542 switch (errno) {
543 case EOPNOTSUPP:
544 warnx("The value of %s is not available", string);
545 return;
546 case ENOTDIR:
547 warnx("The specification of %s is incomplete",
548 string);
549 return;
550 case ENOMEM:
551 warnx("The type %s is unknown to this program",
552 string);
553 return;
554 default:
555 warn("sysctl() for %s failed", string);
556 return;
557 }
558 }
559 if (special & CLOCK) {
560 struct clockinfo *clkp = (struct clockinfo *)buf;
561
562 if (!nflag)
563 printf("%s: ", string);
564 printf(
565 "tick = %d, tickadj = %d, hz = %d, profhz = %d, stathz = %d\n",
566 clkp->tick, clkp->tickadj, clkp->hz, clkp->profhz, clkp->stathz);
567 return;
568 }
569 if (special & BOOTTIME) {
570 struct timeval *btp = (struct timeval *)buf;
571 time_t boottime;
572
573 if (!nflag) {
574 boottime = btp->tv_sec;
575 /* ctime() provides the trailing newline */
576 printf("%s = %s", string, ctime(&boottime));
577 } else
578 printf("%ld\n", (long) btp->tv_sec);
579 return;
580 }
581 if (special & CONSDEV) {
582 dev_t dev = *(dev_t *)buf;
583
584 if (!nflag)
585 printf("%s = %s\n", string, devname(dev, S_IFCHR));
586 else
587 printf("0x%x\n", dev);
588 return;
589 }
590 if (special & DISKINFO) {
591 /* Don't know a good way to deal with this i386 specific one */
592 return;
593 }
594 if (special & CPTIME) {
595 u_int64_t *cp_time = (u_int64_t *)buf;
596
597 if (!nflag)
598 printf("%s: ", string);
599 printf("user = %llu, nice = %llu, sys = %llu, intr = %llu, "
600 "idle = %llu\n", (unsigned long long) cp_time[0],
601 (unsigned long long) cp_time[1],
602 (unsigned long long) cp_time[2],
603 (unsigned long long) cp_time[3],
604 (unsigned long long) cp_time[4]);
605 return;
606 }
607
608 switch (type) {
609 case CTLTYPE_INT:
610 if (newsize == 0) {
611 if (!nflag)
612 printf("%s = ", string);
613 printf("%d\n", *(int *)buf);
614 } else {
615 if (!nflag)
616 printf("%s: %d -> ", string, *(int *)buf);
617 printf("%d\n", *(int *)newval);
618 }
619 return;
620
621 case CTLTYPE_STRING:
622 if (newsize == 0) {
623 if (!nflag)
624 printf("%s = ", string);
625 printf("%s\n", buf);
626 } else {
627 if (!nflag)
628 printf("%s: %s -> ", string, buf);
629 printf("%s\n", (char *) newval);
630 }
631 return;
632
633 case CTLTYPE_LIMIT:
634 #define PRINTF_LIMIT(lim) { \
635 if ((lim) == RLIM_INFINITY) \
636 printf("unlimited");\
637 else \
638 printf("%lld", (long long)(lim)); \
639 }
640
641 if (newsize == 0) {
642 if (!nflag)
643 printf("%s = ", string);
644 PRINTF_LIMIT((long long)(*(quad_t *)buf));
645 } else {
646 if (!nflag) {
647 printf("%s: ", string);
648 PRINTF_LIMIT((long long)(*(quad_t *)buf));
649 printf(" -> ");
650 }
651 PRINTF_LIMIT((long long)(*(quad_t *)newval));
652 }
653 printf("\n");
654 return;
655 #undef PRINTF_LIMIT
656
657 case CTLTYPE_QUAD:
658 if (newsize == 0) {
659 if (!nflag)
660 printf("%s = ", string);
661 printf("%lld\n", (long long)(*(quad_t *)buf));
662 } else {
663 if (!nflag)
664 printf("%s: %lld -> ", string,
665 (long long)(*(quad_t *)buf));
666 printf("%lld\n", (long long)(*(quad_t *)newval));
667 }
668 return;
669
670 case CTLTYPE_STRUCT:
671 warnx("%s: unknown structure returned", string);
672 return;
673
674 default:
675 case CTLTYPE_NODE:
676 warnx("%s: unknown type returned", string);
677 return;
678 }
679 }
680
681 /*
682 * Initialize the set of debugging names
683 */
684 static void
685 debuginit()
686 {
687 int mib[3], loc, i;
688 size_t size;
689
690 if (secondlevel[CTL_DEBUG].list != 0)
691 return;
692 secondlevel[CTL_DEBUG].list = debugname;
693 mib[0] = CTL_DEBUG;
694 mib[2] = CTL_DEBUG_NAME;
695 for (loc = 0, i = 0; i < CTL_DEBUG_MAXID; i++) {
696 mib[1] = i;
697 size = BUFSIZ - loc;
698 if (sysctl(mib, 3, &names[loc], &size, NULL, 0) == -1)
699 continue;
700 debugname[i].ctl_name = &names[loc];
701 debugname[i].ctl_type = CTLTYPE_INT;
702 loc += size;
703 }
704 }
705
706 struct ctlname inetname[] = CTL_IPPROTO_NAMES;
707 struct ctlname ipname[] = IPCTL_NAMES;
708 struct ctlname icmpname[] = ICMPCTL_NAMES;
709 struct ctlname tcpname[] = TCPCTL_NAMES;
710 struct ctlname udpname[] = UDPCTL_NAMES;
711 #ifdef IPSEC
712 struct ctlname ipsecname[] = IPSECCTL_NAMES;
713 #endif
714 struct list inetlist = { inetname, IPPROTO_MAXID };
715 struct list inetvars[] = {
716 /*0*/ { ipname, IPCTL_MAXID }, /* ip */
717 { icmpname, ICMPCTL_MAXID }, /* icmp */
718 { 0, 0 }, /* igmp */
719 { 0, 0 }, /* ggmp */
720 { 0, 0 },
721 { 0, 0 },
722 { tcpname, TCPCTL_MAXID }, /* tcp */
723 { 0, 0 },
724 { 0, 0 }, /* egp */
725 { 0, 0 },
726 /*10*/ { 0, 0 },
727 { 0, 0 },
728 { 0, 0 }, /* pup */
729 { 0, 0 },
730 { 0, 0 },
731 { 0, 0 },
732 { 0, 0 },
733 { udpname, UDPCTL_MAXID }, /* udp */
734 { 0, 0 },
735 { 0, 0 },
736 /*20*/ { 0, 0 },
737 { 0, 0 },
738 { 0, 0 }, /* idp */
739 { 0, 0 },
740 { 0, 0 },
741 { 0, 0 },
742 { 0, 0 },
743 { 0, 0 },
744 { 0, 0 },
745 { 0, 0 },
746 /*30*/ { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
747 { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
748 /*40*/ { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
749 { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
750 #ifdef IPSEC
751 { ipsecname, IPSECCTL_MAXID }, /* esp - for backward compatibility */
752 { ipsecname, IPSECCTL_MAXID }, /* ah */
753 #else
754 { 0, 0 },
755 { 0, 0 },
756 #endif
757 };
758
759 /*
760 * handle internet requests
761 */
762 static int
763 sysctl_inet(string, bufpp, mib, flags, typep)
764 char *string;
765 char **bufpp;
766 int mib[];
767 int flags;
768 int *typep;
769 {
770 struct list *lp;
771 int indx;
772
773 if (*bufpp == NULL) {
774 listall(string, &inetlist);
775 return (-1);
776 }
777 if ((indx = findname(string, "third", bufpp, &inetlist)) == -1)
778 return (-1);
779 mib[2] = indx;
780 if (indx <= IPPROTO_MAXID && inetvars[indx].list != NULL)
781 lp = &inetvars[indx];
782 else if (!flags)
783 return (-1);
784 else {
785 warnx("No variables defined for protocol %s", string);
786 return (-1);
787 }
788 if (*bufpp == NULL) {
789 listall(string, lp);
790 return (-1);
791 }
792 if ((indx = findname(string, "fourth", bufpp, lp)) == -1)
793 return (-1);
794 mib[3] = indx;
795 *typep = lp->list[indx].ctl_type;
796 return (4);
797 }
798
799 #ifdef INET6
800 struct ctlname inet6name[] = CTL_IPV6PROTO_NAMES;
801 struct ctlname ip6name[] = IPV6CTL_NAMES;
802 struct ctlname icmp6name[] = ICMPV6CTL_NAMES;
803 #ifdef TCP6
804 struct ctlname tcp6name[] = TCP6CTL_NAMES;
805 #endif
806 struct ctlname udp6name[] = UDP6CTL_NAMES;
807 struct ctlname pim6name[] = PIM6CTL_NAMES;
808 struct ctlname ipsec6name[] = IPSEC6CTL_NAMES;
809 struct list inet6list = { inet6name, IPV6PROTO_MAXID };
810 struct list inet6vars[] = {
811 /*0*/ { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
812 { 0, 0 },
813 #ifdef TCP6
814 { tcp6name, TCP6CTL_MAXID }, /* tcp6 */
815 #else
816 { 0, 0 },
817 #endif
818 { 0, 0 },
819 { 0, 0 },
820 { 0, 0 },
821 /*10*/ { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
822 { 0, 0 },
823 { 0, 0 },
824 { udp6name, UDP6CTL_MAXID }, /* udp6 */
825 { 0, 0 },
826 { 0, 0 },
827 /*20*/ { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
828 { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
829 /*30*/ { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
830 { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
831 /*40*/ { 0, 0 },
832 { ip6name, IPV6CTL_MAXID }, /* ipv6 */
833 { 0, 0 },
834 { 0, 0 },
835 { 0, 0 },
836 { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
837 #ifdef IPSEC
838 /*50*/ { ipsec6name, IPSECCTL_MAXID }, /* esp6 - for backward compatibility */
839 { ipsec6name, IPSECCTL_MAXID }, /* ah6 */
840 #else
841 { 0, 0 },
842 { 0, 0 },
843 #endif
844 { 0, 0 },
845 { 0, 0 },
846 { 0, 0 },
847 { 0, 0 },
848 { 0, 0 },
849 { 0, 0 },
850 { icmp6name, ICMPV6CTL_MAXID }, /* icmp6 */
851 { 0, 0 },
852 /*60*/ { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
853 { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
854 /*70*/ { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
855 { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
856 /*80*/ { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
857 { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
858 /*90*/ { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
859 { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
860 /*100*/ { 0, 0 },
861 { 0, 0 },
862 { 0, 0 },
863 { pim6name, PIM6CTL_MAXID }, /* pim6 */
864 };
865
866 /*
867 * handle internet6 requests
868 */
869 static int
870 sysctl_inet6(string, bufpp, mib, flags, typep)
871 char *string;
872 char **bufpp;
873 int mib[];
874 int flags;
875 int *typep;
876 {
877 struct list *lp;
878 int indx;
879
880 if (*bufpp == NULL) {
881 listall(string, &inet6list);
882 return (-1);
883 }
884 if ((indx = findname(string, "third", bufpp, &inet6list)) == -1)
885 return (-1);
886 mib[2] = indx;
887 if (indx <= sizeof(inet6vars)/sizeof(inet6vars[0])
888 && inet6vars[indx].list != NULL) {
889 lp = &inet6vars[indx];
890 } else if (!flags) {
891 return (-1);
892 } else {
893 fprintf(stderr, "%s: no variables defined for this protocol\n",
894 string);
895 return (-1);
896 }
897 if (*bufpp == NULL) {
898 listall(string, lp);
899 return (-1);
900 }
901 if ((indx = findname(string, "fourth", bufpp, lp)) == -1)
902 return (-1);
903 mib[3] = indx;
904 *typep = lp->list[indx].ctl_type;
905 return (4);
906 }
907 #endif /* INET6 */
908
909 #ifdef IPSEC
910 struct ctlname keynames[] = KEYCTL_NAMES;
911 struct list keylist = { keynames, KEYCTL_MAXID };
912
913 /*
914 * handle key requests
915 */
916 static int
917 sysctl_key(string, bufpp, mib, flags, typep)
918 char *string;
919 char **bufpp;
920 int mib[];
921 int flags;
922 int *typep;
923 {
924 struct list *lp;
925 int indx;
926
927 if (*bufpp == NULL) {
928 listall(string, &keylist);
929 return (-1);
930 }
931 if ((indx = findname(string, "third", bufpp, &keylist)) == -1)
932 return (-1);
933 mib[2] = indx;
934 lp = &keylist;
935 *typep = lp->list[indx].ctl_type;
936 return 3;
937 }
938 #endif /*IPSEC*/
939
940 struct ctlname ffsname[] = FFS_NAMES;
941 struct ctlname nfsname[] = NFS_NAMES;
942 struct list vfsvars[] = {
943 { 0, 0 }, /* generic */
944 { ffsname, FFS_MAXID }, /* FFS */
945 { nfsname, NFS_MAXID }, /* NFS */
946 { 0, 0 }, /* MFS */
947 { 0, 0 }, /* MSDOS */
948 { 0, 0 }, /* LFS */
949 { 0, 0 }, /* old LOFS */
950 { 0, 0 }, /* FDESC */
951 { 0, 0 }, /* PORTAL */
952 { 0, 0 }, /* NULL */
953 { 0, 0 }, /* UMAP */
954 { 0, 0 }, /* KERNFS */
955 { 0, 0 }, /* PROCFS */
956 { 0, 0 }, /* AFS */
957 { 0, 0 }, /* CD9660 */
958 { 0, 0 }, /* UNION */
959 { 0, 0 }, /* ADOSFS */
960 { 0, 0 }, /* EXT2FS */
961 { 0, 0 }, /* CODA */
962 { 0, 0 }, /* FILECORE */
963 };
964
965 /*
966 * handle vfs requests
967 */
968 static int
969 sysctl_vfs(string, bufpp, mib, flags, typep)
970 char *string;
971 char **bufpp;
972 int mib[];
973 int flags;
974 int *typep;
975 {
976 struct list *lp = &vfsvars[mib[1]];
977 int indx;
978
979 if (lp->list == NULL) {
980 if (flags)
981 warnx("No variables defined for file system %s",
982 string);
983 return (-1);
984 }
985 if (*bufpp == NULL) {
986 listall(string, lp);
987 return (-1);
988 }
989 if ((indx = findname(string, "third", bufpp, lp)) == -1)
990 return (-1);
991 mib[2] = indx;
992 *typep = lp->list[indx].ctl_type;
993 return (3);
994 }
995
996 struct ctlname vfsgenname[] = CTL_VFSGENCTL_NAMES;
997 struct list vfsgenvars = { vfsgenname, VFSGEN_MAXID };
998
999 /*
1000 * handle vfs.generic requests
1001 */
1002 static int
1003 sysctl_vfsgen(string, bufpp, mib, flags, typep)
1004 char *string;
1005 char **bufpp;
1006 int mib[];
1007 int flags;
1008 int *typep;
1009 {
1010 struct list *lp = &vfsgenvars;
1011 int indx;
1012
1013 if (*bufpp == NULL) {
1014 listall(string, lp);
1015 return (-1);
1016 }
1017 if ((indx = findname(string, "third", bufpp, lp)) == -1)
1018 return (-1);
1019 /* Don't bother with VFS_CONF. */
1020 if (indx == VFS_CONF)
1021 return (-1);
1022 mib[2] = indx;
1023 *typep = lp->list[indx].ctl_type;
1024 return (3);
1025 }
1026
1027 struct ctlname procnames[] = PROC_PID_NAMES;
1028 struct list procvars = {procnames, PROC_PID_MAXID};
1029 struct ctlname proclimitnames[] = PROC_PID_LIMIT_NAMES;
1030 struct list proclimitvars = {proclimitnames, PROC_PID_LIMIT_MAXID};
1031 struct ctlname proclimittypenames[] = PROC_PID_LIMIT_TYPE_NAMES;
1032 struct list proclimittypevars = {proclimittypenames,
1033 PROC_PID_LIMIT_TYPE_MAXID};
1034 /*
1035 * handle kern.proc requests
1036 */
1037 static int
1038 sysctl_proc(string, bufpp, mib, flags, typep)
1039 char *string;
1040 char **bufpp;
1041 int mib[];
1042 int flags;
1043 int *typep;
1044 {
1045 char *cp, name[BUFSIZ];
1046 struct list *lp;
1047 int indx;
1048
1049 if (*bufpp == NULL) {
1050 strcpy(name, string);
1051 cp = &name[strlen(name)];
1052 *cp++ = '.';
1053 strcpy(cp, "curproc");
1054 parse (name, Aflag);
1055 return (-1);
1056 }
1057 cp = strsep(bufpp, ".");
1058 if (cp == NULL) {
1059 warnx("%s: incomplete specification", string);
1060 return (-1);
1061 }
1062 if (strcmp(cp, "curproc") == 0) {
1063 mib[1] = PROC_CURPROC;
1064 } else {
1065 mib[1] = atoi(cp);
1066 if (mib[1] == 0) {
1067 warnx("second level name %s in %s is invalid", cp,
1068 string);
1069 return (-1);
1070 }
1071 }
1072 *typep = CTLTYPE_NODE;
1073 lp = &procvars;
1074 if (*bufpp == NULL) {
1075 listall(string, lp);
1076 return (-1);
1077 }
1078 if ((indx = findname(string, "third", bufpp, lp)) == -1)
1079 return (-1);
1080 mib[2] = indx;
1081 *typep = lp->list[indx].ctl_type;
1082 if (*typep != CTLTYPE_NODE)
1083 return(3);
1084 lp = &proclimitvars;
1085 if (*bufpp == NULL) {
1086 listall(string, lp);
1087 return (-1);
1088 }
1089 if ((indx = findname(string, "fourth", bufpp, lp)) == -1)
1090 return (-1);
1091 mib[3] = indx;
1092 lp = &proclimittypevars;
1093 if (*bufpp == NULL) {
1094 listall(string, lp);
1095 return (-1);
1096 }
1097 if ((indx = findname(string, "fifth", bufpp, lp)) == -1)
1098 return (-1);
1099 mib[4] = indx;
1100 *typep = CTLTYPE_LIMIT;
1101 return(5);
1102 }
1103
1104 struct ctlname mbufnames[] = CTL_MBUF_NAMES;
1105 struct list mbufvars = { mbufnames, MBUF_MAXID };
1106 /*
1107 * handle kern.mbuf requests
1108 */
1109 static int
1110 sysctl_mbuf(string, bufpp, mib, flags, typep)
1111 char *string;
1112 char **bufpp;
1113 int mib[];
1114 int flags;
1115 int *typep;
1116 {
1117 struct list *lp = &mbufvars;
1118 int indx;
1119
1120 if (*bufpp == NULL) {
1121 listall(string, lp);
1122 return (-1);
1123 }
1124 if ((indx = findname(string, "third", bufpp, lp)) == -1)
1125 return (-1);
1126 mib[2] = indx;
1127 *typep = lp->list[indx].ctl_type;
1128 return (3);
1129 }
1130
1131 /*
1132 * Scan a list of names searching for a particular name.
1133 */
1134 static int
1135 findname(string, level, bufp, namelist)
1136 char *string;
1137 char *level;
1138 char **bufp;
1139 struct list *namelist;
1140 {
1141 char *name;
1142 int i;
1143
1144 if (namelist->list == 0 || (name = strsep(bufp, ".")) == NULL) {
1145 warnx("%s: incomplete specification", string);
1146 return (-1);
1147 }
1148 for (i = 0; i < namelist->size; i++)
1149 if (namelist->list[i].ctl_name != NULL &&
1150 strcmp(name, namelist->list[i].ctl_name) == 0)
1151 break;
1152 if (i == namelist->size) {
1153 warnx("%s level name %s in %s is invalid",
1154 level, name, string);
1155 return (-1);
1156 }
1157 return (i);
1158 }
1159
1160 static void
1161 usage()
1162 {
1163 const char *progname = getprogname();
1164
1165 (void)fprintf(stderr, "Usage:\t%s %s\n\t%s %s\n\t%s %s\n\t%s %s\n\t%s %s\n",
1166 progname, "[-n] variable ...",
1167 progname, "[-n] -w variable=value ...",
1168 progname, "[-n] -a",
1169 progname, "[-n] -A",
1170 progname, "[-n] -f file");
1171 exit(1);
1172 }
1173