1e4e21ee1SDavid van Moolenbroek
2e4e21ee1SDavid van Moolenbroek #include "inc.h"
3e4e21ee1SDavid van Moolenbroek
425d39513SDavid van Moolenbroek #include <sys/time.h>
5e4e21ee1SDavid van Moolenbroek #include <sys/sysctl.h>
625d39513SDavid van Moolenbroek #include <sys/sched.h>
725d39513SDavid van Moolenbroek #include <sys/resource.h>
8e4e21ee1SDavid van Moolenbroek
9e4e21ee1SDavid van Moolenbroek struct sysctl_tab {
10e4e21ee1SDavid van Moolenbroek int id;
11e4e21ee1SDavid van Moolenbroek size_t size;
12e4e21ee1SDavid van Moolenbroek const struct sysctl_tab *tab;
13e4e21ee1SDavid van Moolenbroek int (*proc)(struct trace_proc *, const char *, int, const void *,
14e4e21ee1SDavid van Moolenbroek vir_bytes, size_t);
15e4e21ee1SDavid van Moolenbroek };
16e4e21ee1SDavid van Moolenbroek #define NODE(i,t) { .id = i, .size = __arraycount(t), .tab = t }
17e4e21ee1SDavid van Moolenbroek #define PROC(i,s,p) { .id = i, .size = s, .proc = p }
18e4e21ee1SDavid van Moolenbroek
1925d39513SDavid van Moolenbroek /*
2025d39513SDavid van Moolenbroek * Print CTL_KERN KERN_CLOCKRATE.
2125d39513SDavid van Moolenbroek */
2225d39513SDavid van Moolenbroek static int
put_kern_clockrate(struct trace_proc * proc,const char * name,int type __unused,const void * ptr,vir_bytes addr __unused,size_t size __unused)2325d39513SDavid van Moolenbroek put_kern_clockrate(struct trace_proc * proc, const char * name,
2425d39513SDavid van Moolenbroek int type __unused, const void * ptr, vir_bytes addr __unused,
2525d39513SDavid van Moolenbroek size_t size __unused)
2625d39513SDavid van Moolenbroek {
27b58e161cSDavid van Moolenbroek const struct clockinfo *ci;
2825d39513SDavid van Moolenbroek
29b58e161cSDavid van Moolenbroek ci = (const struct clockinfo *)ptr;
3025d39513SDavid van Moolenbroek
3125d39513SDavid van Moolenbroek put_value(proc, "hz", "%d", ci->hz);
3225d39513SDavid van Moolenbroek put_value(proc, "tick", "%d", ci->tick);
3325d39513SDavid van Moolenbroek if (verbose > 0) {
3425d39513SDavid van Moolenbroek put_value(proc, "tickadj", "%d", ci->tickadj);
3525d39513SDavid van Moolenbroek put_value(proc, "stathz", "%d", ci->stathz);
3625d39513SDavid van Moolenbroek put_value(proc, "profhz", "%d", ci->profhz);
3725d39513SDavid van Moolenbroek return TRUE;
3825d39513SDavid van Moolenbroek } else
3925d39513SDavid van Moolenbroek return FALSE;
4025d39513SDavid van Moolenbroek }
4125d39513SDavid van Moolenbroek
4225d39513SDavid van Moolenbroek /*
4325d39513SDavid van Moolenbroek * Print CTL_KERN KERN_PROC2.
4425d39513SDavid van Moolenbroek */
4525d39513SDavid van Moolenbroek static int
put_kern_proc2(struct trace_proc * proc,const char * name,int type,const void * ptr,vir_bytes addr,size_t size)4625d39513SDavid van Moolenbroek put_kern_proc2(struct trace_proc * proc, const char * name, int type,
4725d39513SDavid van Moolenbroek const void * ptr, vir_bytes addr, size_t size)
4825d39513SDavid van Moolenbroek {
4925d39513SDavid van Moolenbroek const int *mib;
5025d39513SDavid van Moolenbroek const char *text;
51b58e161cSDavid van Moolenbroek unsigned int i;
5225d39513SDavid van Moolenbroek
5325d39513SDavid van Moolenbroek if (type == ST_NAME) {
5425d39513SDavid van Moolenbroek mib = (const int *)ptr;
5525d39513SDavid van Moolenbroek
5625d39513SDavid van Moolenbroek for (i = 0; i < size; i++) {
5725d39513SDavid van Moolenbroek text = NULL;
5825d39513SDavid van Moolenbroek
5925d39513SDavid van Moolenbroek if (i == 0) {
6025d39513SDavid van Moolenbroek switch (mib[i]) {
6125d39513SDavid van Moolenbroek case KERN_PROC_ALL: text = "<all>"; break;
6225d39513SDavid van Moolenbroek case KERN_PROC_PID: text = "<pid>"; break;
6325d39513SDavid van Moolenbroek case KERN_PROC_PGRP: text = "<pgrp>"; break;
6425d39513SDavid van Moolenbroek case KERN_PROC_SESSION:
6525d39513SDavid van Moolenbroek text = "<session>"; break;
6625d39513SDavid van Moolenbroek case KERN_PROC_TTY: text = "<tty>"; break;
6725d39513SDavid van Moolenbroek case KERN_PROC_UID: text = "<uid>"; break;
6825d39513SDavid van Moolenbroek case KERN_PROC_RUID: text = "<ruid>"; break;
6925d39513SDavid van Moolenbroek case KERN_PROC_GID: text = "<gid>"; break;
7025d39513SDavid van Moolenbroek case KERN_PROC_RGID: text = "<rgid>"; break;
7125d39513SDavid van Moolenbroek }
7225d39513SDavid van Moolenbroek } else if (i == 1 && mib[0] == KERN_PROC_TTY) {
7325d39513SDavid van Moolenbroek switch ((dev_t)mib[i]) {
7425d39513SDavid van Moolenbroek case KERN_PROC_TTY_NODEV:
7525d39513SDavid van Moolenbroek text = "<nodev>"; break;
7625d39513SDavid van Moolenbroek case KERN_PROC_TTY_REVOKE:
7725d39513SDavid van Moolenbroek text = "<revoke>"; break;
7825d39513SDavid van Moolenbroek }
7925d39513SDavid van Moolenbroek }
8025d39513SDavid van Moolenbroek
8125d39513SDavid van Moolenbroek if (!valuesonly && text != NULL)
8225d39513SDavid van Moolenbroek put_field(proc, NULL, text);
8325d39513SDavid van Moolenbroek else
8425d39513SDavid van Moolenbroek put_value(proc, NULL, "%d", mib[i]);
8525d39513SDavid van Moolenbroek }
8625d39513SDavid van Moolenbroek
8725d39513SDavid van Moolenbroek /*
8825d39513SDavid van Moolenbroek * Save the requested structure length, so that we can later
8925d39513SDavid van Moolenbroek * determine how many elements were returned (see below).
9025d39513SDavid van Moolenbroek */
9125d39513SDavid van Moolenbroek proc->sctl_arg = (size == 4) ? mib[2] : 0;
9225d39513SDavid van Moolenbroek
9325d39513SDavid van Moolenbroek return 0;
9425d39513SDavid van Moolenbroek }
9525d39513SDavid van Moolenbroek
9625d39513SDavid van Moolenbroek if (proc->sctl_arg > 0) {
9725d39513SDavid van Moolenbroek /* TODO: optionally dump struct kinfo_drivers array */
9825d39513SDavid van Moolenbroek put_open(proc, name, 0, "[", ", ");
9925d39513SDavid van Moolenbroek if (size > 0)
10025d39513SDavid van Moolenbroek put_tail(proc, size / proc->sctl_arg, 0);
10125d39513SDavid van Moolenbroek put_close(proc, "]");
10225d39513SDavid van Moolenbroek } else
10325d39513SDavid van Moolenbroek put_ptr(proc, name, addr);
10425d39513SDavid van Moolenbroek
10525d39513SDavid van Moolenbroek return TRUE;
10625d39513SDavid van Moolenbroek }
10725d39513SDavid van Moolenbroek
10825d39513SDavid van Moolenbroek /*
10925d39513SDavid van Moolenbroek * Print CTL_KERN KERN_PROC_ARGS.
11025d39513SDavid van Moolenbroek */
11125d39513SDavid van Moolenbroek static int
put_kern_proc_args(struct trace_proc * proc,const char * name,int type,const void * ptr,vir_bytes addr,size_t size)11225d39513SDavid van Moolenbroek put_kern_proc_args(struct trace_proc * proc, const char * name, int type,
11325d39513SDavid van Moolenbroek const void * ptr, vir_bytes addr, size_t size)
11425d39513SDavid van Moolenbroek {
11525d39513SDavid van Moolenbroek const int *mib;
11625d39513SDavid van Moolenbroek const char *text;
117b58e161cSDavid van Moolenbroek unsigned int i;
118b58e161cSDavid van Moolenbroek int v;
11925d39513SDavid van Moolenbroek
12025d39513SDavid van Moolenbroek if (type == ST_NAME) {
12125d39513SDavid van Moolenbroek mib = (const int *)ptr;
12225d39513SDavid van Moolenbroek
12325d39513SDavid van Moolenbroek for (i = 0; i < size; i++) {
12425d39513SDavid van Moolenbroek text = NULL;
12525d39513SDavid van Moolenbroek
12625d39513SDavid van Moolenbroek if (i == 1) {
12725d39513SDavid van Moolenbroek switch (mib[i]) {
12825d39513SDavid van Moolenbroek case KERN_PROC_ARGV: text = "<argv>"; break;
12925d39513SDavid van Moolenbroek case KERN_PROC_ENV: text = "<env>"; break;
13025d39513SDavid van Moolenbroek case KERN_PROC_NARGV: text = "<nargv>"; break;
13125d39513SDavid van Moolenbroek case KERN_PROC_NENV: text = "<nenv>"; break;
13225d39513SDavid van Moolenbroek }
13325d39513SDavid van Moolenbroek }
13425d39513SDavid van Moolenbroek
13525d39513SDavid van Moolenbroek if (!valuesonly && text != NULL)
13625d39513SDavid van Moolenbroek put_field(proc, NULL, text);
13725d39513SDavid van Moolenbroek else
13825d39513SDavid van Moolenbroek put_value(proc, NULL, "%d", mib[i]);
13925d39513SDavid van Moolenbroek }
14025d39513SDavid van Moolenbroek
14125d39513SDavid van Moolenbroek /* Save the subrequest, so that we can later print data. */
14225d39513SDavid van Moolenbroek proc->sctl_arg = (size == 2) ? mib[1] : -999;
14325d39513SDavid van Moolenbroek
14425d39513SDavid van Moolenbroek return 0;
14525d39513SDavid van Moolenbroek }
14625d39513SDavid van Moolenbroek
14725d39513SDavid van Moolenbroek if ((proc->sctl_arg == KERN_PROC_NARGV ||
14825d39513SDavid van Moolenbroek proc->sctl_arg == KERN_PROC_NENV) && size == sizeof(v) &&
14925d39513SDavid van Moolenbroek mem_get_data(proc->pid, addr, &v, sizeof(v)) >= 0) {
15025d39513SDavid van Moolenbroek put_open(proc, name, PF_NONAME, "{", ", ");
15125d39513SDavid van Moolenbroek
15225d39513SDavid van Moolenbroek put_value(proc, NULL, "%d", v);
15325d39513SDavid van Moolenbroek
15425d39513SDavid van Moolenbroek put_close(proc, "}");
15525d39513SDavid van Moolenbroek } else
15625d39513SDavid van Moolenbroek put_ptr(proc, name, addr);
15725d39513SDavid van Moolenbroek
15825d39513SDavid van Moolenbroek return TRUE;
15925d39513SDavid van Moolenbroek }
16025d39513SDavid van Moolenbroek
16125d39513SDavid van Moolenbroek /*
16225d39513SDavid van Moolenbroek * Print CTL_KERN KERN_CP_TIME.
16325d39513SDavid van Moolenbroek */
16425d39513SDavid van Moolenbroek static int
put_kern_cp_time(struct trace_proc * proc,const char * name __unused,int type,const void * ptr,vir_bytes addr __unused,size_t size)16525d39513SDavid van Moolenbroek put_kern_cp_time(struct trace_proc * proc, const char * name __unused,
16625d39513SDavid van Moolenbroek int type, const void * ptr, vir_bytes addr __unused, size_t size)
16725d39513SDavid van Moolenbroek {
168b58e161cSDavid van Moolenbroek const uint64_t *p;
16925d39513SDavid van Moolenbroek unsigned int i;
17025d39513SDavid van Moolenbroek const int *mib;
17125d39513SDavid van Moolenbroek
17225d39513SDavid van Moolenbroek if (type == ST_NAME) {
17325d39513SDavid van Moolenbroek mib = (const int *)ptr;
17425d39513SDavid van Moolenbroek for (i = 0; i < size; i++)
17525d39513SDavid van Moolenbroek put_value(proc, NULL, "%d", mib[i]);
17625d39513SDavid van Moolenbroek
17725d39513SDavid van Moolenbroek return 0;
17825d39513SDavid van Moolenbroek }
17925d39513SDavid van Moolenbroek
180b58e161cSDavid van Moolenbroek p = (const uint64_t *)ptr;
18125d39513SDavid van Moolenbroek
18225d39513SDavid van Moolenbroek /* TODO: support for multi-CPU results */
18325d39513SDavid van Moolenbroek for (i = 0; i < CPUSTATES; i++)
18425d39513SDavid van Moolenbroek put_value(proc, NULL, "%"PRIu64, p[i]);
18525d39513SDavid van Moolenbroek
18625d39513SDavid van Moolenbroek return TRUE;
18725d39513SDavid van Moolenbroek }
18825d39513SDavid van Moolenbroek
18925d39513SDavid van Moolenbroek /*
19025d39513SDavid van Moolenbroek * Print CTL_KERN KERN_CONSDEV.
19125d39513SDavid van Moolenbroek */
19225d39513SDavid van Moolenbroek static int
put_kern_consdev(struct trace_proc * proc,const char * name,int type __unused,const void * ptr,vir_bytes addr __unused,size_t size __unused)19325d39513SDavid van Moolenbroek put_kern_consdev(struct trace_proc * proc, const char * name,
19425d39513SDavid van Moolenbroek int type __unused, const void * ptr, vir_bytes addr __unused,
19525d39513SDavid van Moolenbroek size_t size __unused)
19625d39513SDavid van Moolenbroek {
19725d39513SDavid van Moolenbroek
198b58e161cSDavid van Moolenbroek put_dev(proc, NULL, *(const dev_t *)ptr);
19925d39513SDavid van Moolenbroek
20025d39513SDavid van Moolenbroek return TRUE;
20125d39513SDavid van Moolenbroek }
20225d39513SDavid van Moolenbroek
20325d39513SDavid van Moolenbroek /*
20425d39513SDavid van Moolenbroek * Print CTL_KERN KERN_DRIVERS.
20525d39513SDavid van Moolenbroek */
20625d39513SDavid van Moolenbroek static int
put_kern_drivers(struct trace_proc * proc,const char * name,int type __unused,const void * ptr __unused,vir_bytes addr __unused,size_t size)20725d39513SDavid van Moolenbroek put_kern_drivers(struct trace_proc * proc, const char * name,
20825d39513SDavid van Moolenbroek int type __unused, const void * ptr __unused, vir_bytes addr __unused,
20925d39513SDavid van Moolenbroek size_t size)
21025d39513SDavid van Moolenbroek {
21125d39513SDavid van Moolenbroek
21225d39513SDavid van Moolenbroek /* TODO: optionally dump struct kinfo_drivers array */
21325d39513SDavid van Moolenbroek put_open(proc, name, 0, "[", ", ");
21425d39513SDavid van Moolenbroek if (size > 0)
21525d39513SDavid van Moolenbroek put_tail(proc, size / sizeof(struct kinfo_drivers), 0);
21625d39513SDavid van Moolenbroek put_close(proc, "]");
21725d39513SDavid van Moolenbroek
21825d39513SDavid van Moolenbroek return TRUE;
21925d39513SDavid van Moolenbroek }
22025d39513SDavid van Moolenbroek
22125d39513SDavid van Moolenbroek /*
22225d39513SDavid van Moolenbroek * Print CTL_KERN KERN_BOOTTIME.
22325d39513SDavid van Moolenbroek */
22425d39513SDavid van Moolenbroek static int
put_kern_boottime(struct trace_proc * proc,const char * name,int type __unused,const void * ptr __unused,vir_bytes addr,size_t size)22525d39513SDavid van Moolenbroek put_kern_boottime(struct trace_proc * proc, const char * name,
22625d39513SDavid van Moolenbroek int type __unused, const void * ptr __unused, vir_bytes addr,
22725d39513SDavid van Moolenbroek size_t size)
22825d39513SDavid van Moolenbroek {
22925d39513SDavid van Moolenbroek
23025d39513SDavid van Moolenbroek if (size == sizeof(struct timeval))
23125d39513SDavid van Moolenbroek put_struct_timeval(proc, name, 0, addr);
23225d39513SDavid van Moolenbroek else
23325d39513SDavid van Moolenbroek put_ptr(proc, name, addr);
23425d39513SDavid van Moolenbroek
23525d39513SDavid van Moolenbroek return TRUE;
23625d39513SDavid van Moolenbroek }
23725d39513SDavid van Moolenbroek
2382f09e77bSDavid van Moolenbroek /*
2392f09e77bSDavid van Moolenbroek * Print CTL_KERN KERN_SYSVIPC KERN_SYSVIPC_INFO.
2402f09e77bSDavid van Moolenbroek */
2412f09e77bSDavid van Moolenbroek static int
put_kern_sysvipc_info(struct trace_proc * proc,const char * name,int type,const void * ptr,vir_bytes addr,size_t size)2422f09e77bSDavid van Moolenbroek put_kern_sysvipc_info(struct trace_proc * proc, const char * name,
243*764cd267SDavid van Moolenbroek int type, const void * ptr, vir_bytes addr, size_t size)
2442f09e77bSDavid van Moolenbroek {
2452f09e77bSDavid van Moolenbroek const int *mib;
2462f09e77bSDavid van Moolenbroek const char *text;
247b58e161cSDavid van Moolenbroek unsigned int i;
2482f09e77bSDavid van Moolenbroek
2492f09e77bSDavid van Moolenbroek /*
2502f09e77bSDavid van Moolenbroek * TODO: print the obtained structure(s). For now we are just
2512f09e77bSDavid van Moolenbroek * concerned with the name components.
2522f09e77bSDavid van Moolenbroek */
2532f09e77bSDavid van Moolenbroek if (type != ST_NAME) {
2542f09e77bSDavid van Moolenbroek put_ptr(proc, name, addr);
2552f09e77bSDavid van Moolenbroek
2562f09e77bSDavid van Moolenbroek return TRUE;
2572f09e77bSDavid van Moolenbroek }
2582f09e77bSDavid van Moolenbroek
2592f09e77bSDavid van Moolenbroek mib = (const int *)ptr;
2602f09e77bSDavid van Moolenbroek
2612f09e77bSDavid van Moolenbroek for (i = 0; i < size; i++) {
2622f09e77bSDavid van Moolenbroek text = NULL;
2632f09e77bSDavid van Moolenbroek
2642f09e77bSDavid van Moolenbroek if (i == 0) {
2652f09e77bSDavid van Moolenbroek switch (mib[i]) {
2662f09e77bSDavid van Moolenbroek case KERN_SYSVIPC_SEM_INFO: text = "<sem>"; break;
2672f09e77bSDavid van Moolenbroek case KERN_SYSVIPC_SHM_INFO: text = "<shm>"; break;
2682f09e77bSDavid van Moolenbroek case KERN_SYSVIPC_MSG_INFO: text = "<msg>"; break;
2692f09e77bSDavid van Moolenbroek }
2702f09e77bSDavid van Moolenbroek }
2712f09e77bSDavid van Moolenbroek
2722f09e77bSDavid van Moolenbroek if (!valuesonly && text != NULL)
2732f09e77bSDavid van Moolenbroek put_field(proc, NULL, text);
2742f09e77bSDavid van Moolenbroek else
2752f09e77bSDavid van Moolenbroek put_value(proc, NULL, "%d", mib[i]);
2762f09e77bSDavid van Moolenbroek }
2772f09e77bSDavid van Moolenbroek
2782f09e77bSDavid van Moolenbroek return 0;
2792f09e77bSDavid van Moolenbroek }
2802f09e77bSDavid van Moolenbroek
2812f09e77bSDavid van Moolenbroek /* The CTL_KERN KERN_SYSVIPC table. */
2822f09e77bSDavid van Moolenbroek static const struct sysctl_tab kern_sysvipc_tab[] = {
2832f09e77bSDavid van Moolenbroek PROC(KERN_SYSVIPC_INFO, 0, put_kern_sysvipc_info),
2842f09e77bSDavid van Moolenbroek };
2852f09e77bSDavid van Moolenbroek
286e4e21ee1SDavid van Moolenbroek /* The CTL_KERN table. */
287e4e21ee1SDavid van Moolenbroek static const struct sysctl_tab kern_tab[] = {
28825d39513SDavid van Moolenbroek PROC(KERN_CLOCKRATE, sizeof(struct clockinfo), put_kern_clockrate),
28925d39513SDavid van Moolenbroek PROC(KERN_PROC2, 0, put_kern_proc2),
29025d39513SDavid van Moolenbroek PROC(KERN_PROC_ARGS, 0, put_kern_proc_args),
29125d39513SDavid van Moolenbroek PROC(KERN_CP_TIME, sizeof(uint64_t) * CPUSTATES, put_kern_cp_time),
29225d39513SDavid van Moolenbroek PROC(KERN_CONSDEV, sizeof(dev_t), put_kern_consdev),
29325d39513SDavid van Moolenbroek PROC(KERN_DRIVERS, 0, put_kern_drivers),
2942f09e77bSDavid van Moolenbroek NODE(KERN_SYSVIPC, kern_sysvipc_tab),
29525d39513SDavid van Moolenbroek PROC(KERN_BOOTTIME, 0, put_kern_boottime),
29625d39513SDavid van Moolenbroek };
29725d39513SDavid van Moolenbroek
29825d39513SDavid van Moolenbroek /*
29925d39513SDavid van Moolenbroek * Print CTL_VM VM_LOADAVG.
30025d39513SDavid van Moolenbroek */
30125d39513SDavid van Moolenbroek static int
put_vm_loadavg(struct trace_proc * proc,const char * name __unused,int type __unused,const void * ptr,vir_bytes addr __unused,size_t size __unused)30225d39513SDavid van Moolenbroek put_vm_loadavg(struct trace_proc * proc, const char * name __unused,
30325d39513SDavid van Moolenbroek int type __unused, const void * ptr, vir_bytes addr __unused,
30425d39513SDavid van Moolenbroek size_t size __unused)
30525d39513SDavid van Moolenbroek {
306b58e161cSDavid van Moolenbroek const struct loadavg *loadavg;
30725d39513SDavid van Moolenbroek unsigned int i;
30825d39513SDavid van Moolenbroek
309b58e161cSDavid van Moolenbroek loadavg = (const struct loadavg *)ptr;
31025d39513SDavid van Moolenbroek
31125d39513SDavid van Moolenbroek put_open(proc, "ldavg", 0, "{", ", ");
31225d39513SDavid van Moolenbroek
31325d39513SDavid van Moolenbroek for (i = 0; i < __arraycount(loadavg->ldavg); i++)
31425d39513SDavid van Moolenbroek put_value(proc, NULL, "%"PRIu32, loadavg->ldavg[i]);
31525d39513SDavid van Moolenbroek
31625d39513SDavid van Moolenbroek put_close(proc, "}");
31725d39513SDavid van Moolenbroek
31825d39513SDavid van Moolenbroek if (verbose > 0) {
31925d39513SDavid van Moolenbroek put_value(proc, "fscale", "%ld", loadavg->fscale);
32025d39513SDavid van Moolenbroek
32125d39513SDavid van Moolenbroek return TRUE;
32225d39513SDavid van Moolenbroek } else
32325d39513SDavid van Moolenbroek return FALSE;
32425d39513SDavid van Moolenbroek }
32525d39513SDavid van Moolenbroek
32625d39513SDavid van Moolenbroek /* The CTL_VM table. */
32725d39513SDavid van Moolenbroek static const struct sysctl_tab vm_tab[] = {
32825d39513SDavid van Moolenbroek PROC(VM_LOADAVG, sizeof(struct loadavg), put_vm_loadavg),
329e4e21ee1SDavid van Moolenbroek };
330e4e21ee1SDavid van Moolenbroek
331*764cd267SDavid van Moolenbroek /*
332*764cd267SDavid van Moolenbroek * Print CTL_NET PF_ROUTE 0.
333*764cd267SDavid van Moolenbroek */
334*764cd267SDavid van Moolenbroek static int
put_net_route_rtable(struct trace_proc * proc,const char * name,int type,const void * ptr,vir_bytes addr,size_t size)335*764cd267SDavid van Moolenbroek put_net_route_rtable(struct trace_proc * proc, const char * name,
336*764cd267SDavid van Moolenbroek int type, const void * ptr, vir_bytes addr, size_t size)
337*764cd267SDavid van Moolenbroek {
338*764cd267SDavid van Moolenbroek const int *mib;
339*764cd267SDavid van Moolenbroek const char *text;
340*764cd267SDavid van Moolenbroek unsigned int i;
341*764cd267SDavid van Moolenbroek
342*764cd267SDavid van Moolenbroek /*
343*764cd267SDavid van Moolenbroek * TODO: print the obtained structure(s). For now we are just
344*764cd267SDavid van Moolenbroek * concerned with the name components.
345*764cd267SDavid van Moolenbroek */
346*764cd267SDavid van Moolenbroek if (type != ST_NAME) {
347*764cd267SDavid van Moolenbroek put_ptr(proc, name, addr);
348*764cd267SDavid van Moolenbroek
349*764cd267SDavid van Moolenbroek return TRUE;
350*764cd267SDavid van Moolenbroek }
351*764cd267SDavid van Moolenbroek
352*764cd267SDavid van Moolenbroek mib = (const int *)ptr;
353*764cd267SDavid van Moolenbroek
354*764cd267SDavid van Moolenbroek for (i = 0; i < size; i++) {
355*764cd267SDavid van Moolenbroek text = NULL;
356*764cd267SDavid van Moolenbroek
357*764cd267SDavid van Moolenbroek switch (i) {
358*764cd267SDavid van Moolenbroek case 0:
359*764cd267SDavid van Moolenbroek switch (mib[i]) {
360*764cd267SDavid van Moolenbroek case AF_UNSPEC: text = "<all>"; break;
361*764cd267SDavid van Moolenbroek case AF_LINK: text = "<link>"; break;
362*764cd267SDavid van Moolenbroek case AF_INET: text = "<inet>"; break;
363*764cd267SDavid van Moolenbroek case AF_INET6: text = "<inet6>"; break;
364*764cd267SDavid van Moolenbroek /* TODO: add more address families here */
365*764cd267SDavid van Moolenbroek }
366*764cd267SDavid van Moolenbroek break;
367*764cd267SDavid van Moolenbroek case 1:
368*764cd267SDavid van Moolenbroek switch (mib[i]) {
369*764cd267SDavid van Moolenbroek case NET_RT_DUMP: text = "<dump>"; break;
370*764cd267SDavid van Moolenbroek case NET_RT_FLAGS: text = "<flags>"; break;
371*764cd267SDavid van Moolenbroek case NET_RT_IFLIST: text = "<iflist>"; break;
372*764cd267SDavid van Moolenbroek }
373*764cd267SDavid van Moolenbroek break;
374*764cd267SDavid van Moolenbroek case 2:
375*764cd267SDavid van Moolenbroek if (mib[1] == NET_RT_IFLIST && mib[i] == 0)
376*764cd267SDavid van Moolenbroek text = "<all>";
377*764cd267SDavid van Moolenbroek }
378*764cd267SDavid van Moolenbroek
379*764cd267SDavid van Moolenbroek if (!valuesonly && text != NULL)
380*764cd267SDavid van Moolenbroek put_field(proc, NULL, text);
381*764cd267SDavid van Moolenbroek else
382*764cd267SDavid van Moolenbroek put_value(proc, NULL, "%d", mib[i]);
383*764cd267SDavid van Moolenbroek }
384*764cd267SDavid van Moolenbroek
385*764cd267SDavid van Moolenbroek return 0;
386*764cd267SDavid van Moolenbroek }
387*764cd267SDavid van Moolenbroek
388*764cd267SDavid van Moolenbroek /* The CTL_NET PF_ROUTE table. */
389*764cd267SDavid van Moolenbroek static const struct sysctl_tab net_route_tab[] = {
390*764cd267SDavid van Moolenbroek PROC(0, 0, put_net_route_rtable),
391*764cd267SDavid van Moolenbroek };
392*764cd267SDavid van Moolenbroek
393*764cd267SDavid van Moolenbroek /* The CTL_NET table. */
394*764cd267SDavid van Moolenbroek static const struct sysctl_tab net_tab[] = {
395*764cd267SDavid van Moolenbroek NODE(PF_ROUTE, net_route_tab),
396*764cd267SDavid van Moolenbroek };
397*764cd267SDavid van Moolenbroek
398e4e21ee1SDavid van Moolenbroek /* The top-level table, which is indexed by identifier. */
399e4e21ee1SDavid van Moolenbroek static const struct sysctl_tab root_tab[] = {
400e4e21ee1SDavid van Moolenbroek [CTL_KERN] = NODE(0, kern_tab),
40125d39513SDavid van Moolenbroek [CTL_VM] = NODE(0, vm_tab),
402*764cd267SDavid van Moolenbroek [CTL_NET] = NODE(0, net_tab),
403e4e21ee1SDavid van Moolenbroek };
404e4e21ee1SDavid van Moolenbroek
405e4e21ee1SDavid van Moolenbroek /*
406e4e21ee1SDavid van Moolenbroek * This buffer should be large enough to avoid having to perform dynamic
407e4e21ee1SDavid van Moolenbroek * allocation in all but highly exceptional cases. The CTL_KERN subtree is
408e4e21ee1SDavid van Moolenbroek * currently the largest, so we base the buffer size on its length.
409e4e21ee1SDavid van Moolenbroek * TODO: merge this buffer with ioctlbuf.
410e4e21ee1SDavid van Moolenbroek */
411e4e21ee1SDavid van Moolenbroek static char sysctlbuf[sizeof(struct sysctlnode) * KERN_MAXID];
412e4e21ee1SDavid van Moolenbroek
413e4e21ee1SDavid van Moolenbroek static const struct flags sysctl_flags[] = {
414e4e21ee1SDavid van Moolenbroek FLAG_MASK(SYSCTL_VERS_MASK, SYSCTL_VERS_0),
415e4e21ee1SDavid van Moolenbroek FLAG_MASK(SYSCTL_VERS_MASK, SYSCTL_VERSION),
416e4e21ee1SDavid van Moolenbroek #define SYSCTL_VER_ENTRIES 2 /* the first N entries are for SYSCTL_VERS_MASK */
417e4e21ee1SDavid van Moolenbroek FLAG(CTLFLAG_UNSIGNED),
418e4e21ee1SDavid van Moolenbroek FLAG(CTLFLAG_OWNDESC),
419e4e21ee1SDavid van Moolenbroek FLAG(CTLFLAG_MMAP),
420e4e21ee1SDavid van Moolenbroek FLAG(CTLFLAG_ALIAS),
421e4e21ee1SDavid van Moolenbroek FLAG(CTLFLAG_ANYNUMBER),
422e4e21ee1SDavid van Moolenbroek FLAG(CTLFLAG_ROOT),
423e4e21ee1SDavid van Moolenbroek FLAG(CTLFLAG_HEX),
424e4e21ee1SDavid van Moolenbroek FLAG(CTLFLAG_IMMEDIATE),
425e4e21ee1SDavid van Moolenbroek FLAG(CTLFLAG_OWNDATA),
426e4e21ee1SDavid van Moolenbroek FLAG(CTLFLAG_HIDDEN),
427e4e21ee1SDavid van Moolenbroek FLAG(CTLFLAG_PERMANENT),
428e4e21ee1SDavid van Moolenbroek FLAG(CTLFLAG_PRIVATE),
429e4e21ee1SDavid van Moolenbroek FLAG(CTLFLAG_ANYWRITE),
430e4e21ee1SDavid van Moolenbroek FLAG_MASK(CTLFLAG_READWRITE, CTLFLAG_READONLY),
431e4e21ee1SDavid van Moolenbroek FLAG_MASK(CTLFLAG_READWRITE, CTLFLAG_READWRITE),
432e4e21ee1SDavid van Moolenbroek FLAG_MASK(SYSCTL_TYPEMASK, CTLTYPE_NODE),
433e4e21ee1SDavid van Moolenbroek FLAG_MASK(SYSCTL_TYPEMASK, CTLTYPE_INT),
434e4e21ee1SDavid van Moolenbroek FLAG_MASK(SYSCTL_TYPEMASK, CTLTYPE_STRING),
435e4e21ee1SDavid van Moolenbroek FLAG_MASK(SYSCTL_TYPEMASK, CTLTYPE_QUAD),
436e4e21ee1SDavid van Moolenbroek FLAG_MASK(SYSCTL_TYPEMASK, CTLTYPE_STRUCT),
437e4e21ee1SDavid van Moolenbroek FLAG_MASK(SYSCTL_TYPEMASK, CTLTYPE_BOOL),
438e4e21ee1SDavid van Moolenbroek };
439e4e21ee1SDavid van Moolenbroek
440e4e21ee1SDavid van Moolenbroek /*
441e4e21ee1SDavid van Moolenbroek * Print the immediate value of a sysctl node.
442e4e21ee1SDavid van Moolenbroek */
443e4e21ee1SDavid van Moolenbroek static void
put_sysctl_imm(struct trace_proc * proc,struct sysctlnode * scn,int use_name)444e4e21ee1SDavid van Moolenbroek put_sysctl_imm(struct trace_proc * proc, struct sysctlnode * scn, int use_name)
445e4e21ee1SDavid van Moolenbroek {
446b58e161cSDavid van Moolenbroek const char *name;
447e4e21ee1SDavid van Moolenbroek
448e4e21ee1SDavid van Moolenbroek name = NULL;
449e4e21ee1SDavid van Moolenbroek
450e4e21ee1SDavid van Moolenbroek switch (SYSCTL_TYPE(scn->sysctl_flags)) {
451e4e21ee1SDavid van Moolenbroek case CTLTYPE_INT:
452e4e21ee1SDavid van Moolenbroek if (use_name)
453e4e21ee1SDavid van Moolenbroek name = "sysctl_idata";
454e4e21ee1SDavid van Moolenbroek if (scn->sysctl_flags & CTLFLAG_HEX)
455e4e21ee1SDavid van Moolenbroek put_value(proc, name, "0x%x", scn->sysctl_idata);
456e4e21ee1SDavid van Moolenbroek else if (scn->sysctl_flags & CTLFLAG_UNSIGNED)
457e4e21ee1SDavid van Moolenbroek put_value(proc, name, "%u", scn->sysctl_idata);
458e4e21ee1SDavid van Moolenbroek else
459e4e21ee1SDavid van Moolenbroek put_value(proc, name, "%d", scn->sysctl_idata);
460e4e21ee1SDavid van Moolenbroek break;
461e4e21ee1SDavid van Moolenbroek case CTLTYPE_BOOL:
462e4e21ee1SDavid van Moolenbroek if (use_name)
463e4e21ee1SDavid van Moolenbroek name = "sysctl_bdata";
464e4e21ee1SDavid van Moolenbroek put_field(proc, name, (scn->sysctl_bdata) ? "true" : "false");
465e4e21ee1SDavid van Moolenbroek break;
466e4e21ee1SDavid van Moolenbroek case CTLTYPE_QUAD:
467e4e21ee1SDavid van Moolenbroek if (use_name)
468e4e21ee1SDavid van Moolenbroek name = "sysctl_qdata";
469e4e21ee1SDavid van Moolenbroek if (scn->sysctl_flags & CTLFLAG_HEX)
470e4e21ee1SDavid van Moolenbroek put_value(proc, name, "0x%"PRIx64, scn->sysctl_qdata);
471e4e21ee1SDavid van Moolenbroek else
472e4e21ee1SDavid van Moolenbroek put_value(proc, name, "%"PRIu64, scn->sysctl_qdata);
473e4e21ee1SDavid van Moolenbroek break;
474e4e21ee1SDavid van Moolenbroek }
475e4e21ee1SDavid van Moolenbroek }
476e4e21ee1SDavid van Moolenbroek
477e4e21ee1SDavid van Moolenbroek /*
478e4e21ee1SDavid van Moolenbroek * Printer for CTL_QUERY data.
479e4e21ee1SDavid van Moolenbroek */
480e4e21ee1SDavid van Moolenbroek static int
put_sysctl_query(struct trace_proc * proc,const char * name,int type,const void * data __unused,vir_bytes addr,size_t size)481e4e21ee1SDavid van Moolenbroek put_sysctl_query(struct trace_proc * proc, const char * name, int type,
482e4e21ee1SDavid van Moolenbroek const void * data __unused, vir_bytes addr, size_t size)
483e4e21ee1SDavid van Moolenbroek {
484e4e21ee1SDavid van Moolenbroek struct sysctlnode scn;
485e4e21ee1SDavid van Moolenbroek
486e4e21ee1SDavid van Moolenbroek if (type == ST_NEWP) {
487e4e21ee1SDavid van Moolenbroek if (!put_open_struct(proc, name, 0, addr, &scn, sizeof(scn)))
488e4e21ee1SDavid van Moolenbroek return TRUE;
489e4e21ee1SDavid van Moolenbroek
490e4e21ee1SDavid van Moolenbroek /* Print just the protocol version, that's all there is. */
491e4e21ee1SDavid van Moolenbroek if (verbose > 1)
492e4e21ee1SDavid van Moolenbroek put_flags(proc, "sysctl_flags", sysctl_flags,
493e4e21ee1SDavid van Moolenbroek SYSCTL_VER_ENTRIES, "0x%x", scn.sysctl_flags);
494e4e21ee1SDavid van Moolenbroek
495e4e21ee1SDavid van Moolenbroek put_close_struct(proc, FALSE /*all*/);
496e4e21ee1SDavid van Moolenbroek } else {
497e4e21ee1SDavid van Moolenbroek /* TODO: optionally dump struct sysctlnode array */
498e4e21ee1SDavid van Moolenbroek put_open(proc, name, 0, "[", ", ");
499e4e21ee1SDavid van Moolenbroek if (size > 0)
500e4e21ee1SDavid van Moolenbroek put_tail(proc, size / sizeof(scn), 0);
501e4e21ee1SDavid van Moolenbroek put_close(proc, "]");
502e4e21ee1SDavid van Moolenbroek }
503e4e21ee1SDavid van Moolenbroek
504e4e21ee1SDavid van Moolenbroek return TRUE;
505e4e21ee1SDavid van Moolenbroek }
506e4e21ee1SDavid van Moolenbroek
507e4e21ee1SDavid van Moolenbroek /*
508e4e21ee1SDavid van Moolenbroek * Printer for CTL_CREATE data.
509e4e21ee1SDavid van Moolenbroek */
510e4e21ee1SDavid van Moolenbroek static int
put_sysctl_create(struct trace_proc * proc,const char * name,int type,const void * data __unused,vir_bytes addr,size_t size)511e4e21ee1SDavid van Moolenbroek put_sysctl_create(struct trace_proc * proc, const char * name, int type,
512e4e21ee1SDavid van Moolenbroek const void * data __unused, vir_bytes addr, size_t size)
513e4e21ee1SDavid van Moolenbroek {
514e4e21ee1SDavid van Moolenbroek struct sysctlnode scn;
515e4e21ee1SDavid van Moolenbroek
516e4e21ee1SDavid van Moolenbroek if (!put_open_struct(proc, name, 0, addr, &scn, sizeof(scn)))
517e4e21ee1SDavid van Moolenbroek return TRUE;
518e4e21ee1SDavid van Moolenbroek
519e4e21ee1SDavid van Moolenbroek if (type == ST_NEWP)
520e4e21ee1SDavid van Moolenbroek put_flags(proc, "sysctl_flags", sysctl_flags,
521e4e21ee1SDavid van Moolenbroek COUNT(sysctl_flags), "0x%x", scn.sysctl_flags);
522e4e21ee1SDavid van Moolenbroek
523e4e21ee1SDavid van Moolenbroek if (scn.sysctl_num == CTL_CREATE && type == ST_NEWP && !valuesonly)
524e4e21ee1SDavid van Moolenbroek put_field(proc, "sysctl_num", "CTL_CREATE");
525e4e21ee1SDavid van Moolenbroek else
526e4e21ee1SDavid van Moolenbroek put_value(proc, "sysctl_num", "%d", scn.sysctl_num);
527e4e21ee1SDavid van Moolenbroek
528e4e21ee1SDavid van Moolenbroek if (type == ST_NEWP) {
529e4e21ee1SDavid van Moolenbroek put_buf(proc, "sysctl_name", PF_LOCADDR | PF_STRING,
530e4e21ee1SDavid van Moolenbroek (vir_bytes)scn.sysctl_name, sizeof(scn.sysctl_name));
531e4e21ee1SDavid van Moolenbroek }
532e4e21ee1SDavid van Moolenbroek if (scn.sysctl_ver != 0 && verbose > 0)
533e4e21ee1SDavid van Moolenbroek put_value(proc, "sysctl_ver", "%u", scn.sysctl_ver);
534e4e21ee1SDavid van Moolenbroek
535e4e21ee1SDavid van Moolenbroek if (type == ST_NEWP) {
536e4e21ee1SDavid van Moolenbroek if (scn.sysctl_flags & CTLFLAG_IMMEDIATE)
537e4e21ee1SDavid van Moolenbroek put_sysctl_imm(proc, &scn, TRUE /*use_name*/);
538e4e21ee1SDavid van Moolenbroek
539e4e21ee1SDavid van Moolenbroek switch (SYSCTL_TYPE(scn.sysctl_flags)) {
540e4e21ee1SDavid van Moolenbroek case CTLTYPE_NODE:
541e4e21ee1SDavid van Moolenbroek break;
542e4e21ee1SDavid van Moolenbroek case CTLTYPE_STRING:
543e4e21ee1SDavid van Moolenbroek if (scn.sysctl_data != NULL)
544e4e21ee1SDavid van Moolenbroek put_buf(proc, "sysctl_data", PF_STRING,
545e4e21ee1SDavid van Moolenbroek (vir_bytes)scn.sysctl_data,
546e4e21ee1SDavid van Moolenbroek (scn.sysctl_size > 0) ? scn.sysctl_size :
547e4e21ee1SDavid van Moolenbroek SSIZE_MAX /* hopefully it stops early */);
548e4e21ee1SDavid van Moolenbroek if (scn.sysctl_data != NULL || verbose == 0)
549e4e21ee1SDavid van Moolenbroek break;
550e4e21ee1SDavid van Moolenbroek /* FALLTHROUGH */
551e4e21ee1SDavid van Moolenbroek default:
552e4e21ee1SDavid van Moolenbroek if (!(scn.sysctl_flags & CTLFLAG_IMMEDIATE) &&
553e4e21ee1SDavid van Moolenbroek verbose > 0)
554e4e21ee1SDavid van Moolenbroek put_ptr(proc, "sysctl_data",
555e4e21ee1SDavid van Moolenbroek (vir_bytes)scn.sysctl_data);
556e4e21ee1SDavid van Moolenbroek break;
557e4e21ee1SDavid van Moolenbroek }
558e4e21ee1SDavid van Moolenbroek
559e4e21ee1SDavid van Moolenbroek if (SYSCTL_TYPE(scn.sysctl_flags) == CTLTYPE_STRUCT ||
560e4e21ee1SDavid van Moolenbroek verbose > 0)
561e4e21ee1SDavid van Moolenbroek put_value(proc, "sysctl_size", "%zu", scn.sysctl_size);
562e4e21ee1SDavid van Moolenbroek }
563e4e21ee1SDavid van Moolenbroek
564e4e21ee1SDavid van Moolenbroek put_close_struct(proc, FALSE /*all*/);
565e4e21ee1SDavid van Moolenbroek
566e4e21ee1SDavid van Moolenbroek return TRUE;
567e4e21ee1SDavid van Moolenbroek }
568e4e21ee1SDavid van Moolenbroek
569e4e21ee1SDavid van Moolenbroek /*
570e4e21ee1SDavid van Moolenbroek * Printer for CTL_DESTROY data.
571e4e21ee1SDavid van Moolenbroek */
572e4e21ee1SDavid van Moolenbroek static int
put_sysctl_destroy(struct trace_proc * proc,const char * name,int type,const void * data __unused,vir_bytes addr,size_t size)573e4e21ee1SDavid van Moolenbroek put_sysctl_destroy(struct trace_proc * proc, const char * name, int type,
574e4e21ee1SDavid van Moolenbroek const void * data __unused, vir_bytes addr, size_t size)
575e4e21ee1SDavid van Moolenbroek {
576e4e21ee1SDavid van Moolenbroek struct sysctlnode scn;
577e4e21ee1SDavid van Moolenbroek
578e4e21ee1SDavid van Moolenbroek if (!put_open_struct(proc, name, 0, addr, &scn, sizeof(scn)))
579e4e21ee1SDavid van Moolenbroek return TRUE;
580e4e21ee1SDavid van Moolenbroek
581e4e21ee1SDavid van Moolenbroek if (type == ST_NEWP) {
582e4e21ee1SDavid van Moolenbroek put_value(proc, "sysctl_num", "%d", scn.sysctl_num);
583e4e21ee1SDavid van Moolenbroek if (scn.sysctl_name[0] != '\0')
584e4e21ee1SDavid van Moolenbroek put_buf(proc, "sysctl_name", PF_LOCADDR | PF_STRING,
585e4e21ee1SDavid van Moolenbroek (vir_bytes)scn.sysctl_name,
586e4e21ee1SDavid van Moolenbroek sizeof(scn.sysctl_name));
587e4e21ee1SDavid van Moolenbroek if (scn.sysctl_ver != 0 && verbose > 0)
588e4e21ee1SDavid van Moolenbroek put_value(proc, "sysctl_ver", "%u", scn.sysctl_ver);
589e4e21ee1SDavid van Moolenbroek }
590e4e21ee1SDavid van Moolenbroek
591e4e21ee1SDavid van Moolenbroek put_close_struct(proc, FALSE /*all*/);
592e4e21ee1SDavid van Moolenbroek
593e4e21ee1SDavid van Moolenbroek return TRUE;
594e4e21ee1SDavid van Moolenbroek }
595e4e21ee1SDavid van Moolenbroek
596e4e21ee1SDavid van Moolenbroek /*
597e4e21ee1SDavid van Moolenbroek * Printer for CTL_CREATE data.
598e4e21ee1SDavid van Moolenbroek */
599e4e21ee1SDavid van Moolenbroek static int
put_sysctl_describe(struct trace_proc * proc,const char * name,int type,const void * data __unused,vir_bytes addr,size_t size)600e4e21ee1SDavid van Moolenbroek put_sysctl_describe(struct trace_proc * proc, const char * name, int type,
601e4e21ee1SDavid van Moolenbroek const void * data __unused, vir_bytes addr, size_t size)
602e4e21ee1SDavid van Moolenbroek {
603e4e21ee1SDavid van Moolenbroek struct sysctlnode scn;
604e4e21ee1SDavid van Moolenbroek
605e4e21ee1SDavid van Moolenbroek if (type == ST_NEWP) {
606e4e21ee1SDavid van Moolenbroek if (!put_open_struct(proc, name, 0, addr, &scn, sizeof(scn)))
607e4e21ee1SDavid van Moolenbroek return TRUE;
608e4e21ee1SDavid van Moolenbroek
609e4e21ee1SDavid van Moolenbroek /* Print just the protocol version, that's all there is. */
610e4e21ee1SDavid van Moolenbroek if (verbose > 1)
611e4e21ee1SDavid van Moolenbroek put_flags(proc, "sysctl_flags", sysctl_flags,
612e4e21ee1SDavid van Moolenbroek SYSCTL_VER_ENTRIES, "0x%x", scn.sysctl_flags);
613e4e21ee1SDavid van Moolenbroek
614e4e21ee1SDavid van Moolenbroek put_value(proc, "sysctl_num", "%d", scn.sysctl_num);
615e4e21ee1SDavid van Moolenbroek
616e4e21ee1SDavid van Moolenbroek if (scn.sysctl_desc != NULL)
617e4e21ee1SDavid van Moolenbroek put_buf(proc, "sysctl_desc", PF_STRING,
618e4e21ee1SDavid van Moolenbroek (vir_bytes)scn.sysctl_desc, 1024 /*no constant!*/);
619e4e21ee1SDavid van Moolenbroek else if (verbose > 0)
620e4e21ee1SDavid van Moolenbroek put_ptr(proc, "sysctl_desc",
621e4e21ee1SDavid van Moolenbroek (vir_bytes)scn.sysctl_desc);
622e4e21ee1SDavid van Moolenbroek
623e4e21ee1SDavid van Moolenbroek put_close_struct(proc, FALSE /*all*/);
624e4e21ee1SDavid van Moolenbroek } else {
625e4e21ee1SDavid van Moolenbroek /* TODO: optionally dump struct sysctldesc array */
626e4e21ee1SDavid van Moolenbroek put_field(proc, name, (size == 0) ? "[]" : "[..]");
627e4e21ee1SDavid van Moolenbroek }
628e4e21ee1SDavid van Moolenbroek
629e4e21ee1SDavid van Moolenbroek return TRUE;
630e4e21ee1SDavid van Moolenbroek }
631e4e21ee1SDavid van Moolenbroek
632e4e21ee1SDavid van Moolenbroek /*
633e4e21ee1SDavid van Moolenbroek * Printer for generic data, using the node flags stored in proc->sysctl_flags.
634e4e21ee1SDavid van Moolenbroek */
635e4e21ee1SDavid van Moolenbroek static int
put_sysctl_generic(struct trace_proc * proc,const char * name,int type,const void * data __unused,vir_bytes addr,size_t size)636e4e21ee1SDavid van Moolenbroek put_sysctl_generic(struct trace_proc * proc, const char * name, int type,
637e4e21ee1SDavid van Moolenbroek const void * data __unused, vir_bytes addr, size_t size)
638e4e21ee1SDavid van Moolenbroek {
639e4e21ee1SDavid van Moolenbroek struct sysctlnode scn;
640e4e21ee1SDavid van Moolenbroek void *ptr;
641e4e21ee1SDavid van Moolenbroek size_t len;
642e4e21ee1SDavid van Moolenbroek
643e4e21ee1SDavid van Moolenbroek switch (SYSCTL_TYPE(proc->sctl_flags)) {
644e4e21ee1SDavid van Moolenbroek case CTLTYPE_STRING:
645e4e21ee1SDavid van Moolenbroek put_buf(proc, name, PF_STRING, addr, size);
646e4e21ee1SDavid van Moolenbroek return TRUE;
647e4e21ee1SDavid van Moolenbroek case CTLTYPE_INT:
648e4e21ee1SDavid van Moolenbroek ptr = &scn.sysctl_idata;
649e4e21ee1SDavid van Moolenbroek len = sizeof(scn.sysctl_idata);
650e4e21ee1SDavid van Moolenbroek break;
651e4e21ee1SDavid van Moolenbroek case CTLTYPE_BOOL:
652e4e21ee1SDavid van Moolenbroek ptr = &scn.sysctl_bdata;
653e4e21ee1SDavid van Moolenbroek len = sizeof(scn.sysctl_bdata);
654e4e21ee1SDavid van Moolenbroek break;
655e4e21ee1SDavid van Moolenbroek case CTLTYPE_QUAD:
656e4e21ee1SDavid van Moolenbroek ptr = &scn.sysctl_qdata;
657e4e21ee1SDavid van Moolenbroek len = sizeof(scn.sysctl_qdata);
658e4e21ee1SDavid van Moolenbroek break;
659e4e21ee1SDavid van Moolenbroek case CTLTYPE_STRUCT:
660e4e21ee1SDavid van Moolenbroek default:
661e4e21ee1SDavid van Moolenbroek ptr = NULL;
662e4e21ee1SDavid van Moolenbroek len = 0;
663e4e21ee1SDavid van Moolenbroek break;
664e4e21ee1SDavid van Moolenbroek }
665e4e21ee1SDavid van Moolenbroek
666e4e21ee1SDavid van Moolenbroek if (ptr == NULL || len != size ||
667e4e21ee1SDavid van Moolenbroek mem_get_data(proc->pid, addr, ptr, len) < 0) {
668e4e21ee1SDavid van Moolenbroek put_ptr(proc, name, addr);
669e4e21ee1SDavid van Moolenbroek return TRUE;
670e4e21ee1SDavid van Moolenbroek }
671e4e21ee1SDavid van Moolenbroek
672e4e21ee1SDavid van Moolenbroek put_open(proc, name, PF_NONAME, "{", ", ");
673e4e21ee1SDavid van Moolenbroek
674e4e21ee1SDavid van Moolenbroek scn.sysctl_flags = proc->sctl_flags;
675e4e21ee1SDavid van Moolenbroek
676e4e21ee1SDavid van Moolenbroek put_sysctl_imm(proc, &scn, FALSE);
677e4e21ee1SDavid van Moolenbroek
678e4e21ee1SDavid van Moolenbroek put_close(proc, "}");
679e4e21ee1SDavid van Moolenbroek
680e4e21ee1SDavid van Moolenbroek return TRUE;
681e4e21ee1SDavid van Moolenbroek }
682e4e21ee1SDavid van Moolenbroek
683e4e21ee1SDavid van Moolenbroek /*
684e4e21ee1SDavid van Moolenbroek * Obtain information about a particular node 'id' in the node directory
685e4e21ee1SDavid van Moolenbroek * identified by the MIB path 'name' (length 'namelen'). Return TRUE if the
686e4e21ee1SDavid van Moolenbroek * node was found, in which case it is copied into 'scnp'. Return FALSE if the
687e4e21ee1SDavid van Moolenbroek * node was not found or another error occurred.
688e4e21ee1SDavid van Moolenbroek */
689e4e21ee1SDavid van Moolenbroek static int
get_sysctl_node(const int * name,unsigned int namelen,int id,struct sysctlnode * scnp)690e4e21ee1SDavid van Moolenbroek get_sysctl_node(const int * name, unsigned int namelen, int id,
691e4e21ee1SDavid van Moolenbroek struct sysctlnode * scnp)
692e4e21ee1SDavid van Moolenbroek {
693e4e21ee1SDavid van Moolenbroek struct sysctlnode *scn, *escn, *fscn;
694e4e21ee1SDavid van Moolenbroek char *buf;
695e4e21ee1SDavid van Moolenbroek size_t len, elen;
696e4e21ee1SDavid van Moolenbroek int r, mib[CTL_MAXNAME];
697e4e21ee1SDavid van Moolenbroek
698e4e21ee1SDavid van Moolenbroek assert(namelen < CTL_MAXNAME);
699e4e21ee1SDavid van Moolenbroek assert(id >= 0);
700e4e21ee1SDavid van Moolenbroek
701e4e21ee1SDavid van Moolenbroek /* Query the parent, first using our static buffer for the results. */
702e4e21ee1SDavid van Moolenbroek memcpy(mib, name, sizeof(mib[0]) * namelen);
703e4e21ee1SDavid van Moolenbroek mib[namelen] = CTL_QUERY;
704e4e21ee1SDavid van Moolenbroek len = sizeof(sysctlbuf);
705e4e21ee1SDavid van Moolenbroek r = sysctl(mib, namelen + 1, sysctlbuf, &len, NULL, 0);
706e4e21ee1SDavid van Moolenbroek if (r == -1 && (errno != ENOMEM || len == 0))
707e4e21ee1SDavid van Moolenbroek return FALSE;
708e4e21ee1SDavid van Moolenbroek
709e4e21ee1SDavid van Moolenbroek /* Even with partial results, check if we already found the node. */
710e4e21ee1SDavid van Moolenbroek elen = MIN(len, sizeof(sysctlbuf));
711e4e21ee1SDavid van Moolenbroek scn = (struct sysctlnode *)sysctlbuf;
712e4e21ee1SDavid van Moolenbroek escn = (struct sysctlnode *)&sysctlbuf[elen];
713e4e21ee1SDavid van Moolenbroek fscn = NULL; /* pointer to the node once found, NULL until then */
714e4e21ee1SDavid van Moolenbroek for (; scn < escn && fscn == NULL; scn++)
715e4e21ee1SDavid van Moolenbroek if (scn->sysctl_num == id)
716e4e21ee1SDavid van Moolenbroek fscn = scn;
717e4e21ee1SDavid van Moolenbroek
718e4e21ee1SDavid van Moolenbroek /* If our buffer was too small, use a temporary buffer. */
719e4e21ee1SDavid van Moolenbroek if (fscn == NULL && r == -1) {
720e4e21ee1SDavid van Moolenbroek if ((buf = malloc(len)) == NULL)
721e4e21ee1SDavid van Moolenbroek return FALSE;
722e4e21ee1SDavid van Moolenbroek if (sysctl(mib, namelen, buf, &len, NULL, 0) == 0) {
723e4e21ee1SDavid van Moolenbroek scn = (struct sysctlnode *)sysctlbuf;
724e4e21ee1SDavid van Moolenbroek escn = (struct sysctlnode *)&sysctlbuf[len];
725e4e21ee1SDavid van Moolenbroek for (; scn < escn && fscn != NULL; scn++)
726e4e21ee1SDavid van Moolenbroek if (scn->sysctl_num == id)
727e4e21ee1SDavid van Moolenbroek fscn = scn;
728e4e21ee1SDavid van Moolenbroek }
729e4e21ee1SDavid van Moolenbroek free(buf);
730e4e21ee1SDavid van Moolenbroek }
731e4e21ee1SDavid van Moolenbroek
732e4e21ee1SDavid van Moolenbroek if (fscn != NULL) {
733e4e21ee1SDavid van Moolenbroek memcpy(scnp, fscn, sizeof(*scnp));
734e4e21ee1SDavid van Moolenbroek return TRUE;
735e4e21ee1SDavid van Moolenbroek } else
736e4e21ee1SDavid van Moolenbroek return FALSE;
737e4e21ee1SDavid van Moolenbroek }
738e4e21ee1SDavid van Moolenbroek
739e4e21ee1SDavid van Moolenbroek /*
740e4e21ee1SDavid van Moolenbroek * Print the name string of one level of a sysctl(2) name, while also gathering
741e4e21ee1SDavid van Moolenbroek * information about the target node. Return 1 if name interpretation should
742e4e21ee1SDavid van Moolenbroek * continue as before, meaning this function will also be called for the next
743e4e21ee1SDavid van Moolenbroek * name component (if any). Return 0 if the rest of the name should be printed
744e4e21ee1SDavid van Moolenbroek * as numbers, without interpretation. Return -1 if printing the name is now
745e4e21ee1SDavid van Moolenbroek * complete.
746e4e21ee1SDavid van Moolenbroek */
747e4e21ee1SDavid van Moolenbroek static int
put_sysctl_namestr(struct trace_proc * proc,const int * name,unsigned int namelen,unsigned int n,int all,const struct sysctl_tab ** sctp)748e4e21ee1SDavid van Moolenbroek put_sysctl_namestr(struct trace_proc * proc, const int * name,
749e4e21ee1SDavid van Moolenbroek unsigned int namelen, unsigned int n, int all,
750e4e21ee1SDavid van Moolenbroek const struct sysctl_tab ** sctp)
751e4e21ee1SDavid van Moolenbroek {
752e4e21ee1SDavid van Moolenbroek const struct sysctl_tab *sct;
753e4e21ee1SDavid van Moolenbroek struct sysctlnode scn;
754e4e21ee1SDavid van Moolenbroek const char *namestr;
755e4e21ee1SDavid van Moolenbroek int i, r, id, is_last;
756e4e21ee1SDavid van Moolenbroek
757e4e21ee1SDavid van Moolenbroek assert(n < namelen);
758e4e21ee1SDavid van Moolenbroek
759e4e21ee1SDavid van Moolenbroek id = name[n];
760e4e21ee1SDavid van Moolenbroek is_last = (n == namelen - 1 && all);
761e4e21ee1SDavid van Moolenbroek namestr = NULL;
762e4e21ee1SDavid van Moolenbroek
763e4e21ee1SDavid van Moolenbroek /* Negative identifiers are meta-identifiers. */
764e4e21ee1SDavid van Moolenbroek if (id < 0) {
765e4e21ee1SDavid van Moolenbroek switch (id) {
766e4e21ee1SDavid van Moolenbroek case CTL_EOL: namestr = "<eol>"; break;
767e4e21ee1SDavid van Moolenbroek case CTL_QUERY: namestr = "<query>"; break;
768e4e21ee1SDavid van Moolenbroek case CTL_CREATE: namestr = "<create>"; break;
769e4e21ee1SDavid van Moolenbroek case CTL_CREATESYM: namestr = "<createsym>"; break;
770e4e21ee1SDavid van Moolenbroek case CTL_DESTROY: namestr = "<destroy>"; break;
771e4e21ee1SDavid van Moolenbroek case CTL_MMAP: namestr = "<mmap>"; break;
772e4e21ee1SDavid van Moolenbroek case CTL_DESCRIBE: namestr = "<describe>"; break;
773e4e21ee1SDavid van Moolenbroek }
774e4e21ee1SDavid van Moolenbroek
775e4e21ee1SDavid van Moolenbroek /* For some of them, we can print their parameters. */
776e4e21ee1SDavid van Moolenbroek if (is_last) {
777e4e21ee1SDavid van Moolenbroek switch (id) {
778e4e21ee1SDavid van Moolenbroek case CTL_QUERY:
779e4e21ee1SDavid van Moolenbroek proc->sctl_proc = put_sysctl_query;
780e4e21ee1SDavid van Moolenbroek break;
781e4e21ee1SDavid van Moolenbroek case CTL_CREATE:
782e4e21ee1SDavid van Moolenbroek proc->sctl_proc = put_sysctl_create;
783e4e21ee1SDavid van Moolenbroek break;
784e4e21ee1SDavid van Moolenbroek case CTL_DESTROY:
785e4e21ee1SDavid van Moolenbroek proc->sctl_proc = put_sysctl_destroy;
786e4e21ee1SDavid van Moolenbroek break;
787e4e21ee1SDavid van Moolenbroek case CTL_DESCRIBE:
788e4e21ee1SDavid van Moolenbroek proc->sctl_proc = put_sysctl_describe;
789e4e21ee1SDavid van Moolenbroek break;
790e4e21ee1SDavid van Moolenbroek }
791e4e21ee1SDavid van Moolenbroek }
792e4e21ee1SDavid van Moolenbroek
793e4e21ee1SDavid van Moolenbroek /*
794e4e21ee1SDavid van Moolenbroek * Meta-identifiers are allowed only at the very end of a name,
795e4e21ee1SDavid van Moolenbroek * so if anything follows a meta-identifier, there is no good
796e4e21ee1SDavid van Moolenbroek * way to interpret it. We just print numbers.
797e4e21ee1SDavid van Moolenbroek */
798e4e21ee1SDavid van Moolenbroek r = 0;
799e4e21ee1SDavid van Moolenbroek } else if (get_sysctl_node(name, n, id, &scn)) {
800e4e21ee1SDavid van Moolenbroek /*
801e4e21ee1SDavid van Moolenbroek * For regular identifiers, first see if we have a callback
802e4e21ee1SDavid van Moolenbroek * function that does the interpretation. The use of the
803e4e21ee1SDavid van Moolenbroek * callback function depends on whether the current node is of
804e4e21ee1SDavid van Moolenbroek * type CTLTYPE_NODE: if it is, the callback function is
805e4e21ee1SDavid van Moolenbroek * responsible for printing the rest of the name (and we return
806e4e21ee1SDavid van Moolenbroek * -1 here after we are done, #1); if it isn't, then we just
807e4e21ee1SDavid van Moolenbroek * use the callback function to interpret the node value (#2).
808e4e21ee1SDavid van Moolenbroek * If we do not have a callback function, but the current node
809e4e21ee1SDavid van Moolenbroek * is of type CTLTYPE_NODE *and* has a non-NULL callback
810e4e21ee1SDavid van Moolenbroek * function registered in the MIB service, the remote callback
811e4e21ee1SDavid van Moolenbroek * function would interpret the rest of the name, so we simply
812e4e21ee1SDavid van Moolenbroek * print the rest of the name as numbers (returning 0 once we
813e4e21ee1SDavid van Moolenbroek * are done, #3). Without a MIB-service callback function,
814e4e21ee1SDavid van Moolenbroek * such nodes are just taken as path components and thus we
815e4e21ee1SDavid van Moolenbroek * return 1 to continue resolution (#4). Finally, if we do not
816e4e21ee1SDavid van Moolenbroek * have a callback function, and the current node is a data
817e4e21ee1SDavid van Moolenbroek * node (i.e., *not* of type CTLTYPE_NODE), we try to interpret
818e4e21ee1SDavid van Moolenbroek * it generically if it is the last component (#5), or we give
819e4e21ee1SDavid van Moolenbroek * up and just print numbers otherwise (#6).
820e4e21ee1SDavid van Moolenbroek */
821e4e21ee1SDavid van Moolenbroek
822e4e21ee1SDavid van Moolenbroek /* Okay, so start by looking up the node in our own tables. */
823e4e21ee1SDavid van Moolenbroek sct = NULL;
824e4e21ee1SDavid van Moolenbroek if (n == 0) {
825e4e21ee1SDavid van Moolenbroek /* The top level is ID-indexed for performance. */
826e4e21ee1SDavid van Moolenbroek if ((unsigned int)id < __arraycount(root_tab))
827e4e21ee1SDavid van Moolenbroek *sctp = &root_tab[id];
828e4e21ee1SDavid van Moolenbroek else
829e4e21ee1SDavid van Moolenbroek *sctp = NULL;
830e4e21ee1SDavid van Moolenbroek } else if (*sctp != NULL) {
831e4e21ee1SDavid van Moolenbroek /* Other levels are searched, because of sparseness. */
832e4e21ee1SDavid van Moolenbroek sct = (*sctp)->tab; /* NULL if missing or leaf */
833e4e21ee1SDavid van Moolenbroek for (i = (int)(*sctp)->size; sct != NULL && i > 0;
834e4e21ee1SDavid van Moolenbroek i--, sct++)
835e4e21ee1SDavid van Moolenbroek if (sct->id == id)
836e4e21ee1SDavid van Moolenbroek break;
837e4e21ee1SDavid van Moolenbroek if (i == 0)
838e4e21ee1SDavid van Moolenbroek sct = NULL;
839e4e21ee1SDavid van Moolenbroek *sctp = sct;
840e4e21ee1SDavid van Moolenbroek }
841e4e21ee1SDavid van Moolenbroek
842e4e21ee1SDavid van Moolenbroek /* Now determine what to do. */
843e4e21ee1SDavid van Moolenbroek if (SYSCTL_TYPE(scn.sysctl_flags) == CTLTYPE_NODE) {
844e4e21ee1SDavid van Moolenbroek if (sct != NULL && sct->proc != NULL) {
845e4e21ee1SDavid van Moolenbroek proc->sctl_size = sct->size;
846e4e21ee1SDavid van Moolenbroek proc->sctl_proc = sct->proc;
847e4e21ee1SDavid van Moolenbroek r = -1; /* #1 */
848e4e21ee1SDavid van Moolenbroek } else if (scn.sysctl_func != NULL)
849e4e21ee1SDavid van Moolenbroek r = 0; /* #3 */
850e4e21ee1SDavid van Moolenbroek else
851e4e21ee1SDavid van Moolenbroek r = 1; /* #4 */
852e4e21ee1SDavid van Moolenbroek } else {
853e4e21ee1SDavid van Moolenbroek if (!is_last)
854e4e21ee1SDavid van Moolenbroek r = 0; /* #6 */
855e4e21ee1SDavid van Moolenbroek else if (sct != NULL && sct->proc != NULL) {
856e4e21ee1SDavid van Moolenbroek /* A nonzero size must match the node size. */
857e4e21ee1SDavid van Moolenbroek if (sct->size == 0 ||
858e4e21ee1SDavid van Moolenbroek sct->size == scn.sysctl_size) {
859e4e21ee1SDavid van Moolenbroek proc->sctl_size = sct->size;
860e4e21ee1SDavid van Moolenbroek proc->sctl_proc = sct->proc;
861e4e21ee1SDavid van Moolenbroek }
862e4e21ee1SDavid van Moolenbroek r = 0; /* #2 */
863e4e21ee1SDavid van Moolenbroek } else {
864e4e21ee1SDavid van Moolenbroek proc->sctl_flags = scn.sysctl_flags;
865e4e21ee1SDavid van Moolenbroek proc->sctl_proc = put_sysctl_generic;
866e4e21ee1SDavid van Moolenbroek r = 0; /* #5 */
867e4e21ee1SDavid van Moolenbroek }
868e4e21ee1SDavid van Moolenbroek }
869e4e21ee1SDavid van Moolenbroek
870e4e21ee1SDavid van Moolenbroek namestr = scn.sysctl_name;
871e4e21ee1SDavid van Moolenbroek } else {
872e4e21ee1SDavid van Moolenbroek /*
873e4e21ee1SDavid van Moolenbroek * The node was not found. This basically means that we will
874e4e21ee1SDavid van Moolenbroek * not be able to get any information about deeper nodes
875e4e21ee1SDavid van Moolenbroek * either. We do not even try: just print numbers.
876e4e21ee1SDavid van Moolenbroek */
877e4e21ee1SDavid van Moolenbroek r = 0;
878e4e21ee1SDavid van Moolenbroek }
879e4e21ee1SDavid van Moolenbroek
880e4e21ee1SDavid van Moolenbroek if (!valuesonly && namestr != NULL)
881e4e21ee1SDavid van Moolenbroek put_field(proc, NULL, namestr);
882e4e21ee1SDavid van Moolenbroek else
883e4e21ee1SDavid van Moolenbroek put_value(proc, NULL, "%d", id);
884e4e21ee1SDavid van Moolenbroek
885e4e21ee1SDavid van Moolenbroek /*
886e4e21ee1SDavid van Moolenbroek * Did we determine that the rest of the name should be printed by the
887e4e21ee1SDavid van Moolenbroek * callback function? Then we might as well make that happen. The
888e4e21ee1SDavid van Moolenbroek * abuse of the parameter types is not great, oh well.
889e4e21ee1SDavid van Moolenbroek */
890e4e21ee1SDavid van Moolenbroek if (r == -1)
891e4e21ee1SDavid van Moolenbroek (void)proc->sctl_proc(proc, NULL, ST_NAME, &name[n + 1], 0,
892e4e21ee1SDavid van Moolenbroek namelen - n - 1);
893e4e21ee1SDavid van Moolenbroek
894e4e21ee1SDavid van Moolenbroek return r;
895e4e21ee1SDavid van Moolenbroek }
896e4e21ee1SDavid van Moolenbroek
897e4e21ee1SDavid van Moolenbroek /*
898e4e21ee1SDavid van Moolenbroek * Print the sysctl(2) name parameter, and gather information needed to print
899e4e21ee1SDavid van Moolenbroek * the oldp and newp parameters later.
900e4e21ee1SDavid van Moolenbroek */
901e4e21ee1SDavid van Moolenbroek static void
put_sysctl_name(struct trace_proc * proc,const char * name,int flags,vir_bytes addr,unsigned int namelen)902e4e21ee1SDavid van Moolenbroek put_sysctl_name(struct trace_proc * proc, const char * name, int flags,
903e4e21ee1SDavid van Moolenbroek vir_bytes addr, unsigned int namelen)
904e4e21ee1SDavid van Moolenbroek {
905e4e21ee1SDavid van Moolenbroek const struct sysctl_tab *sct = NULL;
906e4e21ee1SDavid van Moolenbroek int r, all, namebuf[CTL_MAXNAME];
907e4e21ee1SDavid van Moolenbroek unsigned int n;
908e4e21ee1SDavid van Moolenbroek
909e4e21ee1SDavid van Moolenbroek if (namelen > CTL_MAXNAME) {
910e4e21ee1SDavid van Moolenbroek namelen = CTL_MAXNAME;
911e4e21ee1SDavid van Moolenbroek all = 0;
912e4e21ee1SDavid van Moolenbroek } else
913e4e21ee1SDavid van Moolenbroek all = 1;
914e4e21ee1SDavid van Moolenbroek
915e4e21ee1SDavid van Moolenbroek if ((flags & PF_FAILED) || valuesonly > 1 || namelen > CTL_MAXNAME ||
916e4e21ee1SDavid van Moolenbroek (namelen > 0 && !(flags & PF_LOCADDR) &&
917e4e21ee1SDavid van Moolenbroek mem_get_data(proc->pid, addr, namebuf,
918e4e21ee1SDavid van Moolenbroek namelen * sizeof(namebuf[0])) < 0)) {
919e4e21ee1SDavid van Moolenbroek if (flags & PF_LOCADDR)
920e4e21ee1SDavid van Moolenbroek put_field(proc, name, "&..");
921e4e21ee1SDavid van Moolenbroek else
922e4e21ee1SDavid van Moolenbroek put_ptr(proc, name, addr);
923e4e21ee1SDavid van Moolenbroek return;
924e4e21ee1SDavid van Moolenbroek } else if (namelen > 0 && (flags & PF_LOCADDR))
925e4e21ee1SDavid van Moolenbroek memcpy(namebuf, (void *)addr, sizeof(namebuf[0]) * namelen);
926e4e21ee1SDavid van Moolenbroek
927e4e21ee1SDavid van Moolenbroek /*
928e4e21ee1SDavid van Moolenbroek * Print the path name of the node as possible, and find information
929e4e21ee1SDavid van Moolenbroek * about the target node as we go along. See put_sysctl_namestr() for
930e4e21ee1SDavid van Moolenbroek * the meaning of 'r'.
931e4e21ee1SDavid van Moolenbroek */
932e4e21ee1SDavid van Moolenbroek put_open(proc, name, PF_NONAME, "[", ".");
933e4e21ee1SDavid van Moolenbroek for (n = 0, r = 1; n < namelen; n++) {
934e4e21ee1SDavid van Moolenbroek if (r == 1) {
935e4e21ee1SDavid van Moolenbroek if ((r = put_sysctl_namestr(proc, namebuf, namelen, n,
936e4e21ee1SDavid van Moolenbroek all, &sct)) < 0)
937e4e21ee1SDavid van Moolenbroek break;
938e4e21ee1SDavid van Moolenbroek } else
939e4e21ee1SDavid van Moolenbroek put_value(proc, NULL, "%d", namebuf[n]);
940e4e21ee1SDavid van Moolenbroek }
941e4e21ee1SDavid van Moolenbroek if (!all)
942e4e21ee1SDavid van Moolenbroek put_field(proc, NULL, "..");
943e4e21ee1SDavid van Moolenbroek put_close(proc, "]");
944e4e21ee1SDavid van Moolenbroek }
945e4e21ee1SDavid van Moolenbroek
946e4e21ee1SDavid van Moolenbroek /*
947e4e21ee1SDavid van Moolenbroek * Print the sysctl(2) oldp or newp parameter. PF_ALT means that the given
948e4e21ee1SDavid van Moolenbroek * parameter is newp rather than oldp, in which case PF_FAILED will not be set.
949e4e21ee1SDavid van Moolenbroek */
950e4e21ee1SDavid van Moolenbroek static void
put_sysctl_data(struct trace_proc * proc,const char * name,int flags,vir_bytes addr,size_t len)951e4e21ee1SDavid van Moolenbroek put_sysctl_data(struct trace_proc * proc, const char * name, int flags,
952e4e21ee1SDavid van Moolenbroek vir_bytes addr, size_t len)
953e4e21ee1SDavid van Moolenbroek {
954e4e21ee1SDavid van Moolenbroek char *ptr;
955e4e21ee1SDavid van Moolenbroek int type, all;
956e4e21ee1SDavid van Moolenbroek
957e4e21ee1SDavid van Moolenbroek if ((flags & PF_FAILED) || addr == 0 || valuesonly > 1 ||
958e4e21ee1SDavid van Moolenbroek proc->sctl_proc == NULL || proc->sctl_size > sizeof(sysctlbuf) ||
959e4e21ee1SDavid van Moolenbroek (proc->sctl_size > 0 && (proc->sctl_size != len ||
960e4e21ee1SDavid van Moolenbroek mem_get_data(proc->pid, addr, sysctlbuf, proc->sctl_size) < 0))) {
961e4e21ee1SDavid van Moolenbroek put_ptr(proc, name, addr);
962e4e21ee1SDavid van Moolenbroek return;
963e4e21ee1SDavid van Moolenbroek }
964e4e21ee1SDavid van Moolenbroek
965e4e21ee1SDavid van Moolenbroek type = (flags & PF_ALT) ? ST_NEWP : ST_OLDP;
966e4e21ee1SDavid van Moolenbroek ptr = (proc->sctl_size > 0) ? sysctlbuf : NULL;
967e4e21ee1SDavid van Moolenbroek
968e4e21ee1SDavid van Moolenbroek /*
969e4e21ee1SDavid van Moolenbroek * The rough idea here: we have a "simple" mode and a "flexible" mode,
970e4e21ee1SDavid van Moolenbroek * depending on whether a size was specified in our table. For the
971e4e21ee1SDavid van Moolenbroek * simple mode, we only call the callback function when we have been
972e4e21ee1SDavid van Moolenbroek * able to copy in the data. A surrounding {} block will be printed
973e4e21ee1SDavid van Moolenbroek * automatically, the callback function only has to print the data
974e4e21ee1SDavid van Moolenbroek * fields. The simple mode is basically for structures. In contrast,
975e4e21ee1SDavid van Moolenbroek * the flexible mode leaves both the copying and the printing entirely
976e4e21ee1SDavid van Moolenbroek * to the callback function, which thus may print the pointer on copy
977e4e21ee1SDavid van Moolenbroek * failure (in which case the surrounding {}s would get in the way).
978e4e21ee1SDavid van Moolenbroek */
979e4e21ee1SDavid van Moolenbroek if (ptr != NULL)
980e4e21ee1SDavid van Moolenbroek put_open(proc, name, 0, "{", ", ");
981e4e21ee1SDavid van Moolenbroek
982e4e21ee1SDavid van Moolenbroek all = proc->sctl_proc(proc, name, type, ptr, addr, len);
983e4e21ee1SDavid van Moolenbroek
984e4e21ee1SDavid van Moolenbroek if (ptr != NULL) {
985e4e21ee1SDavid van Moolenbroek if (all == FALSE)
986e4e21ee1SDavid van Moolenbroek put_field(proc, NULL, "..");
987e4e21ee1SDavid van Moolenbroek put_close(proc, "}");
988e4e21ee1SDavid van Moolenbroek }
989e4e21ee1SDavid van Moolenbroek }
990e4e21ee1SDavid van Moolenbroek
991e4e21ee1SDavid van Moolenbroek static int
mib_sysctl_out(struct trace_proc * proc,const message * m_out)992e4e21ee1SDavid van Moolenbroek mib_sysctl_out(struct trace_proc * proc, const message * m_out)
993e4e21ee1SDavid van Moolenbroek {
994e4e21ee1SDavid van Moolenbroek unsigned int namelen;
995e4e21ee1SDavid van Moolenbroek
996e4e21ee1SDavid van Moolenbroek /* Reset the sysctl-related state. */
997e4e21ee1SDavid van Moolenbroek proc->sctl_flags = 0;
998e4e21ee1SDavid van Moolenbroek proc->sctl_size = 0;
999e4e21ee1SDavid van Moolenbroek proc->sctl_proc = NULL;
1000e4e21ee1SDavid van Moolenbroek proc->sctl_arg = 0;
1001e4e21ee1SDavid van Moolenbroek
1002e4e21ee1SDavid van Moolenbroek namelen = m_out->m_lc_mib_sysctl.namelen;
1003e4e21ee1SDavid van Moolenbroek
1004e4e21ee1SDavid van Moolenbroek /* As part of processing the name, we initialize the state. */
1005e4e21ee1SDavid van Moolenbroek if (namelen <= CTL_SHORTNAME)
1006e4e21ee1SDavid van Moolenbroek put_sysctl_name(proc, "name", PF_LOCADDR,
1007e4e21ee1SDavid van Moolenbroek (vir_bytes)&m_out->m_lc_mib_sysctl.name, namelen);
1008e4e21ee1SDavid van Moolenbroek else
1009e4e21ee1SDavid van Moolenbroek put_sysctl_name(proc, "name", 0, m_out->m_lc_mib_sysctl.namep,
1010e4e21ee1SDavid van Moolenbroek namelen);
1011e4e21ee1SDavid van Moolenbroek
1012e4e21ee1SDavid van Moolenbroek put_value(proc, "namelen", "%u", namelen);
1013e4e21ee1SDavid van Moolenbroek
1014e4e21ee1SDavid van Moolenbroek if (m_out->m_lc_mib_sysctl.oldp == 0 || valuesonly > 1) {
1015e4e21ee1SDavid van Moolenbroek put_sysctl_data(proc, "oldp", 0,
1016e4e21ee1SDavid van Moolenbroek m_out->m_lc_mib_sysctl.oldp,
1017e4e21ee1SDavid van Moolenbroek m_out->m_lc_mib_sysctl.oldlen);
1018e4e21ee1SDavid van Moolenbroek /* If oldp is NULL, oldlen may contain garbage; don't print. */
1019e4e21ee1SDavid van Moolenbroek if (m_out->m_lc_mib_sysctl.oldp != 0)
1020e4e21ee1SDavid van Moolenbroek put_value(proc, "oldlen", "%zu", /* {%zu} is more */
1021e4e21ee1SDavid van Moolenbroek m_out->m_lc_mib_sysctl.oldlen); /* correct.. */
1022e4e21ee1SDavid van Moolenbroek else
1023e4e21ee1SDavid van Moolenbroek put_value(proc, "oldlen", "%d", 0);
1024e4e21ee1SDavid van Moolenbroek put_sysctl_data(proc, "newp", PF_ALT,
1025e4e21ee1SDavid van Moolenbroek m_out->m_lc_mib_sysctl.newp,
1026e4e21ee1SDavid van Moolenbroek m_out->m_lc_mib_sysctl.newlen);
1027e4e21ee1SDavid van Moolenbroek put_value(proc, "newlen", "%zu",
1028e4e21ee1SDavid van Moolenbroek m_out->m_lc_mib_sysctl.newlen);
1029e4e21ee1SDavid van Moolenbroek return CT_DONE;
1030e4e21ee1SDavid van Moolenbroek } else
1031e4e21ee1SDavid van Moolenbroek return CT_NOTDONE;
1032e4e21ee1SDavid van Moolenbroek }
1033e4e21ee1SDavid van Moolenbroek
1034e4e21ee1SDavid van Moolenbroek static void
mib_sysctl_in(struct trace_proc * proc,const message * m_out,const message * m_in,int failed)1035e4e21ee1SDavid van Moolenbroek mib_sysctl_in(struct trace_proc * proc, const message * m_out,
1036e4e21ee1SDavid van Moolenbroek const message * m_in, int failed)
1037e4e21ee1SDavid van Moolenbroek {
1038e4e21ee1SDavid van Moolenbroek int err;
1039e4e21ee1SDavid van Moolenbroek
1040e4e21ee1SDavid van Moolenbroek if (m_out->m_lc_mib_sysctl.oldp != 0 && valuesonly <= 1) {
1041e4e21ee1SDavid van Moolenbroek put_sysctl_data(proc, "oldp", failed,
1042e4e21ee1SDavid van Moolenbroek m_out->m_lc_mib_sysctl.oldp,
1043e4e21ee1SDavid van Moolenbroek m_in->m_mib_lc_sysctl.oldlen /* the returned length */);
1044e4e21ee1SDavid van Moolenbroek put_value(proc, "oldlen", "%zu", /* {%zu} is more correct.. */
1045e4e21ee1SDavid van Moolenbroek m_out->m_lc_mib_sysctl.oldlen);
1046e4e21ee1SDavid van Moolenbroek put_sysctl_data(proc, "newp", PF_ALT,
1047e4e21ee1SDavid van Moolenbroek m_out->m_lc_mib_sysctl.newp,
1048e4e21ee1SDavid van Moolenbroek m_out->m_lc_mib_sysctl.newlen);
1049e4e21ee1SDavid van Moolenbroek put_value(proc, "newlen", "%zu",
1050e4e21ee1SDavid van Moolenbroek m_out->m_lc_mib_sysctl.newlen);
1051e4e21ee1SDavid van Moolenbroek put_equals(proc);
1052e4e21ee1SDavid van Moolenbroek }
1053e4e21ee1SDavid van Moolenbroek
1054e4e21ee1SDavid van Moolenbroek put_result(proc);
1055e4e21ee1SDavid van Moolenbroek
1056e4e21ee1SDavid van Moolenbroek /*
1057e4e21ee1SDavid van Moolenbroek * We want to print the returned old length in the following cases:
1058e4e21ee1SDavid van Moolenbroek * 1. the call succeeded, the old pointer was NULL, and no new data was
1059e4e21ee1SDavid van Moolenbroek * supplied;
1060e4e21ee1SDavid van Moolenbroek * 2. the call succeeded, the old pointer was not NULL, and the
1061e4e21ee1SDavid van Moolenbroek * returned old length is different from the supplied old length.
1062e4e21ee1SDavid van Moolenbroek * 3. the call failed with ENOMEM or EEXIST, and the old pointer was
1063e4e21ee1SDavid van Moolenbroek * not NULL (an undocumented NetBSD feature, used by sysctl(8)).
1064e4e21ee1SDavid van Moolenbroek */
1065e4e21ee1SDavid van Moolenbroek if (/*#1*/ (!failed && m_out->m_lc_mib_sysctl.oldp == 0 &&
1066e4e21ee1SDavid van Moolenbroek (m_out->m_lc_mib_sysctl.newp == 0 ||
1067e4e21ee1SDavid van Moolenbroek m_out->m_lc_mib_sysctl.newlen == 0)) ||
1068e4e21ee1SDavid van Moolenbroek /*#2*/ (!failed && m_out->m_lc_mib_sysctl.oldp != 0 &&
1069e4e21ee1SDavid van Moolenbroek m_out->m_lc_mib_sysctl.oldlen != m_in->m_mib_lc_sysctl.oldlen) ||
1070e4e21ee1SDavid van Moolenbroek /*#3*/ (failed && call_errno(proc, &err) &&
1071e4e21ee1SDavid van Moolenbroek (err == ENOMEM || err == EEXIST) &&
1072e4e21ee1SDavid van Moolenbroek m_out->m_lc_mib_sysctl.oldp != 0)) {
1073e4e21ee1SDavid van Moolenbroek put_open(proc, NULL, 0, "(", ", ");
1074e4e21ee1SDavid van Moolenbroek put_value(proc, "oldlen", "%zu", m_in->m_mib_lc_sysctl.oldlen);
1075e4e21ee1SDavid van Moolenbroek put_close(proc, ")");
1076e4e21ee1SDavid van Moolenbroek }
1077e4e21ee1SDavid van Moolenbroek }
1078e4e21ee1SDavid van Moolenbroek
1079e4e21ee1SDavid van Moolenbroek #define MIB_CALL(c) [((MIB_ ## c) - MIB_BASE)]
1080e4e21ee1SDavid van Moolenbroek
1081e4e21ee1SDavid van Moolenbroek static const struct call_handler mib_map[] = {
1082e4e21ee1SDavid van Moolenbroek MIB_CALL(SYSCTL) = HANDLER("sysctl", mib_sysctl_out, mib_sysctl_in),
1083e4e21ee1SDavid van Moolenbroek };
1084e4e21ee1SDavid van Moolenbroek
1085e4e21ee1SDavid van Moolenbroek const struct calls mib_calls = {
1086e4e21ee1SDavid van Moolenbroek .endpt = MIB_PROC_NR,
1087e4e21ee1SDavid van Moolenbroek .base = MIB_BASE,
1088e4e21ee1SDavid van Moolenbroek .map = mib_map,
1089e4e21ee1SDavid van Moolenbroek .count = COUNT(mib_map)
1090e4e21ee1SDavid van Moolenbroek };
1091