1 2 #include "inc.h" 3 4 #include <sys/time.h> 5 #include <sys/sysctl.h> 6 #include <sys/sched.h> 7 #include <sys/resource.h> 8 9 struct sysctl_tab { 10 int id; 11 size_t size; 12 const struct sysctl_tab *tab; 13 int (*proc)(struct trace_proc *, const char *, int, const void *, 14 vir_bytes, size_t); 15 }; 16 #define NODE(i,t) { .id = i, .size = __arraycount(t), .tab = t } 17 #define PROC(i,s,p) { .id = i, .size = s, .proc = p } 18 19 /* 20 * Print CTL_KERN KERN_CLOCKRATE. 21 */ 22 static int 23 put_kern_clockrate(struct trace_proc * proc, const char * name, 24 int type __unused, const void * ptr, vir_bytes addr __unused, 25 size_t size __unused) 26 { 27 const struct clockinfo *ci; 28 29 ci = (const struct clockinfo *)ptr; 30 31 put_value(proc, "hz", "%d", ci->hz); 32 put_value(proc, "tick", "%d", ci->tick); 33 if (verbose > 0) { 34 put_value(proc, "tickadj", "%d", ci->tickadj); 35 put_value(proc, "stathz", "%d", ci->stathz); 36 put_value(proc, "profhz", "%d", ci->profhz); 37 return TRUE; 38 } else 39 return FALSE; 40 } 41 42 /* 43 * Print CTL_KERN KERN_PROC2. 44 */ 45 static int 46 put_kern_proc2(struct trace_proc * proc, const char * name, int type, 47 const void * ptr, vir_bytes addr, size_t size) 48 { 49 const int *mib; 50 const char *text; 51 unsigned int i; 52 53 if (type == ST_NAME) { 54 mib = (const int *)ptr; 55 56 for (i = 0; i < size; i++) { 57 text = NULL; 58 59 if (i == 0) { 60 switch (mib[i]) { 61 case KERN_PROC_ALL: text = "<all>"; break; 62 case KERN_PROC_PID: text = "<pid>"; break; 63 case KERN_PROC_PGRP: text = "<pgrp>"; break; 64 case KERN_PROC_SESSION: 65 text = "<session>"; break; 66 case KERN_PROC_TTY: text = "<tty>"; break; 67 case KERN_PROC_UID: text = "<uid>"; break; 68 case KERN_PROC_RUID: text = "<ruid>"; break; 69 case KERN_PROC_GID: text = "<gid>"; break; 70 case KERN_PROC_RGID: text = "<rgid>"; break; 71 } 72 } else if (i == 1 && mib[0] == KERN_PROC_TTY) { 73 switch ((dev_t)mib[i]) { 74 case KERN_PROC_TTY_NODEV: 75 text = "<nodev>"; break; 76 case KERN_PROC_TTY_REVOKE: 77 text = "<revoke>"; break; 78 } 79 } 80 81 if (!valuesonly && text != NULL) 82 put_field(proc, NULL, text); 83 else 84 put_value(proc, NULL, "%d", mib[i]); 85 } 86 87 /* 88 * Save the requested structure length, so that we can later 89 * determine how many elements were returned (see below). 90 */ 91 proc->sctl_arg = (size == 4) ? mib[2] : 0; 92 93 return 0; 94 } 95 96 if (proc->sctl_arg > 0) { 97 /* TODO: optionally dump struct kinfo_drivers array */ 98 put_open(proc, name, 0, "[", ", "); 99 if (size > 0) 100 put_tail(proc, size / proc->sctl_arg, 0); 101 put_close(proc, "]"); 102 } else 103 put_ptr(proc, name, addr); 104 105 return TRUE; 106 } 107 108 /* 109 * Print CTL_KERN KERN_PROC_ARGS. 110 */ 111 static int 112 put_kern_proc_args(struct trace_proc * proc, const char * name, int type, 113 const void * ptr, vir_bytes addr, size_t size) 114 { 115 const int *mib; 116 const char *text; 117 unsigned int i; 118 int v; 119 120 if (type == ST_NAME) { 121 mib = (const int *)ptr; 122 123 for (i = 0; i < size; i++) { 124 text = NULL; 125 126 if (i == 1) { 127 switch (mib[i]) { 128 case KERN_PROC_ARGV: text = "<argv>"; break; 129 case KERN_PROC_ENV: text = "<env>"; break; 130 case KERN_PROC_NARGV: text = "<nargv>"; break; 131 case KERN_PROC_NENV: text = "<nenv>"; break; 132 } 133 } 134 135 if (!valuesonly && text != NULL) 136 put_field(proc, NULL, text); 137 else 138 put_value(proc, NULL, "%d", mib[i]); 139 } 140 141 /* Save the subrequest, so that we can later print data. */ 142 proc->sctl_arg = (size == 2) ? mib[1] : -999; 143 144 return 0; 145 } 146 147 if ((proc->sctl_arg == KERN_PROC_NARGV || 148 proc->sctl_arg == KERN_PROC_NENV) && size == sizeof(v) && 149 mem_get_data(proc->pid, addr, &v, sizeof(v)) >= 0) { 150 put_open(proc, name, PF_NONAME, "{", ", "); 151 152 put_value(proc, NULL, "%d", v); 153 154 put_close(proc, "}"); 155 } else 156 put_ptr(proc, name, addr); 157 158 return TRUE; 159 } 160 161 /* 162 * Print CTL_KERN KERN_CP_TIME. 163 */ 164 static int 165 put_kern_cp_time(struct trace_proc * proc, const char * name __unused, 166 int type, const void * ptr, vir_bytes addr __unused, size_t size) 167 { 168 const uint64_t *p; 169 unsigned int i; 170 const int *mib; 171 172 if (type == ST_NAME) { 173 mib = (const int *)ptr; 174 for (i = 0; i < size; i++) 175 put_value(proc, NULL, "%d", mib[i]); 176 177 return 0; 178 } 179 180 p = (const uint64_t *)ptr; 181 182 /* TODO: support for multi-CPU results */ 183 for (i = 0; i < CPUSTATES; i++) 184 put_value(proc, NULL, "%"PRIu64, p[i]); 185 186 return TRUE; 187 } 188 189 /* 190 * Print CTL_KERN KERN_CONSDEV. 191 */ 192 static int 193 put_kern_consdev(struct trace_proc * proc, const char * name, 194 int type __unused, const void * ptr, vir_bytes addr __unused, 195 size_t size __unused) 196 { 197 198 put_dev(proc, NULL, *(const dev_t *)ptr); 199 200 return TRUE; 201 } 202 203 /* 204 * Print CTL_KERN KERN_DRIVERS. 205 */ 206 static int 207 put_kern_drivers(struct trace_proc * proc, const char * name, 208 int type __unused, const void * ptr __unused, vir_bytes addr __unused, 209 size_t size) 210 { 211 212 /* TODO: optionally dump struct kinfo_drivers array */ 213 put_open(proc, name, 0, "[", ", "); 214 if (size > 0) 215 put_tail(proc, size / sizeof(struct kinfo_drivers), 0); 216 put_close(proc, "]"); 217 218 return TRUE; 219 } 220 221 /* 222 * Print CTL_KERN KERN_BOOTTIME. 223 */ 224 static int 225 put_kern_boottime(struct trace_proc * proc, const char * name, 226 int type __unused, const void * ptr __unused, vir_bytes addr, 227 size_t size) 228 { 229 230 if (size == sizeof(struct timeval)) 231 put_struct_timeval(proc, name, 0, addr); 232 else 233 put_ptr(proc, name, addr); 234 235 return TRUE; 236 } 237 238 /* 239 * Print CTL_KERN KERN_SYSVIPC KERN_SYSVIPC_INFO. 240 */ 241 static int 242 put_kern_sysvipc_info(struct trace_proc * proc, const char * name, 243 int type, const void * ptr __unused, vir_bytes addr, size_t size) 244 { 245 const int *mib; 246 const char *text; 247 unsigned int i; 248 249 /* 250 * TODO: print the obtained structure(s). For now we are just 251 * concerned with the name components. 252 */ 253 if (type != ST_NAME) { 254 put_ptr(proc, name, addr); 255 256 return TRUE; 257 } 258 259 mib = (const int *)ptr; 260 261 for (i = 0; i < size; i++) { 262 text = NULL; 263 264 if (i == 0) { 265 switch (mib[i]) { 266 case KERN_SYSVIPC_SEM_INFO: text = "<sem>"; break; 267 case KERN_SYSVIPC_SHM_INFO: text = "<shm>"; break; 268 case KERN_SYSVIPC_MSG_INFO: text = "<msg>"; break; 269 } 270 } 271 272 if (!valuesonly && text != NULL) 273 put_field(proc, NULL, text); 274 else 275 put_value(proc, NULL, "%d", mib[i]); 276 } 277 278 return 0; 279 } 280 281 /* The CTL_KERN KERN_SYSVIPC table. */ 282 static const struct sysctl_tab kern_sysvipc_tab[] = { 283 PROC(KERN_SYSVIPC_INFO, 0, put_kern_sysvipc_info), 284 }; 285 286 /* The CTL_KERN table. */ 287 static const struct sysctl_tab kern_tab[] = { 288 PROC(KERN_CLOCKRATE, sizeof(struct clockinfo), put_kern_clockrate), 289 PROC(KERN_PROC2, 0, put_kern_proc2), 290 PROC(KERN_PROC_ARGS, 0, put_kern_proc_args), 291 PROC(KERN_CP_TIME, sizeof(uint64_t) * CPUSTATES, put_kern_cp_time), 292 PROC(KERN_CONSDEV, sizeof(dev_t), put_kern_consdev), 293 PROC(KERN_DRIVERS, 0, put_kern_drivers), 294 NODE(KERN_SYSVIPC, kern_sysvipc_tab), 295 PROC(KERN_BOOTTIME, 0, put_kern_boottime), 296 }; 297 298 /* 299 * Print CTL_VM VM_LOADAVG. 300 */ 301 static int 302 put_vm_loadavg(struct trace_proc * proc, const char * name __unused, 303 int type __unused, const void * ptr, vir_bytes addr __unused, 304 size_t size __unused) 305 { 306 const struct loadavg *loadavg; 307 unsigned int i; 308 309 loadavg = (const struct loadavg *)ptr; 310 311 put_open(proc, "ldavg", 0, "{", ", "); 312 313 for (i = 0; i < __arraycount(loadavg->ldavg); i++) 314 put_value(proc, NULL, "%"PRIu32, loadavg->ldavg[i]); 315 316 put_close(proc, "}"); 317 318 if (verbose > 0) { 319 put_value(proc, "fscale", "%ld", loadavg->fscale); 320 321 return TRUE; 322 } else 323 return FALSE; 324 } 325 326 /* The CTL_VM table. */ 327 static const struct sysctl_tab vm_tab[] = { 328 PROC(VM_LOADAVG, sizeof(struct loadavg), put_vm_loadavg), 329 }; 330 331 /* The top-level table, which is indexed by identifier. */ 332 static const struct sysctl_tab root_tab[] = { 333 [CTL_KERN] = NODE(0, kern_tab), 334 [CTL_VM] = NODE(0, vm_tab), 335 }; 336 337 /* 338 * This buffer should be large enough to avoid having to perform dynamic 339 * allocation in all but highly exceptional cases. The CTL_KERN subtree is 340 * currently the largest, so we base the buffer size on its length. 341 * TODO: merge this buffer with ioctlbuf. 342 */ 343 static char sysctlbuf[sizeof(struct sysctlnode) * KERN_MAXID]; 344 345 static const struct flags sysctl_flags[] = { 346 FLAG_MASK(SYSCTL_VERS_MASK, SYSCTL_VERS_0), 347 FLAG_MASK(SYSCTL_VERS_MASK, SYSCTL_VERSION), 348 #define SYSCTL_VER_ENTRIES 2 /* the first N entries are for SYSCTL_VERS_MASK */ 349 FLAG(CTLFLAG_UNSIGNED), 350 FLAG(CTLFLAG_OWNDESC), 351 FLAG(CTLFLAG_MMAP), 352 FLAG(CTLFLAG_ALIAS), 353 FLAG(CTLFLAG_ANYNUMBER), 354 FLAG(CTLFLAG_ROOT), 355 FLAG(CTLFLAG_HEX), 356 FLAG(CTLFLAG_IMMEDIATE), 357 FLAG(CTLFLAG_OWNDATA), 358 FLAG(CTLFLAG_HIDDEN), 359 FLAG(CTLFLAG_PERMANENT), 360 FLAG(CTLFLAG_PRIVATE), 361 FLAG(CTLFLAG_ANYWRITE), 362 FLAG_MASK(CTLFLAG_READWRITE, CTLFLAG_READONLY), 363 FLAG_MASK(CTLFLAG_READWRITE, CTLFLAG_READWRITE), 364 FLAG_MASK(SYSCTL_TYPEMASK, CTLTYPE_NODE), 365 FLAG_MASK(SYSCTL_TYPEMASK, CTLTYPE_INT), 366 FLAG_MASK(SYSCTL_TYPEMASK, CTLTYPE_STRING), 367 FLAG_MASK(SYSCTL_TYPEMASK, CTLTYPE_QUAD), 368 FLAG_MASK(SYSCTL_TYPEMASK, CTLTYPE_STRUCT), 369 FLAG_MASK(SYSCTL_TYPEMASK, CTLTYPE_BOOL), 370 }; 371 372 /* 373 * Print the immediate value of a sysctl node. 374 */ 375 static void 376 put_sysctl_imm(struct trace_proc * proc, struct sysctlnode * scn, int use_name) 377 { 378 const char *name; 379 380 name = NULL; 381 382 switch (SYSCTL_TYPE(scn->sysctl_flags)) { 383 case CTLTYPE_INT: 384 if (use_name) 385 name = "sysctl_idata"; 386 if (scn->sysctl_flags & CTLFLAG_HEX) 387 put_value(proc, name, "0x%x", scn->sysctl_idata); 388 else if (scn->sysctl_flags & CTLFLAG_UNSIGNED) 389 put_value(proc, name, "%u", scn->sysctl_idata); 390 else 391 put_value(proc, name, "%d", scn->sysctl_idata); 392 break; 393 case CTLTYPE_BOOL: 394 if (use_name) 395 name = "sysctl_bdata"; 396 put_field(proc, name, (scn->sysctl_bdata) ? "true" : "false"); 397 break; 398 case CTLTYPE_QUAD: 399 if (use_name) 400 name = "sysctl_qdata"; 401 if (scn->sysctl_flags & CTLFLAG_HEX) 402 put_value(proc, name, "0x%"PRIx64, scn->sysctl_qdata); 403 else 404 put_value(proc, name, "%"PRIu64, scn->sysctl_qdata); 405 break; 406 } 407 } 408 409 /* 410 * Printer for CTL_QUERY data. 411 */ 412 static int 413 put_sysctl_query(struct trace_proc * proc, const char * name, int type, 414 const void * data __unused, vir_bytes addr, size_t size) 415 { 416 struct sysctlnode scn; 417 418 if (type == ST_NEWP) { 419 if (!put_open_struct(proc, name, 0, addr, &scn, sizeof(scn))) 420 return TRUE; 421 422 /* Print just the protocol version, that's all there is. */ 423 if (verbose > 1) 424 put_flags(proc, "sysctl_flags", sysctl_flags, 425 SYSCTL_VER_ENTRIES, "0x%x", scn.sysctl_flags); 426 427 put_close_struct(proc, FALSE /*all*/); 428 } else { 429 /* TODO: optionally dump struct sysctlnode array */ 430 put_open(proc, name, 0, "[", ", "); 431 if (size > 0) 432 put_tail(proc, size / sizeof(scn), 0); 433 put_close(proc, "]"); 434 } 435 436 return TRUE; 437 } 438 439 /* 440 * Printer for CTL_CREATE data. 441 */ 442 static int 443 put_sysctl_create(struct trace_proc * proc, const char * name, int type, 444 const void * data __unused, vir_bytes addr, size_t size) 445 { 446 struct sysctlnode scn; 447 448 if (!put_open_struct(proc, name, 0, addr, &scn, sizeof(scn))) 449 return TRUE; 450 451 if (type == ST_NEWP) 452 put_flags(proc, "sysctl_flags", sysctl_flags, 453 COUNT(sysctl_flags), "0x%x", scn.sysctl_flags); 454 455 if (scn.sysctl_num == CTL_CREATE && type == ST_NEWP && !valuesonly) 456 put_field(proc, "sysctl_num", "CTL_CREATE"); 457 else 458 put_value(proc, "sysctl_num", "%d", scn.sysctl_num); 459 460 if (type == ST_NEWP) { 461 put_buf(proc, "sysctl_name", PF_LOCADDR | PF_STRING, 462 (vir_bytes)scn.sysctl_name, sizeof(scn.sysctl_name)); 463 } 464 if (scn.sysctl_ver != 0 && verbose > 0) 465 put_value(proc, "sysctl_ver", "%u", scn.sysctl_ver); 466 467 if (type == ST_NEWP) { 468 if (scn.sysctl_flags & CTLFLAG_IMMEDIATE) 469 put_sysctl_imm(proc, &scn, TRUE /*use_name*/); 470 471 switch (SYSCTL_TYPE(scn.sysctl_flags)) { 472 case CTLTYPE_NODE: 473 break; 474 case CTLTYPE_STRING: 475 if (scn.sysctl_data != NULL) 476 put_buf(proc, "sysctl_data", PF_STRING, 477 (vir_bytes)scn.sysctl_data, 478 (scn.sysctl_size > 0) ? scn.sysctl_size : 479 SSIZE_MAX /* hopefully it stops early */); 480 if (scn.sysctl_data != NULL || verbose == 0) 481 break; 482 /* FALLTHROUGH */ 483 default: 484 if (!(scn.sysctl_flags & CTLFLAG_IMMEDIATE) && 485 verbose > 0) 486 put_ptr(proc, "sysctl_data", 487 (vir_bytes)scn.sysctl_data); 488 break; 489 } 490 491 if (SYSCTL_TYPE(scn.sysctl_flags) == CTLTYPE_STRUCT || 492 verbose > 0) 493 put_value(proc, "sysctl_size", "%zu", scn.sysctl_size); 494 } 495 496 put_close_struct(proc, FALSE /*all*/); 497 498 return TRUE; 499 } 500 501 /* 502 * Printer for CTL_DESTROY data. 503 */ 504 static int 505 put_sysctl_destroy(struct trace_proc * proc, const char * name, int type, 506 const void * data __unused, vir_bytes addr, size_t size) 507 { 508 struct sysctlnode scn; 509 510 if (!put_open_struct(proc, name, 0, addr, &scn, sizeof(scn))) 511 return TRUE; 512 513 if (type == ST_NEWP) { 514 put_value(proc, "sysctl_num", "%d", scn.sysctl_num); 515 if (scn.sysctl_name[0] != '\0') 516 put_buf(proc, "sysctl_name", PF_LOCADDR | PF_STRING, 517 (vir_bytes)scn.sysctl_name, 518 sizeof(scn.sysctl_name)); 519 if (scn.sysctl_ver != 0 && verbose > 0) 520 put_value(proc, "sysctl_ver", "%u", scn.sysctl_ver); 521 } 522 523 put_close_struct(proc, FALSE /*all*/); 524 525 return TRUE; 526 } 527 528 /* 529 * Printer for CTL_CREATE data. 530 */ 531 static int 532 put_sysctl_describe(struct trace_proc * proc, const char * name, int type, 533 const void * data __unused, vir_bytes addr, size_t size) 534 { 535 struct sysctlnode scn; 536 537 if (type == ST_NEWP) { 538 if (!put_open_struct(proc, name, 0, addr, &scn, sizeof(scn))) 539 return TRUE; 540 541 /* Print just the protocol version, that's all there is. */ 542 if (verbose > 1) 543 put_flags(proc, "sysctl_flags", sysctl_flags, 544 SYSCTL_VER_ENTRIES, "0x%x", scn.sysctl_flags); 545 546 put_value(proc, "sysctl_num", "%d", scn.sysctl_num); 547 548 if (scn.sysctl_desc != NULL) 549 put_buf(proc, "sysctl_desc", PF_STRING, 550 (vir_bytes)scn.sysctl_desc, 1024 /*no constant!*/); 551 else if (verbose > 0) 552 put_ptr(proc, "sysctl_desc", 553 (vir_bytes)scn.sysctl_desc); 554 555 put_close_struct(proc, FALSE /*all*/); 556 } else { 557 /* TODO: optionally dump struct sysctldesc array */ 558 put_field(proc, name, (size == 0) ? "[]" : "[..]"); 559 } 560 561 return TRUE; 562 } 563 564 /* 565 * Printer for generic data, using the node flags stored in proc->sysctl_flags. 566 */ 567 static int 568 put_sysctl_generic(struct trace_proc * proc, const char * name, int type, 569 const void * data __unused, vir_bytes addr, size_t size) 570 { 571 struct sysctlnode scn; 572 void *ptr; 573 size_t len; 574 575 switch (SYSCTL_TYPE(proc->sctl_flags)) { 576 case CTLTYPE_STRING: 577 put_buf(proc, name, PF_STRING, addr, size); 578 return TRUE; 579 case CTLTYPE_INT: 580 ptr = &scn.sysctl_idata; 581 len = sizeof(scn.sysctl_idata); 582 break; 583 case CTLTYPE_BOOL: 584 ptr = &scn.sysctl_bdata; 585 len = sizeof(scn.sysctl_bdata); 586 break; 587 case CTLTYPE_QUAD: 588 ptr = &scn.sysctl_qdata; 589 len = sizeof(scn.sysctl_qdata); 590 break; 591 case CTLTYPE_STRUCT: 592 default: 593 ptr = NULL; 594 len = 0; 595 break; 596 } 597 598 if (ptr == NULL || len != size || 599 mem_get_data(proc->pid, addr, ptr, len) < 0) { 600 put_ptr(proc, name, addr); 601 return TRUE; 602 } 603 604 put_open(proc, name, PF_NONAME, "{", ", "); 605 606 scn.sysctl_flags = proc->sctl_flags; 607 608 put_sysctl_imm(proc, &scn, FALSE); 609 610 put_close(proc, "}"); 611 612 return TRUE; 613 } 614 615 /* 616 * Obtain information about a particular node 'id' in the node directory 617 * identified by the MIB path 'name' (length 'namelen'). Return TRUE if the 618 * node was found, in which case it is copied into 'scnp'. Return FALSE if the 619 * node was not found or another error occurred. 620 */ 621 static int 622 get_sysctl_node(const int * name, unsigned int namelen, int id, 623 struct sysctlnode * scnp) 624 { 625 struct sysctlnode *scn, *escn, *fscn; 626 char *buf; 627 size_t len, elen; 628 int r, mib[CTL_MAXNAME]; 629 630 assert(namelen < CTL_MAXNAME); 631 assert(id >= 0); 632 633 /* Query the parent, first using our static buffer for the results. */ 634 memcpy(mib, name, sizeof(mib[0]) * namelen); 635 mib[namelen] = CTL_QUERY; 636 len = sizeof(sysctlbuf); 637 r = sysctl(mib, namelen + 1, sysctlbuf, &len, NULL, 0); 638 if (r == -1 && (errno != ENOMEM || len == 0)) 639 return FALSE; 640 641 /* Even with partial results, check if we already found the node. */ 642 elen = MIN(len, sizeof(sysctlbuf)); 643 scn = (struct sysctlnode *)sysctlbuf; 644 escn = (struct sysctlnode *)&sysctlbuf[elen]; 645 fscn = NULL; /* pointer to the node once found, NULL until then */ 646 for (; scn < escn && fscn == NULL; scn++) 647 if (scn->sysctl_num == id) 648 fscn = scn; 649 650 /* If our buffer was too small, use a temporary buffer. */ 651 if (fscn == NULL && r == -1) { 652 if ((buf = malloc(len)) == NULL) 653 return FALSE; 654 if (sysctl(mib, namelen, buf, &len, NULL, 0) == 0) { 655 scn = (struct sysctlnode *)sysctlbuf; 656 escn = (struct sysctlnode *)&sysctlbuf[len]; 657 for (; scn < escn && fscn != NULL; scn++) 658 if (scn->sysctl_num == id) 659 fscn = scn; 660 } 661 free(buf); 662 } 663 664 if (fscn != NULL) { 665 memcpy(scnp, fscn, sizeof(*scnp)); 666 return TRUE; 667 } else 668 return FALSE; 669 } 670 671 /* 672 * Print the name string of one level of a sysctl(2) name, while also gathering 673 * information about the target node. Return 1 if name interpretation should 674 * continue as before, meaning this function will also be called for the next 675 * name component (if any). Return 0 if the rest of the name should be printed 676 * as numbers, without interpretation. Return -1 if printing the name is now 677 * complete. 678 */ 679 static int 680 put_sysctl_namestr(struct trace_proc * proc, const int * name, 681 unsigned int namelen, unsigned int n, int all, 682 const struct sysctl_tab ** sctp) 683 { 684 const struct sysctl_tab *sct; 685 struct sysctlnode scn; 686 const char *namestr; 687 int i, r, id, is_last; 688 689 assert(n < namelen); 690 691 id = name[n]; 692 is_last = (n == namelen - 1 && all); 693 namestr = NULL; 694 695 /* Negative identifiers are meta-identifiers. */ 696 if (id < 0) { 697 switch (id) { 698 case CTL_EOL: namestr = "<eol>"; break; 699 case CTL_QUERY: namestr = "<query>"; break; 700 case CTL_CREATE: namestr = "<create>"; break; 701 case CTL_CREATESYM: namestr = "<createsym>"; break; 702 case CTL_DESTROY: namestr = "<destroy>"; break; 703 case CTL_MMAP: namestr = "<mmap>"; break; 704 case CTL_DESCRIBE: namestr = "<describe>"; break; 705 } 706 707 /* For some of them, we can print their parameters. */ 708 if (is_last) { 709 switch (id) { 710 case CTL_QUERY: 711 proc->sctl_proc = put_sysctl_query; 712 break; 713 case CTL_CREATE: 714 proc->sctl_proc = put_sysctl_create; 715 break; 716 case CTL_DESTROY: 717 proc->sctl_proc = put_sysctl_destroy; 718 break; 719 case CTL_DESCRIBE: 720 proc->sctl_proc = put_sysctl_describe; 721 break; 722 } 723 } 724 725 /* 726 * Meta-identifiers are allowed only at the very end of a name, 727 * so if anything follows a meta-identifier, there is no good 728 * way to interpret it. We just print numbers. 729 */ 730 r = 0; 731 } else if (get_sysctl_node(name, n, id, &scn)) { 732 /* 733 * For regular identifiers, first see if we have a callback 734 * function that does the interpretation. The use of the 735 * callback function depends on whether the current node is of 736 * type CTLTYPE_NODE: if it is, the callback function is 737 * responsible for printing the rest of the name (and we return 738 * -1 here after we are done, #1); if it isn't, then we just 739 * use the callback function to interpret the node value (#2). 740 * If we do not have a callback function, but the current node 741 * is of type CTLTYPE_NODE *and* has a non-NULL callback 742 * function registered in the MIB service, the remote callback 743 * function would interpret the rest of the name, so we simply 744 * print the rest of the name as numbers (returning 0 once we 745 * are done, #3). Without a MIB-service callback function, 746 * such nodes are just taken as path components and thus we 747 * return 1 to continue resolution (#4). Finally, if we do not 748 * have a callback function, and the current node is a data 749 * node (i.e., *not* of type CTLTYPE_NODE), we try to interpret 750 * it generically if it is the last component (#5), or we give 751 * up and just print numbers otherwise (#6). 752 */ 753 754 /* Okay, so start by looking up the node in our own tables. */ 755 sct = NULL; 756 if (n == 0) { 757 /* The top level is ID-indexed for performance. */ 758 if ((unsigned int)id < __arraycount(root_tab)) 759 *sctp = &root_tab[id]; 760 else 761 *sctp = NULL; 762 } else if (*sctp != NULL) { 763 /* Other levels are searched, because of sparseness. */ 764 sct = (*sctp)->tab; /* NULL if missing or leaf */ 765 for (i = (int)(*sctp)->size; sct != NULL && i > 0; 766 i--, sct++) 767 if (sct->id == id) 768 break; 769 if (i == 0) 770 sct = NULL; 771 *sctp = sct; 772 } 773 774 /* Now determine what to do. */ 775 if (SYSCTL_TYPE(scn.sysctl_flags) == CTLTYPE_NODE) { 776 if (sct != NULL && sct->proc != NULL) { 777 proc->sctl_size = sct->size; 778 proc->sctl_proc = sct->proc; 779 r = -1; /* #1 */ 780 } else if (scn.sysctl_func != NULL) 781 r = 0; /* #3 */ 782 else 783 r = 1; /* #4 */ 784 } else { 785 if (!is_last) 786 r = 0; /* #6 */ 787 else if (sct != NULL && sct->proc != NULL) { 788 /* A nonzero size must match the node size. */ 789 if (sct->size == 0 || 790 sct->size == scn.sysctl_size) { 791 proc->sctl_size = sct->size; 792 proc->sctl_proc = sct->proc; 793 } 794 r = 0; /* #2 */ 795 } else { 796 proc->sctl_flags = scn.sysctl_flags; 797 proc->sctl_proc = put_sysctl_generic; 798 r = 0; /* #5 */ 799 } 800 } 801 802 namestr = scn.sysctl_name; 803 } else { 804 /* 805 * The node was not found. This basically means that we will 806 * not be able to get any information about deeper nodes 807 * either. We do not even try: just print numbers. 808 */ 809 r = 0; 810 } 811 812 if (!valuesonly && namestr != NULL) 813 put_field(proc, NULL, namestr); 814 else 815 put_value(proc, NULL, "%d", id); 816 817 /* 818 * Did we determine that the rest of the name should be printed by the 819 * callback function? Then we might as well make that happen. The 820 * abuse of the parameter types is not great, oh well. 821 */ 822 if (r == -1) 823 (void)proc->sctl_proc(proc, NULL, ST_NAME, &name[n + 1], 0, 824 namelen - n - 1); 825 826 return r; 827 } 828 829 /* 830 * Print the sysctl(2) name parameter, and gather information needed to print 831 * the oldp and newp parameters later. 832 */ 833 static void 834 put_sysctl_name(struct trace_proc * proc, const char * name, int flags, 835 vir_bytes addr, unsigned int namelen) 836 { 837 const struct sysctl_tab *sct = NULL; 838 int r, all, namebuf[CTL_MAXNAME]; 839 unsigned int n; 840 841 if (namelen > CTL_MAXNAME) { 842 namelen = CTL_MAXNAME; 843 all = 0; 844 } else 845 all = 1; 846 847 if ((flags & PF_FAILED) || valuesonly > 1 || namelen > CTL_MAXNAME || 848 (namelen > 0 && !(flags & PF_LOCADDR) && 849 mem_get_data(proc->pid, addr, namebuf, 850 namelen * sizeof(namebuf[0])) < 0)) { 851 if (flags & PF_LOCADDR) 852 put_field(proc, name, "&.."); 853 else 854 put_ptr(proc, name, addr); 855 return; 856 } else if (namelen > 0 && (flags & PF_LOCADDR)) 857 memcpy(namebuf, (void *)addr, sizeof(namebuf[0]) * namelen); 858 859 /* 860 * Print the path name of the node as possible, and find information 861 * about the target node as we go along. See put_sysctl_namestr() for 862 * the meaning of 'r'. 863 */ 864 put_open(proc, name, PF_NONAME, "[", "."); 865 for (n = 0, r = 1; n < namelen; n++) { 866 if (r == 1) { 867 if ((r = put_sysctl_namestr(proc, namebuf, namelen, n, 868 all, &sct)) < 0) 869 break; 870 } else 871 put_value(proc, NULL, "%d", namebuf[n]); 872 } 873 if (!all) 874 put_field(proc, NULL, ".."); 875 put_close(proc, "]"); 876 } 877 878 /* 879 * Print the sysctl(2) oldp or newp parameter. PF_ALT means that the given 880 * parameter is newp rather than oldp, in which case PF_FAILED will not be set. 881 */ 882 static void 883 put_sysctl_data(struct trace_proc * proc, const char * name, int flags, 884 vir_bytes addr, size_t len) 885 { 886 char *ptr; 887 int type, all; 888 889 if ((flags & PF_FAILED) || addr == 0 || valuesonly > 1 || 890 proc->sctl_proc == NULL || proc->sctl_size > sizeof(sysctlbuf) || 891 (proc->sctl_size > 0 && (proc->sctl_size != len || 892 mem_get_data(proc->pid, addr, sysctlbuf, proc->sctl_size) < 0))) { 893 put_ptr(proc, name, addr); 894 return; 895 } 896 897 type = (flags & PF_ALT) ? ST_NEWP : ST_OLDP; 898 ptr = (proc->sctl_size > 0) ? sysctlbuf : NULL; 899 900 /* 901 * The rough idea here: we have a "simple" mode and a "flexible" mode, 902 * depending on whether a size was specified in our table. For the 903 * simple mode, we only call the callback function when we have been 904 * able to copy in the data. A surrounding {} block will be printed 905 * automatically, the callback function only has to print the data 906 * fields. The simple mode is basically for structures. In contrast, 907 * the flexible mode leaves both the copying and the printing entirely 908 * to the callback function, which thus may print the pointer on copy 909 * failure (in which case the surrounding {}s would get in the way). 910 */ 911 if (ptr != NULL) 912 put_open(proc, name, 0, "{", ", "); 913 914 all = proc->sctl_proc(proc, name, type, ptr, addr, len); 915 916 if (ptr != NULL) { 917 if (all == FALSE) 918 put_field(proc, NULL, ".."); 919 put_close(proc, "}"); 920 } 921 } 922 923 static int 924 mib_sysctl_out(struct trace_proc * proc, const message * m_out) 925 { 926 unsigned int namelen; 927 928 /* Reset the sysctl-related state. */ 929 proc->sctl_flags = 0; 930 proc->sctl_size = 0; 931 proc->sctl_proc = NULL; 932 proc->sctl_arg = 0; 933 934 namelen = m_out->m_lc_mib_sysctl.namelen; 935 936 /* As part of processing the name, we initialize the state. */ 937 if (namelen <= CTL_SHORTNAME) 938 put_sysctl_name(proc, "name", PF_LOCADDR, 939 (vir_bytes)&m_out->m_lc_mib_sysctl.name, namelen); 940 else 941 put_sysctl_name(proc, "name", 0, m_out->m_lc_mib_sysctl.namep, 942 namelen); 943 944 put_value(proc, "namelen", "%u", namelen); 945 946 if (m_out->m_lc_mib_sysctl.oldp == 0 || valuesonly > 1) { 947 put_sysctl_data(proc, "oldp", 0, 948 m_out->m_lc_mib_sysctl.oldp, 949 m_out->m_lc_mib_sysctl.oldlen); 950 /* If oldp is NULL, oldlen may contain garbage; don't print. */ 951 if (m_out->m_lc_mib_sysctl.oldp != 0) 952 put_value(proc, "oldlen", "%zu", /* {%zu} is more */ 953 m_out->m_lc_mib_sysctl.oldlen); /* correct.. */ 954 else 955 put_value(proc, "oldlen", "%d", 0); 956 put_sysctl_data(proc, "newp", PF_ALT, 957 m_out->m_lc_mib_sysctl.newp, 958 m_out->m_lc_mib_sysctl.newlen); 959 put_value(proc, "newlen", "%zu", 960 m_out->m_lc_mib_sysctl.newlen); 961 return CT_DONE; 962 } else 963 return CT_NOTDONE; 964 } 965 966 static void 967 mib_sysctl_in(struct trace_proc * proc, const message * m_out, 968 const message * m_in, int failed) 969 { 970 int err; 971 972 if (m_out->m_lc_mib_sysctl.oldp != 0 && valuesonly <= 1) { 973 put_sysctl_data(proc, "oldp", failed, 974 m_out->m_lc_mib_sysctl.oldp, 975 m_in->m_mib_lc_sysctl.oldlen /* the returned length */); 976 put_value(proc, "oldlen", "%zu", /* {%zu} is more correct.. */ 977 m_out->m_lc_mib_sysctl.oldlen); 978 put_sysctl_data(proc, "newp", PF_ALT, 979 m_out->m_lc_mib_sysctl.newp, 980 m_out->m_lc_mib_sysctl.newlen); 981 put_value(proc, "newlen", "%zu", 982 m_out->m_lc_mib_sysctl.newlen); 983 put_equals(proc); 984 } 985 986 put_result(proc); 987 988 /* 989 * We want to print the returned old length in the following cases: 990 * 1. the call succeeded, the old pointer was NULL, and no new data was 991 * supplied; 992 * 2. the call succeeded, the old pointer was not NULL, and the 993 * returned old length is different from the supplied old length. 994 * 3. the call failed with ENOMEM or EEXIST, and the old pointer was 995 * not NULL (an undocumented NetBSD feature, used by sysctl(8)). 996 */ 997 if (/*#1*/ (!failed && m_out->m_lc_mib_sysctl.oldp == 0 && 998 (m_out->m_lc_mib_sysctl.newp == 0 || 999 m_out->m_lc_mib_sysctl.newlen == 0)) || 1000 /*#2*/ (!failed && m_out->m_lc_mib_sysctl.oldp != 0 && 1001 m_out->m_lc_mib_sysctl.oldlen != m_in->m_mib_lc_sysctl.oldlen) || 1002 /*#3*/ (failed && call_errno(proc, &err) && 1003 (err == ENOMEM || err == EEXIST) && 1004 m_out->m_lc_mib_sysctl.oldp != 0)) { 1005 put_open(proc, NULL, 0, "(", ", "); 1006 put_value(proc, "oldlen", "%zu", m_in->m_mib_lc_sysctl.oldlen); 1007 put_close(proc, ")"); 1008 } 1009 } 1010 1011 #define MIB_CALL(c) [((MIB_ ## c) - MIB_BASE)] 1012 1013 static const struct call_handler mib_map[] = { 1014 MIB_CALL(SYSCTL) = HANDLER("sysctl", mib_sysctl_out, mib_sysctl_in), 1015 }; 1016 1017 const struct calls mib_calls = { 1018 .endpt = MIB_PROC_NR, 1019 .base = MIB_BASE, 1020 .map = mib_map, 1021 .count = COUNT(mib_map) 1022 }; 1023