net-snmp sun mods install: make sure destdirs exist
[unleashed-userland.git] / components / sysutils / net-snmp / sun / agent / modules / healthMonitor / healthMonitor.c
blob3ca9193b1bda8db8252d3df5d6196f116bf70271
2 /*
3 * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
4 *
5 * U.S. Government Rights - Commercial software. Government users are subject to
6 * the Sun Microsystems, Inc. standard license agreement and applicable
7 * provisions of the FAR and its supplements.
8 *
9 *
10 * This distribution may include materials developed by third parties. Sun, Sun
11 * Microsystems, the Sun logo and Solaris are trademarks or registered
12 * trademarks of Sun Microsystems, Inc. in the U.S. and other countries.
17 * Note: this file originally auto-generated by mib2c using :
18 * mib2c.scalar.conf,v 1.5 2002/07/18 14:18:52 dts12 Exp $
22 * This Module implements all the nodes in health-monitor-mib.mib.
23 * mib2c.scalar.conf is used to generate template for all nodes except the
24 * hmDiskGroup mib2c.iterate.conf is used to generate template for
25 * hmDiskGroup (which contains a Table) The two templates are merged so that
26 * all the implementation for health-monitor-mib is present as one module.
27 * Template functions are filled and new functions are added to do the
28 * following: 1) Data Acquisition, 2) Automatic refresh, 3) trap generation,
29 * 4) subscribe for thresholds from health_monitor.conf file.
33 #include <net-snmp/net-snmp-config.h>
34 #include <net-snmp/net-snmp-includes.h>
35 #include <net-snmp/agent/net-snmp-agent-includes.h>
36 #include "healthMonitor.h"
37 #include <netdb.h>
41 * DATA: Following are the variables in which data collected for various
42 * nodes is stored. The values are refreshed every "refresh interval"
43 * (default 60 seconds). The value stored in this variable is returned
44 * whenever a "get" request comes.
47 /* Data for SWAP node */
48 int swapavail_data, swapresv_data, swapalloc_data, swapused_data,
49 swaptotal_data;
51 /* Data for Kernel node */
52 ulong sum_smtx = 0;
53 int ncpus;
55 /* Data for NFS node */
56 double calls;
57 int badcalls, retrans, badxids, timeouts, newcreds, badverfs,
58 timers, nomem, cantsend, interrupts;
59 char callsStr[8];
61 /* Data for CPU node */
62 int runque, waiting, swapque;
64 /* Data for RAM node */
65 int handspread, scan;
68 * Data for KMEM node . Only alloc_fail and mem_free are published through
69 * the MIB
71 int alloc, alloc_fail=0, buf_size, buf_avail, buf_total, buf_max;
72 int mem_avail=0, mem_inuse=0, mem_free=0;
75 * Data for DNLC node . hits, misses, hitrate and refrate are published
76 * through the MIB. Rest of variables are temp data used for processing alarm
77 * conditions.
80 int firsttime = 1;
81 int lasthits = 0;
82 int lastmisses = 0;
83 int prevhits = 0;
84 int prevmisses = 0;
85 long prevtime = 0;
87 long hits, misses;
88 long hitrate, refrate;
91 * Data for diskGroup. We maintain the disk table in memory as a linked list
92 * of hmDiskTable objects "head" points to the first memeber of the linked
93 * list
96 hmDiskTable *head;
97 int diskCount;
100 * Following are the variables that hold threshold's used to determine alarm
101 * conditions. The variables are updated with threshold settings in
102 * health_monitor.conf file, when module is initialized.
105 /* Thresholds and States for SWAP node */
106 int threshold_swapavail_info = 500000, threshold_swapavail_warning = 100000,
107 threshold_swapavail_error = 40000;
109 int prev_SWAP_state = OK;
110 int new_SWAP_state = OK;
111 int SWAP_rule_state = NOTINIT;
113 /* Thresholds for Kernel node */
114 ulong threshold_mutex_info = 200, threshold_mutex_warning = 500;
116 int prev_mutex_state = OK;
117 int new_mutex_state = OK;
118 int Kernel_rule_state = NOTINIT;
120 /* Thresholds for NFS node */
121 float threshold_mincalls = 0.1, threshold_badxids = 0.0, threshold_timeouts = 5.0;
123 int prev_NFS_state = OK;
124 int new_NFS_state = OK;
125 int NFS_rule_state = NOTINIT;
127 /* Thresholds for CPU node */
128 float threshold_cpuload_info = 1.0, threshold_cpuload_warning = 2.0,
129 threshold_cpuload_error = 3.0;
131 int prev_cpuload_state = OK;
132 int new_cpuload_state = OK;
133 int CPU_rule_state = NOTINIT;
135 /* Thresholds for RAM node */
136 int threshold_restime_long = 600, threshold_restime_ok = 40,
137 threshold_restime_error = 20;
139 int prev_restime_state = OK;
140 int new_restime_state = OK;
141 int RAM_rule_state = NOTINIT;
143 /* Thresholds for KMEM node */
144 int threshold_freemem_low = 1;
145 int firstkmemerrs = 0, lastkmemerrs = 0; /* These must be Global
146 * variables and
147 * preserved across
148 * invocation of
149 * check_state_KMEM()
150 * function */
152 int prev_kmem_state = OK;
153 int new_kmem_state = OK;
154 int KMEM_rule_state = NOTINIT;
156 /* Thresholds for DNLC node */
158 float threshold_dnlc_active = 100.0, threshold_dnlc_warning = 80;
160 int prev_dnlc_state = OK;
161 int new_dnlc_state = OK;
162 int DNLC_rule_state = NOTINIT;
164 /* Thresholds for diskGroup */
166 long disk_busy_warning = 10.0, disk_busy_problem = 30.0, disk_svc_t_warning = 20.0,
167 disk_svc_t_problem = 30.0;
170 /* COMMON data variables */
172 u_char hostName[MAXHOSTNAMELEN], moduleName[15], statusOIDContext[5];
173 int hm_refresh_interval=60;
174 time_t hm_prev_ref_time=1;
175 time_t hm_prev_disk_ref=1;
178 /** Initializes the healthMonitor module */
179 void
180 init_healthMonitor(void)
183 int retCode;
185 static oid hmSpinsOnMutexes_oid[] = {1, 3, 6, 1, 4, 1, 42, 2, 12, 2, 2, 11, 2, 1, 1, 0};
186 static oid hmTotProcInRunQueue_oid[] = {1, 3, 6, 1, 4, 1, 42, 2, 12, 2, 2, 11, 4, 1, 1, 0};
187 static oid hmTotRPCCalls_oid[] = {1, 3, 6, 1, 4, 1, 42, 2, 12, 2, 2, 11, 3, 1, 1, 0};
188 static oid hmUsedSwapSpace_oid[] = {1, 3, 6, 1, 4, 1, 42, 2, 12, 2, 2, 11, 1, 1, 4, 0};
189 static oid hmDNLCMisses_oid[] = {1, 3, 6, 1, 4, 1, 42, 2, 12, 2, 2, 11, 8, 1, 2, 0};
190 static oid hmReservedSwapSpace_oid[] = {1, 3, 6, 1, 4, 1, 42, 2, 12, 2, 2, 11, 1, 1, 2, 0};
191 static oid hmTotMemAllocFails_oid[] = {1, 3, 6, 1, 4, 1, 42, 2, 12, 2, 2, 11, 3, 1, 9, 0};
192 static oid hmAvailableSwapSpace_oid[] = {1, 3, 6, 1, 4, 1, 42, 2, 12, 2, 2, 11, 1, 1, 1, 0};
193 static oid hmDNLCHitRate_oid[] = {1, 3, 6, 1, 4, 1, 42, 2, 12, 2, 2, 11, 8, 1, 3, 0};
194 static oid hmDNLCHits_oid[] = {1, 3, 6, 1, 4, 1, 42, 2, 12, 2, 2, 11, 8, 1, 1, 0};
195 static oid hmAllocatedSwapSpace_oid[] = {1, 3, 6, 1, 4, 1, 42, 2, 12, 2, 2, 11, 1, 1, 3, 0};
196 static oid hmTotNumOfCPUs_oid[] = {1, 3, 6, 1, 4, 1, 42, 2, 12, 2, 2, 11, 2, 1, 2, 0};
197 static oid hmPageScanRate_oid[] = {1, 3, 6, 1, 4, 1, 42, 2, 12, 2, 2, 11, 6, 1, 2, 0};
198 static oid hmTimers_oid[] = {1, 3, 6, 1, 4, 1, 42, 2, 12, 2, 2, 11, 3, 1, 8, 0};
199 static oid hmTotBadRPCCalls_oid[] = {1, 3, 6, 1, 4, 1, 42, 2, 12, 2, 2, 11, 3, 1, 2, 0};
200 static oid hmDNLCRefRate_oid[] = {1, 3, 6, 1, 4, 1, 42, 2, 12, 2, 2, 11, 8, 1, 4, 0};
201 static oid hmTotSendFails_oid[] = {1, 3, 6, 1, 4, 1, 42, 2, 12, 2, 2, 11, 3, 1, 10, 0};
202 static oid hmTotFailedCallsBV_oid[] = {1, 3, 6, 1, 4, 1, 42, 2, 12, 2, 2, 11, 3, 1, 7, 0};
203 static oid hmTotNumOfAuthRefresh_oid[] = {1, 3, 6, 1, 4, 1, 42, 2, 12, 2, 2, 11, 3, 1, 6, 0};
204 static oid hmHandspread_oid[] = {1, 3, 6, 1, 4, 1, 42, 2, 12, 2, 2, 11, 6, 1, 1, 0};
205 static oid hmTotRPCRetransmissions_oid[] = {1, 3, 6, 1, 4, 1, 42, 2, 12, 2, 2, 11, 3, 1, 3, 0};
206 static oid hmKmemFreeMem_oid[] = {1, 3, 6, 1, 4, 1, 42, 2, 12, 2, 2, 11, 7, 1, 2, 0};
207 static oid hmTotBadRPCReplies_oid[] = {1, 3, 6, 1, 4, 1, 42, 2, 12, 2, 2, 11, 3, 1, 4, 0};
208 static oid hmKmemErrors_oid[] = {1, 3, 6, 1, 4, 1, 42, 2, 12, 2, 2, 11, 7, 1, 1, 0};
209 static oid hmTotProcReadyInSwap_oid[] = {1, 3, 6, 1, 4, 1, 42, 2, 12, 2, 2, 11, 4, 1, 3, 0};
210 static oid hmTotProcBlocked_oid[] = {1, 3, 6, 1, 4, 1, 42, 2, 12, 2, 2, 11, 4, 1, 2, 0};
211 static oid hmTotRPCCallsTimedOut_oid[] = {1, 3, 6, 1, 4, 1, 42, 2, 12, 2, 2, 11, 3, 1, 5, 0};
213 DEBUGMSGTL(("healthMonitor", "Initializing\n"));
215 netsnmp_register_read_only_instance(netsnmp_create_handler_registration
216 ("hmSpinsOnMutexes",
217 get_hmSpinsOnMutexes,
218 hmSpinsOnMutexes_oid,
219 OID_LENGTH(hmSpinsOnMutexes_oid),
220 HANDLER_CAN_RONLY));
221 netsnmp_register_read_only_instance(netsnmp_create_handler_registration
222 ("hmTotProcInRunQueue",
223 get_hmTotProcInRunQueue,
224 hmTotProcInRunQueue_oid,
225 OID_LENGTH(hmTotProcInRunQueue_oid),
226 HANDLER_CAN_RONLY));
227 netsnmp_register_read_only_instance(netsnmp_create_handler_registration
228 ("hmTotRPCCalls",
229 get_hmTotRPCCalls,
230 hmTotRPCCalls_oid,
231 OID_LENGTH(hmTotRPCCalls_oid),
232 HANDLER_CAN_RONLY));
233 netsnmp_register_read_only_instance(netsnmp_create_handler_registration
234 ("hmUsedSwapSpace",
235 get_hmUsedSwapSpace,
236 hmUsedSwapSpace_oid,
237 OID_LENGTH(hmUsedSwapSpace_oid),
238 HANDLER_CAN_RONLY));
239 netsnmp_register_read_only_instance(netsnmp_create_handler_registration
240 ("hmDNLCMisses",
241 get_hmDNLCMisses,
242 hmDNLCMisses_oid,
243 OID_LENGTH(hmDNLCMisses_oid),
244 HANDLER_CAN_RONLY));
245 netsnmp_register_read_only_instance(netsnmp_create_handler_registration
246 ("hmReservedSwapSpace",
247 get_hmReservedSwapSpace,
248 hmReservedSwapSpace_oid,
249 OID_LENGTH(hmReservedSwapSpace_oid),
250 HANDLER_CAN_RONLY));
251 netsnmp_register_read_only_instance(netsnmp_create_handler_registration
252 ("hmTotMemAllocFails",
253 get_hmTotMemAllocFails,
254 hmTotMemAllocFails_oid,
255 OID_LENGTH(hmTotMemAllocFails_oid),
256 HANDLER_CAN_RONLY));
257 netsnmp_register_read_only_instance(netsnmp_create_handler_registration
258 ("hmAvailableSwapSpace",
259 get_hmAvailableSwapSpace,
260 hmAvailableSwapSpace_oid,
261 OID_LENGTH(hmAvailableSwapSpace_oid),
262 HANDLER_CAN_RONLY));
263 netsnmp_register_read_only_instance(netsnmp_create_handler_registration
264 ("hmDNLCHitRate",
265 get_hmDNLCHitRate,
266 hmDNLCHitRate_oid,
267 OID_LENGTH(hmDNLCHitRate_oid),
268 HANDLER_CAN_RONLY));
269 netsnmp_register_read_only_instance(netsnmp_create_handler_registration
270 ("hmDNLCHits",
271 get_hmDNLCHits,
272 hmDNLCHits_oid,
273 OID_LENGTH(hmDNLCHits_oid),
274 HANDLER_CAN_RONLY));
275 netsnmp_register_read_only_instance(netsnmp_create_handler_registration
276 ("hmAllocatedSwapSpace",
277 get_hmAllocatedSwapSpace,
278 hmAllocatedSwapSpace_oid,
279 OID_LENGTH(hmAllocatedSwapSpace_oid),
280 HANDLER_CAN_RONLY));
281 netsnmp_register_read_only_instance(netsnmp_create_handler_registration
282 ("hmTotNumOfCPUs",
283 get_hmTotNumOfCPUs,
284 hmTotNumOfCPUs_oid,
285 OID_LENGTH(hmTotNumOfCPUs_oid),
286 HANDLER_CAN_RONLY));
287 netsnmp_register_read_only_instance(netsnmp_create_handler_registration
288 ("hmPageScanRate",
289 get_hmPageScanRate,
290 hmPageScanRate_oid,
291 OID_LENGTH(hmPageScanRate_oid),
292 HANDLER_CAN_RONLY));
293 netsnmp_register_read_only_instance(netsnmp_create_handler_registration
294 ("hmTimers",
295 get_hmTimers,
296 hmTimers_oid,
297 OID_LENGTH(hmTimers_oid),
298 HANDLER_CAN_RONLY));
299 netsnmp_register_read_only_instance(netsnmp_create_handler_registration
300 ("hmTotBadRPCCalls",
301 get_hmTotBadRPCCalls,
302 hmTotBadRPCCalls_oid,
303 OID_LENGTH(hmTotBadRPCCalls_oid),
304 HANDLER_CAN_RONLY));
305 netsnmp_register_read_only_instance(netsnmp_create_handler_registration
306 ("hmDNLCRefRate",
307 get_hmDNLCRefRate,
308 hmDNLCRefRate_oid,
309 OID_LENGTH(hmDNLCRefRate_oid),
310 HANDLER_CAN_RONLY));
311 netsnmp_register_read_only_instance(netsnmp_create_handler_registration
312 ("hmTotSendFails",
313 get_hmTotSendFails,
314 hmTotSendFails_oid,
315 OID_LENGTH(hmTotSendFails_oid),
316 HANDLER_CAN_RONLY));
317 netsnmp_register_read_only_instance(netsnmp_create_handler_registration
318 ("hmTotFailedCallsBV",
319 get_hmTotFailedCallsBV,
320 hmTotFailedCallsBV_oid,
321 OID_LENGTH(hmTotFailedCallsBV_oid),
322 HANDLER_CAN_RONLY));
323 netsnmp_register_read_only_instance(netsnmp_create_handler_registration
324 ("hmTotNumOfAuthRefresh",
325 get_hmTotNumOfAuthRefresh,
326 hmTotNumOfAuthRefresh_oid,
327 OID_LENGTH(hmTotNumOfAuthRefresh_oid),
328 HANDLER_CAN_RONLY));
329 netsnmp_register_read_only_instance(netsnmp_create_handler_registration
330 ("hmHandspread",
331 get_hmHandspread,
332 hmHandspread_oid,
333 OID_LENGTH(hmHandspread_oid),
334 HANDLER_CAN_RONLY));
335 netsnmp_register_read_only_instance(netsnmp_create_handler_registration
336 ("hmTotRPCRetransmissions",
337 get_hmTotRPCRetransmissions,
338 hmTotRPCRetransmissions_oid,
339 OID_LENGTH(hmTotRPCRetransmissions_oid),
340 HANDLER_CAN_RONLY));
341 netsnmp_register_read_only_instance(netsnmp_create_handler_registration
342 ("hmKmemFreeMem",
343 get_hmKmemFreeMem,
344 hmKmemFreeMem_oid,
345 OID_LENGTH(hmKmemFreeMem_oid),
346 HANDLER_CAN_RONLY));
347 netsnmp_register_read_only_instance(netsnmp_create_handler_registration
348 ("hmTotBadRPCReplies",
349 get_hmTotBadRPCReplies,
350 hmTotBadRPCReplies_oid,
351 OID_LENGTH(hmTotBadRPCReplies_oid),
352 HANDLER_CAN_RONLY));
353 netsnmp_register_read_only_instance(netsnmp_create_handler_registration
354 ("hmKmemErrors",
355 get_hmKmemErrors,
356 hmKmemErrors_oid,
357 OID_LENGTH(hmKmemErrors_oid),
358 HANDLER_CAN_RONLY));
359 netsnmp_register_read_only_instance(netsnmp_create_handler_registration
360 ("hmTotProcReadyInSwap",
361 get_hmTotProcReadyInSwap,
362 hmTotProcReadyInSwap_oid,
363 OID_LENGTH(hmTotProcReadyInSwap_oid),
364 HANDLER_CAN_RONLY));
365 netsnmp_register_read_only_instance(netsnmp_create_handler_registration
366 ("hmTotProcBlocked",
367 get_hmTotProcBlocked,
368 hmTotProcBlocked_oid,
369 OID_LENGTH(hmTotProcBlocked_oid),
370 HANDLER_CAN_RONLY));
371 netsnmp_register_read_only_instance(netsnmp_create_handler_registration
372 ("hmTotRPCCallsTimedOut",
373 get_hmTotRPCCallsTimedOut,
374 hmTotRPCCallsTimedOut_oid,
375 OID_LENGTH(hmTotRPCCallsTimedOut_oid),
376 HANDLER_CAN_RONLY));
379 /* Initialize Disk stuff */
381 /* here we initialize all the tables we're planning on supporting */
383 initialize_table_hmDiskTable();
387 * Additions to init function to register callbacks for tokens. Whenever
388 * a token is encountered in health_monitor.conf file, the function
389 * read_health_monitor_thresholds is called by the agent
392 register_config_handler("health_monitor", "hm_refresh_interval",
393 read_health_monitor_thresholds, NULL, NULL);
395 register_config_handler("health_monitor", "threshold_swapavail_info",
396 read_health_monitor_thresholds, NULL, NULL);
398 register_config_handler("health_monitor", "threshold_swapavail_warning",
399 read_health_monitor_thresholds, NULL, NULL);
401 register_config_handler("health_monitor", "threshold_swapavail_error",
402 read_health_monitor_thresholds, NULL, NULL);
404 register_config_handler("health_monitor", "threshold_mutex_info",
405 read_health_monitor_thresholds, NULL, NULL);
407 register_config_handler("health_monitor", "threshold_mutex_warning",
408 read_health_monitor_thresholds, NULL, NULL);
410 register_config_handler("health_monitor", "threshold_mincalls",
411 read_health_monitor_thresholds, NULL, NULL);
413 register_config_handler("health_monitor", "threshold_badxids",
414 read_health_monitor_thresholds, NULL, NULL);
416 register_config_handler("health_monitor", "threshold_timeouts",
417 read_health_monitor_thresholds, NULL, NULL);
419 register_config_handler("health_monitor", "threshold_cpuload_info",
420 read_health_monitor_thresholds, NULL, NULL);
422 register_config_handler("health_monitor", "threshold_cpuload_warning",
423 read_health_monitor_thresholds, NULL, NULL);
425 register_config_handler("health_monitor", "threshold_cpuload_error",
426 read_health_monitor_thresholds, NULL, NULL);
428 register_config_handler("health_monitor", "threshold_restime_long",
429 read_health_monitor_thresholds, NULL, NULL);
431 register_config_handler("health_monitor", "threshold_restime_ok",
432 read_health_monitor_thresholds, NULL, NULL);
434 register_config_handler("health_monitor", "threshold_restime_error",
435 read_health_monitor_thresholds, NULL, NULL);
437 register_config_handler("health_monitor", "threshold_freemem_low",
438 read_health_monitor_thresholds, NULL, NULL);
440 register_config_handler("health_monitor", "threshold_dnlc_active",
441 read_health_monitor_thresholds, NULL, NULL);
443 register_config_handler("health_monitor", "threshold_dnlc_warning",
444 read_health_monitor_thresholds, NULL, NULL);
446 register_config_handler("health_monitor", "disk_busy_warning",
447 read_health_monitor_thresholds, NULL, NULL);
449 register_config_handler("health_monitor", "disk_busy_problem",
450 read_health_monitor_thresholds, NULL, NULL);
452 register_config_handler("health_monitor", "disk_svc_t_warning",
453 read_health_monitor_thresholds, NULL, NULL);
455 register_config_handler("health_monitor", "disk_svc_t_problem",
456 read_health_monitor_thresholds, NULL, NULL);
461 * Initialize data that's required in the trap - The hostname,
462 * modulenaem, statusOIDContext
465 retCode = gethostname((char *) hostName, MAXHOSTNAMELEN);
466 if (retCode != 0)
467 strcpy((char *) hostName, "null\0");
469 strcpy((char *) moduleName, "Health-Monitor\0");
471 strcpy((char *) statusOIDContext, "null\0");
474 snmp_register_callback(SNMP_CALLBACK_LIBRARY, SNMP_CALLBACK_POST_READ_CONFIG,
475 hm_post_read_config, NULL);
480 /** Initialize the hmDiskTable table by defining its contents and how it's structured */
481 void
482 initialize_table_hmDiskTable(void)
484 static oid hmDiskTable_oid[] = {1, 3, 6, 1, 4, 1, 42, 2, 12, 2, 2, 11, 5, 1};
485 netsnmp_table_registration_info *table_info;
486 netsnmp_handler_registration *my_handler;
487 netsnmp_iterator_info *iinfo;
489 /* create the table structure itself */
490 table_info = SNMP_MALLOC_TYPEDEF(netsnmp_table_registration_info);
491 iinfo = SNMP_MALLOC_TYPEDEF(netsnmp_iterator_info);
494 * if your table is read only, it's easiest to change the
495 * HANDLER_CAN_RWRITE definition below to HANDLER_CAN_RONLY
497 my_handler = netsnmp_create_handler_registration("hmDiskTable",
498 hmDiskTable_handler,
499 hmDiskTable_oid,
500 OID_LENGTH(hmDiskTable_oid),
501 HANDLER_CAN_RONLY);
503 if (!my_handler || !table_info || !iinfo)
504 return; /* mallocs failed */
506 /***************************************************
507 * Setting up the table's definition
509 netsnmp_table_helper_add_indexes(table_info,
510 ASN_OCTET_STR, /* index: hmDiskName */
513 table_info->min_column = 1;
514 table_info->max_column = 5;
516 /* iterator access routines */
517 iinfo->get_first_data_point = hmDiskTable_get_first_data_point;
518 iinfo->get_next_data_point = hmDiskTable_get_next_data_point;
520 iinfo->table_reginfo = table_info;
522 /***************************************************
523 * registering the table with the master agent
525 DEBUGMSGTL(("initialize_table_hmDiskTable",
526 "Registering table hmDiskTable as a table iterator\n"));
527 netsnmp_register_table_iterator(my_handler, iinfo);
531 get_hmSpinsOnMutexes(netsnmp_mib_handler * handler,
532 netsnmp_handler_registration * reginfo,
533 netsnmp_agent_request_info * reqinfo,
534 netsnmp_request_info * requests)
538 * We are never called for a GETNEXT if it's registered as a "instance",
539 * as it's "magically" handled for us.
543 * a instance handler also only hands us one request at a time, so we
544 * don't need to loop over a list of requests; we'll only get one.
547 switch (reqinfo->mode) {
549 case MODE_GET:
551 snmp_set_var_typed_value(requests->requestvb, ASN_INTEGER, (u_char *) & sum_smtx, sizeof(sum_smtx));
552 break;
555 default:
556 /* we should never get here, so this is a really bad error */
557 return SNMP_ERR_GENERR;
560 return SNMP_ERR_NOERROR;
564 get_hmTotProcInRunQueue(netsnmp_mib_handler * handler,
565 netsnmp_handler_registration * reginfo,
566 netsnmp_agent_request_info * reqinfo,
567 netsnmp_request_info * requests)
570 * We are never called for a GETNEXT if it's registered as a "instance",
571 * as it's "magically" handled for us.
575 * a instance handler also only hands us one request at a time, so we
576 * don't need to loop over a list of requests; we'll only get one.
579 long runque_long;
580 switch (reqinfo->mode) {
582 case MODE_GET:
584 runque_long = (long) runque;
585 snmp_set_var_typed_value(requests->requestvb, ASN_INTEGER, (u_char *) & runque_long, sizeof(runque_long));
586 break;
589 default:
590 /* we should never get here, so this is a really bad error */
591 return SNMP_ERR_GENERR;
594 return SNMP_ERR_NOERROR;
598 get_hmTotRPCCalls(netsnmp_mib_handler * handler,
599 netsnmp_handler_registration * reginfo,
600 netsnmp_agent_request_info * reqinfo,
601 netsnmp_request_info * requests)
604 * We are never called for a GETNEXT if it's registered as a "instance",
605 * as it's "magically" handled for us.
609 * a instance handler also only hands us one request at a time, so we
610 * don't need to loop over a list of requests; we'll only get one.
613 switch (reqinfo->mode) {
615 case MODE_GET:
616 snmp_set_var_typed_value(requests->requestvb, ASN_OCTET_STR, (u_char *) callsStr, strlen(callsStr) );
617 break;
620 default:
621 /* we should never get here, so this is a really bad error */
622 return SNMP_ERR_GENERR;
625 return SNMP_ERR_NOERROR;
629 get_hmUsedSwapSpace(netsnmp_mib_handler * handler,
630 netsnmp_handler_registration * reginfo,
631 netsnmp_agent_request_info * reqinfo,
632 netsnmp_request_info * requests)
635 * We are never called for a GETNEXT if it's registered as a "instance",
636 * as it's "magically" handled for us.
640 * a instance handler also only hands us one request at a time, so we
641 * don't need to loop over a list of requests; we'll only get one.
644 long swapused_data_long;
645 switch (reqinfo->mode) {
647 case MODE_GET:
649 swapused_data_long = (long)swapused_data;
650 snmp_set_var_typed_value(requests->requestvb, ASN_INTEGER, (u_char *) & swapused_data_long, sizeof(swapused_data_long));
651 break;
654 default:
655 /* we should never get here, so this is a really bad error */
656 return SNMP_ERR_GENERR;
659 return SNMP_ERR_NOERROR;
663 get_hmDNLCMisses(netsnmp_mib_handler * handler,
664 netsnmp_handler_registration * reginfo,
665 netsnmp_agent_request_info * reqinfo,
666 netsnmp_request_info * requests)
669 * We are never called for a GETNEXT if it's registered as a "instance",
670 * as it's "magically" handled for us.
674 * a instance handler also only hands us one request at a time, so we
675 * don't need to loop over a list of requests; we'll only get one.
678 switch (reqinfo->mode) {
680 case MODE_GET:
681 snmp_set_var_typed_value(requests->requestvb, ASN_UNSIGNED, (u_char *) & misses, sizeof(misses));
682 break;
685 default:
686 /* we should never get here, so this is a really bad error */
687 return SNMP_ERR_GENERR;
690 return SNMP_ERR_NOERROR;
694 get_hmReservedSwapSpace(netsnmp_mib_handler * handler,
695 netsnmp_handler_registration * reginfo,
696 netsnmp_agent_request_info * reqinfo,
697 netsnmp_request_info * requests)
700 * We are never called for a GETNEXT if it's registered as a "instance",
701 * as it's "magically" handled for us.
705 * a instance handler also only hands us one request at a time, so we
706 * don't need to loop over a list of requests; we'll only get one.
709 long swapresv_data_long;
710 switch (reqinfo->mode) {
712 case MODE_GET:
714 swapresv_data_long = (long) swapresv_data;
715 snmp_set_var_typed_value(requests->requestvb, ASN_INTEGER, (u_char *) & swapresv_data_long, sizeof(swapresv_data_long));
716 break;
719 default:
720 /* we should never get here, so this is a really bad error */
721 return SNMP_ERR_GENERR;
724 return SNMP_ERR_NOERROR;
728 get_hmTotMemAllocFails(netsnmp_mib_handler * handler,
729 netsnmp_handler_registration * reginfo,
730 netsnmp_agent_request_info * reqinfo,
731 netsnmp_request_info * requests)
734 * We are never called for a GETNEXT if it's registered as a "instance",
735 * as it's "magically" handled for us.
739 * a instance handler also only hands us one request at a time, so we
740 * don't need to loop over a list of requests; we'll only get one.
743 long nomem_long;
744 switch (reqinfo->mode) {
746 case MODE_GET:
748 nomem_long = (long) nomem;
749 snmp_set_var_typed_value(requests->requestvb, ASN_INTEGER, (u_char *) & nomem_long, sizeof(nomem_long));
750 break;
753 default:
754 /* we should never get here, so this is a really bad error */
755 return SNMP_ERR_GENERR;
758 return SNMP_ERR_NOERROR;
762 get_hmAvailableSwapSpace(netsnmp_mib_handler * handler,
763 netsnmp_handler_registration * reginfo,
764 netsnmp_agent_request_info * reqinfo,
765 netsnmp_request_info * requests)
768 * We are never called for a GETNEXT if it's registered as a "instance",
769 * as it's "magically" handled for us.
773 * a instance handler also only hands us one request at a time, so we
774 * don't need to loop over a list of requests; we'll only get one.
777 switch (reqinfo->mode) {
779 long swapavail_data_long;
781 case MODE_GET:
783 swapavail_data_long = (long) swapavail_data;
784 snmp_set_var_typed_value(requests->requestvb, ASN_INTEGER, (u_char *) & swapavail_data_long, sizeof(swapavail_data_long));
785 break;
788 default:
789 /* we should never get here, so this is a really bad error */
790 return SNMP_ERR_GENERR;
793 return SNMP_ERR_NOERROR;
797 get_hmDNLCHitRate(netsnmp_mib_handler * handler,
798 netsnmp_handler_registration * reginfo,
799 netsnmp_agent_request_info * reqinfo,
800 netsnmp_request_info * requests)
803 * We are never called for a GETNEXT if it's registered as a "instance",
804 * as it's "magically" handled for us.
808 * a instance handler also only hands us one request at a time, so we
809 * don't need to loop over a list of requests; we'll only get one.
812 switch (reqinfo->mode) {
814 case MODE_GET:
815 snmp_set_var_typed_value(requests->requestvb, ASN_UNSIGNED, (u_char *) & hitrate, sizeof(hitrate));
816 break;
819 default:
820 /* we should never get here, so this is a really bad error */
821 return SNMP_ERR_GENERR;
824 return SNMP_ERR_NOERROR;
828 get_hmDNLCHits(netsnmp_mib_handler * handler,
829 netsnmp_handler_registration * reginfo,
830 netsnmp_agent_request_info * reqinfo,
831 netsnmp_request_info * requests)
834 * We are never called for a GETNEXT if it's registered as a "instance",
835 * as it's "magically" handled for us.
839 * a instance handler also only hands us one request at a time, so we
840 * don't need to loop over a list of requests; we'll only get one.
843 switch (reqinfo->mode) {
845 case MODE_GET:
846 snmp_set_var_typed_value(requests->requestvb, ASN_UNSIGNED, (u_char *) & hits, sizeof(hits));
847 break;
850 default:
851 /* we should never get here, so this is a really bad error */
852 return SNMP_ERR_GENERR;
855 return SNMP_ERR_NOERROR;
860 get_hmAllocatedSwapSpace(netsnmp_mib_handler * handler,
861 netsnmp_handler_registration * reginfo,
862 netsnmp_agent_request_info * reqinfo,
863 netsnmp_request_info * requests)
866 * We are never called for a GETNEXT if it's registered as a "instance",
867 * as it's "magically" handled for us.
871 * a instance handler also only hands us one request at a time, so we
872 * don't need to loop over a list of requests; we'll only get one.
875 long swapalloc_data_long;
876 switch (reqinfo->mode) {
878 case MODE_GET:
880 swapalloc_data_long = (long) swapalloc_data;
881 snmp_set_var_typed_value(requests->requestvb, ASN_INTEGER, (u_char *) & swapalloc_data_long, sizeof(swapalloc_data_long));
882 break;
885 default:
886 /* we should never get here, so this is a really bad error */
887 return SNMP_ERR_GENERR;
890 return SNMP_ERR_NOERROR;
894 get_hmTotNumOfCPUs(netsnmp_mib_handler * handler,
895 netsnmp_handler_registration * reginfo,
896 netsnmp_agent_request_info * reqinfo,
897 netsnmp_request_info * requests)
901 * We are never called for a GETNEXT if it's registered as a "instance",
902 * as it's "magically" handled for us.
906 * a instance handler also only hands us one request at a time, so we
907 * don't need to loop over a list of requests; we'll only get one.
910 long ncpus_long;
911 switch (reqinfo->mode) {
913 case MODE_GET:
915 ncpus_long = (long)ncpus;
916 snmp_set_var_typed_value(requests->requestvb, ASN_INTEGER, (u_char *) & ncpus_long, sizeof(ncpus_long));
917 break;
920 default:
921 /* we should never get here, so this is a really bad error */
922 return SNMP_ERR_GENERR;
925 return SNMP_ERR_NOERROR;
929 get_hmPageScanRate(netsnmp_mib_handler * handler,
930 netsnmp_handler_registration * reginfo,
931 netsnmp_agent_request_info * reqinfo,
932 netsnmp_request_info * requests)
935 * We are never called for a GETNEXT if it's registered as a "instance",
936 * as it's "magically" handled for us.
940 * a instance handler also only hands us one request at a time, so we
941 * don't need to loop over a list of requests; we'll only get one.
944 long scan_long;
945 switch (reqinfo->mode) {
947 case MODE_GET:
949 scan_long = (long) scan;
950 snmp_set_var_typed_value(requests->requestvb, ASN_INTEGER, (u_char *) & scan_long, sizeof(scan_long));
951 break;
954 default:
955 /* we should never get here, so this is a really bad error */
956 return SNMP_ERR_GENERR;
959 return SNMP_ERR_NOERROR;
963 get_hmTimers(netsnmp_mib_handler * handler,
964 netsnmp_handler_registration * reginfo,
965 netsnmp_agent_request_info * reqinfo,
966 netsnmp_request_info * requests)
969 * We are never called for a GETNEXT if it's registered as a "instance",
970 * as it's "magically" handled for us.
974 * a instance handler also only hands us one request at a time, so we
975 * don't need to loop over a list of requests; we'll only get one.
978 long timers_long;
979 switch (reqinfo->mode) {
981 case MODE_GET:
983 timers_long = (long) timers;
984 snmp_set_var_typed_value(requests->requestvb, ASN_INTEGER, (u_char *) & timers_long, sizeof(timers_long));
985 break;
988 default:
989 /* we should never get here, so this is a really bad error */
990 return SNMP_ERR_GENERR;
993 return SNMP_ERR_NOERROR;
997 get_hmTotBadRPCCalls(netsnmp_mib_handler * handler,
998 netsnmp_handler_registration * reginfo,
999 netsnmp_agent_request_info * reqinfo,
1000 netsnmp_request_info * requests)
1003 * We are never called for a GETNEXT if it's registered as a "instance",
1004 * as it's "magically" handled for us.
1008 * a instance handler also only hands us one request at a time, so we
1009 * don't need to loop over a list of requests; we'll only get one.
1012 long badcalls_long;
1013 switch (reqinfo->mode) {
1015 case MODE_GET:
1017 badcalls_long = (long) badcalls ;
1018 snmp_set_var_typed_value(requests->requestvb, ASN_INTEGER, (u_char *) & badcalls_long, sizeof(badcalls_long));
1019 break;
1022 default:
1023 /* we should never get here, so this is a really bad error */
1024 return SNMP_ERR_GENERR;
1027 return SNMP_ERR_NOERROR;
1031 get_hmDNLCRefRate(netsnmp_mib_handler * handler,
1032 netsnmp_handler_registration * reginfo,
1033 netsnmp_agent_request_info * reqinfo,
1034 netsnmp_request_info * requests)
1037 * We are never called for a GETNEXT if it's registered as a "instance",
1038 * as it's "magically" handled for us.
1042 * a instance handler also only hands us one request at a time, so we
1043 * don't need to loop over a list of requests; we'll only get one.
1046 switch (reqinfo->mode) {
1048 case MODE_GET:
1049 snmp_set_var_typed_value(requests->requestvb, ASN_UNSIGNED, (u_char *) & refrate, sizeof(refrate));
1050 break;
1053 default:
1054 /* we should never get here, so this is a really bad error */
1055 return SNMP_ERR_GENERR;
1058 return SNMP_ERR_NOERROR;
1063 get_hmTotSendFails(netsnmp_mib_handler * handler,
1064 netsnmp_handler_registration * reginfo,
1065 netsnmp_agent_request_info * reqinfo,
1066 netsnmp_request_info * requests)
1069 * We are never called for a GETNEXT if it's registered as a "instance",
1070 * as it's "magically" handled for us.
1074 * a instance handler also only hands us one request at a time, so we
1075 * don't need to loop over a list of requests; we'll only get one.
1078 long cantsend_long;
1079 switch (reqinfo->mode) {
1081 case MODE_GET:
1083 cantsend_long = (long) cantsend;
1084 snmp_set_var_typed_value(requests->requestvb, ASN_INTEGER, (u_char *) & cantsend_long, sizeof(cantsend_long));
1085 break;
1088 default:
1089 /* we should never get here, so this is a really bad error */
1090 return SNMP_ERR_GENERR;
1093 return SNMP_ERR_NOERROR;
1097 get_hmTotFailedCallsBV(netsnmp_mib_handler * handler,
1098 netsnmp_handler_registration * reginfo,
1099 netsnmp_agent_request_info * reqinfo,
1100 netsnmp_request_info * requests)
1103 * We are never called for a GETNEXT if it's registered as a "instance",
1104 * as it's "magically" handled for us.
1108 * a instance handler also only hands us one request at a time, so we
1109 * don't need to loop over a list of requests; we'll only get one.
1112 long badxids_long;
1113 switch (reqinfo->mode) {
1115 case MODE_GET:
1117 badxids_long = (long) badxids;
1118 snmp_set_var_typed_value(requests->requestvb, ASN_INTEGER, (u_char *) & badxids_long, sizeof(badxids_long));
1119 break;
1122 default:
1123 /* we should never get here, so this is a really bad error */
1124 return SNMP_ERR_GENERR;
1127 return SNMP_ERR_NOERROR;
1131 get_hmTotNumOfAuthRefresh(netsnmp_mib_handler * handler,
1132 netsnmp_handler_registration * reginfo,
1133 netsnmp_agent_request_info * reqinfo,
1134 netsnmp_request_info * requests)
1137 * We are never called for a GETNEXT if it's registered as a "instance",
1138 * as it's "magically" handled for us.
1142 * a instance handler also only hands us one request at a time, so we
1143 * don't need to loop over a list of requests; we'll only get one.
1146 long newcreds_long;
1147 switch (reqinfo->mode) {
1149 case MODE_GET:
1151 newcreds_long = (long) newcreds;
1152 snmp_set_var_typed_value(requests->requestvb, ASN_INTEGER, (u_char *) & newcreds_long, sizeof(newcreds_long));
1153 break;
1156 default:
1157 /* we should never get here, so this is a really bad error */
1158 return SNMP_ERR_GENERR;
1161 return SNMP_ERR_NOERROR;
1165 get_hmHandspread(netsnmp_mib_handler * handler,
1166 netsnmp_handler_registration * reginfo,
1167 netsnmp_agent_request_info * reqinfo,
1168 netsnmp_request_info * requests)
1171 * We are never called for a GETNEXT if it's registered as a "instance",
1172 * as it's "magically" handled for us.
1176 * a instance handler also only hands us one request at a time, so we
1177 * don't need to loop over a list of requests; we'll only get one.
1180 long handspread_long;
1181 switch (reqinfo->mode) {
1183 case MODE_GET:
1185 handspread_long = (long) handspread;
1186 snmp_set_var_typed_value(requests->requestvb, ASN_INTEGER, (u_char *) & handspread_long, sizeof(handspread_long));
1187 break;
1190 default:
1191 /* we should never get here, so this is a really bad error */
1192 return SNMP_ERR_GENERR;
1195 return SNMP_ERR_NOERROR;
1199 get_hmTotRPCRetransmissions(netsnmp_mib_handler * handler,
1200 netsnmp_handler_registration * reginfo,
1201 netsnmp_agent_request_info * reqinfo,
1202 netsnmp_request_info * requests)
1205 * We are never called for a GETNEXT if it's registered as a "instance",
1206 * as it's "magically" handled for us.
1210 * a instance handler also only hands us one request at a time, so we
1211 * don't need to loop over a list of requests; we'll only get one.
1214 long interrupts_long;
1215 switch (reqinfo->mode) {
1217 case MODE_GET:
1219 interrupts_long = (long) interrupts;
1220 snmp_set_var_typed_value(requests->requestvb, ASN_INTEGER, (u_char *) & interrupts_long, sizeof(interrupts_long));
1221 break;
1224 default:
1225 /* we should never get here, so this is a really bad error */
1226 return SNMP_ERR_GENERR;
1229 return SNMP_ERR_NOERROR;
1233 get_hmKmemFreeMem(netsnmp_mib_handler * handler,
1234 netsnmp_handler_registration * reginfo,
1235 netsnmp_agent_request_info * reqinfo,
1236 netsnmp_request_info * requests)
1239 * We are never called for a GETNEXT if it's registered as a "instance",
1240 * as it's "magically" handled for us.
1244 * a instance handler also only hands us one request at a time, so we
1245 * don't need to loop over a list of requests; we'll only get one.
1248 long mem_free_long;
1249 switch (reqinfo->mode) {
1251 case MODE_GET:
1253 mem_free_long = (long) mem_free;
1254 snmp_set_var_typed_value(requests->requestvb, ASN_INTEGER, (u_char *) & mem_free_long, sizeof(mem_free_long));
1255 break;
1258 default:
1259 /* we should never get here, so this is a really bad error */
1260 return SNMP_ERR_GENERR;
1263 return SNMP_ERR_NOERROR;
1267 get_hmTotBadRPCReplies(netsnmp_mib_handler * handler,
1268 netsnmp_handler_registration * reginfo,
1269 netsnmp_agent_request_info * reqinfo,
1270 netsnmp_request_info * requests)
1273 * We are never called for a GETNEXT if it's registered as a "instance",
1274 * as it's "magically" handled for us.
1278 * a instance handler also only hands us one request at a time, so we
1279 * don't need to loop over a list of requests; we'll only get one.
1282 long badverfs_long;
1283 switch (reqinfo->mode) {
1285 case MODE_GET:
1287 badverfs_long = (long) badverfs;
1288 snmp_set_var_typed_value(requests->requestvb, ASN_INTEGER, (u_char *) & badverfs_long, sizeof(badverfs_long));
1289 break;
1292 default:
1293 /* we should never get here, so this is a really bad error */
1294 return SNMP_ERR_GENERR;
1297 return SNMP_ERR_NOERROR;
1301 get_hmKmemErrors(netsnmp_mib_handler * handler,
1302 netsnmp_handler_registration * reginfo,
1303 netsnmp_agent_request_info * reqinfo,
1304 netsnmp_request_info * requests)
1307 * We are never called for a GETNEXT if it's registered as a "instance",
1308 * as it's "magically" handled for us.
1312 * a instance handler also only hands us one request at a time, so we
1313 * don't need to loop over a list of requests; we'll only get one.
1316 long alloc_fail_long;
1317 switch (reqinfo->mode) {
1319 case MODE_GET:
1321 alloc_fail_long = (long) alloc_fail;
1322 snmp_set_var_typed_value(requests->requestvb, ASN_INTEGER, (u_char *) & alloc_fail_long, sizeof(alloc_fail_long));
1323 break;
1326 default:
1327 /* we should never get here, so this is a really bad error */
1328 return SNMP_ERR_GENERR;
1331 return SNMP_ERR_NOERROR;
1335 get_hmTotProcReadyInSwap(netsnmp_mib_handler * handler,
1336 netsnmp_handler_registration * reginfo,
1337 netsnmp_agent_request_info * reqinfo,
1338 netsnmp_request_info * requests)
1341 * We are never called for a GETNEXT if it's registered as a "instance",
1342 * as it's "magically" handled for us.
1346 * a instance handler also only hands us one request at a time, so we
1347 * don't need to loop over a list of requests; we'll only get one.
1350 long swapque_long;
1351 switch (reqinfo->mode) {
1353 case MODE_GET:
1355 swapque_long = (long) swapque;
1356 snmp_set_var_typed_value(requests->requestvb, ASN_INTEGER, (u_char *) & swapque_long, sizeof(swapque_long));
1357 break;
1360 default:
1361 /* we should never get here, so this is a really bad error */
1362 return SNMP_ERR_GENERR;
1365 return SNMP_ERR_NOERROR;
1369 get_hmTotProcBlocked(netsnmp_mib_handler * handler,
1370 netsnmp_handler_registration * reginfo,
1371 netsnmp_agent_request_info * reqinfo,
1372 netsnmp_request_info * requests)
1375 * We are never called for a GETNEXT if it's registered as a "instance",
1376 * as it's "magically" handled for us.
1380 * a instance handler also only hands us one request at a time, so we
1381 * don't need to loop over a list of requests; we'll only get one.
1384 long waiting_long;
1385 switch (reqinfo->mode) {
1387 case MODE_GET:
1389 waiting_long = (long) waiting;
1390 snmp_set_var_typed_value(requests->requestvb, ASN_INTEGER, (u_char *) & waiting_long, sizeof(waiting_long));
1391 break;
1394 default:
1395 /* we should never get here, so this is a really bad error */
1396 return SNMP_ERR_GENERR;
1399 return SNMP_ERR_NOERROR;
1403 get_hmTotRPCCallsTimedOut(netsnmp_mib_handler * handler,
1404 netsnmp_handler_registration * reginfo,
1405 netsnmp_agent_request_info * reqinfo,
1406 netsnmp_request_info * requests)
1409 * We are never called for a GETNEXT if it's registered as a "instance",
1410 * as it's "magically" handled for us.
1414 * a instance handler also only hands us one request at a time, so we
1415 * don't need to loop over a list of requests; we'll only get one.
1418 long timeouts_long;
1419 switch (reqinfo->mode) {
1421 case MODE_GET:
1423 timeouts_long = (long) timeouts;
1424 snmp_set_var_typed_value(requests->requestvb, ASN_INTEGER, (u_char *) & timeouts_long, sizeof(timeouts_long));
1425 break;
1428 default:
1429 /* we should never get here, so this is a really bad error */
1430 return SNMP_ERR_GENERR;
1433 return SNMP_ERR_NOERROR;
1437 int hm_post_read_config(int a, int b, void *c, void *d)
1441 * Refresh the HealthMonitor module data every 60 seconds. Every 60
1442 * seconds, the function refresh_all_HM_data is called automatically by
1443 * the agent. Also, load data into nodes now by calling the refresh
1444 * function once
1447 construct_DISK_table();
1448 refresh_all_HM_data(0, NULL);
1450 snmp_alarm_register(hm_refresh_interval, SA_REPEAT, refresh_DISK_table, NULL);
1451 snmp_alarm_register(hm_refresh_interval, SA_REPEAT, refresh_all_HM_data, NULL);
1457 hmDiskTable *
1458 get_first_node()
1460 return head;
1463 /** returns the first data point within the hmDiskTable table data.
1465 Set the my_loop_context variable to the first data point structure
1466 of your choice (from which you can find the next one). This could
1467 be anything from the first node in a linked list, to an integer
1468 pointer containing the beginning of an array variable.
1470 Set the my_data_context variable to something to be returned to
1471 you later that will provide you with the data to return in a given
1472 row. This could be the same pointer as what my_loop_context is
1473 set to, or something different.
1475 The put_index_data variable contains a list of snmp variable
1476 bindings, one for each index in your table. Set the values of
1477 each appropriately according to the data matching the first row
1478 and return the put_index_data variable at the end of the function.
1481 netsnmp_variable_list *
1482 hmDiskTable_get_first_data_point(void **my_loop_context, void **my_data_context,
1483 netsnmp_variable_list * put_index_data,
1484 netsnmp_iterator_info * mydata)
1487 netsnmp_variable_list *vptr;
1489 hmDiskTable *firstNode = get_first_node();
1490 if (!firstNode) {
1491 return NULL;
1493 *my_loop_context = firstNode;
1494 *my_data_context = firstNode;
1496 vptr = put_index_data;
1498 snmp_set_var_value(vptr, (u_char *) firstNode->hmDiskName, strlen(firstNode->hmDiskName) /* XXX: length of
1499 hmDiskName data */ );
1500 vptr = vptr->next_variable;
1502 return put_index_data;
1505 /** functionally the same as hmDiskTable_get_first_data_point, but
1506 my_loop_context has already been set to a previous value and should
1507 be updated to the next in the list. For example, if it was a
1508 linked list, you might want to cast it and the return
1509 my_loop_context->next. The my_data_context pointer should be set
1510 to something you need later and the indexes in put_index_data
1511 updated again. */
1513 netsnmp_variable_list *
1514 hmDiskTable_get_next_data_point(void **my_loop_context, void **my_data_context,
1515 netsnmp_variable_list * put_index_data,
1516 netsnmp_iterator_info * mydata)
1519 netsnmp_variable_list *vptr;
1521 hmDiskTable *nextNode = (hmDiskTable *) * my_loop_context;
1523 /* This check is not really required */
1524 if(!nextNode) {
1525 snmp_log(LOG_DEBUG,"No data returned in get_next\n");
1526 return NULL;
1529 nextNode = nextNode->pNext;
1531 if (!nextNode) {
1532 snmp_log(LOG_DEBUG,"No data returned in get_next\n");
1533 return NULL;
1535 *my_loop_context = nextNode;
1536 *my_data_context = nextNode;
1538 vptr = put_index_data;
1540 snmp_set_var_value(vptr, (u_char *) nextNode->hmDiskName /* XXX: hmDiskName data */ , strlen(nextNode->hmDiskName) /* XXX: length of
1541 hmDiskName data */ );
1542 vptr = vptr->next_variable;
1544 return put_index_data;
1547 /** handles requests for the hmDiskTable table, if anything else needs to be done */
1549 hmDiskTable_handler(
1550 netsnmp_mib_handler * handler,
1551 netsnmp_handler_registration * reginfo,
1552 netsnmp_agent_request_info * reqinfo,
1553 netsnmp_request_info * requests)
1556 netsnmp_request_info *request;
1557 netsnmp_table_request_info *table_info;
1558 netsnmp_variable_list *var;
1560 hmDiskTable *data;
1562 for (request = requests; request; request = request->next) {
1563 var = request->requestvb;
1564 if (request->processed != 0)
1565 continue;
1568 * perform anything here that you need to do before each request is
1569 * processed.
1573 * the following extracts the my_data_context pointer set in the loop
1574 * functions above. You can then use the results to help return data
1575 * for the columns of the hmDiskTable table in question
1577 data = (hmDiskTable *) netsnmp_extract_iterator_context(request);
1578 if (data == NULL) {
1579 if (reqinfo->mode == MODE_GET) {
1580 netsnmp_set_request_error(reqinfo, request, SNMP_NOSUCHINSTANCE);
1581 continue;
1584 * XXX: no row existed, if you support creation and this is a
1585 * set, start dealing with it here, else continue
1588 /* extracts the information about the table from the request */
1589 table_info = netsnmp_extract_table_info(request);
1590 /* table_info->colnum contains the column number requested */
1592 * table_info->indexes contains a linked list of snmp variable
1593 * bindings for the indexes of the table. Values in the list have
1594 * been set corresponding to the indexes of the request
1596 if (table_info == NULL) {
1597 continue;
1599 switch (reqinfo->mode) {
1601 * the table_iterator helper should change all GETNEXTs into GETs
1602 * for you automatically, so you don't have to worry about the
1603 * GETNEXT case. Only GETs and SETs need to be dealt with here
1605 case MODE_GET:
1606 switch (table_info->colnum) {
1607 case COLUMN_HMDISKNAME:
1608 snmp_set_var_typed_value(var, ASN_OCTET_STR, (u_char *) data->hmDiskName, strlen(data->hmDiskName));
1609 break;
1611 case COLUMN_HMDISKALIASNAME:
1612 snmp_set_var_typed_value(var, ASN_OCTET_STR, (u_char *) data->hmDiskAliasName, strlen(data->hmDiskAliasName));
1613 break;
1615 case COLUMN_HMAVGWAITTRANSACTIONS:
1616 snmp_set_var_typed_value(var, ASN_OCTET_STR, (u_char *) data->hmAvgWaitTransactions, strlen(data->hmAvgWaitTransactions));
1617 break;
1619 case COLUMN_HMDISKBUSYPCNT:
1620 snmp_set_var_typed_value(var, ASN_OCTET_STR, (u_char *) data->hmDiskBusyPcnt, strlen(data->hmDiskBusyPcnt));
1621 break;
1623 case COLUMN_HMAVGDISKSVCTIME:
1624 snmp_set_var_typed_value(var, ASN_OCTET_STR, (u_char *) data->hmAvgDiskSvcTime, strlen(data->hmAvgDiskSvcTime));
1625 break;
1627 default:
1628 /* We shouldn't get here */
1629 snmp_log(LOG_ERR, "problem encountered in hmDiskTable_handler: unknown column\n");
1631 break;
1633 case MODE_SET_RESERVE1:
1634 /* set handling... */
1636 default:
1637 snmp_log(LOG_ERR, "problem encountered in hmDiskTable_handler: unsupported mode\n");
1640 return SNMP_ERR_NOERROR;
1644 * *****
1645 * New Functions that are added to the template generated by mib2c
1646 * *****
1651 * The following refresh functions are called every 60 seconds. The data
1652 * nodes are updated with latest data
1655 void
1656 refresh_SWAP_data()
1659 int code = 0;
1661 code = krgetswapusage(&swapavail_data, &swapresv_data, &swapalloc_data, &swapused_data, &swaptotal_data);
1664 * code == -1 : Error in swapctl code == 0 : Success Can be verified
1665 * using "swap -s" on shell
1668 if (code != 0) {
1669 snmp_log(LOG_ERR,"Health Monitor Module: errror getting SWAP info\n");
1670 swapavail_data = 0;
1671 swapresv_data = 0;
1672 swapalloc_data = 0;
1673 swapused_data = 0;
1677 void
1678 refresh_Kernel_data()
1681 int code = 0;
1683 code = krgetsmtx(&sum_smtx, &ncpus);
1685 if (code != 0) {
1686 snmp_log(LOG_ERR,"Health Monitor Module: errror getting Kernel info\n");
1687 sum_smtx = 0;
1688 ncpus = 0;
1692 void
1693 refresh_NFS_data()
1696 int code = 0;
1698 code = krgetclientrpcdetail(&calls, &badcalls, &retrans, &badxids, &timeouts, &newcreds, &badverfs, &timers, &nomem, &cantsend);
1700 if (code != 0) {
1701 snmp_log(LOG_ERR,"Health Monitor Module: errror getting NFS info\n");
1702 calls = 0;
1703 badcalls = 0;
1704 retrans = 0;
1705 badxids = 0;
1706 timeouts = 0;
1707 newcreds = 0;
1708 badverfs = 0;
1709 timers = 0;
1710 nomem = 0;
1711 cantsend = 0;
1714 /* "calls" is defined as a "DisplayString" in the MIB. So, converting
1715 * it to String
1718 sprintf(callsStr, "%3.1f\0", calls);
1721 void
1722 refresh_CPU_data()
1725 int code = 0;
1727 code = krgetprocdetail(&runque, &waiting, &swapque);
1729 if (code != 0) {
1731 snmp_log(LOG_ERR,"Health Monitor Module: errror getting CPU info\n");
1732 runque = 0;
1733 waiting = 0;
1734 swapque = 0;
1738 void
1739 refresh_RAM_data()
1742 int code = 0;
1744 code = krgetramdetail(&handspread, &scan);
1746 if (code != 0) {
1748 snmp_log(LOG_ERR,"Health Monitor Module: errror getting RAM info\n");
1749 handspread = 0;
1750 scan = 0;
1755 void
1756 refresh_KMEM_data()
1759 int code = 0;
1760 char char_name[2] = "*\n";
1762 /* char char_name='*'; */
1764 /* The first argument of "*" requests sum of statistics of all caches */
1766 code = krgetkmemdetail(char_name, &alloc, &alloc_fail, &buf_size, &buf_avail, &buf_total, &buf_max);
1768 if (code >= 0)
1769 code = krgetmemusage(&mem_avail, &mem_inuse, &mem_free);
1771 if (code != 0) {
1773 snmp_log(LOG_ERR,"Health Monitor Module: errror getting KMEM info\n");
1774 alloc_fail = 0;
1775 mem_free = 0;
1780 void
1781 refresh_DNLC_data()
1784 int code = 0;
1785 long curtime;
1787 curtime = time(&curtime);
1788 if (prevtime != curtime) {
1790 code = krgetncstatdetail(&hits, &misses);
1792 if (code != 0) {
1794 snmp_log(LOG_ERR,"Health Monitor Module: errror getting DNLC info\n");
1795 hits = 0;
1796 misses = 0;
1798 } /* NOTE : Should we do below even if
1799 * hits=0,misses=0 ? Yes, according to SunMC
1800 * rule */
1801 if (firsttime == 1) {
1802 firsttime = 0;
1803 lasthits = hits;
1804 lastmisses = misses;
1805 } else {
1806 lasthits = prevhits;
1807 lastmisses = prevmisses;
1810 prevhits = hits;
1811 prevmisses = misses;
1813 refrate = (hits - lasthits) + (misses - lastmisses);
1814 if (refrate == 0) {
1815 hitrate = 100;
1816 } else {
1817 hitrate = 100 * (hits - lasthits) / refrate;
1818 refrate = refrate / (curtime - prevtime);
1821 prevtime = curtime;
1825 void
1826 construct_DISK_table()
1829 hmDiskTable *prevPtr = NULL;
1831 char name[MAXNAMELEN];
1832 char alias[MAXNAMELEN];
1833 double rps, wps, tps, krps, kwps, kps, avw, avr;
1834 double w_pct, r_pct, wserv, rserv, serv;
1835 int code = 0;
1838 /* set to 0 so that we can block any other refresh's */
1839 hm_prev_disk_ref = 0;
1841 /* Keeps track of number of disks */
1842 diskCount = 0;
1844 do {
1846 hmDiskTable *ptr = (hmDiskTable *) malloc(sizeof(hmDiskTable));
1848 if ( ptr == NULL) {
1849 snmp_log(LOG_DEBUG,"malloc failed when constructing DISK table in health monitor module \n");
1850 return;
1853 code = krgetdiskdetail(name, alias, &rps, &wps, &tps, &krps, &kwps, &kps, &avw, &avr);
1855 if (code < 0) {
1856 /* Error occured during kstat read */
1857 snmp_log(LOG_ERR,"Health Monitor Module: errror getting disk info\n");
1858 return;
1860 code = krgetdisksrv(name, alias, &w_pct, &r_pct, &wserv, &rserv, &serv);
1862 if (code < 0) {
1863 /* Error occured during kstat read */
1864 snmp_log(LOG_ERR,"Health Monitor Module: errror getting disk info\n");
1865 return;
1867 /* Allocate required memory to hold each disk data. */
1869 ptr->hmDiskName = (char *) malloc(strlen(name) + 1);
1870 ptr->hmDiskAliasName = (char *) malloc(strlen(alias) + 1);
1871 ptr->hmAvgWaitTransactions = (char *) malloc(DISK_DATA_LEN);
1872 ptr->hmDiskBusyPcnt = (char *) malloc(DISK_DATA_LEN);
1873 ptr->hmAvgDiskSvcTime = (char *) malloc(DISK_DATA_LEN);
1875 if ( ptr->hmAvgDiskSvcTime == NULL) {
1876 snmp_log(LOG_DEBUG,"malloc failed when constructing DISK table in health monitor module \n");
1877 return;
1880 strcpy(ptr->hmDiskName,name);
1882 strcpy(ptr->hmDiskAliasName,alias);
1884 sprintf(ptr->hmAvgWaitTransactions, "%3.1f\0", w_pct);
1886 sprintf(ptr->hmDiskBusyPcnt, "%3.1f\0", r_pct);
1888 sprintf(ptr->hmAvgDiskSvcTime, "%3.1f\0", serv);
1890 /* Set the state of Disk to OK. */
1892 ptr->hmDiskState = OK;
1894 diskCount++;
1895 ptr->pNext = NULL;
1896 if (prevPtr == NULL) {
1897 head = prevPtr = ptr;
1898 } else {
1900 prevPtr->pNext = ptr;
1901 prevPtr = ptr;
1903 /* code is set to value 0 if there is more disk information */
1904 } while (code == 0);
1906 check_state_DISK();
1908 /* set the time of first refresh */
1910 time(&hm_prev_disk_ref);
1915 void
1916 refresh_DISK_table(unsigned int clientreg, void *clientarg)
1919 char name[MAXNAMELEN];
1920 char alias[MAXNAMELEN];
1921 double rps, wps, tps, krps, kwps, kps, avw, avr;
1922 double w_pct, r_pct, wserv, rserv, serv;
1923 int code = 0;
1924 hmDiskTable *headPtr;
1925 hmDiskTable *ptr;
1926 hmDiskTable *tailPtr, *p1, *p2;
1929 time_t hm_current_time;
1931 /* Did the previous refresh really finish ??
1932 * This means that previous refresh is still in progress */
1933 if (hm_prev_disk_ref == 0) return;
1935 time(&hm_current_time);
1937 /* Did the previous refresh finish too close to start another refresh ???
1938 * This means that the previous refresh finished relatively closer to current time
1939 * so, another refresh is not necessary. hm_prev_disk_ref is initialized to 1
1940 * during variable declaration. so, the first time refresh is called, it will always
1941 * proceed.
1944 if ( (hm_current_time - hm_prev_disk_ref) < (hm_refresh_interval / 4) ) return;
1946 /* set to 0 so that we can block any other refresh's */
1947 hm_prev_disk_ref = 0;
1949 diskCount=0;
1951 /* Set tailPtr to the last structure
1952 * set "hmTraversed" to 0 for all disks
1955 tailPtr = head;
1956 while (tailPtr->pNext != NULL) {
1957 tailPtr->hmTraversed=0;
1958 tailPtr = tailPtr->pNext;
1960 if(tailPtr != NULL) tailPtr->hmTraversed=0;
1962 do {
1964 int hit = 0;
1965 code = krgetdiskdetail(name, alias, &rps, &wps, &tps, &krps, &kwps, &kps, &avw, &avr);
1967 if (code < 0) {
1968 /* Error occured during kstat read */
1969 snmp_log(LOG_ERR,"Health Monitor Module: errror getting disk info\n");
1970 return;
1972 code = krgetdisksrv(name, alias, &w_pct, &r_pct, &wserv, &rserv, &serv);
1974 if (code < 0) {
1975 /* Error occured during kstat read */
1976 snmp_log(LOG_ERR,"Health Monitor Module: errror getting disk info\n");
1977 return;
1980 /* For each row in the table, refresh the data */
1982 headPtr = head;
1983 while ((headPtr != NULL) && (hit == 0)) {
1985 if (strncmp(headPtr->hmDiskName, name, strlen(name)) == 0) {
1988 * This Disk is already part of the list. Just update the
1989 * data
1992 hit = 1;
1994 strcpy(headPtr->hmDiskAliasName,alias);
1995 sprintf(headPtr->hmAvgWaitTransactions, "%3.1f\0", w_pct);
1996 sprintf(headPtr->hmDiskBusyPcnt, "%3.1f\0", r_pct);
1997 sprintf(headPtr->hmAvgDiskSvcTime, "%3.1f\0", serv);
2000 * Don't change the hmDiskState here because existing
2001 * diskState should be maintained
2004 headPtr->hmTraversed=1;
2007 headPtr = headPtr->pNext;
2009 } /* End of while loop around each row */
2011 if (hit != 1) {
2014 /* A new Disk is found in this refresh cycle . How likely ? */
2016 ptr = (hmDiskTable *) malloc(sizeof(hmDiskTable));
2018 ptr->hmDiskName = (char *) malloc(strlen(name) + 1);
2019 ptr->hmDiskAliasName = (char *) malloc(strlen(alias) + 1);
2020 ptr->hmAvgWaitTransactions = (char *) malloc(DISK_DATA_LEN);
2021 ptr->hmDiskBusyPcnt = (char *) malloc(DISK_DATA_LEN);
2022 ptr->hmAvgDiskSvcTime = (char *) malloc(DISK_DATA_LEN);
2024 if ( ptr->hmAvgDiskSvcTime == NULL) {
2025 snmp_log(LOG_DEBUG,"malloc failed when refreshing DISK table in health monitor module \n");
2026 return;
2029 strcpy(ptr->hmDiskName,name);
2031 strcpy(ptr->hmDiskAliasName,alias);
2033 sprintf(ptr->hmAvgWaitTransactions, "%3.1f\0", w_pct);
2035 sprintf(ptr->hmDiskBusyPcnt, "%3.1f\0", r_pct);
2037 sprintf(ptr->hmAvgDiskSvcTime, "%3.1f\0", serv);
2039 /* Set the state of Disk to OK. */
2041 ptr->hmDiskState = OK;
2043 /* Set Traversed to 1 */
2045 ptr->hmTraversed=1;
2048 ptr->pNext = NULL;
2050 if (tailPtr == NULL) {
2051 head = tailPtr = ptr;
2052 } else {
2054 tailPtr->pNext = ptr;
2055 tailPtr = ptr;
2059 diskCount++;
2061 } while (code == 0);
2063 /* Any disk that is not "touched" previously (i.e, has
2064 * hmTraversal value of 0, means that it's a removed disk.
2065 * Traverse through the whole list again and remove those
2066 * entries from the list.
2069 p1=head;
2070 p2=head;
2072 while( p2 != NULL) {
2074 if (p2->hmTraversed == 0) {
2076 /* Take care of removing this disk */
2078 if(p2->pNext != NULL) {
2079 p1->pNext = p2->pNext;
2080 free(p2);
2081 p2=p1->pNext;
2082 } else {
2083 p1->pNext=NULL;
2084 free(p2);
2085 p2=NULL;
2087 } else {
2089 /* Extend pointers by 1 step */
2091 if(p2->pNext != NULL) {
2093 p1=p2;
2094 p2=p2->pNext;
2095 } else {
2097 p2=p2->pNext;
2103 check_state_DISK();
2105 time(&hm_prev_disk_ref);
2110 * Function: refresh_all_HM_data. This function collects the data for all
2111 * nodes in the module and stores the data in the data variables. The
2112 * function is called every "refresh-interval" automatically. After the data
2113 * is refreshed, the alarm condition is checked and a trap is sent if the
2114 * conditions are met.
2117 void
2118 refresh_all_HM_data(unsigned int clientreg, void *clientarg)
2121 time_t hm_current_time;
2123 /* Did the previous refresh really finish ??
2124 * This means that previous refresh is still in progress */
2125 if (hm_prev_ref_time == 0) return;
2127 time(&hm_current_time);
2129 /* Did the previous refresh finish too close to start another refresh ???
2130 * This means that the previous refresh finished relatively closer to current time
2131 * so, another refresh is not necessary. hm_prev_ref_time is initialized to 1
2132 * during variable declaration. so, the first time refresh is called, it will always
2133 * proceed.
2136 /* printf("%u %u %u\n",hm_current_time, hm_prev_ref_time, hm_refresh_interval/4);*/
2137 if ( (hm_current_time - hm_prev_ref_time) < (hm_refresh_interval / 4) ) return;
2139 /* set to 0 so that we can block any other refresh's */
2140 hm_prev_ref_time = 0;
2142 /* refresh data for SWAP nodes and check alarm condition */
2144 refresh_SWAP_data();
2145 hm_handle_rule(&SWAP_rule_state, &SWAP_rule);
2147 /* Acquire data for Kernel nodes */
2149 refresh_Kernel_data();
2150 hm_handle_rule(&Kernel_rule_state, &Kernel_rule);
2152 /* Acquire data for NFS nodes */
2154 refresh_NFS_data();
2155 hm_handle_rule(&NFS_rule_state, &NFS_rule);
2157 /* Acquire data for CPU nodes */
2159 refresh_CPU_data();
2160 hm_handle_rule(&CPU_rule_state, &CPU_rule);
2162 /* Acquire data for RAM nodes */
2164 refresh_RAM_data();
2165 hm_handle_rule(&RAM_rule_state, &RAM_rule);
2167 /* Acquire data for KMEM nodes */
2169 refresh_KMEM_data();
2170 hm_handle_rule(&KMEM_rule_state, &KMEM_rule);
2172 /* Acquire data for DNLC nodes */
2174 refresh_DNLC_data();
2175 hm_handle_rule(&DNLC_rule_state, &DNLC_rule);
2177 /* End of Data acquisition for HM module */
2179 time(&hm_prev_ref_time);
2181 return;
2186 * Function: read_health_monitor_thresholds: This function is called whenever
2187 * a registered token is encountered in health_monitor.conf file. The
2188 * function simply stores the token's value in the appropriate threshold
2189 * variable.
2192 void
2193 read_health_monitor_thresholds(const char *token, char *cptr)
2196 if (strcmp(token, "hm_refresh_interval") == 0) {
2197 hm_refresh_interval = atoi(cptr);
2198 } else if (strcmp(token, "threshold_swapavail_info") == 0) {
2199 threshold_swapavail_info = atoi(cptr);
2200 } else if (strcmp(token, "threshold_swapavail_warning") == 0) {
2201 threshold_swapavail_warning = atoi(cptr);
2202 } else if (strcmp(token, "threshold_swapavail_error") == 0) {
2203 threshold_swapavail_error = atoi(cptr);
2204 } else if (strcmp(token, "threshold_mutex_info") == 0) {
2205 threshold_mutex_info = atol(cptr);
2206 } else if (strcmp(token, "threshold_mutex_warning") == 0) {
2207 threshold_mutex_warning = atol(cptr);
2208 } else if (strcmp(token, "threshold_mincalls") == 0) {
2209 threshold_mincalls = atof(cptr);
2210 } else if (strcmp(token, "threshold_badxids") == 0) {
2211 threshold_badxids = atof(cptr);
2212 } else if (strcmp(token, "threshold_timeouts") == 0) {
2213 threshold_timeouts = atof(cptr);
2214 } else if (strcmp(token, "threshold_cpuload_info") == 0) {
2215 threshold_cpuload_info = atof(cptr);
2216 } else if (strcmp(token, "threshold_cpuload_warning") == 0) {
2217 threshold_cpuload_warning = atof(cptr);
2218 } else if (strcmp(token, "threshold_cpuload_error") == 0) {
2219 threshold_cpuload_error = atof(cptr);
2220 } else if (strcmp(token, "threshold_restime_long") == 0) {
2221 threshold_restime_long = atoi(cptr);
2222 } else if (strcmp(token, "threshold_restime_ok") == 0) {
2223 threshold_restime_ok = atoi(cptr);
2224 } else if (strcmp(token, "threshold_restime_error") == 0) {
2225 threshold_restime_error = atoi(cptr);
2226 } else if (strcmp(token, "threshold_freemem_low") == 0) {
2227 threshold_freemem_low = atoi(cptr);
2228 } else if (strcmp(token, "threshold_dnlc_active") == 0) {
2229 threshold_dnlc_active = atof(cptr);
2230 } else if (strcmp(token, "threshold_dnlc_warning") == 0) {
2231 threshold_dnlc_warning = atof(cptr);
2232 } else if (strcmp(token, "disk_busy_warning") == 0) {
2233 disk_busy_warning = atol(cptr);
2234 } else if (strcmp(token, "disk_busy_problem") == 0) {
2235 disk_busy_problem = atol(cptr);
2236 } else if (strcmp(token, "disk_svc_t_warning") == 0) {
2237 disk_svc_t_warning = atol(cptr);
2238 } else if (strcmp(token, "disk_svc_t_problem") == 0) {
2239 disk_svc_t_problem = atol(cptr);
2240 } else {
2241 /* Do nothing */
2245 return;
2249 * hm_handle_rule:
2251 * arguments: rule_state = previous state of the rule rule = Function
2252 * pointer to the actual rule
2254 * This function first determines the new state of the rule by calling
2255 * rule(CONDITION).
2257 * In the switch loop, depending on the previous rule state (the rule_state) and
2258 * new state, the rule function is again called appropriately. For example,
2259 * if the previous state is INIT and the new state is > OK, then rule(OPEN)
2260 * is called.
2265 void
2266 hm_handle_rule(int *rule_state, int (*rule) (int))
2269 int new_alarm_state;
2271 if (*rule_state == NOTINIT) {
2272 *rule_state = INIT;
2273 rule(INIT);
2275 new_alarm_state = rule(CONDITION);
2277 switch (*rule_state) {
2279 case INIT:
2280 if (new_alarm_state > OK) {
2281 *rule_state = OPEN;
2282 rule(OPEN);
2284 return;
2285 case OPEN:
2286 if (new_alarm_state == OK) {
2287 *rule_state = CLOSE;
2288 rule(CLOSE);
2289 } else {
2290 *rule_state = CONTINUE;
2291 rule(CONTINUE);
2293 return;
2294 case CONTINUE:
2295 if (new_alarm_state == OK) {
2296 *rule_state = CLOSE;
2297 rule(CLOSE);
2298 } else {
2299 *rule_state = CONTINUE;
2300 rule(CONTINUE);
2302 return;
2303 case CLOSE:
2304 if (new_alarm_state > OK) {
2305 *rule_state = OPEN;
2306 rule(OPEN);
2308 return;
2315 * Function: send_trap : This function sends a *statusChange* trap with
2316 * appropriate varbind's see SMA trap mib for detailed trap notification
2317 * definition.
2319 * hostname - Name of host on which alarm occured ; modulename - Name of the
2320 * module generating the trap ; moduleContext - The context of the module, if
2321 * any; statusOID - The trapoid; size - The size of trapoid (not included in
2322 * the trap); status - status of the node; description - description of the
2323 * trap; dvalue - value of the node on which trap occured; dtype - data type of
2324 * the value
2327 void
2328 send_trap(u_char * hostname, u_char * modulename, u_char * moduleContext, oid * trapoid, int size, u_char * status, u_char * description, u_char * dvalue, int dtype)
2331 /* This is the notification type itself. This is statusChange trap */
2333 oid notification_oid[] = {1, 3, 6, 1, 4, 1, 42, 2, 2, 4, 3, 0, 1};
2335 size_t notification_oid_len = OID_LENGTH(notification_oid);
2338 * In the notification, we have to assign our notification OID to the
2339 * snmpTrapOID.0 object. Here is it's definition.
2342 oid objid_snmptrap[] = {1, 3, 6, 1, 6, 3, 1, 1, 4, 1, 0};
2343 size_t objid_snmptrap_len = OID_LENGTH(objid_snmptrap);
2346 * here is where we store the variables to be sent in the trap
2349 netsnmp_variable_list *notification_vars = NULL;
2351 oid hostname_oid[] = {1, 3, 6, 1, 4, 1, 42, 2, 2, 4, 3, 1, 1, 0};
2353 size_t hostname_oid_len = OID_LENGTH(hostname_oid);
2356 oid modulename_oid[] = {1, 3, 6, 1, 4, 1, 42, 2, 2, 4, 3, 1, 2, 0};
2358 size_t modulename_oid_len = OID_LENGTH(modulename_oid);
2361 oid nodeoid_oid[] = {1, 3, 6, 1, 4, 1, 42, 2, 2, 4, 3, 1, 3, 0};
2363 size_t nodeoid_oid_len = OID_LENGTH(nodeoid_oid);
2366 oid moduleContext_oid[] = {1, 3, 6, 1, 4, 1, 42, 2, 2, 4, 3, 1, 4, 0};
2368 size_t moduleContext_oid_len = OID_LENGTH(moduleContext_oid);
2371 oid status_oid[] = {1, 3, 6, 1, 4, 1, 42, 2, 2, 4, 3, 1, 5, 0};
2373 size_t status_oid_len = OID_LENGTH(status_oid);
2376 oid description_oid[] = {1, 3, 6, 1, 4, 1, 42, 2, 2, 4, 3, 1, 6, 0};
2378 size_t description_oid_len = OID_LENGTH(description_oid);
2380 oid dvalue_oid[] = {1, 3, 6, 1, 4, 1, 42, 2, 2, 4, 3, 1, 7, 0};
2382 size_t dvalue_oid_len = OID_LENGTH(dvalue_oid);
2384 oid dtype_oid[] = {1, 3, 6, 1, 4, 1, 42, 2, 2, 4, 3, 1, 8, 0};
2386 size_t dtype_oid_len = OID_LENGTH(dtype_oid);
2390 * add in the trap definition object
2393 snmp_varlist_add_variable(&notification_vars,
2395 * the snmpTrapOID.0 variable
2397 objid_snmptrap, objid_snmptrap_len,
2399 * value type is an OID
2401 ASN_OBJECT_ID,
2403 * value contents is our notification OID
2405 (u_char *) notification_oid,
2407 * size in bytes = oid length * sizeof(oid)
2409 notification_oid_len * sizeof(oid));
2413 * if we wanted to insert additional objects, we'd do it here
2417 snmp_varlist_add_variable(&notification_vars,
2418 hostname_oid, hostname_oid_len,
2420 * value type is an OID
2422 ASN_OCTET_STR,
2424 * value contents is our notification OID
2426 (u_char *) hostname,
2428 * size in bytes = oid length * sizeof(oid)
2430 strlen((char *) hostname));
2433 snmp_varlist_add_variable(&notification_vars,
2434 modulename_oid, modulename_oid_len,
2436 * value type is an OID
2438 ASN_OCTET_STR,
2440 * value contents is our notification OID
2442 (u_char *) modulename,
2444 * size in bytes = oid length * sizeof(oid)
2446 strlen((char *) modulename));
2449 snmp_varlist_add_variable(&notification_vars,
2450 nodeoid_oid, nodeoid_oid_len,
2452 * value type is an OID
2454 ASN_OBJECT_ID,
2456 * value contents is our notification OID
2458 (u_char *) trapoid,
2460 * size in bytes = oid length * sizeof(oid)
2462 size * sizeof(oid));
2465 snmp_varlist_add_variable(&notification_vars,
2466 moduleContext_oid, moduleContext_oid_len,
2468 * value type is an OID
2470 ASN_OCTET_STR,
2472 * value contents is our notification OID
2474 (u_char *) moduleContext,
2476 * size in bytes = oid length * sizeof(oid)
2478 strlen((char *) moduleContext));
2481 snmp_varlist_add_variable(&notification_vars,
2482 status_oid, status_oid_len,
2484 * value type is an OID
2486 ASN_OCTET_STR,
2488 * value contents is our notification OID
2490 (u_char *) status,
2492 * size in bytes = oid length * sizeof(oid)
2494 strlen((char *) status));
2497 snmp_varlist_add_variable(&notification_vars,
2498 description_oid, description_oid_len,
2500 * value type is an OID
2502 ASN_OCTET_STR,
2504 * value contents is our notification OID
2506 (u_char *) description,
2508 * size in bytes = oid length * sizeof(oid)
2510 strlen((char *) description));
2513 snmp_varlist_add_variable(&notification_vars,
2514 dvalue_oid, dvalue_oid_len,
2516 * value type is an OID
2518 ASN_OCTET_STR,
2520 * value contents is our notification OID
2522 (u_char *) dvalue,
2524 * size in bytes = oid length * sizeof(oid)
2526 strlen((char *) dvalue));
2530 snmp_varlist_add_variable(&notification_vars,
2531 dtype_oid, dtype_oid_len,
2533 * value type is an OID
2535 ASN_INTEGER,
2537 * value contents is our notification OID
2539 (u_char *) & dtype,
2541 * size in bytes = oid length * sizeof(oid)
2543 sizeof(dtype));
2546 /* SEND THE TRAP !!!! */
2548 send_v2trap(notification_vars);
2551 * free the created notification variable list
2554 DEBUGMSGTL(("example_notification", "cleaning up\n"));
2555 snmp_free_varbind(notification_vars);
2557 return;
2562 * Function: conv_alarm_state : This function returns appropriate charecter
2563 * string for each integer alarm type
2566 char *
2567 conv_alarm_state(int state)
2569 switch (state) {
2570 case OK:
2571 return "OK\0";
2572 case INFO:
2573 return "INFO\0";
2574 case WARNING:
2575 return "WARNING\0";
2576 case ERROR:
2577 return "ERROR\0";
2578 default:
2579 return "INVALID\0";
2586 * Function: SWAP_rule : This function checks the state of SWAP nodes and
2587 * issues trap if necessary
2590 int
2591 SWAP_rule(int action)
2594 /* This is the OID of hmAvailableSwapSpace */
2595 oid trapoid[] = {1, 3, 6, 1, 4, 1, 42, 2, 12, 2, 2, 11, 1, 1, 1, 0};
2596 u_char status[8];
2597 u_char description[] = "Available Swap space on the system is low";
2598 int size;
2599 u_char dvalue[15];
2600 /* The value of dtype is 1 here becuase swapavail_data is of "int" type */
2601 int dtype = 1;
2603 sprintf((char *) dvalue, "%d\0", swapavail_data);
2604 size = sizeof(trapoid) / sizeof(oid);
2606 switch (action) {
2608 case CONDITION:
2611 * Quite straightforward. Depending on the threshold that is crossed,
2612 * assign the new state
2615 if ((swapavail_data <= threshold_swapavail_info) && (swapavail_data > threshold_swapavail_warning)) {
2616 new_SWAP_state = INFO;
2617 return INFO;
2618 } else if ((swapavail_data <= threshold_swapavail_warning) && (swapavail_data > threshold_swapavail_error)) {
2619 new_SWAP_state = WARNING;
2620 return WARNING;
2621 } else if (swapavail_data <= threshold_swapavail_error) {
2622 new_SWAP_state = ERROR;
2623 return ERROR;
2625 new_SWAP_state = OK;
2626 return OK;
2628 case OPEN:
2630 strcpy((char *) status, conv_alarm_state(new_SWAP_state));
2631 send_trap(hostName, moduleName, statusOIDContext, trapoid, size, status, description, dvalue, dtype);
2632 return 0;
2634 case INIT:
2636 return 0;
2638 case CONTINUE:
2640 strcpy((char *) status, conv_alarm_state(new_SWAP_state));
2641 if (new_SWAP_state > prev_SWAP_state) {
2643 /* Send trap */
2644 send_trap(hostName, moduleName, statusOIDContext, trapoid, size, status, description, dvalue, dtype);
2645 prev_SWAP_state = new_SWAP_state;
2648 return 0;
2650 case CLOSE:
2652 strcpy((char *) status, conv_alarm_state(new_SWAP_state));
2653 send_trap(hostName, moduleName, statusOIDContext, trapoid, size, status, description, dvalue, dtype);
2654 return 0;
2656 default:
2658 return 0;
2664 * Function: Kernel_rule : This function checks the state of Kernel nodes and
2665 * issues trap if necessary
2668 int
2669 Kernel_rule(int action)
2672 int mutexrate;
2674 /* This is the OID of hmSpinsOnMutexes */
2675 oid trapoid[] = {1, 3, 6, 1, 4, 1, 42, 2, 12, 2, 2, 11, 2, 1, 1, 0};
2676 u_char status[8];
2677 u_char description[] = "Mutex contention rate is high , kernel overload \0";
2678 int size;
2679 u_char dvalue[15];
2681 * dtype is set to 1 because the hmSpinsOnMutexes node is defined as
2682 * Integer32 in the mib
2684 int dtype = 1;
2686 sprintf((char *) dvalue, "%lu\0", sum_smtx);
2687 size = sizeof(trapoid) / sizeof(oid);
2689 switch (action) {
2691 case CONDITION:
2693 if (ncpus == 0) {
2694 /* this happens only during initialization */
2695 new_mutex_state = OK;
2696 return OK;
2698 mutexrate = sum_smtx / ncpus;
2700 /* Determine if there is a new Alarm state */
2702 if (mutexrate < threshold_mutex_info) {
2703 if (mutexrate == 0) {
2706 * This is a change from existing rule. It makes more sense
2707 * that if mutexrate is 0, then the state should be OK. i.e,
2708 * no problems
2711 new_mutex_state = OK;
2712 return OK;
2714 } else {
2715 new_mutex_state = INFO;
2716 return INFO;
2718 } else if (mutexrate < threshold_mutex_warning) {
2719 new_mutex_state = WARNING;
2720 return WARNING;
2721 } else {
2722 new_mutex_state = ERROR;
2723 return WARNING;
2726 case OPEN:
2728 strcpy((char *) status, conv_alarm_state(new_mutex_state));
2729 send_trap(hostName, moduleName, statusOIDContext, trapoid, size, status, description, dvalue, dtype);
2730 return 0;
2732 case INIT:
2734 return 0;
2736 case CONTINUE:
2738 strcpy((char *) status, conv_alarm_state(new_mutex_state));
2740 if (new_mutex_state > prev_mutex_state) {
2742 /* Send trap */
2743 send_trap(hostName, moduleName, statusOIDContext, trapoid, size, status, description, dvalue, dtype);
2744 prev_mutex_state = new_mutex_state;
2747 return 0;
2749 case CLOSE:
2751 strcpy((char *) status, conv_alarm_state(new_mutex_state));
2752 send_trap(hostName, moduleName, statusOIDContext, trapoid, size, status, description, dvalue, dtype);
2753 return 0;
2755 default:
2757 return 0;
2763 * Function: NFS_rule : This function checks the state of NFS nodes and
2764 * issues trap if necessary
2767 int
2768 NFS_rule(int action)
2771 float maxtimeout, maxbadxid;
2774 * This is the OID of hmNFSClientRPCGroup. Note that this rule uses data
2775 * from more than one node to determine the alarm state
2777 oid trapoid[] = {1, 3, 6, 1, 4, 1, 42, 2, 12, 2, 2, 11, 3, 1};
2778 u_char status[8];
2779 u_char description[] = "Bad Network or Server is slow. May need to increase timeout \0 ";
2780 int size;
2781 u_char dvalue[15];
2782 int dtype = 1;
2785 * It's tricky which "value" should be put in dvalue field. More than one
2786 * node's data is looked at to determine alarm state.
2788 sprintf((char *) dvalue, "%d\0", timeouts);
2789 size = sizeof(trapoid) / sizeof(oid);
2791 switch (action) {
2793 case CONDITION:
2795 if (calls <= threshold_mincalls) {
2797 * This is a change from existing rule (which has INFO). It makes
2798 * sense that no trap is sent when calls is < threshold_mincalls.
2801 new_NFS_state = OK;
2802 return OK;
2803 } else {
2804 maxtimeout = threshold_timeouts * calls / 100.0;
2806 if (timeouts < maxtimeout) {
2809 * This is a change from existing rule (which has INFO). It
2810 * makes sense that no trap is sent when timeouts is <
2811 * maxtimeout
2814 new_NFS_state = OK;
2815 return OK;
2817 } else {
2818 maxbadxid = threshold_badxids * timeouts / 100.0;
2819 if ((maxtimeout <= timeouts) && (badxids <= maxbadxid)) {
2820 new_NFS_state = WARNING;
2821 return WARNING;
2822 } else {
2824 * This will be the case when timeout >= maxtimeout AND
2825 * badxids > maxbadxid
2827 new_NFS_state = ERROR;
2828 return ERROR;
2833 case OPEN:
2835 strcpy((char *) status, conv_alarm_state(new_NFS_state));
2836 send_trap(hostName, moduleName, statusOIDContext, trapoid, size, status, description, dvalue, dtype);
2837 return 0;
2839 case INIT:
2841 return 0;
2843 case CONTINUE:
2845 strcpy((char *) status, conv_alarm_state(new_NFS_state));
2846 if (new_NFS_state > prev_NFS_state) {
2848 /* Send trap */
2849 send_trap(hostName, moduleName, statusOIDContext, trapoid, size, status, description, dvalue, dtype);
2850 prev_NFS_state = new_NFS_state;
2853 return 0;
2855 case CLOSE:
2857 strcpy((char *) status, conv_alarm_state(new_NFS_state));
2858 send_trap(hostName, moduleName, statusOIDContext, trapoid, size, status, description, dvalue, dtype);
2859 return 0;
2861 default:
2863 return 0;
2869 * Function: CPU_rule : This function checks the state of CPU nodes and
2870 * issues trap if necessary
2873 int
2874 CPU_rule(int action)
2877 /* This is the OID for hmTotProcInRunQueue */
2878 oid trapoid[] = {1, 3, 6, 1, 4, 1, 42, 2, 12, 2, 2, 11, 4, 1, 1, 0};
2879 u_char status[8];
2880 u_char description[] = "CPU overloaded \0";
2881 int size;
2882 u_char dvalue[15];
2883 /* dtype is given a value of 1 because runque is of "int" type */
2884 int dtype = 1;
2886 float cpuload;
2888 sprintf((char *) dvalue, "%d\0", runque);
2889 size = sizeof(trapoid) / sizeof(oid);
2891 switch (action) {
2893 case CONDITION:
2896 * Added this If statement to existing rule. From Kernel_rule, it
2897 * looks like ncpus may be 0 during initialization
2899 if (ncpus == 0) {
2900 /* this happens only during initialization */
2901 new_cpuload_state = OK;
2902 return OK;
2904 cpuload = runque / ncpus;
2907 * Quite straightforward. If the threshold is crossed, set the state
2908 * accordingly
2911 if (cpuload < threshold_cpuload_info) {
2912 new_cpuload_state = OK;
2913 return OK;
2914 } else if (cpuload < threshold_cpuload_warning) {
2915 new_cpuload_state = INFO;
2916 return INFO;
2917 } else if (cpuload < threshold_cpuload_error) {
2918 new_cpuload_state = WARNING;
2919 return WARNING;
2920 } else {
2921 new_cpuload_state = ERROR;
2922 return ERROR;
2925 case OPEN:
2927 strcpy((char *) status, conv_alarm_state(new_cpuload_state));
2928 send_trap(hostName, moduleName, statusOIDContext, trapoid, size, status, description, dvalue, dtype);
2929 return 0;
2931 case INIT:
2933 return 0;
2935 case CONTINUE:
2937 strcpy((char *) status, conv_alarm_state(new_cpuload_state));
2938 if (new_cpuload_state > prev_cpuload_state) {
2940 /* Send trap */
2941 send_trap(hostName, moduleName, statusOIDContext, trapoid, size, status, description, dvalue, dtype);
2942 prev_cpuload_state = new_cpuload_state;
2945 return 0;
2947 case CLOSE:
2949 strcpy((char *) status, conv_alarm_state(new_cpuload_state));
2950 send_trap(hostName, moduleName, statusOIDContext, trapoid, size, status, description, dvalue, dtype);
2951 return 0;
2953 default:
2955 return 0;
2961 * Function: RAM_rule : This function checks the state of RAM nodes and
2962 * issues trap if necessary
2965 int
2966 RAM_rule(int action)
2970 * This is the OID of hmRamMemoryPagingGroup. Note that this rule uses
2971 * data from more than one node to determine the alarm state
2973 oid trapoid[] = {1, 3, 6, 1, 4, 1, 42, 2, 12, 2, 2, 11, 6, 1};
2974 u_char status[8];
2975 u_char description[] = "RAM shortage \0";
2976 int size;
2977 u_char dvalue[15];
2979 /* dtype is given a value of 1 because scan is of "int" type */
2980 int dtype = 1;
2982 float restime;
2985 * It's tricky which "value" should be put in dvalue field. More than one
2986 * node's data is looked at to determine alarm state.
2988 sprintf((char *) dvalue, "%d\0", scan);
2990 size = sizeof(trapoid) / sizeof(oid);
2992 switch (action) {
2994 case CONDITION:
2996 if (scan == 0) {
2997 restime = threshold_restime_long;
2998 } else {
2999 restime = handspread / scan;
3002 if (restime > threshold_restime_long) {
3003 restime = threshold_restime_long;
3005 if (restime >= threshold_restime_long) {
3006 /* This is a change from existing rule (which has INFO). */
3008 new_restime_state = OK;
3009 return OK;
3010 } else {
3011 if (restime > threshold_restime_ok) {
3012 new_restime_state = INFO;
3013 return INFO;
3014 } else {
3015 if (restime > threshold_restime_error) {
3016 new_restime_state = WARNING;
3017 return WARNING;
3018 } else {
3019 new_restime_state = ERROR;
3020 return ERROR;
3025 case OPEN:
3027 strcpy((char *) status, conv_alarm_state(new_restime_state));
3028 send_trap(hostName, moduleName, statusOIDContext, trapoid, size, status, description, dvalue, dtype);
3029 return 0;
3031 case INIT:
3033 return 0;
3035 case CONTINUE:
3037 strcpy((char *) status, conv_alarm_state(new_restime_state));
3038 if (new_restime_state > prev_restime_state) {
3040 /* Send trap */
3041 send_trap(hostName, moduleName, statusOIDContext, trapoid, size, status, description, dvalue, dtype);
3042 prev_restime_state = new_restime_state;
3045 return 0;
3047 case CLOSE:
3049 strcpy((char *) status, conv_alarm_state(new_restime_state));
3050 send_trap(hostName, moduleName, statusOIDContext, trapoid, size, status, description, dvalue, dtype);
3051 return 0;
3053 default:
3055 return 0;
3061 * Function: KMEM_rule : This function checks the state of KMEM nodes and
3062 * issues trap if necessary
3065 int
3066 KMEM_rule(int action)
3070 * This is the OID of hmKmemStatisticsGroup. Note that this rule uses
3071 * data from more than one node to determine the alarm state
3073 oid trapoid[] = {1, 3, 6, 1, 4, 1, 42, 2, 12, 2, 2, 11, 7, 1};
3074 u_char status[8];
3075 u_char description[] = "Kernel Memory allocation errors \0";
3076 int size;
3077 u_char dvalue[15];
3078 /* dtype is given a value of 1 because alloc_fail is of "int" type */
3079 int dtype = 1;
3081 int firsterrs, lasterrs;
3084 * It's tricky which "value" should be put in dvalue field. More than one
3085 * node's data is looked at to determine alarm state.
3087 sprintf((char *) dvalue, "%d\0", alloc_fail);
3089 size = sizeof(trapoid) / sizeof(oid);
3091 switch (action) {
3093 case CONDITION:
3095 /* This is a slightly confusing rule */
3097 firsterrs = firstkmemerrs;
3098 lasterrs = lastkmemerrs;
3100 if (alloc_fail == firsterrs) {
3101 if (alloc_fail == 0) {
3103 * This is a change from existing rule (which has INFO). It
3104 * makes sense that an OK state should be returned when
3105 * alloc_fail is 0
3107 new_kmem_state = OK;
3108 return OK;
3109 } else {
3110 new_kmem_state = INFO;
3111 return INFO;
3113 } else {
3114 if (alloc_fail == lasterrs) {
3115 new_kmem_state = WARNING;
3116 return WARNING;
3117 } else {
3118 new_kmem_state = ERROR;
3119 lastkmemerrs = alloc_fail;
3120 if (mem_free > threshold_freemem_low) {
3122 * Kernel memory allocation problem. The state is already
3123 * set to ERROR.
3125 } else {
3127 * Kernel memory allocation problem. The state is already
3128 * set to ERROR.
3131 return ERROR;
3135 case OPEN:
3137 firstkmemerrs = alloc_fail;
3138 lastkmemerrs = alloc_fail;
3139 strcpy((char *) status, conv_alarm_state(new_kmem_state));
3140 send_trap(hostName, moduleName, statusOIDContext, trapoid, size, status, description, dvalue, dtype);
3141 return 0;
3143 case INIT:
3145 firstkmemerrs = 0;
3146 lastkmemerrs = 0;
3147 return 0;
3149 case CONTINUE:
3151 strcpy((char *) status, conv_alarm_state(new_kmem_state));
3152 if (new_kmem_state > prev_kmem_state) {
3154 /* Send trap */
3155 send_trap(hostName, moduleName, statusOIDContext, trapoid, size, status, description, dvalue, dtype);
3156 prev_kmem_state = new_kmem_state;
3159 return 0;
3161 case CLOSE:
3163 strcpy((char *) status, conv_alarm_state(new_kmem_state));
3164 send_trap(hostName, moduleName, statusOIDContext, trapoid, size, status, description, dvalue, dtype);
3165 return 0;
3167 default:
3169 return 0;
3175 * Function: DNLC_rule : This function checks the state of DNLC nodes and
3176 * issues trap if necessary
3179 int
3180 DNLC_rule(int action)
3183 /* This is the OID for hmDNLCStatGroup */
3184 oid trapoid[] = {1, 3, 6, 1, 4, 1, 42, 2, 12, 2, 2, 11, 8, 1};
3185 u_char status[8];
3186 u_char description[] = "Poor DNLC Hit rate \0";
3187 int size;
3188 u_char dvalue[15];
3189 /* dtype is given a value of 1 because hitrate is of "int" type */
3190 int dtype = 1;
3193 * It's tricky which "value" should be put in dvalue field. More than one
3194 * node's data is looked at to determine alarm state.
3196 sprintf((char *) dvalue, "%d\0", hitrate);
3198 size = sizeof(trapoid) / sizeof(oid);
3200 switch (action) {
3202 case CONDITION:
3205 * Changed the rule from existing rule. Used OK instead of INFO when
3206 * there is no problem
3209 if (refrate < threshold_dnlc_active) {
3210 new_dnlc_state = OK;
3211 return OK;
3212 } else {
3213 if (hitrate > threshold_dnlc_warning) {
3214 new_dnlc_state = OK;
3215 return OK;
3216 } else {
3217 new_dnlc_state = WARNING;
3218 return WARNING;
3223 case OPEN:
3225 strcpy((char *) status, conv_alarm_state(new_dnlc_state));
3226 send_trap(hostName, moduleName, statusOIDContext, trapoid, size, status, description, dvalue, dtype);
3227 return 0;
3229 case INIT:
3231 return 0;
3233 case CONTINUE:
3235 strcpy((char *) status, conv_alarm_state(new_dnlc_state));
3236 if (new_dnlc_state > prev_dnlc_state) {
3238 /* Send trap */
3239 send_trap(hostName, moduleName, statusOIDContext, trapoid, size, status, description, dvalue, dtype);
3240 prev_dnlc_state = new_dnlc_state;
3243 return 0;
3245 case CLOSE:
3247 strcpy((char *) status, conv_alarm_state(new_dnlc_state));
3248 send_trap(hostName, moduleName, statusOIDContext, trapoid, size, status, description, dvalue, dtype);
3249 return 0;
3251 default:
3253 return 0;
3258 void
3259 check_state_DISK()
3262 /* TRAP STUFF */
3264 oid *trapoid;
3265 u_char status[8];
3266 u_char description[] = "Disk Loaded \0";
3269 * A value of 12 is given to dtype because the diskName is of
3270 * "DisplayString" type. Disk Name is used for dvalue because multiple
3271 * values are used to determine trap state. No single value can be used
3274 int dtype = 12;
3276 /* Maintain a pointer to diskTable called headPtr */
3278 hmDiskTable *headPtr;
3279 int nameSize;
3280 headPtr = head;
3282 /* For each row in the table, determine if there is a new Alarm Condition */
3284 while (headPtr != NULL) {
3286 /* For each disk, set the new state back to OK again */
3287 int new_disk_state = OK;
3288 int i;
3290 long wait = atol(headPtr->hmAvgWaitTransactions);
3291 long svcTime = atol(headPtr->hmAvgDiskSvcTime);
3292 long busyTime = atol(headPtr->hmDiskBusyPcnt);
3294 /* For cases where busyTime < disk_busy_warning, svcTime < disk_svc_t_warning,
3295 state is set to OK instead of INFO (as in existing rule);
3298 if (busyTime < disk_busy_warning) {
3299 new_disk_state = OK;
3300 } else {
3301 if (svcTime < disk_svc_t_warning) {
3302 new_disk_state = OK;
3303 } else {
3304 if (disk_busy_problem <= busyTime) {
3305 if ((disk_svc_t_warning <= svcTime) && (svcTime < disk_svc_t_problem)) {
3306 new_disk_state = WARNING;
3307 } else {
3308 if (disk_svc_t_problem <= svcTime) {
3309 new_disk_state = ERROR;
3312 } else {
3313 new_disk_state = WARNING;
3319 nameSize = strlen(headPtr->hmDiskName);
3322 * Compose the trap OID here. It is:
3323 * 1.3.6.1.4.1.42.2.12.2.2.11.5.1.1.1.<size-of-index>.index
3326 trapoid = malloc((16 * sizeof(oid)) + sizeof(oid) + (nameSize * sizeof(oid)));
3328 if ( trapoid == NULL) {
3329 snmp_log(LOG_DEBUG,"malloc failed when constructing trapoid in health monitor module \n");
3330 return;
3333 trapoid[0] = 1;
3334 trapoid[1] = 3;
3335 trapoid[2] = 6;
3336 trapoid[3] = 1;
3337 trapoid[4] = 4;
3338 trapoid[5] = 1;
3339 trapoid[6] = 42;
3340 trapoid[7] = 2;
3341 trapoid[8] = 12;
3342 trapoid[9] = 2;
3343 trapoid[10] = 2;
3344 trapoid[11] = 11;
3345 trapoid[12] = 5;
3346 trapoid[13] = 1;
3347 trapoid[14] = 1;
3348 trapoid[15] = 1;
3350 trapoid[16] = nameSize;
3352 for (i = 1; i <= nameSize; i++) {
3353 trapoid[16 + i] = headPtr->hmDiskName[i - 1];
3356 /* Depending on the new state, send trap if necessary */
3358 if (new_disk_state > headPtr->hmDiskState) {
3360 /* Send trap */
3361 strcpy((char *) status, conv_alarm_state(new_disk_state));
3362 send_trap(hostName, moduleName, statusOIDContext, trapoid, 17 + nameSize, status, description, (u_char *) headPtr->hmDiskName, dtype);
3363 headPtr->hmDiskState = new_disk_state;
3365 } else if (new_disk_state == headPtr->hmDiskState) {
3367 /* No Change in state .. Do nothing */
3369 } else if (new_disk_state < headPtr->hmDiskState) {
3371 if (new_disk_state == OK) {
3373 /* Send OK trap */
3374 strcpy((char *) status, conv_alarm_state(new_disk_state));
3375 send_trap(hostName, moduleName, statusOIDContext, trapoid, 17 + nameSize, status, description, (u_char *) headPtr->hmDiskName, dtype);
3376 headPtr->hmDiskState = OK;
3381 headPtr = headPtr->pNext;
3383 } /* End of while loop that traverses each row */
3386 return;