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, 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 /* 332 * Print CTL_NET PF_ROUTE 0. 333 */ 334 static int 335 put_net_route_rtable(struct trace_proc * proc, const char * name, 336 int type, const void * ptr, vir_bytes addr, size_t size) 337 { 338 const int *mib; 339 const char *text; 340 unsigned int i; 341 342 /* 343 * TODO: print the obtained structure(s). For now we are just 344 * concerned with the name components. 345 */ 346 if (type != ST_NAME) { 347 put_ptr(proc, name, addr); 348 349 return TRUE; 350 } 351 352 mib = (const int *)ptr; 353 354 for (i = 0; i < size; i++) { 355 text = NULL; 356 357 switch (i) { 358 case 0: 359 switch (mib[i]) { 360 case AF_UNSPEC: text = "<all>"; break; 361 case AF_LINK: text = "<link>"; break; 362 case AF_INET: text = "<inet>"; break; 363 case AF_INET6: text = "<inet6>"; break; 364 /* TODO: add more address families here */ 365 } 366 break; 367 case 1: 368 switch (mib[i]) { 369 case NET_RT_DUMP: text = "<dump>"; break; 370 case NET_RT_FLAGS: text = "<flags>"; break; 371 case NET_RT_IFLIST: text = "<iflist>"; break; 372 } 373 break; 374 case 2: 375 if (mib[1] == NET_RT_IFLIST && mib[i] == 0) 376 text = "<all>"; 377 } 378 379 if (!valuesonly && text != NULL) 380 put_field(proc, NULL, text); 381 else 382 put_value(proc, NULL, "%d", mib[i]); 383 } 384 385 return 0; 386 } 387 388 /* The CTL_NET PF_ROUTE table. */ 389 static const struct sysctl_tab net_route_tab[] = { 390 PROC(0, 0, put_net_route_rtable), 391 }; 392 393 /* The CTL_NET table. */ 394 static const struct sysctl_tab net_tab[] = { 395 NODE(PF_ROUTE, net_route_tab), 396 }; 397 398 /* The top-level table, which is indexed by identifier. */ 399 static const struct sysctl_tab root_tab[] = { 400 [CTL_KERN] = NODE(0, kern_tab), 401 [CTL_VM] = NODE(0, vm_tab), 402 [CTL_NET] = NODE(0, net_tab), 403 }; 404 405 /* 406 * This buffer should be large enough to avoid having to perform dynamic 407 * allocation in all but highly exceptional cases. The CTL_KERN subtree is 408 * currently the largest, so we base the buffer size on its length. 409 * TODO: merge this buffer with ioctlbuf. 410 */ 411 static char sysctlbuf[sizeof(struct sysctlnode) * KERN_MAXID]; 412 413 static const struct flags sysctl_flags[] = { 414 FLAG_MASK(SYSCTL_VERS_MASK, SYSCTL_VERS_0), 415 FLAG_MASK(SYSCTL_VERS_MASK, SYSCTL_VERSION), 416 #define SYSCTL_VER_ENTRIES 2 /* the first N entries are for SYSCTL_VERS_MASK */ 417 FLAG(CTLFLAG_UNSIGNED), 418 FLAG(CTLFLAG_OWNDESC), 419 FLAG(CTLFLAG_MMAP), 420 FLAG(CTLFLAG_ALIAS), 421 FLAG(CTLFLAG_ANYNUMBER), 422 FLAG(CTLFLAG_ROOT), 423 FLAG(CTLFLAG_HEX), 424 FLAG(CTLFLAG_IMMEDIATE), 425 FLAG(CTLFLAG_OWNDATA), 426 FLAG(CTLFLAG_HIDDEN), 427 FLAG(CTLFLAG_PERMANENT), 428 FLAG(CTLFLAG_PRIVATE), 429 FLAG(CTLFLAG_ANYWRITE), 430 FLAG_MASK(CTLFLAG_READWRITE, CTLFLAG_READONLY), 431 FLAG_MASK(CTLFLAG_READWRITE, CTLFLAG_READWRITE), 432 FLAG_MASK(SYSCTL_TYPEMASK, CTLTYPE_NODE), 433 FLAG_MASK(SYSCTL_TYPEMASK, CTLTYPE_INT), 434 FLAG_MASK(SYSCTL_TYPEMASK, CTLTYPE_STRING), 435 FLAG_MASK(SYSCTL_TYPEMASK, CTLTYPE_QUAD), 436 FLAG_MASK(SYSCTL_TYPEMASK, CTLTYPE_STRUCT), 437 FLAG_MASK(SYSCTL_TYPEMASK, CTLTYPE_BOOL), 438 }; 439 440 /* 441 * Print the immediate value of a sysctl node. 442 */ 443 static void 444 put_sysctl_imm(struct trace_proc * proc, struct sysctlnode * scn, int use_name) 445 { 446 const char *name; 447 448 name = NULL; 449 450 switch (SYSCTL_TYPE(scn->sysctl_flags)) { 451 case CTLTYPE_INT: 452 if (use_name) 453 name = "sysctl_idata"; 454 if (scn->sysctl_flags & CTLFLAG_HEX) 455 put_value(proc, name, "0x%x", scn->sysctl_idata); 456 else if (scn->sysctl_flags & CTLFLAG_UNSIGNED) 457 put_value(proc, name, "%u", scn->sysctl_idata); 458 else 459 put_value(proc, name, "%d", scn->sysctl_idata); 460 break; 461 case CTLTYPE_BOOL: 462 if (use_name) 463 name = "sysctl_bdata"; 464 put_field(proc, name, (scn->sysctl_bdata) ? "true" : "false"); 465 break; 466 case CTLTYPE_QUAD: 467 if (use_name) 468 name = "sysctl_qdata"; 469 if (scn->sysctl_flags & CTLFLAG_HEX) 470 put_value(proc, name, "0x%"PRIx64, scn->sysctl_qdata); 471 else 472 put_value(proc, name, "%"PRIu64, scn->sysctl_qdata); 473 break; 474 } 475 } 476 477 /* 478 * Printer for CTL_QUERY data. 479 */ 480 static int 481 put_sysctl_query(struct trace_proc * proc, const char * name, int type, 482 const void * data __unused, vir_bytes addr, size_t size) 483 { 484 struct sysctlnode scn; 485 486 if (type == ST_NEWP) { 487 if (!put_open_struct(proc, name, 0, addr, &scn, sizeof(scn))) 488 return TRUE; 489 490 /* Print just the protocol version, that's all there is. */ 491 if (verbose > 1) 492 put_flags(proc, "sysctl_flags", sysctl_flags, 493 SYSCTL_VER_ENTRIES, "0x%x", scn.sysctl_flags); 494 495 put_close_struct(proc, FALSE /*all*/); 496 } else { 497 /* TODO: optionally dump struct sysctlnode array */ 498 put_open(proc, name, 0, "[", ", "); 499 if (size > 0) 500 put_tail(proc, size / sizeof(scn), 0); 501 put_close(proc, "]"); 502 } 503 504 return TRUE; 505 } 506 507 /* 508 * Printer for CTL_CREATE data. 509 */ 510 static int 511 put_sysctl_create(struct trace_proc * proc, const char * name, int type, 512 const void * data __unused, vir_bytes addr, size_t size) 513 { 514 struct sysctlnode scn; 515 516 if (!put_open_struct(proc, name, 0, addr, &scn, sizeof(scn))) 517 return TRUE; 518 519 if (type == ST_NEWP) 520 put_flags(proc, "sysctl_flags", sysctl_flags, 521 COUNT(sysctl_flags), "0x%x", scn.sysctl_flags); 522 523 if (scn.sysctl_num == CTL_CREATE && type == ST_NEWP && !valuesonly) 524 put_field(proc, "sysctl_num", "CTL_CREATE"); 525 else 526 put_value(proc, "sysctl_num", "%d", scn.sysctl_num); 527 528 if (type == ST_NEWP) { 529 put_buf(proc, "sysctl_name", PF_LOCADDR | PF_STRING, 530 (vir_bytes)scn.sysctl_name, sizeof(scn.sysctl_name)); 531 } 532 if (scn.sysctl_ver != 0 && verbose > 0) 533 put_value(proc, "sysctl_ver", "%u", scn.sysctl_ver); 534 535 if (type == ST_NEWP) { 536 if (scn.sysctl_flags & CTLFLAG_IMMEDIATE) 537 put_sysctl_imm(proc, &scn, TRUE /*use_name*/); 538 539 switch (SYSCTL_TYPE(scn.sysctl_flags)) { 540 case CTLTYPE_NODE: 541 break; 542 case CTLTYPE_STRING: 543 if (scn.sysctl_data != NULL) 544 put_buf(proc, "sysctl_data", PF_STRING, 545 (vir_bytes)scn.sysctl_data, 546 (scn.sysctl_size > 0) ? scn.sysctl_size : 547 SSIZE_MAX /* hopefully it stops early */); 548 if (scn.sysctl_data != NULL || verbose == 0) 549 break; 550 /* FALLTHROUGH */ 551 default: 552 if (!(scn.sysctl_flags & CTLFLAG_IMMEDIATE) && 553 verbose > 0) 554 put_ptr(proc, "sysctl_data", 555 (vir_bytes)scn.sysctl_data); 556 break; 557 } 558 559 if (SYSCTL_TYPE(scn.sysctl_flags) == CTLTYPE_STRUCT || 560 verbose > 0) 561 put_value(proc, "sysctl_size", "%zu", scn.sysctl_size); 562 } 563 564 put_close_struct(proc, FALSE /*all*/); 565 566 return TRUE; 567 } 568 569 /* 570 * Printer for CTL_DESTROY data. 571 */ 572 static int 573 put_sysctl_destroy(struct trace_proc * proc, const char * name, int type, 574 const void * data __unused, vir_bytes addr, size_t size) 575 { 576 struct sysctlnode scn; 577 578 if (!put_open_struct(proc, name, 0, addr, &scn, sizeof(scn))) 579 return TRUE; 580 581 if (type == ST_NEWP) { 582 put_value(proc, "sysctl_num", "%d", scn.sysctl_num); 583 if (scn.sysctl_name[0] != '\0') 584 put_buf(proc, "sysctl_name", PF_LOCADDR | PF_STRING, 585 (vir_bytes)scn.sysctl_name, 586 sizeof(scn.sysctl_name)); 587 if (scn.sysctl_ver != 0 && verbose > 0) 588 put_value(proc, "sysctl_ver", "%u", scn.sysctl_ver); 589 } 590 591 put_close_struct(proc, FALSE /*all*/); 592 593 return TRUE; 594 } 595 596 /* 597 * Printer for CTL_CREATE data. 598 */ 599 static int 600 put_sysctl_describe(struct trace_proc * proc, const char * name, int type, 601 const void * data __unused, vir_bytes addr, size_t size) 602 { 603 struct sysctlnode scn; 604 605 if (type == ST_NEWP) { 606 if (!put_open_struct(proc, name, 0, addr, &scn, sizeof(scn))) 607 return TRUE; 608 609 /* Print just the protocol version, that's all there is. */ 610 if (verbose > 1) 611 put_flags(proc, "sysctl_flags", sysctl_flags, 612 SYSCTL_VER_ENTRIES, "0x%x", scn.sysctl_flags); 613 614 put_value(proc, "sysctl_num", "%d", scn.sysctl_num); 615 616 if (scn.sysctl_desc != NULL) 617 put_buf(proc, "sysctl_desc", PF_STRING, 618 (vir_bytes)scn.sysctl_desc, 1024 /*no constant!*/); 619 else if (verbose > 0) 620 put_ptr(proc, "sysctl_desc", 621 (vir_bytes)scn.sysctl_desc); 622 623 put_close_struct(proc, FALSE /*all*/); 624 } else { 625 /* TODO: optionally dump struct sysctldesc array */ 626 put_field(proc, name, (size == 0) ? "[]" : "[..]"); 627 } 628 629 return TRUE; 630 } 631 632 /* 633 * Printer for generic data, using the node flags stored in proc->sysctl_flags. 634 */ 635 static int 636 put_sysctl_generic(struct trace_proc * proc, const char * name, int type, 637 const void * data __unused, vir_bytes addr, size_t size) 638 { 639 struct sysctlnode scn; 640 void *ptr; 641 size_t len; 642 643 switch (SYSCTL_TYPE(proc->sctl_flags)) { 644 case CTLTYPE_STRING: 645 put_buf(proc, name, PF_STRING, addr, size); 646 return TRUE; 647 case CTLTYPE_INT: 648 ptr = &scn.sysctl_idata; 649 len = sizeof(scn.sysctl_idata); 650 break; 651 case CTLTYPE_BOOL: 652 ptr = &scn.sysctl_bdata; 653 len = sizeof(scn.sysctl_bdata); 654 break; 655 case CTLTYPE_QUAD: 656 ptr = &scn.sysctl_qdata; 657 len = sizeof(scn.sysctl_qdata); 658 break; 659 case CTLTYPE_STRUCT: 660 default: 661 ptr = NULL; 662 len = 0; 663 break; 664 } 665 666 if (ptr == NULL || len != size || 667 mem_get_data(proc->pid, addr, ptr, len) < 0) { 668 put_ptr(proc, name, addr); 669 return TRUE; 670 } 671 672 put_open(proc, name, PF_NONAME, "{", ", "); 673 674 scn.sysctl_flags = proc->sctl_flags; 675 676 put_sysctl_imm(proc, &scn, FALSE); 677 678 put_close(proc, "}"); 679 680 return TRUE; 681 } 682 683 /* 684 * Obtain information about a particular node 'id' in the node directory 685 * identified by the MIB path 'name' (length 'namelen'). Return TRUE if the 686 * node was found, in which case it is copied into 'scnp'. Return FALSE if the 687 * node was not found or another error occurred. 688 */ 689 static int 690 get_sysctl_node(const int * name, unsigned int namelen, int id, 691 struct sysctlnode * scnp) 692 { 693 struct sysctlnode *scn, *escn, *fscn; 694 char *buf; 695 size_t len, elen; 696 int r, mib[CTL_MAXNAME]; 697 698 assert(namelen < CTL_MAXNAME); 699 assert(id >= 0); 700 701 /* Query the parent, first using our static buffer for the results. */ 702 memcpy(mib, name, sizeof(mib[0]) * namelen); 703 mib[namelen] = CTL_QUERY; 704 len = sizeof(sysctlbuf); 705 r = sysctl(mib, namelen + 1, sysctlbuf, &len, NULL, 0); 706 if (r == -1 && (errno != ENOMEM || len == 0)) 707 return FALSE; 708 709 /* Even with partial results, check if we already found the node. */ 710 elen = MIN(len, sizeof(sysctlbuf)); 711 scn = (struct sysctlnode *)sysctlbuf; 712 escn = (struct sysctlnode *)&sysctlbuf[elen]; 713 fscn = NULL; /* pointer to the node once found, NULL until then */ 714 for (; scn < escn && fscn == NULL; scn++) 715 if (scn->sysctl_num == id) 716 fscn = scn; 717 718 /* If our buffer was too small, use a temporary buffer. */ 719 if (fscn == NULL && r == -1) { 720 if ((buf = malloc(len)) == NULL) 721 return FALSE; 722 if (sysctl(mib, namelen, buf, &len, NULL, 0) == 0) { 723 scn = (struct sysctlnode *)sysctlbuf; 724 escn = (struct sysctlnode *)&sysctlbuf[len]; 725 for (; scn < escn && fscn != NULL; scn++) 726 if (scn->sysctl_num == id) 727 fscn = scn; 728 } 729 free(buf); 730 } 731 732 if (fscn != NULL) { 733 memcpy(scnp, fscn, sizeof(*scnp)); 734 return TRUE; 735 } else 736 return FALSE; 737 } 738 739 /* 740 * Print the name string of one level of a sysctl(2) name, while also gathering 741 * information about the target node. Return 1 if name interpretation should 742 * continue as before, meaning this function will also be called for the next 743 * name component (if any). Return 0 if the rest of the name should be printed 744 * as numbers, without interpretation. Return -1 if printing the name is now 745 * complete. 746 */ 747 static int 748 put_sysctl_namestr(struct trace_proc * proc, const int * name, 749 unsigned int namelen, unsigned int n, int all, 750 const struct sysctl_tab ** sctp) 751 { 752 const struct sysctl_tab *sct; 753 struct sysctlnode scn; 754 const char *namestr; 755 int i, r, id, is_last; 756 757 assert(n < namelen); 758 759 id = name[n]; 760 is_last = (n == namelen - 1 && all); 761 namestr = NULL; 762 763 /* Negative identifiers are meta-identifiers. */ 764 if (id < 0) { 765 switch (id) { 766 case CTL_EOL: namestr = "<eol>"; break; 767 case CTL_QUERY: namestr = "<query>"; break; 768 case CTL_CREATE: namestr = "<create>"; break; 769 case CTL_CREATESYM: namestr = "<createsym>"; break; 770 case CTL_DESTROY: namestr = "<destroy>"; break; 771 case CTL_MMAP: namestr = "<mmap>"; break; 772 case CTL_DESCRIBE: namestr = "<describe>"; break; 773 } 774 775 /* For some of them, we can print their parameters. */ 776 if (is_last) { 777 switch (id) { 778 case CTL_QUERY: 779 proc->sctl_proc = put_sysctl_query; 780 break; 781 case CTL_CREATE: 782 proc->sctl_proc = put_sysctl_create; 783 break; 784 case CTL_DESTROY: 785 proc->sctl_proc = put_sysctl_destroy; 786 break; 787 case CTL_DESCRIBE: 788 proc->sctl_proc = put_sysctl_describe; 789 break; 790 } 791 } 792 793 /* 794 * Meta-identifiers are allowed only at the very end of a name, 795 * so if anything follows a meta-identifier, there is no good 796 * way to interpret it. We just print numbers. 797 */ 798 r = 0; 799 } else if (get_sysctl_node(name, n, id, &scn)) { 800 /* 801 * For regular identifiers, first see if we have a callback 802 * function that does the interpretation. The use of the 803 * callback function depends on whether the current node is of 804 * type CTLTYPE_NODE: if it is, the callback function is 805 * responsible for printing the rest of the name (and we return 806 * -1 here after we are done, #1); if it isn't, then we just 807 * use the callback function to interpret the node value (#2). 808 * If we do not have a callback function, but the current node 809 * is of type CTLTYPE_NODE *and* has a non-NULL callback 810 * function registered in the MIB service, the remote callback 811 * function would interpret the rest of the name, so we simply 812 * print the rest of the name as numbers (returning 0 once we 813 * are done, #3). Without a MIB-service callback function, 814 * such nodes are just taken as path components and thus we 815 * return 1 to continue resolution (#4). Finally, if we do not 816 * have a callback function, and the current node is a data 817 * node (i.e., *not* of type CTLTYPE_NODE), we try to interpret 818 * it generically if it is the last component (#5), or we give 819 * up and just print numbers otherwise (#6). 820 */ 821 822 /* Okay, so start by looking up the node in our own tables. */ 823 sct = NULL; 824 if (n == 0) { 825 /* The top level is ID-indexed for performance. */ 826 if ((unsigned int)id < __arraycount(root_tab)) 827 *sctp = &root_tab[id]; 828 else 829 *sctp = NULL; 830 } else if (*sctp != NULL) { 831 /* Other levels are searched, because of sparseness. */ 832 sct = (*sctp)->tab; /* NULL if missing or leaf */ 833 for (i = (int)(*sctp)->size; sct != NULL && i > 0; 834 i--, sct++) 835 if (sct->id == id) 836 break; 837 if (i == 0) 838 sct = NULL; 839 *sctp = sct; 840 } 841 842 /* Now determine what to do. */ 843 if (SYSCTL_TYPE(scn.sysctl_flags) == CTLTYPE_NODE) { 844 if (sct != NULL && sct->proc != NULL) { 845 proc->sctl_size = sct->size; 846 proc->sctl_proc = sct->proc; 847 r = -1; /* #1 */ 848 } else if (scn.sysctl_func != NULL) 849 r = 0; /* #3 */ 850 else 851 r = 1; /* #4 */ 852 } else { 853 if (!is_last) 854 r = 0; /* #6 */ 855 else if (sct != NULL && sct->proc != NULL) { 856 /* A nonzero size must match the node size. */ 857 if (sct->size == 0 || 858 sct->size == scn.sysctl_size) { 859 proc->sctl_size = sct->size; 860 proc->sctl_proc = sct->proc; 861 } 862 r = 0; /* #2 */ 863 } else { 864 proc->sctl_flags = scn.sysctl_flags; 865 proc->sctl_proc = put_sysctl_generic; 866 r = 0; /* #5 */ 867 } 868 } 869 870 namestr = scn.sysctl_name; 871 } else { 872 /* 873 * The node was not found. This basically means that we will 874 * not be able to get any information about deeper nodes 875 * either. We do not even try: just print numbers. 876 */ 877 r = 0; 878 } 879 880 if (!valuesonly && namestr != NULL) 881 put_field(proc, NULL, namestr); 882 else 883 put_value(proc, NULL, "%d", id); 884 885 /* 886 * Did we determine that the rest of the name should be printed by the 887 * callback function? Then we might as well make that happen. The 888 * abuse of the parameter types is not great, oh well. 889 */ 890 if (r == -1) 891 (void)proc->sctl_proc(proc, NULL, ST_NAME, &name[n + 1], 0, 892 namelen - n - 1); 893 894 return r; 895 } 896 897 /* 898 * Print the sysctl(2) name parameter, and gather information needed to print 899 * the oldp and newp parameters later. 900 */ 901 static void 902 put_sysctl_name(struct trace_proc * proc, const char * name, int flags, 903 vir_bytes addr, unsigned int namelen) 904 { 905 const struct sysctl_tab *sct = NULL; 906 int r, all, namebuf[CTL_MAXNAME]; 907 unsigned int n; 908 909 if (namelen > CTL_MAXNAME) { 910 namelen = CTL_MAXNAME; 911 all = 0; 912 } else 913 all = 1; 914 915 if ((flags & PF_FAILED) || valuesonly > 1 || namelen > CTL_MAXNAME || 916 (namelen > 0 && !(flags & PF_LOCADDR) && 917 mem_get_data(proc->pid, addr, namebuf, 918 namelen * sizeof(namebuf[0])) < 0)) { 919 if (flags & PF_LOCADDR) 920 put_field(proc, name, "&.."); 921 else 922 put_ptr(proc, name, addr); 923 return; 924 } else if (namelen > 0 && (flags & PF_LOCADDR)) 925 memcpy(namebuf, (void *)addr, sizeof(namebuf[0]) * namelen); 926 927 /* 928 * Print the path name of the node as possible, and find information 929 * about the target node as we go along. See put_sysctl_namestr() for 930 * the meaning of 'r'. 931 */ 932 put_open(proc, name, PF_NONAME, "[", "."); 933 for (n = 0, r = 1; n < namelen; n++) { 934 if (r == 1) { 935 if ((r = put_sysctl_namestr(proc, namebuf, namelen, n, 936 all, &sct)) < 0) 937 break; 938 } else 939 put_value(proc, NULL, "%d", namebuf[n]); 940 } 941 if (!all) 942 put_field(proc, NULL, ".."); 943 put_close(proc, "]"); 944 } 945 946 /* 947 * Print the sysctl(2) oldp or newp parameter. PF_ALT means that the given 948 * parameter is newp rather than oldp, in which case PF_FAILED will not be set. 949 */ 950 static void 951 put_sysctl_data(struct trace_proc * proc, const char * name, int flags, 952 vir_bytes addr, size_t len) 953 { 954 char *ptr; 955 int type, all; 956 957 if ((flags & PF_FAILED) || addr == 0 || valuesonly > 1 || 958 proc->sctl_proc == NULL || proc->sctl_size > sizeof(sysctlbuf) || 959 (proc->sctl_size > 0 && (proc->sctl_size != len || 960 mem_get_data(proc->pid, addr, sysctlbuf, proc->sctl_size) < 0))) { 961 put_ptr(proc, name, addr); 962 return; 963 } 964 965 type = (flags & PF_ALT) ? ST_NEWP : ST_OLDP; 966 ptr = (proc->sctl_size > 0) ? sysctlbuf : NULL; 967 968 /* 969 * The rough idea here: we have a "simple" mode and a "flexible" mode, 970 * depending on whether a size was specified in our table. For the 971 * simple mode, we only call the callback function when we have been 972 * able to copy in the data. A surrounding {} block will be printed 973 * automatically, the callback function only has to print the data 974 * fields. The simple mode is basically for structures. In contrast, 975 * the flexible mode leaves both the copying and the printing entirely 976 * to the callback function, which thus may print the pointer on copy 977 * failure (in which case the surrounding {}s would get in the way). 978 */ 979 if (ptr != NULL) 980 put_open(proc, name, 0, "{", ", "); 981 982 all = proc->sctl_proc(proc, name, type, ptr, addr, len); 983 984 if (ptr != NULL) { 985 if (all == FALSE) 986 put_field(proc, NULL, ".."); 987 put_close(proc, "}"); 988 } 989 } 990 991 static int 992 mib_sysctl_out(struct trace_proc * proc, const message * m_out) 993 { 994 unsigned int namelen; 995 996 /* Reset the sysctl-related state. */ 997 proc->sctl_flags = 0; 998 proc->sctl_size = 0; 999 proc->sctl_proc = NULL; 1000 proc->sctl_arg = 0; 1001 1002 namelen = m_out->m_lc_mib_sysctl.namelen; 1003 1004 /* As part of processing the name, we initialize the state. */ 1005 if (namelen <= CTL_SHORTNAME) 1006 put_sysctl_name(proc, "name", PF_LOCADDR, 1007 (vir_bytes)&m_out->m_lc_mib_sysctl.name, namelen); 1008 else 1009 put_sysctl_name(proc, "name", 0, m_out->m_lc_mib_sysctl.namep, 1010 namelen); 1011 1012 put_value(proc, "namelen", "%u", namelen); 1013 1014 if (m_out->m_lc_mib_sysctl.oldp == 0 || valuesonly > 1) { 1015 put_sysctl_data(proc, "oldp", 0, 1016 m_out->m_lc_mib_sysctl.oldp, 1017 m_out->m_lc_mib_sysctl.oldlen); 1018 /* If oldp is NULL, oldlen may contain garbage; don't print. */ 1019 if (m_out->m_lc_mib_sysctl.oldp != 0) 1020 put_value(proc, "oldlen", "%zu", /* {%zu} is more */ 1021 m_out->m_lc_mib_sysctl.oldlen); /* correct.. */ 1022 else 1023 put_value(proc, "oldlen", "%d", 0); 1024 put_sysctl_data(proc, "newp", PF_ALT, 1025 m_out->m_lc_mib_sysctl.newp, 1026 m_out->m_lc_mib_sysctl.newlen); 1027 put_value(proc, "newlen", "%zu", 1028 m_out->m_lc_mib_sysctl.newlen); 1029 return CT_DONE; 1030 } else 1031 return CT_NOTDONE; 1032 } 1033 1034 static void 1035 mib_sysctl_in(struct trace_proc * proc, const message * m_out, 1036 const message * m_in, int failed) 1037 { 1038 int err; 1039 1040 if (m_out->m_lc_mib_sysctl.oldp != 0 && valuesonly <= 1) { 1041 put_sysctl_data(proc, "oldp", failed, 1042 m_out->m_lc_mib_sysctl.oldp, 1043 m_in->m_mib_lc_sysctl.oldlen /* the returned length */); 1044 put_value(proc, "oldlen", "%zu", /* {%zu} is more correct.. */ 1045 m_out->m_lc_mib_sysctl.oldlen); 1046 put_sysctl_data(proc, "newp", PF_ALT, 1047 m_out->m_lc_mib_sysctl.newp, 1048 m_out->m_lc_mib_sysctl.newlen); 1049 put_value(proc, "newlen", "%zu", 1050 m_out->m_lc_mib_sysctl.newlen); 1051 put_equals(proc); 1052 } 1053 1054 put_result(proc); 1055 1056 /* 1057 * We want to print the returned old length in the following cases: 1058 * 1. the call succeeded, the old pointer was NULL, and no new data was 1059 * supplied; 1060 * 2. the call succeeded, the old pointer was not NULL, and the 1061 * returned old length is different from the supplied old length. 1062 * 3. the call failed with ENOMEM or EEXIST, and the old pointer was 1063 * not NULL (an undocumented NetBSD feature, used by sysctl(8)). 1064 */ 1065 if (/*#1*/ (!failed && m_out->m_lc_mib_sysctl.oldp == 0 && 1066 (m_out->m_lc_mib_sysctl.newp == 0 || 1067 m_out->m_lc_mib_sysctl.newlen == 0)) || 1068 /*#2*/ (!failed && m_out->m_lc_mib_sysctl.oldp != 0 && 1069 m_out->m_lc_mib_sysctl.oldlen != m_in->m_mib_lc_sysctl.oldlen) || 1070 /*#3*/ (failed && call_errno(proc, &err) && 1071 (err == ENOMEM || err == EEXIST) && 1072 m_out->m_lc_mib_sysctl.oldp != 0)) { 1073 put_open(proc, NULL, 0, "(", ", "); 1074 put_value(proc, "oldlen", "%zu", m_in->m_mib_lc_sysctl.oldlen); 1075 put_close(proc, ")"); 1076 } 1077 } 1078 1079 #define MIB_CALL(c) [((MIB_ ## c) - MIB_BASE)] 1080 1081 static const struct call_handler mib_map[] = { 1082 MIB_CALL(SYSCTL) = HANDLER("sysctl", mib_sysctl_out, mib_sysctl_in), 1083 }; 1084 1085 const struct calls mib_calls = { 1086 .endpt = MIB_PROC_NR, 1087 .base = MIB_BASE, 1088 .map = mib_map, 1089 .count = COUNT(mib_map) 1090 }; 1091