3 * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
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.
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"
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
,
51 /* Data for Kernel node */
55 /* Data for NFS node */
57 int badcalls
, retrans
, badxids
, timeouts
, newcreds
, badverfs
,
58 timers
, nomem
, cantsend
, interrupts
;
61 /* Data for CPU node */
62 int runque
, waiting
, swapque
;
64 /* Data for RAM node */
68 * Data for KMEM node . Only alloc_fail and mem_free are published through
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
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
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
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 */
180 init_healthMonitor(void)
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
217 get_hmSpinsOnMutexes
,
218 hmSpinsOnMutexes_oid
,
219 OID_LENGTH(hmSpinsOnMutexes_oid
),
221 netsnmp_register_read_only_instance(netsnmp_create_handler_registration
222 ("hmTotProcInRunQueue",
223 get_hmTotProcInRunQueue
,
224 hmTotProcInRunQueue_oid
,
225 OID_LENGTH(hmTotProcInRunQueue_oid
),
227 netsnmp_register_read_only_instance(netsnmp_create_handler_registration
231 OID_LENGTH(hmTotRPCCalls_oid
),
233 netsnmp_register_read_only_instance(netsnmp_create_handler_registration
237 OID_LENGTH(hmUsedSwapSpace_oid
),
239 netsnmp_register_read_only_instance(netsnmp_create_handler_registration
243 OID_LENGTH(hmDNLCMisses_oid
),
245 netsnmp_register_read_only_instance(netsnmp_create_handler_registration
246 ("hmReservedSwapSpace",
247 get_hmReservedSwapSpace
,
248 hmReservedSwapSpace_oid
,
249 OID_LENGTH(hmReservedSwapSpace_oid
),
251 netsnmp_register_read_only_instance(netsnmp_create_handler_registration
252 ("hmTotMemAllocFails",
253 get_hmTotMemAllocFails
,
254 hmTotMemAllocFails_oid
,
255 OID_LENGTH(hmTotMemAllocFails_oid
),
257 netsnmp_register_read_only_instance(netsnmp_create_handler_registration
258 ("hmAvailableSwapSpace",
259 get_hmAvailableSwapSpace
,
260 hmAvailableSwapSpace_oid
,
261 OID_LENGTH(hmAvailableSwapSpace_oid
),
263 netsnmp_register_read_only_instance(netsnmp_create_handler_registration
267 OID_LENGTH(hmDNLCHitRate_oid
),
269 netsnmp_register_read_only_instance(netsnmp_create_handler_registration
273 OID_LENGTH(hmDNLCHits_oid
),
275 netsnmp_register_read_only_instance(netsnmp_create_handler_registration
276 ("hmAllocatedSwapSpace",
277 get_hmAllocatedSwapSpace
,
278 hmAllocatedSwapSpace_oid
,
279 OID_LENGTH(hmAllocatedSwapSpace_oid
),
281 netsnmp_register_read_only_instance(netsnmp_create_handler_registration
285 OID_LENGTH(hmTotNumOfCPUs_oid
),
287 netsnmp_register_read_only_instance(netsnmp_create_handler_registration
291 OID_LENGTH(hmPageScanRate_oid
),
293 netsnmp_register_read_only_instance(netsnmp_create_handler_registration
297 OID_LENGTH(hmTimers_oid
),
299 netsnmp_register_read_only_instance(netsnmp_create_handler_registration
301 get_hmTotBadRPCCalls
,
302 hmTotBadRPCCalls_oid
,
303 OID_LENGTH(hmTotBadRPCCalls_oid
),
305 netsnmp_register_read_only_instance(netsnmp_create_handler_registration
309 OID_LENGTH(hmDNLCRefRate_oid
),
311 netsnmp_register_read_only_instance(netsnmp_create_handler_registration
315 OID_LENGTH(hmTotSendFails_oid
),
317 netsnmp_register_read_only_instance(netsnmp_create_handler_registration
318 ("hmTotFailedCallsBV",
319 get_hmTotFailedCallsBV
,
320 hmTotFailedCallsBV_oid
,
321 OID_LENGTH(hmTotFailedCallsBV_oid
),
323 netsnmp_register_read_only_instance(netsnmp_create_handler_registration
324 ("hmTotNumOfAuthRefresh",
325 get_hmTotNumOfAuthRefresh
,
326 hmTotNumOfAuthRefresh_oid
,
327 OID_LENGTH(hmTotNumOfAuthRefresh_oid
),
329 netsnmp_register_read_only_instance(netsnmp_create_handler_registration
333 OID_LENGTH(hmHandspread_oid
),
335 netsnmp_register_read_only_instance(netsnmp_create_handler_registration
336 ("hmTotRPCRetransmissions",
337 get_hmTotRPCRetransmissions
,
338 hmTotRPCRetransmissions_oid
,
339 OID_LENGTH(hmTotRPCRetransmissions_oid
),
341 netsnmp_register_read_only_instance(netsnmp_create_handler_registration
345 OID_LENGTH(hmKmemFreeMem_oid
),
347 netsnmp_register_read_only_instance(netsnmp_create_handler_registration
348 ("hmTotBadRPCReplies",
349 get_hmTotBadRPCReplies
,
350 hmTotBadRPCReplies_oid
,
351 OID_LENGTH(hmTotBadRPCReplies_oid
),
353 netsnmp_register_read_only_instance(netsnmp_create_handler_registration
357 OID_LENGTH(hmKmemErrors_oid
),
359 netsnmp_register_read_only_instance(netsnmp_create_handler_registration
360 ("hmTotProcReadyInSwap",
361 get_hmTotProcReadyInSwap
,
362 hmTotProcReadyInSwap_oid
,
363 OID_LENGTH(hmTotProcReadyInSwap_oid
),
365 netsnmp_register_read_only_instance(netsnmp_create_handler_registration
367 get_hmTotProcBlocked
,
368 hmTotProcBlocked_oid
,
369 OID_LENGTH(hmTotProcBlocked_oid
),
371 netsnmp_register_read_only_instance(netsnmp_create_handler_registration
372 ("hmTotRPCCallsTimedOut",
373 get_hmTotRPCCallsTimedOut
,
374 hmTotRPCCallsTimedOut_oid
,
375 OID_LENGTH(hmTotRPCCallsTimedOut_oid
),
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
);
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 */
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",
500 OID_LENGTH(hmDiskTable_oid
),
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
) {
551 snmp_set_var_typed_value(requests
->requestvb
, ASN_INTEGER
, (u_char
*) & sum_smtx
, sizeof(sum_smtx
));
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.
580 switch (reqinfo
->mode
) {
584 runque_long
= (long) runque
;
585 snmp_set_var_typed_value(requests
->requestvb
, ASN_INTEGER
, (u_char
*) & runque_long
, sizeof(runque_long
));
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
) {
616 snmp_set_var_typed_value(requests
->requestvb
, ASN_OCTET_STR
, (u_char
*) callsStr
, strlen(callsStr
) );
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
) {
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
));
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
) {
681 snmp_set_var_typed_value(requests
->requestvb
, ASN_UNSIGNED
, (u_char
*) & misses
, sizeof(misses
));
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
) {
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
));
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.
744 switch (reqinfo
->mode
) {
748 nomem_long
= (long) nomem
;
749 snmp_set_var_typed_value(requests
->requestvb
, ASN_INTEGER
, (u_char
*) & nomem_long
, sizeof(nomem_long
));
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
;
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
));
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
) {
815 snmp_set_var_typed_value(requests
->requestvb
, ASN_UNSIGNED
, (u_char
*) & hitrate
, sizeof(hitrate
));
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
) {
846 snmp_set_var_typed_value(requests
->requestvb
, ASN_UNSIGNED
, (u_char
*) & hits
, sizeof(hits
));
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
) {
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
));
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.
911 switch (reqinfo
->mode
) {
915 ncpus_long
= (long)ncpus
;
916 snmp_set_var_typed_value(requests
->requestvb
, ASN_INTEGER
, (u_char
*) & ncpus_long
, sizeof(ncpus_long
));
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.
945 switch (reqinfo
->mode
) {
949 scan_long
= (long) scan
;
950 snmp_set_var_typed_value(requests
->requestvb
, ASN_INTEGER
, (u_char
*) & scan_long
, sizeof(scan_long
));
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.
979 switch (reqinfo
->mode
) {
983 timers_long
= (long) timers
;
984 snmp_set_var_typed_value(requests
->requestvb
, ASN_INTEGER
, (u_char
*) & timers_long
, sizeof(timers_long
));
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.
1013 switch (reqinfo
->mode
) {
1017 badcalls_long
= (long) badcalls
;
1018 snmp_set_var_typed_value(requests
->requestvb
, ASN_INTEGER
, (u_char
*) & badcalls_long
, sizeof(badcalls_long
));
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
) {
1049 snmp_set_var_typed_value(requests
->requestvb
, ASN_UNSIGNED
, (u_char
*) & refrate
, sizeof(refrate
));
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.
1079 switch (reqinfo
->mode
) {
1083 cantsend_long
= (long) cantsend
;
1084 snmp_set_var_typed_value(requests
->requestvb
, ASN_INTEGER
, (u_char
*) & cantsend_long
, sizeof(cantsend_long
));
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.
1113 switch (reqinfo
->mode
) {
1117 badxids_long
= (long) badxids
;
1118 snmp_set_var_typed_value(requests
->requestvb
, ASN_INTEGER
, (u_char
*) & badxids_long
, sizeof(badxids_long
));
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.
1147 switch (reqinfo
->mode
) {
1151 newcreds_long
= (long) newcreds
;
1152 snmp_set_var_typed_value(requests
->requestvb
, ASN_INTEGER
, (u_char
*) & newcreds_long
, sizeof(newcreds_long
));
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
) {
1185 handspread_long
= (long) handspread
;
1186 snmp_set_var_typed_value(requests
->requestvb
, ASN_INTEGER
, (u_char
*) & handspread_long
, sizeof(handspread_long
));
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
) {
1219 interrupts_long
= (long) interrupts
;
1220 snmp_set_var_typed_value(requests
->requestvb
, ASN_INTEGER
, (u_char
*) & interrupts_long
, sizeof(interrupts_long
));
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.
1249 switch (reqinfo
->mode
) {
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
));
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.
1283 switch (reqinfo
->mode
) {
1287 badverfs_long
= (long) badverfs
;
1288 snmp_set_var_typed_value(requests
->requestvb
, ASN_INTEGER
, (u_char
*) & badverfs_long
, sizeof(badverfs_long
));
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
) {
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
));
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.
1351 switch (reqinfo
->mode
) {
1355 swapque_long
= (long) swapque
;
1356 snmp_set_var_typed_value(requests
->requestvb
, ASN_INTEGER
, (u_char
*) & swapque_long
, sizeof(swapque_long
));
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.
1385 switch (reqinfo
->mode
) {
1389 waiting_long
= (long) waiting
;
1390 snmp_set_var_typed_value(requests
->requestvb
, ASN_INTEGER
, (u_char
*) & waiting_long
, sizeof(waiting_long
));
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.
1419 switch (reqinfo
->mode
) {
1423 timeouts_long
= (long) timeouts
;
1424 snmp_set_var_typed_value(requests
->requestvb
, ASN_INTEGER
, (u_char
*) & timeouts_long
, sizeof(timeouts_long
));
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
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
);
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();
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
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 */
1525 snmp_log(LOG_DEBUG
,"No data returned in get_next\n");
1529 nextNode
= nextNode
->pNext
;
1532 snmp_log(LOG_DEBUG
,"No data returned in get_next\n");
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
;
1562 for (request
= requests
; request
; request
= request
->next
) {
1563 var
= request
->requestvb
;
1564 if (request
->processed
!= 0)
1568 * perform anything here that you need to do before each request is
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
);
1579 if (reqinfo
->mode
== MODE_GET
) {
1580 netsnmp_set_request_error(reqinfo
, request
, SNMP_NOSUCHINSTANCE
);
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
) {
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
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
));
1611 case COLUMN_HMDISKALIASNAME
:
1612 snmp_set_var_typed_value(var
, ASN_OCTET_STR
, (u_char
*) data
->hmDiskAliasName
, strlen(data
->hmDiskAliasName
));
1615 case COLUMN_HMAVGWAITTRANSACTIONS
:
1616 snmp_set_var_typed_value(var
, ASN_OCTET_STR
, (u_char
*) data
->hmAvgWaitTransactions
, strlen(data
->hmAvgWaitTransactions
));
1619 case COLUMN_HMDISKBUSYPCNT
:
1620 snmp_set_var_typed_value(var
, ASN_OCTET_STR
, (u_char
*) data
->hmDiskBusyPcnt
, strlen(data
->hmDiskBusyPcnt
));
1623 case COLUMN_HMAVGDISKSVCTIME
:
1624 snmp_set_var_typed_value(var
, ASN_OCTET_STR
, (u_char
*) data
->hmAvgDiskSvcTime
, strlen(data
->hmAvgDiskSvcTime
));
1628 /* We shouldn't get here */
1629 snmp_log(LOG_ERR
, "problem encountered in hmDiskTable_handler: unknown column\n");
1633 case MODE_SET_RESERVE1
:
1634 /* set handling... */
1637 snmp_log(LOG_ERR
, "problem encountered in hmDiskTable_handler: unsupported mode\n");
1640 return SNMP_ERR_NOERROR
;
1645 * New Functions that are added to the template generated by mib2c
1651 * The following refresh functions are called every 60 seconds. The data
1652 * nodes are updated with latest data
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
1669 snmp_log(LOG_ERR
,"Health Monitor Module: errror getting SWAP info\n");
1678 refresh_Kernel_data()
1683 code
= krgetsmtx(&sum_smtx
, &ncpus
);
1686 snmp_log(LOG_ERR
,"Health Monitor Module: errror getting Kernel info\n");
1698 code
= krgetclientrpcdetail(&calls
, &badcalls
, &retrans
, &badxids
, &timeouts
, &newcreds
, &badverfs
, &timers
, &nomem
, &cantsend
);
1701 snmp_log(LOG_ERR
,"Health Monitor Module: errror getting NFS info\n");
1714 /* "calls" is defined as a "DisplayString" in the MIB. So, converting
1718 sprintf(callsStr
, "%3.1f\0", calls
);
1727 code
= krgetprocdetail(&runque
, &waiting
, &swapque
);
1731 snmp_log(LOG_ERR
,"Health Monitor Module: errror getting CPU info\n");
1744 code
= krgetramdetail(&handspread
, &scan
);
1748 snmp_log(LOG_ERR
,"Health Monitor Module: errror getting RAM info\n");
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
);
1769 code
= krgetmemusage(&mem_avail
, &mem_inuse
, &mem_free
);
1773 snmp_log(LOG_ERR
,"Health Monitor Module: errror getting KMEM info\n");
1787 curtime
= time(&curtime
);
1788 if (prevtime
!= curtime
) {
1790 code
= krgetncstatdetail(&hits
, &misses
);
1794 snmp_log(LOG_ERR
,"Health Monitor Module: errror getting DNLC info\n");
1798 } /* NOTE : Should we do below even if
1799 * hits=0,misses=0 ? Yes, according to SunMC
1801 if (firsttime
== 1) {
1804 lastmisses
= misses
;
1806 lasthits
= prevhits
;
1807 lastmisses
= prevmisses
;
1811 prevmisses
= misses
;
1813 refrate
= (hits
- lasthits
) + (misses
- lastmisses
);
1817 hitrate
= 100 * (hits
- lasthits
) / refrate
;
1818 refrate
= refrate
/ (curtime
- prevtime
);
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
;
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 */
1846 hmDiskTable
*ptr
= (hmDiskTable
*) malloc(sizeof(hmDiskTable
));
1849 snmp_log(LOG_DEBUG
,"malloc failed when constructing DISK table in health monitor module \n");
1853 code
= krgetdiskdetail(name
, alias
, &rps
, &wps
, &tps
, &krps
, &kwps
, &kps
, &avw
, &avr
);
1856 /* Error occured during kstat read */
1857 snmp_log(LOG_ERR
,"Health Monitor Module: errror getting disk info\n");
1860 code
= krgetdisksrv(name
, alias
, &w_pct
, &r_pct
, &wserv
, &rserv
, &serv
);
1863 /* Error occured during kstat read */
1864 snmp_log(LOG_ERR
,"Health Monitor Module: errror getting disk info\n");
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");
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
;
1896 if (prevPtr
== NULL
) {
1897 head
= prevPtr
= ptr
;
1900 prevPtr
->pNext
= ptr
;
1903 /* code is set to value 0 if there is more disk information */
1904 } while (code
== 0);
1908 /* set the time of first refresh */
1910 time(&hm_prev_disk_ref
);
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
;
1924 hmDiskTable
*headPtr
;
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
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;
1951 /* Set tailPtr to the last structure
1952 * set "hmTraversed" to 0 for all disks
1956 while (tailPtr
->pNext
!= NULL
) {
1957 tailPtr
->hmTraversed
=0;
1958 tailPtr
= tailPtr
->pNext
;
1960 if(tailPtr
!= NULL
) tailPtr
->hmTraversed
=0;
1965 code
= krgetdiskdetail(name
, alias
, &rps
, &wps
, &tps
, &krps
, &kwps
, &kps
, &avw
, &avr
);
1968 /* Error occured during kstat read */
1969 snmp_log(LOG_ERR
,"Health Monitor Module: errror getting disk info\n");
1972 code
= krgetdisksrv(name
, alias
, &w_pct
, &r_pct
, &wserv
, &rserv
, &serv
);
1975 /* Error occured during kstat read */
1976 snmp_log(LOG_ERR
,"Health Monitor Module: errror getting disk info\n");
1980 /* For each row in the table, refresh the data */
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
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 */
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");
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 */
2050 if (tailPtr
== NULL
) {
2051 head
= tailPtr
= ptr
;
2054 tailPtr
->pNext
= ptr
;
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.
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
;
2089 /* Extend pointers by 1 step */
2091 if(p2
->pNext
!= NULL
) {
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.
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
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 */
2155 hm_handle_rule(&NFS_rule_state
, &NFS_rule
);
2157 /* Acquire data for CPU nodes */
2160 hm_handle_rule(&CPU_rule_state
, &CPU_rule
);
2162 /* Acquire data for RAM nodes */
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
);
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
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
);
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
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)
2266 hm_handle_rule(int *rule_state
, int (*rule
) (int))
2269 int new_alarm_state
;
2271 if (*rule_state
== NOTINIT
) {
2275 new_alarm_state
= rule(CONDITION
);
2277 switch (*rule_state
) {
2280 if (new_alarm_state
> OK
) {
2286 if (new_alarm_state
== OK
) {
2287 *rule_state
= CLOSE
;
2290 *rule_state
= CONTINUE
;
2295 if (new_alarm_state
== OK
) {
2296 *rule_state
= CLOSE
;
2299 *rule_state
= CONTINUE
;
2304 if (new_alarm_state
> OK
) {
2315 * Function: send_trap : This function sends a *statusChange* trap with
2316 * appropriate varbind's see SMA trap mib for detailed trap notification
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
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(¬ification_vars
,
2395 * the snmpTrapOID.0 variable
2397 objid_snmptrap
, objid_snmptrap_len
,
2399 * value type is an OID
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(¬ification_vars
,
2418 hostname_oid
, hostname_oid_len
,
2420 * value type is an OID
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(¬ification_vars
,
2434 modulename_oid
, modulename_oid_len
,
2436 * value type is an OID
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(¬ification_vars
,
2450 nodeoid_oid
, nodeoid_oid_len
,
2452 * value type is an OID
2456 * value contents is our notification OID
2460 * size in bytes = oid length * sizeof(oid)
2462 size
* sizeof(oid
));
2465 snmp_varlist_add_variable(¬ification_vars
,
2466 moduleContext_oid
, moduleContext_oid_len
,
2468 * value type is an OID
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(¬ification_vars
,
2482 status_oid
, status_oid_len
,
2484 * value type is an OID
2488 * value contents is our notification OID
2492 * size in bytes = oid length * sizeof(oid)
2494 strlen((char *) status
));
2497 snmp_varlist_add_variable(¬ification_vars
,
2498 description_oid
, description_oid_len
,
2500 * value type is an OID
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(¬ification_vars
,
2514 dvalue_oid
, dvalue_oid_len
,
2516 * value type is an OID
2520 * value contents is our notification OID
2524 * size in bytes = oid length * sizeof(oid)
2526 strlen((char *) dvalue
));
2530 snmp_varlist_add_variable(¬ification_vars
,
2531 dtype_oid
, dtype_oid_len
,
2533 * value type is an OID
2537 * value contents is our notification OID
2541 * size in bytes = oid length * sizeof(oid)
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
);
2562 * Function: conv_alarm_state : This function returns appropriate charecter
2563 * string for each integer alarm type
2567 conv_alarm_state(int state
)
2586 * Function: SWAP_rule : This function checks the state of SWAP nodes and
2587 * issues trap if necessary
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};
2597 u_char description
[] = "Available Swap space on the system is low";
2600 /* The value of dtype is 1 here becuase swapavail_data is of "int" type */
2603 sprintf((char *) dvalue
, "%d\0", swapavail_data
);
2604 size
= sizeof(trapoid
) / sizeof(oid
);
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
;
2618 } else if ((swapavail_data
<= threshold_swapavail_warning
) && (swapavail_data
> threshold_swapavail_error
)) {
2619 new_SWAP_state
= WARNING
;
2621 } else if (swapavail_data
<= threshold_swapavail_error
) {
2622 new_SWAP_state
= ERROR
;
2625 new_SWAP_state
= OK
;
2630 strcpy((char *) status
, conv_alarm_state(new_SWAP_state
));
2631 send_trap(hostName
, moduleName
, statusOIDContext
, trapoid
, size
, status
, description
, dvalue
, dtype
);
2640 strcpy((char *) status
, conv_alarm_state(new_SWAP_state
));
2641 if (new_SWAP_state
> prev_SWAP_state
) {
2644 send_trap(hostName
, moduleName
, statusOIDContext
, trapoid
, size
, status
, description
, dvalue
, dtype
);
2645 prev_SWAP_state
= new_SWAP_state
;
2652 strcpy((char *) status
, conv_alarm_state(new_SWAP_state
));
2653 send_trap(hostName
, moduleName
, statusOIDContext
, trapoid
, size
, status
, description
, dvalue
, dtype
);
2664 * Function: Kernel_rule : This function checks the state of Kernel nodes and
2665 * issues trap if necessary
2669 Kernel_rule(int action
)
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};
2677 u_char description
[] = "Mutex contention rate is high , kernel overload \0";
2681 * dtype is set to 1 because the hmSpinsOnMutexes node is defined as
2682 * Integer32 in the mib
2686 sprintf((char *) dvalue
, "%lu\0", sum_smtx
);
2687 size
= sizeof(trapoid
) / sizeof(oid
);
2694 /* this happens only during initialization */
2695 new_mutex_state
= 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,
2711 new_mutex_state
= OK
;
2715 new_mutex_state
= INFO
;
2718 } else if (mutexrate
< threshold_mutex_warning
) {
2719 new_mutex_state
= WARNING
;
2722 new_mutex_state
= ERROR
;
2728 strcpy((char *) status
, conv_alarm_state(new_mutex_state
));
2729 send_trap(hostName
, moduleName
, statusOIDContext
, trapoid
, size
, status
, description
, dvalue
, dtype
);
2738 strcpy((char *) status
, conv_alarm_state(new_mutex_state
));
2740 if (new_mutex_state
> prev_mutex_state
) {
2743 send_trap(hostName
, moduleName
, statusOIDContext
, trapoid
, size
, status
, description
, dvalue
, dtype
);
2744 prev_mutex_state
= new_mutex_state
;
2751 strcpy((char *) status
, conv_alarm_state(new_mutex_state
));
2752 send_trap(hostName
, moduleName
, statusOIDContext
, trapoid
, size
, status
, description
, dvalue
, dtype
);
2763 * Function: NFS_rule : This function checks the state of NFS nodes and
2764 * issues trap if necessary
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};
2779 u_char description
[] = "Bad Network or Server is slow. May need to increase timeout \0 ";
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
);
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.
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 <
2818 maxbadxid
= threshold_badxids
* timeouts
/ 100.0;
2819 if ((maxtimeout
<= timeouts
) && (badxids
<= maxbadxid
)) {
2820 new_NFS_state
= WARNING
;
2824 * This will be the case when timeout >= maxtimeout AND
2825 * badxids > maxbadxid
2827 new_NFS_state
= ERROR
;
2835 strcpy((char *) status
, conv_alarm_state(new_NFS_state
));
2836 send_trap(hostName
, moduleName
, statusOIDContext
, trapoid
, size
, status
, description
, dvalue
, dtype
);
2845 strcpy((char *) status
, conv_alarm_state(new_NFS_state
));
2846 if (new_NFS_state
> prev_NFS_state
) {
2849 send_trap(hostName
, moduleName
, statusOIDContext
, trapoid
, size
, status
, description
, dvalue
, dtype
);
2850 prev_NFS_state
= new_NFS_state
;
2857 strcpy((char *) status
, conv_alarm_state(new_NFS_state
));
2858 send_trap(hostName
, moduleName
, statusOIDContext
, trapoid
, size
, status
, description
, dvalue
, dtype
);
2869 * Function: CPU_rule : This function checks the state of CPU nodes and
2870 * issues trap if necessary
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};
2880 u_char description
[] = "CPU overloaded \0";
2883 /* dtype is given a value of 1 because runque is of "int" type */
2888 sprintf((char *) dvalue
, "%d\0", runque
);
2889 size
= sizeof(trapoid
) / sizeof(oid
);
2896 * Added this If statement to existing rule. From Kernel_rule, it
2897 * looks like ncpus may be 0 during initialization
2900 /* this happens only during initialization */
2901 new_cpuload_state
= OK
;
2904 cpuload
= runque
/ ncpus
;
2907 * Quite straightforward. If the threshold is crossed, set the state
2911 if (cpuload
< threshold_cpuload_info
) {
2912 new_cpuload_state
= OK
;
2914 } else if (cpuload
< threshold_cpuload_warning
) {
2915 new_cpuload_state
= INFO
;
2917 } else if (cpuload
< threshold_cpuload_error
) {
2918 new_cpuload_state
= WARNING
;
2921 new_cpuload_state
= ERROR
;
2927 strcpy((char *) status
, conv_alarm_state(new_cpuload_state
));
2928 send_trap(hostName
, moduleName
, statusOIDContext
, trapoid
, size
, status
, description
, dvalue
, dtype
);
2937 strcpy((char *) status
, conv_alarm_state(new_cpuload_state
));
2938 if (new_cpuload_state
> prev_cpuload_state
) {
2941 send_trap(hostName
, moduleName
, statusOIDContext
, trapoid
, size
, status
, description
, dvalue
, dtype
);
2942 prev_cpuload_state
= new_cpuload_state
;
2949 strcpy((char *) status
, conv_alarm_state(new_cpuload_state
));
2950 send_trap(hostName
, moduleName
, statusOIDContext
, trapoid
, size
, status
, description
, dvalue
, dtype
);
2961 * Function: RAM_rule : This function checks the state of RAM nodes and
2962 * issues trap if necessary
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};
2975 u_char description
[] = "RAM shortage \0";
2979 /* dtype is given a value of 1 because scan is of "int" type */
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
);
2997 restime
= threshold_restime_long
;
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
;
3011 if (restime
> threshold_restime_ok
) {
3012 new_restime_state
= INFO
;
3015 if (restime
> threshold_restime_error
) {
3016 new_restime_state
= WARNING
;
3019 new_restime_state
= ERROR
;
3027 strcpy((char *) status
, conv_alarm_state(new_restime_state
));
3028 send_trap(hostName
, moduleName
, statusOIDContext
, trapoid
, size
, status
, description
, dvalue
, dtype
);
3037 strcpy((char *) status
, conv_alarm_state(new_restime_state
));
3038 if (new_restime_state
> prev_restime_state
) {
3041 send_trap(hostName
, moduleName
, statusOIDContext
, trapoid
, size
, status
, description
, dvalue
, dtype
);
3042 prev_restime_state
= new_restime_state
;
3049 strcpy((char *) status
, conv_alarm_state(new_restime_state
));
3050 send_trap(hostName
, moduleName
, statusOIDContext
, trapoid
, size
, status
, description
, dvalue
, dtype
);
3061 * Function: KMEM_rule : This function checks the state of KMEM nodes and
3062 * issues trap if necessary
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};
3075 u_char description
[] = "Kernel Memory allocation errors \0";
3078 /* dtype is given a value of 1 because alloc_fail is of "int" type */
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
);
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
3107 new_kmem_state
= OK
;
3110 new_kmem_state
= INFO
;
3114 if (alloc_fail
== lasterrs
) {
3115 new_kmem_state
= WARNING
;
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
3127 * Kernel memory allocation problem. The state is already
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
);
3151 strcpy((char *) status
, conv_alarm_state(new_kmem_state
));
3152 if (new_kmem_state
> prev_kmem_state
) {
3155 send_trap(hostName
, moduleName
, statusOIDContext
, trapoid
, size
, status
, description
, dvalue
, dtype
);
3156 prev_kmem_state
= new_kmem_state
;
3163 strcpy((char *) status
, conv_alarm_state(new_kmem_state
));
3164 send_trap(hostName
, moduleName
, statusOIDContext
, trapoid
, size
, status
, description
, dvalue
, dtype
);
3175 * Function: DNLC_rule : This function checks the state of DNLC nodes and
3176 * issues trap if necessary
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};
3186 u_char description
[] = "Poor DNLC Hit rate \0";
3189 /* dtype is given a value of 1 because hitrate is of "int" type */
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
);
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
;
3213 if (hitrate
> threshold_dnlc_warning
) {
3214 new_dnlc_state
= OK
;
3217 new_dnlc_state
= WARNING
;
3225 strcpy((char *) status
, conv_alarm_state(new_dnlc_state
));
3226 send_trap(hostName
, moduleName
, statusOIDContext
, trapoid
, size
, status
, description
, dvalue
, dtype
);
3235 strcpy((char *) status
, conv_alarm_state(new_dnlc_state
));
3236 if (new_dnlc_state
> prev_dnlc_state
) {
3239 send_trap(hostName
, moduleName
, statusOIDContext
, trapoid
, size
, status
, description
, dvalue
, dtype
);
3240 prev_dnlc_state
= new_dnlc_state
;
3247 strcpy((char *) status
, conv_alarm_state(new_dnlc_state
));
3248 send_trap(hostName
, moduleName
, statusOIDContext
, trapoid
, size
, status
, description
, dvalue
, dtype
);
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
3276 /* Maintain a pointer to diskTable called headPtr */
3278 hmDiskTable
*headPtr
;
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
;
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
;
3301 if (svcTime
< disk_svc_t_warning
) {
3302 new_disk_state
= OK
;
3304 if (disk_busy_problem
<= busyTime
) {
3305 if ((disk_svc_t_warning
<= svcTime
) && (svcTime
< disk_svc_t_problem
)) {
3306 new_disk_state
= WARNING
;
3308 if (disk_svc_t_problem
<= svcTime
) {
3309 new_disk_state
= ERROR
;
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");
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
) {
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
) {
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 */