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