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