hostres_swrun_tbl.c revision 285830
1/* 2 * Copyright (c) 2005-2006 The FreeBSD Project 3 * All rights reserved. 4 * 5 * Author: Victor Cruceru <soc-victor@freebsd.org> 6 * 7 * Redistribution of this software and documentation and use in source and 8 * binary forms, with or without modification, are permitted provided that 9 * the following conditions are met: 10 * 11 * 1. Redistributions of source code or documentation must retain the above 12 * copyright notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. 28 * 29 * $FreeBSD: releng/10.2/usr.sbin/bsnmpd/modules/snmp_hostres/hostres_swrun_tbl.c 240352 2012-09-11 08:28:58Z glebius $ 30 * 31 * Host Resources MIB for SNMPd. Implementation for hrSWRunTable 32 */ 33 34#include <sys/param.h> 35#include <sys/proc.h> 36#include <sys/sysctl.h> 37#include <sys/user.h> 38#include <sys/linker.h> 39 40#include <assert.h> 41#include <signal.h> 42#include <stdlib.h> 43#include <string.h> 44#include <syslog.h> 45 46#include "hostres_snmp.h" 47#include "hostres_oid.h" 48#include "hostres_tree.h" 49 50/* 51 * Ugly thing: PID_MAX, NO_PID defined only in kernel 52 */ 53#define NO_PID 100000 54 55enum SWRunType { 56 SRT_UNKNOWN = 1, 57 SRT_OPERATING_SYSTEM = 2, 58 SRT_DEVICE_DRIVER = 3, 59 SRT_APPLICATION = 4 60 61}; 62 63enum SWRunStatus { 64 SRS_RUNNING = 1, 65 SRS_RUNNABLE = 2, 66 SRS_NOT_RUNNABLE = 3, 67 SRS_INVALID = 4 68}; 69 70/* Maximum lengths for the strings according to the MIB */ 71#define SWR_NAME_MLEN (64 + 1) 72#define SWR_PATH_MLEN (128 + 1) 73#define SWR_PARAM_MLEN (128 + 1) 74 75/* 76 * This structure is used to hold a SNMP table entry 77 * for both hrSWRunTable and hrSWRunPerfTable because 78 * hrSWRunPerfTable AUGMENTS hrSWRunTable 79 */ 80struct swrun_entry { 81 int32_t index; 82 u_char *name; /* it may be NULL */ 83 const struct asn_oid *id; 84 u_char *path; /* it may be NULL */ 85 u_char *parameters; /* it may be NULL */ 86 int32_t type; /* enum SWRunType */ 87 int32_t status; /* enum SWRunStatus */ 88 int32_t perfCPU; 89 int32_t perfMemory; 90#define HR_SWRUN_FOUND 0x001 91 uint32_t flags; 92 uint64_t r_tick; /* tick when entry refreshed */ 93 TAILQ_ENTRY(swrun_entry) link; 94}; 95TAILQ_HEAD(swrun_tbl, swrun_entry); 96 97/* the head of the list with hrSWRunTable's entries */ 98static struct swrun_tbl swrun_tbl = TAILQ_HEAD_INITIALIZER(swrun_tbl); 99 100/* last (agent) tick when hrSWRunTable and hrSWRunPerTable was updated */ 101static uint64_t swrun_tick; 102 103/* maximum number of ticks between updates of SWRun and SWRunPerf table */ 104uint32_t swrun_tbl_refresh = HR_SWRUN_TBL_REFRESH * 100; 105 106/* the value of the MIB object with the same name */ 107static int32_t SWOSIndex; 108 109/** 110 * Malloc a new entry and add it to the list 111 * associated to this table. The item identified by 112 * the index parameter must not exist in this list. 113 */ 114static struct swrun_entry * 115swrun_entry_create(int32_t idx) 116{ 117 struct swrun_entry *entry; 118 119 if ((entry = malloc(sizeof(*entry))) == NULL) { 120 syslog(LOG_WARNING, "%s: %m", __func__); 121 return (NULL); 122 } 123 memset(entry, 0, sizeof(*entry)); 124 entry->index = idx; 125 126 INSERT_OBJECT_INT(entry, &swrun_tbl); 127 return (entry); 128} 129 130/** 131 * Unlink the entry from the list and then free its heap memory 132 */ 133static void 134swrun_entry_delete(struct swrun_entry *entry) 135{ 136 137 assert(entry != NULL); 138 139 TAILQ_REMOVE(&swrun_tbl, entry, link); 140 141 free(entry->name); 142 free(entry->path); 143 free(entry->parameters); 144 free(entry); 145} 146 147/** 148 * Search one item by its index, return NULL if none found 149 */ 150static struct swrun_entry * 151swrun_entry_find_by_index(int32_t idx) 152{ 153 struct swrun_entry *entry; 154 155 TAILQ_FOREACH(entry, &swrun_tbl, link) 156 if (entry->index == idx) 157 return (entry); 158 return (NULL); 159} 160 161/** 162 * Translate the kernel's process status to SNMP. 163 */ 164static enum SWRunStatus 165swrun_OS_get_proc_status(const struct kinfo_proc *kp) 166{ 167 168 assert(kp != NULL); 169 if(kp == NULL) { 170 return (SRS_INVALID); 171 } 172 173 /* 174 * I'm using the old style flags - they look cleaner to me, 175 * at least for the purpose of this SNMP table 176 */ 177 switch (kp->ki_stat) { 178 179 case SSTOP: 180 return (SRS_NOT_RUNNABLE); 181 182 case SWAIT: 183 case SLOCK: 184 case SSLEEP: 185 return (SRS_RUNNABLE); 186 187 case SZOMB: 188 return (SRS_INVALID); 189 190 case SIDL: 191 case SRUN: 192 return (SRS_RUNNING); 193 194 default: 195 syslog(LOG_ERR,"Unknown process state: %d", kp->ki_stat); 196 return (SRS_INVALID); 197 } 198} 199 200/** 201 * Make an SNMP table entry from a kernel one. 202 */ 203static void 204kinfo_proc_to_swrun_entry(const struct kinfo_proc *kp, 205 struct swrun_entry *entry) 206{ 207 char **argv = NULL; 208 uint64_t cpu_time = 0; 209 size_t pname_len; 210 211 pname_len = strlen(kp->ki_comm) + 1; 212 entry->name = reallocf(entry->name, pname_len); 213 if (entry->name != NULL) 214 strlcpy(entry->name, kp->ki_comm, pname_len); 215 216 entry->id = &oid_zeroDotZero; /* unknown id - FIXME */ 217 218 assert(hr_kd != NULL); 219 220 argv = kvm_getargv(hr_kd, kp, SWR_PARAM_MLEN - 1); 221 if(argv != NULL){ 222 u_char param[SWR_PARAM_MLEN]; 223 224 memset(param, '\0', sizeof(param)); 225 226 /* 227 * FIXME 228 * Path seems to not be available. 229 * Try to hack the info in argv[0]; 230 * this argv is under control of the program so this info 231 * is not realiable 232 */ 233 if(*argv != NULL && (*argv)[0] == '/') { 234 size_t path_len; 235 236 path_len = strlen(*argv) + 1; 237 if (path_len > SWR_PATH_MLEN) 238 path_len = SWR_PATH_MLEN; 239 240 entry->path = reallocf(entry->path, path_len); 241 if (entry->path != NULL) { 242 memset(entry->path, '\0', path_len); 243 strlcpy((char*)entry->path, *argv, path_len); 244 } 245 } 246 247 argv++; /* skip the first one which was used for path */ 248 249 while (argv != NULL && *argv != NULL ) { 250 if (param[0] != 0) { 251 /* 252 * add a space between parameters, 253 * except before the first one 254 */ 255 strlcat((char *)param, " ", sizeof(param)); 256 } 257 strlcat((char *)param, *argv, sizeof(param)); 258 argv++; 259 } 260 /* reuse pname_len */ 261 pname_len = strlen(param) + 1; 262 if (pname_len > SWR_PARAM_MLEN) 263 pname_len = SWR_PARAM_MLEN; 264 265 entry->parameters = reallocf(entry->parameters, pname_len); 266 strlcpy(entry->parameters, param, pname_len); 267 } 268 269 entry->type = (int32_t)(IS_KERNPROC(kp) ? SRT_OPERATING_SYSTEM : 270 SRT_APPLICATION); 271 272 entry->status = (int32_t)swrun_OS_get_proc_status(kp); 273 cpu_time = kp->ki_runtime / 100000; /* centi-seconds */ 274 275 /* may overflow the snmp type */ 276 entry->perfCPU = (cpu_time > (uint64_t)INT_MAX ? INT_MAX : cpu_time); 277 entry->perfMemory = kp->ki_size / 1024; /* in kilo-bytes */ 278 entry->r_tick = get_ticks(); 279} 280 281/** 282 * Create a table entry for a KLD 283 */ 284static void 285kld_file_stat_to_swrun(const struct kld_file_stat *kfs, 286 struct swrun_entry *entry) 287{ 288 size_t name_len; 289 290 assert(kfs != NULL); 291 assert(entry != NULL); 292 293 name_len = strlen(kfs->name) + 1; 294 if (name_len > SWR_NAME_MLEN) 295 name_len = SWR_NAME_MLEN; 296 297 entry->name = reallocf(entry->name, name_len); 298 if (entry->name != NULL) 299 strlcpy((char *)entry->name, kfs->name, name_len); 300 301 /* FIXME: can we find the location where the module was loaded from? */ 302 entry->path = NULL; 303 304 /* no parameters for kernel files (.ko) of for the kernel */ 305 entry->parameters = NULL; 306 307 entry->id = &oid_zeroDotZero; /* unknown id - FIXME */ 308 309 if (strcmp(kfs->name, "kernel") == 0) { 310 entry->type = (int32_t)SRT_OPERATING_SYSTEM; 311 SWOSIndex = entry->index; 312 } else { 313 entry->type = (int32_t)SRT_DEVICE_DRIVER; /* well, not really */ 314 } 315 entry->status = (int32_t)SRS_RUNNING; 316 entry->perfCPU = 0; /* Info not available */ 317 entry->perfMemory = kfs->size / 1024; /* in kilo-bytes */ 318 entry->r_tick = get_ticks(); 319} 320 321/** 322 * Get all visible processes including the kernel visible threads 323 */ 324static void 325swrun_OS_get_procs(void) 326{ 327 struct kinfo_proc *plist, *kp; 328 int i; 329 int nproc; 330 struct swrun_entry *entry; 331 332 plist = kvm_getprocs(hr_kd, KERN_PROC_ALL, 0, &nproc); 333 if (plist == NULL || nproc < 0) { 334 syslog(LOG_ERR, "kvm_getprocs() failed: %m"); 335 return; 336 } 337 for (i = 0, kp = plist; i < nproc; i++, kp++) { 338 /* 339 * The SNMP table's index must begin from 1 (as specified by 340 * this table definition), the PIDs are starting from 0 341 * so we are translating the PIDs to +1 342 */ 343 entry = swrun_entry_find_by_index((int32_t)kp->ki_pid + 1); 344 if (entry == NULL) { 345 /* new entry - get memory for it */ 346 entry = swrun_entry_create((int32_t)kp->ki_pid + 1); 347 if (entry == NULL) 348 continue; 349 } 350 entry->flags |= HR_SWRUN_FOUND; /* mark it as found */ 351 352 kinfo_proc_to_swrun_entry(kp, entry); 353 } 354} 355 356/* 357 * Get kernel items: first the kernel itself, then the loaded modules. 358 */ 359static void 360swrun_OS_get_kinfo(void) 361{ 362 int fileid; 363 struct swrun_entry *entry; 364 struct kld_file_stat stat; 365 366 for (fileid = kldnext(0); fileid > 0; fileid = kldnext(fileid)) { 367 stat.version = sizeof(struct kld_file_stat); 368 if (kldstat(fileid, &stat) < 0) { 369 syslog(LOG_ERR, "kldstat() failed: %m"); 370 continue; 371 } 372 373 /* 374 * kernel and kernel files (*.ko) will be indexed starting with 375 * NO_PID + 1; NO_PID is PID_MAX + 1 thus it will be no risk to 376 * overlap with real PIDs which are in range of 1 .. NO_PID 377 */ 378 entry = swrun_entry_find_by_index(NO_PID + 1 + stat.id); 379 if (entry == NULL) { 380 /* new entry - get memory for it */ 381 entry = swrun_entry_create(NO_PID + 1 + stat.id); 382 if (entry == NULL) 383 continue; 384 } 385 entry->flags |= HR_SWRUN_FOUND; /* mark it as found */ 386 387 kld_file_stat_to_swrun(&stat, entry); 388 } 389} 390 391/** 392 * Refresh the hrSWRun and hrSWRunPert tables. 393 */ 394static void 395refresh_swrun_tbl(void) 396{ 397 398 struct swrun_entry *entry, *entry_tmp; 399 400 if (this_tick - swrun_tick < swrun_tbl_refresh) { 401 HRDBG("no refresh needed "); 402 return; 403 } 404 405 /* mark each entry as missing */ 406 TAILQ_FOREACH(entry, &swrun_tbl, link) 407 entry->flags &= ~HR_SWRUN_FOUND; 408 409 swrun_OS_get_procs(); 410 swrun_OS_get_kinfo(); 411 412 /* 413 * Purge items that disappeared 414 */ 415 TAILQ_FOREACH_SAFE(entry, &swrun_tbl, link, entry_tmp) 416 if (!(entry->flags & HR_SWRUN_FOUND)) 417 swrun_entry_delete(entry); 418 419 swrun_tick = this_tick; 420 421 HRDBG("refresh DONE"); 422} 423 424/** 425 * Update the information in this entry 426 */ 427static void 428fetch_swrun_entry(struct swrun_entry *entry) 429{ 430 struct kinfo_proc *plist; 431 int nproc; 432 struct kld_file_stat stat; 433 434 assert(entry != NULL); 435 436 if (entry->index >= NO_PID + 1) { 437 /* 438 * kernel and kernel files (*.ko) will be indexed 439 * starting with NO_PID + 1; NO_PID is PID_MAX + 1 440 * thus it will be no risk to overlap with real PIDs 441 * which are in range of 1 .. NO_PID 442 */ 443 stat.version = sizeof(stat); 444 if (kldstat(entry->index - NO_PID - 1, &stat) == -1) { 445 /* 446 * not found, it's gone. Mark it as invalid for now, it 447 * will be removed from the list at next global refersh 448 */ 449 HRDBG("missing item with kid=%d", 450 entry->index - NO_PID - 1); 451 entry->status = (int32_t)SRS_INVALID; 452 } else 453 kld_file_stat_to_swrun(&stat, entry); 454 455 } else { 456 /* this is a process */ 457 assert(hr_kd != NULL); 458 plist = kvm_getprocs(hr_kd, KERN_PROC_PID, 459 entry->index - 1, &nproc); 460 if (plist == NULL || nproc != 1) { 461 HRDBG("missing item with PID=%d", entry->index - 1); 462 entry->status = (int32_t)SRS_INVALID; 463 } else 464 kinfo_proc_to_swrun_entry(plist, entry); 465 } 466} 467 468/** 469 * Invalidate entry. For KLDs we try to unload it, for processes we SIGKILL it. 470 */ 471static int 472invalidate_swrun_entry(struct swrun_entry *entry, int commit) 473{ 474 struct kinfo_proc *plist; 475 int nproc; 476 struct kld_file_stat stat; 477 478 assert(entry != NULL); 479 480 if (entry->index >= NO_PID + 1) { 481 /* this is a kernel item */ 482 HRDBG("atempt to unload KLD %d", 483 entry->index - NO_PID - 1); 484 485 if (entry->index == SWOSIndex) { 486 /* can't invalidate the kernel itself */ 487 return (SNMP_ERR_NOT_WRITEABLE); 488 } 489 490 stat.version = sizeof(stat); 491 if (kldstat(entry->index - NO_PID - 1, &stat) == -1) { 492 /* 493 * not found, it's gone. Mark it as invalid for now, it 494 * will be removed from the list at next global 495 * refresh 496 */ 497 HRDBG("missing item with kid=%d", 498 entry->index - NO_PID - 1); 499 entry->status = (int32_t)SRS_INVALID; 500 return (SNMP_ERR_NOERROR); 501 } 502 /* 503 * There is no way to try to unload a module. There seems 504 * also no way to find out whether it is busy without unloading 505 * it. We can assume that it is busy, if the reference count 506 * is larger than 2, but if it is 1 nothing helps. 507 */ 508 if (!commit) { 509 if (stat.refs > 1) 510 return (SNMP_ERR_NOT_WRITEABLE); 511 return (SNMP_ERR_NOERROR); 512 } 513 if (kldunload(stat.id) == -1) { 514 syslog(LOG_ERR,"kldunload for %d/%s failed: %m", 515 stat.id, stat.name); 516 if (errno == EBUSY) 517 return (SNMP_ERR_NOT_WRITEABLE); 518 else 519 return (SNMP_ERR_RES_UNAVAIL); 520 } 521 } else { 522 /* this is a process */ 523 assert(hr_kd != NULL); 524 525 plist = kvm_getprocs(hr_kd, KERN_PROC_PID, 526 entry->index - 1, &nproc); 527 if (plist == NULL || nproc != 1) { 528 HRDBG("missing item with PID=%d", entry->index - 1); 529 entry->status = (int32_t)SRS_INVALID; 530 return (SNMP_ERR_NOERROR); 531 } 532 if (IS_KERNPROC(plist)) { 533 /* you don't want to do this */ 534 return (SNMP_ERR_NOT_WRITEABLE); 535 } 536 if (kill(entry->index - 1, commit ? SIGKILL : 0) < 0) { 537 syslog(LOG_ERR,"kill (%d, SIGKILL) failed: %m", 538 entry->index - 1); 539 if (errno == ESRCH) { 540 /* race: just gone */ 541 entry->status = (int32_t)SRS_INVALID; 542 return (SNMP_ERR_NOERROR); 543 } 544 return (SNMP_ERR_GENERR); 545 } 546 } 547 return (SNMP_ERR_NOERROR); 548} 549 550/** 551 * Popuplate the hrSWRunTable. 552 */ 553void 554init_swrun_tbl(void) 555{ 556 557 refresh_swrun_tbl(); 558 HRDBG("done"); 559} 560 561/** 562 * Finalize the hrSWRunTable. 563 */ 564void 565fini_swrun_tbl(void) 566{ 567 struct swrun_entry *n1; 568 569 while ((n1 = TAILQ_FIRST(&swrun_tbl)) != NULL) { 570 TAILQ_REMOVE(&swrun_tbl, n1, link); 571 free(n1); 572 } 573} 574 575/* 576 * This is the implementation for a generated (by a SNMP tool) 577 * function prototype, see hostres_tree.h 578 * It hanldes the SNMP operations for hrSWRunTable 579 */ 580int 581op_hrSWRunTable(struct snmp_context *ctx __unused, struct snmp_value *value, 582 u_int sub, u_int iidx __unused, enum snmp_op curr_op) 583{ 584 struct swrun_entry *entry; 585 int ret; 586 587 refresh_swrun_tbl(); 588 589 switch (curr_op) { 590 591 case SNMP_OP_GETNEXT: 592 if ((entry = NEXT_OBJECT_INT(&swrun_tbl, 593 &value->var, sub)) == NULL) 594 return (SNMP_ERR_NOSUCHNAME); 595 value->var.len = sub + 1; 596 value->var.subs[sub] = entry->index; 597 goto get; 598 599 case SNMP_OP_GET: 600 if ((entry = FIND_OBJECT_INT(&swrun_tbl, 601 &value->var, sub)) == NULL) 602 return (SNMP_ERR_NOSUCHNAME); 603 goto get; 604 605 case SNMP_OP_SET: 606 if ((entry = FIND_OBJECT_INT(&swrun_tbl, 607 &value->var, sub)) == NULL) 608 return (SNMP_ERR_NO_CREATION); 609 610 if (entry->r_tick < this_tick) 611 fetch_swrun_entry(entry); 612 613 switch (value->var.subs[sub - 1]) { 614 615 case LEAF_hrSWRunStatus: 616 if (value->v.integer != (int32_t)SRS_INVALID) 617 return (SNMP_ERR_WRONG_VALUE); 618 619 if (entry->status == (int32_t)SRS_INVALID) 620 return (SNMP_ERR_NOERROR); 621 622 /* 623 * Here we have a problem with the entire SNMP 624 * model: if we kill now, we cannot rollback. 625 * If we kill in the commit code, we cannot 626 * return an error. Because things may change between 627 * SET and COMMIT this is impossible to handle 628 * correctly. 629 */ 630 return (invalidate_swrun_entry(entry, 0)); 631 } 632 return (SNMP_ERR_NOT_WRITEABLE); 633 634 case SNMP_OP_ROLLBACK: 635 return (SNMP_ERR_NOERROR); 636 637 case SNMP_OP_COMMIT: 638 if ((entry = FIND_OBJECT_INT(&swrun_tbl, 639 &value->var, sub)) == NULL) 640 return (SNMP_ERR_NOERROR); 641 642 switch (value->var.subs[sub - 1]) { 643 644 case LEAF_hrSWRunStatus: 645 if (value->v.integer == (int32_t)SRS_INVALID && 646 entry->status != (int32_t)SRS_INVALID) 647 (void)invalidate_swrun_entry(entry, 1); 648 return (SNMP_ERR_NOERROR); 649 } 650 abort(); 651 } 652 abort(); 653 654 get: 655 ret = SNMP_ERR_NOERROR; 656 switch (value->var.subs[sub - 1]) { 657 658 case LEAF_hrSWRunIndex: 659 value->v.integer = entry->index; 660 break; 661 662 case LEAF_hrSWRunName: 663 if (entry->name != NULL) 664 ret = string_get(value, entry->name, -1); 665 else 666 ret = string_get(value, "", -1); 667 break; 668 669 case LEAF_hrSWRunID: 670 assert(entry->id != NULL); 671 value->v.oid = *entry->id; 672 break; 673 674 case LEAF_hrSWRunPath: 675 if (entry->path != NULL) 676 ret = string_get(value, entry->path, -1); 677 else 678 ret = string_get(value, "", -1); 679 break; 680 681 case LEAF_hrSWRunParameters: 682 if (entry->parameters != NULL) 683 ret = string_get(value, entry->parameters, -1); 684 else 685 ret = string_get(value, "", -1); 686 break; 687 688 case LEAF_hrSWRunType: 689 value->v.integer = entry->type; 690 break; 691 692 case LEAF_hrSWRunStatus: 693 value->v.integer = entry->status; 694 break; 695 696 default: 697 abort(); 698 } 699 return (ret); 700} 701 702/** 703 * Scalar(s) in the SWRun group 704 */ 705int 706op_hrSWRun(struct snmp_context *ctx __unused, struct snmp_value *value, 707 u_int sub, u_int iidx __unused, enum snmp_op curr_op) 708{ 709 710 /* only SNMP GET is possible */ 711 switch (curr_op) { 712 713 case SNMP_OP_GET: 714 goto get; 715 716 case SNMP_OP_SET: 717 return (SNMP_ERR_NOT_WRITEABLE); 718 719 case SNMP_OP_ROLLBACK: 720 case SNMP_OP_COMMIT: 721 case SNMP_OP_GETNEXT: 722 abort(); 723 } 724 abort(); 725 726 get: 727 switch (value->var.subs[sub - 1]) { 728 729 case LEAF_hrSWOSIndex: 730 value->v.uint32 = SWOSIndex; 731 return (SNMP_ERR_NOERROR); 732 733 default: 734 abort(); 735 } 736} 737 738/* 739 * This is the implementation for a generated (by a SNMP tool) 740 * function prototype, see hostres_tree.h 741 * It handles the SNMP operations for hrSWRunPerfTable 742 */ 743int 744op_hrSWRunPerfTable(struct snmp_context *ctx __unused, 745 struct snmp_value *value, u_int sub, u_int iidx __unused, 746 enum snmp_op curr_op ) 747{ 748 struct swrun_entry *entry; 749 750 refresh_swrun_tbl(); 751 752 switch (curr_op) { 753 754 case SNMP_OP_GETNEXT: 755 if ((entry = NEXT_OBJECT_INT(&swrun_tbl, 756 &value->var, sub)) == NULL) 757 return (SNMP_ERR_NOSUCHNAME); 758 value->var.len = sub + 1; 759 value->var.subs[sub] = entry->index; 760 goto get; 761 762 case SNMP_OP_GET: 763 if ((entry = FIND_OBJECT_INT(&swrun_tbl, 764 &value->var, sub)) == NULL) 765 return (SNMP_ERR_NOSUCHNAME); 766 goto get; 767 768 case SNMP_OP_SET: 769 if ((entry = FIND_OBJECT_INT(&swrun_tbl, 770 &value->var, sub)) == NULL) 771 return (SNMP_ERR_NO_CREATION); 772 return (SNMP_ERR_NOT_WRITEABLE); 773 774 case SNMP_OP_ROLLBACK: 775 case SNMP_OP_COMMIT: 776 abort(); 777 } 778 abort(); 779 780 get: 781 switch (value->var.subs[sub - 1]) { 782 783 case LEAF_hrSWRunPerfCPU: 784 value->v.integer = entry->perfCPU; 785 return (SNMP_ERR_NOERROR); 786 787 case LEAF_hrSWRunPerfMem: 788 value->v.integer = entry->perfMemory; 789 return (SNMP_ERR_NOERROR); 790 } 791 abort(); 792} 793