From 061495fecbfded199ac8baecc95d72c2b3143656 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=C3=A1ll=20Gu=C3=B0j=C3=B3n=20Sigur=C3=B0sson?= Date: Sun, 14 Mar 2010 00:14:12 +0000 Subject: [PATCH] check_snmp* added. Support for cisco switches and ASA --- check_disks.pl/trunk/check_disks.pl | 5 +- check_snmp/trunk/check_snmp_cpfw.pl | 555 +++++++++++ check_snmp/trunk/check_snmp_env.pl | 1036 ++++++++++++++++++++ check_snmp/trunk/check_snmp_int.pl | 836 ++++++++++++++++ check_snmp/trunk/check_snmp_interfaces | 779 +++++++++++++++ check_snmp/trunk/check_snmp_load.pl | 792 +++++++++++++++ check_snmp/trunk/check_snmp_mem.pl | 525 ++++++++++ check_snmp/trunk/check_snmp_patchlevel.pl | 287 ++++++ check_snmp/trunk/check_snmp_temperature.pl | 714 ++++++++++++++ 9 files changed, 5527 insertions(+), 2 deletions(-) create mode 100644 check_snmp/trunk/check_snmp_cpfw.pl create mode 100644 check_snmp/trunk/check_snmp_env.pl create mode 100644 check_snmp/trunk/check_snmp_int.pl create mode 100755 check_snmp/trunk/check_snmp_interfaces create mode 100755 check_snmp/trunk/check_snmp_load.pl create mode 100755 check_snmp/trunk/check_snmp_mem.pl create mode 100755 check_snmp/trunk/check_snmp_patchlevel.pl create mode 100644 check_snmp/trunk/check_snmp_temperature.pl diff --git a/check_disks.pl/trunk/check_disks.pl b/check_disks.pl/trunk/check_disks.pl index 012ca76..62b71a8 100755 --- a/check_disks.pl/trunk/check_disks.pl +++ b/check_disks.pl/trunk/check_disks.pl @@ -353,11 +353,12 @@ foreach my $f (keys %checkdisks) { $output .= "
" if ($opt_html); } else { if ($opt_v) { - $output .= "[$f " . byte2human($checkdisks{$f}->{free}) . - " (" . $checkdisks{$f}->{pfree} . '% free)] '; + $output .= "\n[$f " . byte2human($checkdisks{$f}->{free}) . + " (" . $checkdisks{$f}->{pfree} . '% free)] ' ; $output .= "
" if ($opt_html); } } + $output .= "\n"; # Donnees de Perfs my $perfwarn=$alldisks{$f}->{somme}*((100-$checkdisks{$f}->{warning})/100); diff --git a/check_snmp/trunk/check_snmp_cpfw.pl b/check_snmp/trunk/check_snmp_cpfw.pl new file mode 100644 index 0000000..bdf790a --- /dev/null +++ b/check_snmp/trunk/check_snmp_cpfw.pl @@ -0,0 +1,555 @@ +#!/usr/bin/perl -w +############################## check_snmp_cpfw ############## +# Version : 1.2.1 +# Date : April 19 2007 +# Author : Patrick Proy (patrick at proy.org) +# Help : http://nagios.manubulon.com +# Licence : GPL - http://www.fsf.org/licenses/gpl.txt +# TODO : +# - check sync method +################################################################# +# +# Help : ./check_snmp_cpfw.pl -h +# + +use strict; +use Net::SNMP; +use Getopt::Long; + +# Nagios specific + +use lib "/usr/local/nagios/libexec"; +use utils qw(%ERRORS $TIMEOUT); +#my $TIMEOUT = 15; +#my %ERRORS=('OK'=>0,'WARNING'=>1,'CRITICAL'=>2,'UNKNOWN'=>3,'DEPENDENT'=>4); + +########### SNMP Datas ########### + +###### FW data +my $policy_state = "1.3.6.1.4.1.2620.1.1.1.0"; # "Installed" +my $policy_name = "1.3.6.1.4.1.2620.1.1.2.0"; # Installed policy name +my $connections = "1.3.6.1.4.1.2620.1.1.25.3.0"; # number of connections +#my $connections_peak = "1.3.6.1.4.1.2620.1.1.25.4.0"; # peak number of connections +my @fw_checks = ($policy_state,$policy_name,$connections); + +###### SVN data +my $svn_status = "1.3.6.1.4.1.2620.1.6.102.0"; # "OK" svn status +my %svn_checks = ($svn_status,"OK"); +my %svn_checks_n = ($svn_status,"SVN status"); +my @svn_checks_oid = ($svn_status); + +###### HA data + +my $ha_active = "1.3.6.1.4.1.2620.1.5.5.0"; # "yes" +my $ha_state = "1.3.6.1.4.1.2620.1.5.6.0"; # "active" / "standby" +my $ha_block_state = "1.3.6.1.4.1.2620.1.5.7.0"; #"OK" : ha blocking state +my $ha_status = "1.3.6.1.4.1.2620.1.5.102.0"; # "OK" : ha status + +my %ha_checks =( $ha_active,"yes",$ha_state,"active",$ha_block_state,"OK",$ha_status,"OK"); +my %ha_checks_stand =( $ha_active,"yes",$ha_state,"standby",$ha_block_state,"OK",$ha_status,"OK"); +my %ha_checks_n =( $ha_active,"HA active",$ha_state,"HA state",$ha_block_state,"HA block state",$ha_status,"ha_status"); +my @ha_checks_oid =( $ha_active,$ha_state,$ha_block_state,$ha_status); + +my $ha_mode = "1.3.6.1.4.1.2620.1.5.11.0"; # "Sync only"/"High Availability (Active Up)" : ha Working mode + +my $ha_tables = "1.3.6.1.4.1.2620.1.5.13.1"; # ha status table +my $ha_tables_index = ".1"; +my $ha_tables_name = ".2"; +my $ha_tables_state = ".3"; # "OK" +my $ha_tables_prbdesc = ".6"; # Description if state is != "OK" + +#my @ha_table_check = ("Synchronization","Filter","cphad","fwd"); # process to check + +####### MGMT data + +my $mgmt_status = "1.3.6.1.4.1.2620.1.7.5.0"; # "active" : management status +my $mgmt_alive = "1.3.6.1.4.1.2620.1.7.6.0"; # 1 : management is alive if 1 +my $mgmt_stat_desc = "1.3.6.1.4.1.2620.1.7.102.0"; # Management status description +my $mgmt_stats_desc_l = "1.3.6.1.4.1.2620.1.7.103.0"; # Management status long description + +my %mgmt_checks = ($mgmt_status,"active",$mgmt_alive,"1"); +my %mgmt_checks_n = ($mgmt_status,"Mgmt status",$mgmt_alive,"Mgmt alive"); +my @mgmt_checks_oid = ($mgmt_status,$mgmt_alive); + +#################################### Globals ##############################"" + +my $Version='1.2.1'; + +my $o_host = undef; # hostname +my $o_community = undef; # community +my $o_version2 =undef; # Version 2 +my $o_port = 161; # port +my $o_help= undef; # wan't some help ? +my $o_verb= undef; # verbose mode +my $o_version= undef; # print version +my $o_timeout= 5; # Default 5s Timeout +my $o_warn= undef; # Warning for connections +my $o_crit= undef; # Crit for connections +my $o_svn= undef; # Check for SVN status +my $o_fw= undef; # Check for FW status +my $o_ha= undef; # Check for HA status +my $o_mgmt= undef; # Check for management status +my $o_policy= undef; # Check for policy name +my $o_conn= undef; # Check for connexions +my $o_perf= undef; # Performance data output + +# SNMPv3 specific +my $o_login= undef; # Login for snmpv3 +my $o_passwd= undef; # Pass for snmpv3 +my $v3protocols=undef; # V3 protocol list. +my $o_authproto='md5'; # Auth protocol +my $o_privproto='des'; # Priv protocol +my $o_privpass= undef; # priv password + +# functions + +sub p_version { print "check_snmp_cpfw version : $Version\n"; } + +sub print_usage { + print "Usage: $0 [-v] -H -C [-2] | (-l login -x passwd [-X pass -L ,]) [-s] [-w [-p=pol_name] [-c=warn,crit]] [-m] [-a [standby] ] [-f] [-p ] [-t ] [-V]\n"; +} + +sub isnnum { # Return true if arg is not a number + my $num = shift; + if ( $num =~ /^(\d+\.?\d*)|(^\.\d+)$/ ) { return 0 ;} + return 1; +} + +sub help { + print "\nSNMP Checkpoint FW-1 Monitor for Nagios version ",$Version,"\n"; + print "GPL Licence, (c)2004-2007 - Patrick Proy\n\n"; + print_usage(); + print <, + : Authentication protocol (md5|sha : default md5) + : Priv protocole (des|aes : default des) +-s, --svn + check for svn status +-w, --fw + check for fw status +-a, --ha[=standby] + check for ha status and node in "active" state + If using SecurePlatform and monitoring a standby unit, put "standby" too +-m, --mgmt + check for management status +-p, --policy=POLICY_NAME + check if installed policy is POLICY_NAME (must have -w) +-c, --connexions=WARN,CRIT + check warn and critical number of connexions (must have -w) +-f, --perfparse + perfparse output (only works with -c) +-P, --port=PORT + SNMP port (Default 161) +-t, --timeout=INTEGER + timeout for SNMP (Default: Nagios default) +-V, --version + prints version number +EOT +} + +# For verbose output +sub verb { my $t=shift; print $t,"\n" if defined($o_verb) ; } + +sub check_options { + Getopt::Long::Configure ("bundling"); + GetOptions( + 'v' => \$o_verb, 'verbose' => \$o_verb, + 'h' => \$o_help, 'help' => \$o_help, + 'H:s' => \$o_host, 'hostname:s' => \$o_host, + 'P:i' => \$o_port, 'port:i' => \$o_port, + 'C:s' => \$o_community, 'community:s' => \$o_community, + '2' => \$o_version2, 'v2c' => \$o_version2, + 'l:s' => \$o_login, 'login:s' => \$o_login, + 'x:s' => \$o_passwd, 'passwd:s' => \$o_passwd, + 'X:s' => \$o_privpass, 'privpass:s' => \$o_privpass, + 'L:s' => \$v3protocols, 'protocols:s' => \$v3protocols, + 't:i' => \$o_timeout, 'timeout:i' => \$o_timeout, + 'V' => \$o_version, 'version' => \$o_version, + 's' => \$o_svn, 'svn' => \$o_svn, + 'w' => \$o_fw, 'fw' => \$o_fw, + 'a:s' => \$o_ha, 'ha:s' => \$o_ha, + 'm' => \$o_mgmt, 'mgmt' => \$o_mgmt, + 'p:s' => \$o_policy, 'policy:s' => \$o_policy, + 'c:s' => \$o_conn, 'connexions:s' => \$o_conn, + 'f' => \$o_perf, 'perfparse' => \$o_perf + ); + if (defined ($o_help) ) { help(); exit $ERRORS{"UNKNOWN"}}; + if (defined($o_version)) { p_version(); exit $ERRORS{"UNKNOWN"}}; + if ( ! defined($o_host) ) # check host and filter + { print_usage(); exit $ERRORS{"UNKNOWN"}} + # check snmp information + if ( !defined($o_community) && (!defined($o_login) || !defined($o_passwd)) ) + { print "Put snmp login info!\n"; print_usage(); exit $ERRORS{"UNKNOWN"}} + if ((defined($o_login) || defined($o_passwd)) && (defined($o_community) || defined($o_version2)) ) + { print "Can't mix snmp v1,2c,3 protocols!\n"; print_usage(); exit $ERRORS{"UNKNOWN"}} + if (defined ($v3protocols)) { + if (!defined($o_login)) { print "Put snmp V3 login info with protocols!\n"; print_usage(); exit $ERRORS{"UNKNOWN"}} + my @v3proto=split(/,/,$v3protocols); + if ((defined ($v3proto[0])) && ($v3proto[0] ne "")) {$o_authproto=$v3proto[0]; } # Auth protocol + if (defined ($v3proto[1])) {$o_privproto=$v3proto[1]; } # Priv protocol + if ((defined ($v3proto[1])) && (!defined($o_privpass))) { + print "Put snmp V3 priv login info with priv protocols!\n"; print_usage(); exit $ERRORS{"UNKNOWN"}} + } + # Check firewall options + if ( defined($o_conn)) { + if ( ! defined($o_fw)) + { print "Cannot check connexions without checking fw\n"; print_usage(); exit $ERRORS{"UNKNOWN"}} + my @warncrit=split(/,/ , $o_conn); + if ( $#warncrit != 1 ) + { print "Put warn,crit levels with -c option\n";print_usage(); exit $ERRORS{"UNKNOWN"}} + ($o_warn,$o_crit)=@warncrit; + if ( isnnum($o_warn) || isnnum($o_crit) ) + { print "Numeric values for warning and critical in -c options\n";print_usage(); exit $ERRORS{"UNKNOWN"}} + if ($o_warn >= $o_crit) + { print "warning <= critical ! \n";print_usage(); exit $ERRORS{"UNKNOWN"}} + } + if ( defined($o_policy)) { + if (! defined($o_fw)) + { print "Cannot check policy name without checking fw\n"; print_usage(); exit $ERRORS{"UNKNOWN"}} + if ($o_policy eq "") + { print "Put a policy name !\n"; print_usage(); exit $ERRORS{"UNKNOWN"}} + } + if (defined($o_perf) && ! defined ($o_conn)) + { print "Nothing selected for perfparse !\n";print_usage(); exit $ERRORS{"UNKNOWN"}} + if (!defined($o_fw) && !defined($o_ha) && !defined($o_mgmt) && !defined($o_svn)) + { print "Must select a product to check !\n";print_usage(); exit $ERRORS{"UNKNOWN"}} + if (defined ($o_ha) && ($o_ha ne "") && ($o_ha ne "standby")) + { print "-a option comes with 'standby' or nothing !\n";print_usage(); exit $ERRORS{"UNKNOWN"}} + +} + +########## MAIN ####### + +check_options(); + +# Check gobal timeout if snmp screws up +if (defined($TIMEOUT)) { + verb("Alarm at $TIMEOUT"); + alarm($TIMEOUT); +} else { + verb("no timeout defined : $o_timeout + 10"); + alarm ($o_timeout+10); +} + +$SIG{'ALRM'} = sub { + print "No answer from host\n"; + exit $ERRORS{"UNKNOWN"}; +}; + +# Connect to host +my ($session,$error); +if ( defined($o_login) && defined($o_passwd)) { + # SNMPv3 login + verb("SNMPv3 login"); + if (!defined ($o_privpass)) { + verb("SNMPv3 AuthNoPriv login : $o_login, $o_authproto"); + ($session, $error) = Net::SNMP->session( + -hostname => $o_host, + -version => '3', + -username => $o_login, + -port => $o_port, + -authpassword => $o_passwd, + -authprotocol => $o_authproto, + -timeout => $o_timeout + ); + } else { + verb("SNMPv3 AuthPriv login : $o_login, $o_authproto, $o_privproto"); + ($session, $error) = Net::SNMP->session( + -hostname => $o_host, + -version => '3', + -username => $o_login, + -port => $o_port, + -authpassword => $o_passwd, + -authprotocol => $o_authproto, + -privpassword => $o_privpass, + -privprotocol => $o_privproto, + -timeout => $o_timeout + ); + } +} else { + if (defined ($o_version2)) { + # SNMPv2 Login + verb("SNMP v2c login"); + ($session, $error) = Net::SNMP->session( + -hostname => $o_host, + -version => 2, + -community => $o_community, + -port => $o_port, + -timeout => $o_timeout + ); + } else { + # SNMPV1 login + verb("SNMP v1 login"); + ($session, $error) = Net::SNMP->session( + -hostname => $o_host, + -community => $o_community, + -port => $o_port, + -timeout => $o_timeout + ); + } +} +if (!defined($session)) { + printf("ERROR opening session: %s.\n", $error); + exit $ERRORS{"UNKNOWN"}; +} + +########### Global checks ################# + +my $global_status=0; # global status : 0=OK, 1=Warn, 2=Crit +my ($resultat,$key)=(undef,undef); + +########## Check SVN status ############# +my $svn_print=""; +my $svn_state=0; + +if (defined ($o_svn)) { + +$resultat = $session->get_request( + Varbindlist => \@svn_checks_oid +); + + if (defined($resultat)) { + foreach $key ( keys %svn_checks) { + verb("$svn_checks_n{$key} : $svn_checks{$key} / $$resultat{$key}"); + if ( $$resultat{$key} ne $svn_checks{$key} ) { + $svn_print .= $svn_checks_n{$key} . ":" . $$resultat{$key} . " "; + $svn_state=2; + } + } + } else { + $svn_print .= "cannot find oids"; + #Critical state if not found because it means soft is not activated + $svn_state=2; + } + + if ($svn_state == 0) { + $svn_print="SVN : OK"; + } else { + $svn_print="SVN : " . $svn_print; + } + verb("$svn_print"); +} +########## Check mgmt status ############# +my $mgmt_state=0; +my $mgmt_print=""; + +if (defined ($o_mgmt)) { +# Check all states + $resultat=undef; + $resultat = $session->get_request( + Varbindlist => \@mgmt_checks_oid + ); + if (defined($resultat)) { + foreach $key ( keys %mgmt_checks) { + verb("$mgmt_checks_n{$key} : $mgmt_checks{$key} / $$resultat{$key}"); + if ( $$resultat{$key} ne $mgmt_checks{$key} ) { + $mgmt_print .= $mgmt_checks_n{$key} . ":" . $$resultat{$key} . " "; + $mgmt_state=2; + } + } + } else { + $mgmt_print .= "cannot find oids"; + #Critical state if not found because it means soft is not activated + $mgmt_state=2; + } + if ($mgmt_state == 0) { + $mgmt_print="MGMT : OK"; + } else { + $mgmt_print="MGMT : " . $mgmt_print; + } + verb("$svn_print"); +} + +########### Check fw status ############## + +my $fw_state=0; +my $fw_print=""; +my $perf_conn=undef; + +if (defined ($o_fw)) { + +# Check all states + + $resultat = $session->get_request( + Varbindlist => \@fw_checks + ); + if (defined($resultat)) { + verb("State : $$resultat{$policy_state}"); + verb("Name : $$resultat{$policy_name}"); + verb("connections : $$resultat{$connections}"); + + if ($$resultat{$policy_state} ne "Installed") { + $fw_state=2; + $fw_print .= "Policy:". $$resultat{$policy_state}." "; + verb("Policy state not installed"); + } + + if (defined($o_policy)) { + if ($$resultat{$policy_name} ne $o_policy) { + $fw_state=2; + $fw_print .= "Policy installed : $$resultat{$policy_name}"; + } + } + + if (defined($o_conn)) { + if ($$resultat{$connections} > $o_crit) { + $fw_state=2; + $fw_print .= "Connexions : ".$$resultat{$connections}." > ".$o_crit." "; + } else { + if ($$resultat{$connections} > $o_warn) { + if ($fw_state!=2) {$fw_state=1;} + $fw_print .= "Connexions : ".$$resultat{$connections}." > ".$o_warn." "; + } + } + $perf_conn=$$resultat{$connections}; + } + } else { + $fw_print .= "cannot find oids"; + #Critical state if not found because it means soft is not activated + $fw_state=2; + } + + if ($fw_state==0) { + $fw_print="FW : OK"; + } else { + $fw_print="FW : " . $fw_print; + } + +} +########### Check ha status ############## + +my $ha_state_n=0; +my $ha_print=""; + +if (defined ($o_ha)) { + # Check all states + + $resultat = $session->get_request( + Varbindlist => \@ha_checks_oid + ); + + if (defined($resultat)) { + foreach $key ( keys %ha_checks) { + verb("$ha_checks_n{$key} : $ha_checks{$key} / $$resultat{$key}"); + if ( $o_ha eq "standby" ) { + if ( $$resultat{$key} ne $ha_checks_stand{$key} ) { + $ha_print .= $ha_checks_n{$key} . ":" . $$resultat{$key} . " "; + $ha_state_n=2; + } + } else { + if ( $$resultat{$key} ne $ha_checks{$key} ) { + $ha_print .= $ha_checks_n{$key} . ":" . $$resultat{$key} . " "; + $ha_state_n=2; + } + } + } + #my $ha_mode = "1.3.6.1.4.1.2620.1.5.11.0"; # "Sync only" : ha Working mode + } else { + $ha_print .= "cannot find oids"; + #Critical state if not found because it means soft is not activated + $ha_state_n=2; + } + + # get ha status table + $resultat = $session->get_table( + Baseoid => $ha_tables + ); + my %status; + my (@index,@oid) = (undef,undef); + my $nindex=0; + my $index_search= $ha_tables . $ha_tables_index; + + if (defined($resultat)) { + foreach $key ( keys %$resultat) { + if ( $key =~ /$index_search/) { + @oid=split (/\./,$key); + pop(@oid); + $index[$nindex]=pop(@oid); + $nindex++; + } + } + } else { + $ha_print .= "cannot find oids" if ($ha_state_n ==0); + #Critical state if not found because it means soft is not activated + $ha_state_n=2; + } + verb ("found $nindex ha softs"); + if ( $nindex == 0 ) + { + $ha_print .= " no ha soft found" if ($ha_state_n ==0); + $ha_state_n=2; + } else { + my $ha_soft_name=undef; + + for (my $i=0;$i<$nindex;$i++) { + + $key=$ha_tables . $ha_tables_name . "." . $index[$i] . ".0"; + $ha_soft_name= $$resultat{$key}; + + $key=$ha_tables . $ha_tables_state . "." . $index[$i] . ".0"; + if (($status{$ha_soft_name} = $$resultat{$key}) ne "OK") { + $key=$ha_tables . $ha_tables_prbdesc . "." . $index[$i] . ".0"; + $status{$ha_soft_name} = $$resultat{$key}; + $ha_print .= $ha_soft_name . ":" . $status{$ha_soft_name} . " "; + $ha_state_n=2 + } + verb ("$ha_soft_name : $status{$ha_soft_name}"); + } + } + + if ($ha_state_n == 0) { + $ha_print = "HA : OK"; + } else { + $ha_print = "HA : " . $ha_print; + } + +} + +$session->close; + +########## print results and exit + +my $f_print=undef; + +if (defined ($o_fw)) { $f_print = $fw_print } +if (defined ($o_svn)) { $f_print = (defined ($f_print)) ? $f_print . " / ". $svn_print : $svn_print } +if (defined ($o_ha)) { $f_print = (defined ($f_print)) ? $f_print . " / ". $ha_print : $ha_print } +if (defined ($o_mgmt)) { $f_print = (defined ($f_print)) ? $f_print . " / ". $mgmt_print : $mgmt_print } + +my $exit_status=undef; +$f_print .= " / CPFW Status : "; +if (($ha_state_n+$svn_state+$fw_state+$mgmt_state) == 0 ) { + $f_print .= "OK"; + $exit_status= $ERRORS{"OK"}; +} else { + if (($fw_state==1) || ($ha_state_n==1) || ($svn_state==1) || ($mgmt_state==1)) { + $f_print .= "WARNING"; + $exit_status= $ERRORS{"WARNING"}; + } else { + $f_print .= "CRITICAL"; + $exit_status=$ERRORS{"CRITICAL"}; + } +} + +if (defined($o_perf) && defined ($perf_conn)) { + $f_print .= " | fw_connexions=" . $perf_conn; +} + +print "$f_print\n"; +exit $exit_status; + diff --git a/check_snmp/trunk/check_snmp_env.pl b/check_snmp/trunk/check_snmp_env.pl new file mode 100644 index 0000000..b07608d --- /dev/null +++ b/check_snmp/trunk/check_snmp_env.pl @@ -0,0 +1,1036 @@ +#!/usr/bin/perl -w +############################## check_snmp_env ################# +# Version : 1.3 +# Date : May 24 2007 +# Author : Patrick Proy ( patrick at proy.org) +# Help : http://www.manubulon.com/nagios/ +# Licence : GPL - http://www.fsf.org/licenses/gpl.txt +# Changelog : +# Contributors : Fredrik Vocks +################################################################# +# +# Help : ./check_snmp_env.pl -h +# + +use strict; +use Net::SNMP; +use Getopt::Long; + +# Nagios specific + +use lib "/usr/local/nagios/libexec"; +use utils qw(%ERRORS $TIMEOUT); +#my $TIMEOUT = 15; +#my %ERRORS=('OK'=>0,'WARNING'=>1,'CRITICAL'=>2,'UNKNOWN'=>3,'DEPENDENT'=>4); + + +my @Nagios_state = ("UNKNOWN","OK","WARNING","CRITICAL"); # Nagios states coding + +# SNMP Datas + +# CISCO-ENVMON-MIB +my $ciscoEnvMonMIB = "1.3.6.1.4.1.9.9.13"; # Cisco env base table +my %CiscoEnvMonState = (1,"normal",2,"warning",3,"critical",4,"shutdown",5,"notPresent", + 6,"notFunctioning"); # Cisco states +my %CiscoEnvMonNagios = (1,1 ,2,2 ,3,3 ,4,3 ,5,0, 6,3); # Nagios states returned for CIsco states (coded see @Nagios_state). +my $ciscoVoltageTable = $ciscoEnvMonMIB.".1.2.1"; # Cisco voltage table +my $ciscoVoltageTableIndex = $ciscoVoltageTable.".1"; #Index table +my $ciscoVoltageTableDesc = $ciscoVoltageTable.".2"; #Description +my $ciscoVoltageTableValue = $ciscoVoltageTable.".3"; #Value +my $ciscoVoltageTableState = $ciscoVoltageTable.".7"; #Status +# CiscoEnvMonVoltageStatusEntry ::= + # 1 ciscoEnvMonVoltageStatusIndex Integer32 (0..2147483647), + # 2 ciscoEnvMonVoltageStatusDescr DisplayString, + # 3 ciscoEnvMonVoltageStatusValue CiscoSignedGauge, + # 4 ciscoEnvMonVoltageThresholdLow Integer32, + # 5 ciscoEnvMonVoltageThresholdHigh Integer32, + # 6 ciscoEnvMonVoltageLastShutdown Integer32, + # 7 ciscoEnvMonVoltageState CiscoEnvMonState +my $ciscoTempTable = $ciscoEnvMonMIB.".1.3.1"; # Cisco temprature table +my $ciscoTempTableIndex = $ciscoTempTable.".1"; #Index table +my $ciscoTempTableDesc = $ciscoTempTable.".2"; #Description +my $ciscoTempTableValue = $ciscoTempTable.".3"; #Value +my $ciscoTempTableState = $ciscoTempTable.".6"; #Status +# CiscoEnvMonTemperatureStatusEntry ::= + # ciscoEnvMonTemperatureStatusIndex Integer32 (0..2147483647), + # ciscoEnvMonTemperatureStatusDescr DisplayString, + # ciscoEnvMonTemperatureStatusValue Gauge32, + # ciscoEnvMonTemperatureThreshold Integer32, + # ciscoEnvMonTemperatureLastShutdown Integer32, + # ciscoEnvMonTemperatureState CiscoEnvMonState +my $ciscoFanTable = $ciscoEnvMonMIB.".1.4.1"; # Cisco fan table +my $ciscoFanTableIndex = $ciscoFanTable.".1"; #Index table +my $ciscoFanTableDesc = $ciscoFanTable.".2"; #Description +my $ciscoFanTableState = $ciscoFanTable.".3"; #Status +# CiscoEnvMonFanStatusEntry ::= + # ciscoEnvMonFanStatusIndex Integer32 (0..2147483647), + # ciscoEnvMonFanStatusDescr DisplayString, + # ciscoEnvMonFanState CiscoEnvMonState +my $ciscoPSTable = $ciscoEnvMonMIB.".1.5.1"; # Cisco power supply table +my $ciscoPSTableIndex = $ciscoPSTable.".1"; #Index table +my $ciscoPSTableDesc = $ciscoPSTable.".2"; #Description +my $ciscoPSTableState = $ciscoPSTable.".3"; #Status +# CiscoEnvMonSupplyStatusEntry ::= + # ciscoEnvMonSupplyStatusIndex Integer32 (0..2147483647), + # ciscoEnvMonSupplyStatusDescr DisplayString, + # ciscoEnvMonSupplyState CiscoEnvMonState, + # ciscoEnvMonSupplySource INTEGER + +# Nokia env mib +my $nokia_temp_tbl= "1.3.6.1.4.1.94.1.21.1.1.5"; +my $nokia_temp= "1.3.6.1.4.1.94.1.21.1.1.5.0"; +my $nokia_fan_table= "1.3.6.1.4.1.94.1.21.1.2"; +my $nokia_fan_status= "1.3.6.1.4.1.94.1.21.1.2.1.1.2"; +my $nokia_ps_table= "1.3.6.1.4.1.94.1.21.1.3"; +my $nokia_ps_temp= "1.3.6.1.4.1.94.1.21.1.3.1.1.2"; +my $nokia_ps_status= "1.3.6.1.4.1.94.1.21.1.3.1.1.3"; + +# Bluecoat env mib +my @bc_SensorCode=("","ok","unknown","not-installed","voltage-low-warning","voltage-low-critical", + "no-power","voltage-high-warning","voltage-high-critical","voltage-high-severe", + "temperature-high-warning","temperature-high-critical","temperature-high-severe", + "fan-slow-warning","fan-slow-critical","fan-stopped"); # BC element status returned by MIB +my @bc_status_nagios=(3,0,3,3,1,2,2,1,2,2,1,2,2,1,2,2); # nagios status equivallent to BC status +my @bc_SensorStatus=("","ok","unavailable","nonoperational"); # ok(1),unavailable(2),nonoperational(3) +my @bc_mesure=("","","","Enum","volts","celsius","rpm"); + +my @bc_DiskStatus=("","present","initializing","inserted","offline","removed","not-present","empty","bad","unknown"); +my @bc_dsk_status_nagios=(3,0,0,1,1,1,2,2,2,3); + +my $bc_sensor_table = "1.3.6.1.4.1.3417.2.1.1.1.1.1"; # sensor table +my $bc_sensor_units = "1.3.6.1.4.1.3417.2.1.1.1.1.1.3"; # cf bc_mesure +my $bc_sensor_Scale = "1.3.6.1.4.1.3417.2.1.1.1.1.1.4"; # * 10^value +my $bc_sensor_Value = "1.3.6.1.4.1.3417.2.1.1.1.1.1.5"; # value +my $bc_sensor_Code = "1.3.6.1.4.1.3417.2.1.1.1.1.1.6"; # bc_SensorCode +my $bc_sensor_Status = "1.3.6.1.4.1.3417.2.1.1.1.1.1.7"; # bc_SensorStatus +my $bc_sensor_Name = "1.3.6.1.4.1.3417.2.1.1.1.1.1.9"; # name + +my $bc_dsk_table = "1.3.6.1.4.1.3417.2.2.1.1.1.1"; #disk table +my $bc_dsk_status = "1.3.6.1.4.1.3417.2.2.1.1.1.1.3"; # cf bc_DiskStatus +my $bc_dsk_vendor = "1.3.6.1.4.1.3417.2.2.1.1.1.1.5"; # cf bc_DiskStatus +my $bc_dsk_serial = "1.3.6.1.4.1.3417.2.2.1.1.1.1.8"; # cf bc_DiskStatus + +# Ironport env mib + +my $iron_ps_table = "1.3.6.1.4.1.15497.1.1.1.8"; # ps table +my $iron_ps_status = "1.3.6.1.4.1.15497.1.1.1.8.1.2"; # ps status +#powerSupplyNotInstalled(1), powerSupplyHealthy(2), powerSupplyNoAC(3), powerSupplyFaulty(4) +my @iron_ps_status_name=("","powerSupplyNotInstalled","powerSupplyHealthy","powerSupplyNoAC","powerSupplyFaulty"); +my @iron_ps_status_nagios=(3,3,0,2,2); +my $iron_ps_ha = "1.3.6.1.4.1.15497.1.1.1.8.1.3"; # ps redundancy status +#powerSupplyRedundancyOK(1), powerSupplyRedundancyLost(2) +my @iron_ps_ha_name=("","powerSupplyRedundancyOK","powerSupplyRedundancyLost"); +my @iron_ps_ha_nagios=(3,0,1); +my $iron_ps_name = "1.3.6.1.4.1.15497.1.1.1.8.1.4"; # ps name + +my $iron_tmp_table = "1.3.6.1.4.1.15497.1.1.1.9"; # temp table +my $iron_tmp_celcius = "1.3.6.1.4.1.15497.1.1.1.9.1.2"; # temp in celcius +my $iron_tmp_name = "1.3.6.1.4.1.15497.1.1.1.9.1.3"; # name + +my $iron_fan_table = "1.3.6.1.4.1.15497.1.1.1.10"; # fan table +my $iron_fan_rpm = "1.3.6.1.4.1.15497.1.1.1.10.1.2"; # fan speed in RPM +my $iron_fan_name = "1.3.6.1.4.1.15497.1.1.1.10.1.3"; # fan name + +# Foundry BigIron Router Switch (FOUNDRY-SN-AGENT-MIB) + +my $foundry_temp = "1.3.6.1.4.1.1991.1.1.1.1.18.0"; # Chassis temperature in Deg C *2 +my $foundry_temp_warn = "1.3.6.1.4.1.1991.1.1.1.1.19.0"; # Chassis warn temperature in Deg C *2 +my $foundry_temp_crit = "1.3.6.1.4.1.1991.1.1.1.1.20.0"; # Chassis warn temperature in Deg C *2 +my $foundry_ps_table = "1.3.6.1.4.1.1991.1.1.1.2.1"; # PS table +my $foundry_ps_desc = "1.3.6.1.4.1.1991.1.1.1.2.1.1.2"; # PS desc +my $foundry_ps_status = "1.3.6.1.4.1.1991.1.1.1.2.1.1.3"; # PS status +my $foundry_fan_table = "1.3.6.1.4.1.1991.1.1.1.3.1"; # FAN table +my $foundry_fan_desc = "1.3.6.1.4.1.1991.1.1.1.3.1.1.2"; # FAN desc +my $foundry_fan_status = "1.3.6.1.4.1.1991.1.1.1.3.1.1.3"; # FAN status + +my @foundry_status = (3,0,2); # oper status : 1:other, 2: Normal, 3: Failure + +# Linux Net-SNMP with LM-SENSORS +my $linux_temp = "1.3.6.1.4.1.2021.13.16.2.1"; # temperature table +my $linux_temp_descr = "1.3.6.1.4.1.2021.13.16.2.1.2"; # temperature entry description +my $linux_temp_value = "1.3.6.1.4.1.2021.13.16.2.1.3"; # temperature entry value (mC) +my $linux_fan = "1.3.6.1.4.1.2021.13.16.3.1"; # fan table +my $linux_fan_descr = "1.3.6.1.4.1.2021.13.16.3.1.2"; # fan entry description +my $linux_fan_value = "1.3.6.1.4.1.2021.13.16.3.1.3"; # fan entry value (RPM) +my $linux_volt = "1.3.6.1.4.1.2021.13.16.4.1"; # voltage table +my $linux_volt_descr = "1.3.6.1.4.1.2021.13.16.4.1.2"; # voltage entry description +my $linux_volt_value = "1.3.6.1.4.1.2021.13.16.4.1.3"; # voltage entry value (mV) +my $linux_misc = "1.3.6.1.4.1.2021.13.16.4.1"; # misc table +my $linux_misc_descr = "1.3.6.1.4.1.2021.13.16.4.1.2"; # misc entry description +my $linux_misc_value = "1.3.6.1.4.1.2021.13.16.4.1.3"; # misc entry value + + +# Globals + +my $Version='1.3'; + +my $o_host = undef; # hostname +my $o_community = undef; # community +my $o_port = 161; # port +my $o_help= undef; # wan't some help ? +my $o_verb= undef; # verbose mode +my $o_version= undef; # print version +my $o_timeout= undef; # Timeout (Default 5) +my $o_perf= undef; # Output performance data +my $o_version2= undef; # use snmp v2c +# check type +my $o_check_type= "cisco"; # default Cisco +my @valid_types =("cisco","nokia","bc","iron","foundry","linux"); +my $o_temp= undef; # max temp +my $o_fan= undef; # min fan speed + +# SNMPv3 specific +my $o_login= undef; # Login for snmpv3 +my $o_passwd= undef; # Pass for snmpv3 +my $v3protocols=undef; # V3 protocol list. +my $o_authproto='md5'; # Auth protocol +my $o_privproto='des'; # Priv protocol +my $o_privpass= undef; # priv password + +# functions + +sub p_version { print "check_snmp_env version : $Version\n"; } + +sub print_usage { + print "Usage: $0 [-v] -H -C [-2] | (-l login -x passwd [-X pass -L ,]) [-p ] -T (cisco|nokia|bc|iron|foundry|linux) [-F ] [-c ] [-f] [-t ] [-V]\n"; +} + +sub isnnum { # Return true if arg is not a number + my $num = shift; + if ( $num =~ /^(\d+\.?\d*)|(^\.\d+)$/ ) { return 0 ;} + return 1; +} + +sub set_status { # return worst status with this order : OK, unknwonw, warning, critical + my $new_status=shift; + my $cur_status=shift; + if (($cur_status == 0)|| ($new_status==$cur_status)){ return $new_status; } + if ($new_status==3) { return $cur_status; } + if ($new_status > $cur_status) {return $new_status;} + return $cur_status; +} + +sub help { + print "\nSNMP environmental Monitor for Nagios version ",$Version,"\n"; + print "GPL Licence, (c)2006-2007 Patrick Proy\n\n"; + print_usage(); + print <, + : Authentication protocol (md5|sha : default md5) + : Priv protocole (des|aes : default des) +-P, --port=PORT + SNMP port (Default 161) +-T, --type=cisco|nokia|bc|iron|foundry + Environemental check : + cisco : All Cisco equipements : voltage,temp,fan,power supply + (will try to check everything in the env mib) + nokia : Nokia IP platforms : fan and power supply + bc : BlueCoat platforms : fans, power supply, voltage, disks + iron : IronPort platforms : fans, power supply, temp + foundry : Foundry Network platforms : power supply, temp + linux : Net-SNMP with LM-SENSORS : temp, fan, volt, misc +-F, --fan= + Minimum fan rpm value (only needed for 'iron' & 'linux') +-c, --celcius= + Maximum temp in degree celcius (only needed for 'iron' & 'linux') +-f, --perfparse + Perfparse compatible output +-t, --timeout=INTEGER + timeout for SNMP in seconds (Default: 5) +-V, --version + prints version number +EOT +} + +# For verbose output +sub verb { my $t=shift; print $t,"\n" if defined($o_verb) ; } + +sub check_options { + Getopt::Long::Configure ("bundling"); + GetOptions( + 'v' => \$o_verb, 'verbose' => \$o_verb, + 'h' => \$o_help, 'help' => \$o_help, + 'H:s' => \$o_host, 'hostname:s' => \$o_host, + 'p:i' => \$o_port, 'port:i' => \$o_port, + 'C:s' => \$o_community, 'community:s' => \$o_community, + 'l:s' => \$o_login, 'login:s' => \$o_login, + 'x:s' => \$o_passwd, 'passwd:s' => \$o_passwd, + 'X:s' => \$o_privpass, 'privpass:s' => \$o_privpass, + 'L:s' => \$v3protocols, 'protocols:s' => \$v3protocols, + 't:i' => \$o_timeout, 'timeout:i' => \$o_timeout, + 'V' => \$o_version, 'version' => \$o_version, + + '2' => \$o_version2, 'v2c' => \$o_version2, + 'f' => \$o_perf, 'perfparse' => \$o_perf, + 'T:s' => \$o_check_type, 'type:s' => \$o_check_type, + 'F:i' => \$o_fan, 'fan:i' => \$o_fan, + 'c:i' => \$o_temp, 'celcius:i' => \$o_temp + ); + # check the -T option + my $T_option_valid=0; + foreach (@valid_types) { if ($_ eq $o_check_type) {$T_option_valid=1} }; + if ( $T_option_valid == 0 ) + {print "Invalid check type (-T)!\n"; print_usage(); exit $ERRORS{"UNKNOWN"}} + # Basic checks + if (defined($o_timeout) && (isnnum($o_timeout) || ($o_timeout < 2) || ($o_timeout > 60))) + { print "Timeout must be >1 and <60 !\n"; print_usage(); exit $ERRORS{"UNKNOWN"}} + if (!defined($o_timeout)) {$o_timeout=5;} + if (defined ($o_help) ) { help(); exit $ERRORS{"UNKNOWN"}}; + if (defined($o_version)) { p_version(); exit $ERRORS{"UNKNOWN"}}; + if ( ! defined($o_host) ) # check host and filter + { print_usage(); exit $ERRORS{"UNKNOWN"}} + # check snmp information + if ( !defined($o_community) && (!defined($o_login) || !defined($o_passwd)) ) + { print "Put snmp login info!\n"; print_usage(); exit $ERRORS{"UNKNOWN"}} + if ((defined($o_login) || defined($o_passwd)) && (defined($o_community) || defined($o_version2)) ) + { print "Can't mix snmp v1,2c,3 protocols!\n"; print_usage(); exit $ERRORS{"UNKNOWN"}} + if (defined ($v3protocols)) { + if (!defined($o_login)) { print "Put snmp V3 login info with protocols!\n"; print_usage(); exit $ERRORS{"UNKNOWN"}} + my @v3proto=split(/,/,$v3protocols); + if ((defined ($v3proto[0])) && ($v3proto[0] ne "")) {$o_authproto=$v3proto[0]; } # Auth protocol + if (defined ($v3proto[1])) {$o_privproto=$v3proto[1]; } # Priv protocol + if ((defined ($v3proto[1])) && (!defined($o_privpass))) { + print "Put snmp V3 priv login info with priv protocols!\n"; print_usage(); exit $ERRORS{"UNKNOWN"}} + } +} + +########## MAIN ####### + +check_options(); + +# Check gobal timeout if snmp screws up +if (defined($TIMEOUT)) { + verb("Alarm at $TIMEOUT + 5"); + alarm($TIMEOUT+5); +} else { + verb("no global timeout defined : $o_timeout + 10"); + alarm ($o_timeout+10); +} + +$SIG{'ALRM'} = sub { + print "No answer from host\n"; + exit $ERRORS{"UNKNOWN"}; +}; + +# Connect to host +my ($session,$error); +if ( defined($o_login) && defined($o_passwd)) { + # SNMPv3 login + verb("SNMPv3 login"); + if (!defined ($o_privpass)) { + verb("SNMPv3 AuthNoPriv login : $o_login, $o_authproto"); + ($session, $error) = Net::SNMP->session( + -hostname => $o_host, + -version => '3', + -username => $o_login, + -authpassword => $o_passwd, + -authprotocol => $o_authproto, + -timeout => $o_timeout + ); + } else { + verb("SNMPv3 AuthPriv login : $o_login, $o_authproto, $o_privproto"); + ($session, $error) = Net::SNMP->session( + -hostname => $o_host, + -version => '3', + -username => $o_login, + -authpassword => $o_passwd, + -authprotocol => $o_authproto, + -privpassword => $o_privpass, + -privprotocol => $o_privproto, + -timeout => $o_timeout + ); + } +} else { + if (defined ($o_version2)) { + # SNMPv2 Login + verb("SNMP v2c login"); + ($session, $error) = Net::SNMP->session( + -hostname => $o_host, + -version => 2, + -community => $o_community, + -port => $o_port, + -timeout => $o_timeout + ); + } else { + # SNMPV1 login + verb("SNMP v1 login"); + ($session, $error) = Net::SNMP->session( + -hostname => $o_host, + -community => $o_community, + -port => $o_port, + -timeout => $o_timeout + ); + } +} +if (!defined($session)) { + printf("ERROR opening session: %s.\n", $error); + exit $ERRORS{"UNKNOWN"}; +} + +my $exit_val=undef; +########### Cisco env checks ############## + +if ($o_check_type eq "cisco") { + +verb("Checking cisco env"); + +# Get load table +my $resultat = (Net::SNMP->VERSION < 4) ? + $session->get_table($ciscoEnvMonMIB) + : $session->get_table(Baseoid => $ciscoEnvMonMIB); + +if (!defined($resultat)) { + printf("ERROR: Description table : %s.\n", $session->error); + $session->close; + exit $ERRORS{"UNKNOWN"}; +} +$session->close; + +# Get env data index +my (@voltindex,@tempindex,@fanindex,@psindex)=(undef,undef,undef,undef); +my ($voltexist,$tempexist,$fanexist,$psexist)=(0,0,0,0); +my @oid=undef; +foreach my $key ( keys %$resultat) { + verb("OID : $key, Desc : $$resultat{$key}"); + if ( $key =~ /$ciscoVoltageTableDesc/ ) { + @oid=split (/\./,$key); + $voltindex[$voltexist++] = pop(@oid); + } + if ( $key =~ /$ciscoTempTableDesc/ ) { + @oid=split (/\./,$key); + $tempindex[$tempexist++] = pop(@oid); + } + if ( $key =~ /$ciscoFanTableDesc/ ) { + @oid=split (/\./,$key); + $fanindex[$fanexist++] = pop(@oid); + } + if ( $key =~ /$ciscoPSTableDesc/ ) { + @oid=split (/\./,$key); + $psindex[$psexist++] = pop(@oid); + } +} + +if ( ($voltexist ==0) && ($tempexist ==0) && ($fanexist ==0) && ($psexist ==0) ) { + print "No Environemental data found : UNKNOWN"; + exit $ERRORS{"UNKNOWN"}; +} + +my $perf_output=""; +# Get the data +my ($i,$cur_status)=(undef,undef); + +my $volt_global=0; +my %volt_status; +if ($fanexist !=0) { + for ($i=0;$i < $voltexist; $i++) { + $cur_status=$$resultat{$ciscoVoltageTableState. "." . $voltindex[$i]}; + verb ($$resultat{$ciscoVoltageTableDesc .".".$voltindex[$i]}); + verb ($cur_status); + if (!defined ($cur_status)) { ### Error TODO + $volt_global=1; + } + if (defined($$resultat{$ciscoVoltageTableValue."." . $voltindex[$i]})) { + $perf_output.=" '".$$resultat{$ciscoVoltageTableDesc .".".$voltindex[$i]}."'=" ; + $perf_output.=$$resultat{$ciscoVoltageTableValue."." . $voltindex[$i]}; + } + if ($Nagios_state[$CiscoEnvMonNagios{$cur_status}] ne "OK") { + $volt_global= 1; + $volt_status{$$resultat{$ciscoVoltageTableDesc .".".$voltindex[$i]}}=$cur_status; + } + } +} + + +my $temp_global=0; +my %temp_status; +if ($tempexist !=0) { + for ($i=0;$i < $tempexist; $i++) { + $cur_status=$$resultat{$ciscoTempTableState . "." . $tempindex[$i]}; + verb ($$resultat{$ciscoTempTableDesc .".".$tempindex[$i]}); + verb ($cur_status); + if (!defined ($cur_status)) { ### Error TODO + $temp_global=1; + } + if (defined($$resultat{$ciscoTempTableValue."." . $tempindex[$i]})) { + $perf_output.=" '".$$resultat{$ciscoTempTableDesc .".".$tempindex[$i]}."'=" ; + $perf_output.=$$resultat{$ciscoTempTableValue."." . $tempindex[$i]}; + } + if ($Nagios_state[$CiscoEnvMonNagios{$cur_status}] ne "OK") { + $temp_global= 1; + $temp_status{$$resultat{$ciscoTempTableDesc .".".$tempindex[$i]}}=$cur_status; + } + } +} + + +my $fan_global=0; +my %fan_status; +if ($fanexist !=0) { + for ($i=0;$i < $fanexist; $i++) { + $cur_status=$$resultat{$ciscoFanTableState . "." . $fanindex[$i]}; + verb ($$resultat{$ciscoFanTableDesc .".".$fanindex[$i]}); + verb ($cur_status); + if (!defined ($cur_status)) { ### Error TODO + $fan_global=1; + } + if ($Nagios_state[$CiscoEnvMonNagios{$cur_status}] ne "OK") { + $fan_global= 1; + $fan_status{$$resultat{$ciscoFanTableDesc .".".$fanindex[$i]}}=$cur_status; + } + } +} + +my $ps_global=0; +my %ps_status; +if ($psexist !=0) { + for ($i=0;$i < $psexist; $i++) { + $cur_status=$$resultat{$ciscoPSTableState . "." . $psindex[$i]}; + if (!defined ($cur_status)) { ### Error TODO + $fan_global=1; + } + if ($Nagios_state[$CiscoEnvMonNagios{$cur_status}] ne "OK") { + $ps_global= 1; + $ps_status{$$resultat{$ciscoPSTableDesc .".".$psindex[$i]}}=$cur_status; + } + } +} + +my $global_state=0; +my $output=""; + +if ($fanexist !=0) { + if ($fan_global ==0) { + $output .= $fanexist." Fan OK"; + $global_state=1 if ($global_state==0); + } else { + foreach (keys %fan_status) { + $output .= "Fan " . $_ . ":" . $CiscoEnvMonState {$fan_status{$_}} ." "; + if ($global_state < $CiscoEnvMonNagios{$fan_status{$_}} ) { + $global_state = $CiscoEnvMonNagios{$fan_status{$_}} ; + } + } + } +} + +if ($psexist !=0) { + $output .= ", " if ($output ne ""); + if ($ps_global ==0) { + $output .= $psexist." ps OK"; + $global_state=1 if ($global_state==0); + } else { + foreach (keys %ps_status) { + $output .= "ps " . $_ . ":" . $CiscoEnvMonState {$ps_status{$_}} ." "; + if ($global_state < $CiscoEnvMonNagios{$ps_status{$_}} ) { + $global_state = $CiscoEnvMonNagios{$ps_status{$_}} ; + } + } + } +} + +if ($voltexist !=0) { + $output .= ", " if ($output ne ""); + if ($volt_global ==0) { + $output .= $voltexist." volt OK"; + $global_state=1 if ($global_state==0); + } else { + foreach (keys %volt_status) { + $output .= "volt " . $_ . ":" . $CiscoEnvMonState {$volt_status{$_}} ." "; + if ($global_state < $CiscoEnvMonNagios{$volt_status{$_}} ) { + $global_state = $CiscoEnvMonNagios{$volt_status{$_}} ; + } + } + } +} + +if ($tempexist !=0) { + $output .= ", " if ($output ne ""); + if ($temp_global ==0) { + $output .= $tempexist." temp OK"; + $global_state=1 if ($global_state==0); + } else { + foreach (keys %temp_status) { + $output .= "temp " . $_ . ":" . $CiscoEnvMonState {$temp_status{$_}} ." "; + if ($global_state < $CiscoEnvMonNagios{$temp_status{$_}} ) { + $global_state = $CiscoEnvMonNagios{$temp_status{$_}} ; + } + } + } +} + +#print $output," : ",$Nagios_state[$global_state]," | ",$perf_output,"\n"; +print $output," : ",$Nagios_state[$global_state],"\n"; +$exit_val=$ERRORS{$Nagios_state[$global_state]}; + +exit $exit_val; + +} + +############# Nokia checks +if ($o_check_type eq "nokia") { + +verb("Checking nokia env"); + +my $resultat; +# status : 0=ok, 1=nok, 2=temp prb +my ($fan_status,$ps_status,$temp_status)=(0,0,0); +my ($fan_exist,$ps_exist,$temp_exist)=(0,0,0); +my ($num_fan,$num_ps)=(0,0); +my ($num_fan_nok,$num_ps_nok)=(0,0); +my $global_status=0; +my $output=""; +# get temp +$resultat = (Net::SNMP->VERSION < 4) ? + $session->get_table($nokia_temp_tbl) + : $session->get_table(Baseoid => $nokia_temp_tbl); +if (defined($resultat)) { + verb ("temp found"); + $temp_exist=1; + if ($$resultat{$nokia_temp} != 1) { + $temp_status=2;$global_status=1; + $output="Temp CRITICAL "; + } else { + $output="Temp OK "; + } +} + +# Get fan table +$resultat = (Net::SNMP->VERSION < 4) ? + $session->get_table($nokia_fan_table) + : $session->get_table(Baseoid => $nokia_fan_table); + +if (defined($resultat)) { + $fan_exist=1; + foreach my $key ( keys %$resultat) { + verb("OID : $key, Desc : $$resultat{$key}"); + if ( $key =~ /$nokia_fan_status/ ) { + if ($$resultat{$key} != 1) { $fan_status=1; $num_fan_nok++} + $num_fan++; + } + } + if ($fan_status==0) { + $output.= ", ".$num_fan." fan OK"; + } else { + $output.= ", ".$num_fan_nok."/".$num_fan." fan CRITICAL"; + $global_status=2; + } +} + +# Get ps table +$resultat = (Net::SNMP->VERSION < 4) ? + $session->get_table($nokia_ps_table) + : $session->get_table(Baseoid => $nokia_ps_table); + +if (defined($resultat)) { + $ps_exist=1; + foreach my $key ( keys %$resultat) { + verb("OID : $key, Desc : $$resultat{$key}"); + if ( $key =~ /$nokia_ps_status/ ) { + if ($$resultat{$key} != 1) { $ps_status=1; $num_ps_nok++;} + $num_ps++; + } + if ( $key =~ /$nokia_ps_temp/ ) { + if ($$resultat{$key} != 1) { if ($ps_status==0) {$ps_status=2;$num_ps_nok++;} } + } + } + if ($ps_status==0) { + $output.= ", ".$num_ps." ps OK"; + } elsif ($ps_status==2) { + $output.= ", ".$num_ps_nok."/".$num_ps." ps WARNING (temp)"; + if ($global_status != 2) {$global_status=1;} + } else { + $output.= ", ".$num_ps_nok."/".$num_ps." ps CRITICAL"; + $global_status=2; + } +} + +$session->close; + +verb ("status : $global_status"); + +if ( ($fan_exist+$ps_exist+$temp_exist) == 0) { + print "No environemental informations found : UNKNOWN\n"; + exit $ERRORS{"UNKNOWN"}; +} + +if ($global_status==0) { + print $output." : all OK\n"; + exit $ERRORS{"OK"}; +} + +if ($global_status==1) { + print $output." : WARNING\n"; + exit $ERRORS{"WARNING"}; +} + +if ($global_status==2) { + print $output." : CRITICAL\n"; + exit $ERRORS{"CRITICAL"}; +} +} + +############# Bluecoat checks +if ($o_check_type eq "bc") { + + verb("Checking bluecoat env"); + + my $resultat; + my $global_status=0; + my ($num_fan,$num_other,$num_volt,$num_temp,$num_disk)=(0,0,0,0,0); + my ($num_fan_ok,$num_other_ok,$num_volt_ok,$num_temp_ok,$num_disk_ok)=(0,0,0,0,0); + my $output=""; + my $output_perf=""; + + + # get sensor table + $resultat = (Net::SNMP->VERSION < 4) ? + $session->get_table($bc_sensor_table) + : $session->get_table(Baseoid => $bc_sensor_table); + if (defined($resultat)) { + verb ("sensor table found"); + my ($sens_name,$sens_status,$sens_value,$sens_unit)=(undef,undef,undef,undef); + foreach my $key ( keys %$resultat) { + if ($key =~ /$bc_sensor_Name/) { + $sens_name = $$resultat{$key}; + $key =~ s/$bc_sensor_Name//; + $sens_unit = $$resultat{$bc_sensor_units.$key}; + if ($$resultat{$bc_sensor_Status.$key} != 1) { # sensor not operating : output and status unknown + if ($output ne "") { $output.=", ";} + $output .= $sens_name ." sensor ".$bc_SensorStatus[$$resultat{$bc_sensor_Status.$key}]; + if ($global_status==0) {$global_status=3;} + } else { # Get status + $sens_status=$bc_status_nagios[$$resultat{$bc_sensor_Code.$key}]; + if ($sens_status != 0) { # warn/critical/unknown : output + if ($output ne "") { $output.=", ";} + $output .= $sens_name . ":".$bc_SensorCode[$sens_status]; + set_status($sens_status,$global_status); + } + } + if (defined($o_perf)) { + if ($output_perf ne "") { $output_perf .=" ";} + $output_perf .= "'".$sens_name."'="; + my $perf_value = $$resultat{$bc_sensor_Value.$key} * 10 ** $$resultat{$bc_sensor_Scale.$key}; + $output_perf .= $perf_value; + } + ### FAN + if ($bc_mesure[$sens_unit] eq "rpm") { + $num_fan++;if ($sens_status == 0) { $num_fan_ok++; } + } elsif ($bc_mesure[$sens_unit] eq "celsius") { + $num_fan++;if ($sens_status == 0) { $num_temp_ok++; } + } elsif ($bc_mesure[$sens_unit] eq "volts") { + $num_volt++;if ($sens_status == 0) { $num_volt_ok++; } + } else { + $num_other++;if ($sens_status == 0) { $num_other_ok++;}} + } + } + } + + # Get disk table + $resultat = (Net::SNMP->VERSION < 4) ? + $session->get_table($bc_dsk_table) + : $session->get_table(Baseoid => $bc_dsk_table); + + if (defined($resultat)) { + foreach my $key ( keys %$resultat) { + verb("OID : $key, Desc : $$resultat{$key}"); + my ($dsk_name,$dsk_status)=(undef,undef,undef); + if ( $key =~ /$bc_dsk_status/ ) { + $num_disk++; + $dsk_status=$bc_dsk_status_nagios[$$resultat{$key}]; + if ( $dsk_status != 0) { + $key =~ s/$bc_dsk_status//; + $dsk_name = $$resultat{$bc_dsk_vendor.$key} . "(".$$resultat{$bc_dsk_serial.$key} . ")"; + if ($output ne "") { $output.=", ";} + $output .= $dsk_name . ":" . $bc_DiskStatus[$$resultat{$bc_dsk_status.$key}]; + set_status($dsk_status,$global_status); + } else { + $num_disk_ok++; + } + } + } + } + + if ($num_fan+$num_other+$num_volt+$num_temp+$num_disk == 0) { + print "No information found : UNKNOWN\n"; + exit $ERRORS{"UNKNOWN"}; + } + + if ($output ne "") { $output.=", ";} + if ($num_fan_ok != 0) { $output.= $num_fan_ok." fan OK ";} + if ($num_other_ok != 0) { $output.= $num_other_ok." other OK ";} + if ($num_volt_ok != 0) { $output.= $num_volt_ok." voltage OK ";} + if ($num_temp_ok != 0) { $output.= $num_temp_ok." temp OK ";} + if ($num_disk_ok != 0) { $output.= $num_disk_ok." disk OK ";} + + if (defined($o_perf)) { $output_perf = " | " . $output_perf;} + if ($global_status==3) { + print $output," : UNKNOWN",$output_perf,"\n"; + exit $ERRORS{"UNKNOWN"}; + } + if ($global_status==2) { + print $output," : CRITICAL",$output_perf,"\n"; + exit $ERRORS{"CRITICAL"}; + } + if ($global_status==1) { + print $output," : WARNING",$output_perf,"\n"; + exit $ERRORS{"WARNING"}; + } + print $output," : OK",$output_perf,"\n"; + exit $ERRORS{"OK"}; + +} + + +############# Ironport checks +if ($o_check_type eq "iron") { + +verb("Checking Ironport env"); + +my $resultat; +# status : 0=ok, 1=warn, 2=crit +my ($fan_status,$ps_status,$temp_status)=(0,0,0); +my ($fan_exist,$ps_exist,$temp_exist)=(0,0,0); +my ($num_fan,$num_ps,$num_temp)=(0,0,0); +my ($num_fan_nok,$num_ps_nok,$num_temp_nok)=(0,0,0); +my $global_status=0; +my $output=""; +# get temp if $o_temp is defined +if (defined($o_temp)) { + verb("Checking temp < $o_temp"); + $resultat = (Net::SNMP->VERSION < 4) ? + $session->get_table($iron_tmp_table) + : $session->get_table(Baseoid => $iron_tmp_table); + if (defined($resultat)) { + verb ("temp found"); + $temp_exist=1; + foreach my $key ( keys %$resultat) { + verb("OID : $key, Desc : $$resultat{$key}"); + if ( $key =~ /$iron_tmp_celcius/ ) { + verb("Status : $$resultat{$key}"); + if ($$resultat{$key} > $o_temp) { + my @index_oid=split(/\./,$key); + my $index_oid_key=pop(@index_oid); + $output .= ",Temp : ". $$resultat{ $iron_tmp_name.".".$index_oid_key}." : ".$$resultat{$key}." C"; + $temp_status=2; + $num_temp_nok++; + } + $num_temp++; + } + } + if ($temp_status==0) { + $output.= ", ".$num_temp." temp < ".$o_temp." OK"; + } else { + $output.= ", ".$num_temp_nok."/".$num_temp." temp probes CRITICAL"; + $global_status=2; + } + } +} + +# Get fan status if $o_fan is defined +if (defined($o_fan)) { + verb("Checking fan > $o_fan"); + $resultat = (Net::SNMP->VERSION < 4) ? + $session->get_table($iron_fan_table) + : $session->get_table(Baseoid => $iron_fan_table); + if (defined($resultat)) { + verb ("fan found"); + $fan_exist=1; + foreach my $key ( keys %$resultat) { + verb("OID : $key, Desc : $$resultat{$key}"); + if ( $key =~ /$iron_fan_rpm/ ) { + verb("Status : $$resultat{$key}"); + if ($$resultat{$key} < $o_fan) { + my @index_oid=split(/\./,$key); + my $index_oid_key=pop(@index_oid); + $output .= ",Fan ". $$resultat{ $iron_fan_name.".".$index_oid_key}." : ".$$resultat{$key}." RPM"; + $fan_status=2; + $num_fan_nok++; + } + $num_fan++; + } + } + if ($fan_status==0) { + $output.= ", ".$num_fan." fan > ".$o_fan." OK"; + } else { + $output.= ", ".$num_fan_nok."/".$num_fan." fans CRITICAL"; + $global_status=2; + } + } +} + +# Get power supply status + verb("Checking PS"); + $resultat = (Net::SNMP->VERSION < 4) ? + $session->get_table($iron_ps_table) + : $session->get_table(Baseoid => $iron_ps_table); + if (defined($resultat)) { + verb ("ps found"); + $ps_exist=1; + foreach my $key ( keys %$resultat) { + verb("OID : $key, Desc : $$resultat{$key}"); + if ( $key =~ /$iron_ps_status/ ) { + verb("Status : $iron_ps_status_name[$$resultat{$key}]"); + if ($iron_ps_status_nagios[$$resultat{$key}] != 0) { + my @index_oid=split(/\./,$key); + my $index_oid_key=pop(@index_oid); + $output .= ",PS ". $$resultat{$iron_ps_name.".".$index_oid_key}." : ".$iron_ps_status_name[$$resultat{$key}]; + $ps_status=2; + $num_ps_nok++; + } + $num_ps++; + } + } + if ($ps_status==0) { + $output.= ", ".$num_ps." ps OK"; + } else { + $output.= ", ".$num_ps_nok."/".$num_ps." ps CRITICAL"; + $global_status=2; + } + } + +$session->close; + +verb ("status : $global_status"); + +if ( ($fan_exist+$ps_exist+$temp_exist) == 0) { + print "No environemental informations found : UNKNOWN\n"; + exit $ERRORS{"UNKNOWN"}; +} + +$output =~ s/^,//; + +if ($global_status==0) { + print $output." : all OK\n"; + exit $ERRORS{"OK"}; +} + +if ($global_status==1) { + print $output." : WARNING\n"; + exit $ERRORS{"WARNING"}; +} + +if ($global_status==2) { + print $output." : CRITICAL\n"; + exit $ERRORS{"CRITICAL"}; +} +} + + +########### Foundry env checks ############## + +if ($o_check_type eq "foundry") { + +verb("Checking foundry env"); + +my $global_status=0; # status to UNKNOWN +my $output=""; + +# Get temperature + +my @foundry_temp_oid=($foundry_temp,$foundry_temp_warn,$foundry_temp_crit); + +my $result_temp = $session->get_request( + Varbindlist => \@foundry_temp_oid +); + +my $temp_found=0; +if (defined($result_temp)) { + $temp_found=1; + #Temp found + $output = "Temp : " . $$result_temp{$foundry_temp} / 2; + if ($$result_temp{$foundry_temp} > $$result_temp{$foundry_temp_crit}) { # Temp above critical + $output.= " > ". $$result_temp{$foundry_temp_crit} / 2 . " : CRITICAL"; + $global_status=3; + } elsif ( $$result_temp{$foundry_temp} > $$result_temp{$foundry_temp_warn}) { # Temp above warning + $output.= " > ". $$result_temp{$foundry_temp_warn} / 2 . " : WARNING"; + $global_status=2; + } else { + $output.= " < ". $$result_temp{$foundry_temp_warn} / 2 . " : OK"; + $global_status=1; + } +} + +# Get PS table (TODO : Bug in FAN table, see with Foundry). + +my $result_ps = (Net::SNMP->VERSION < 4) ? + $session->get_table($foundry_ps_table) + : $session->get_table(Baseoid => $foundry_ps_table); + +my $ps_num=0; +if (defined($result_ps)) { + $output .=", " if defined($output); + foreach my $key ( keys %$result_ps) { + verb("OID : $key, Desc : $$result_ps{$key}"); + if ($$result_ps{$key} =~ /$foundry_ps_desc/) { + $ps_num++; + my @oid_list = split (/\./,$key); + my $index_ps = pop (@oid_list); + $index_ps= $foundry_ps_status . "." . $index_ps; + if (defined ($$result_ps{$index_ps})) { + if ($$result_ps{$index_ps} == 3) { + $output.="PS ".$$result_ps{$key}." : FAILURE"; + $global_status=3; + } elsif ($$result_ps{$index_ps} == 2) { + $global_status=1 if ($global_status==0); + } else { + $output.= "ps ".$$result_ps{$key}." : OTHER"; + } + } else { + $output.= "ps ".$$result_ps{$key}." : UNDEFINED STATUS"; + } + } + } +} + +$session->close; + +if (($ps_num+$temp_found) == 0) { + print "No data found : UNKNOWN\n"; + exit $ERRORS{"UNKNOWN"}; +} + +if ($global_status==1) { + print $output." : all OK\n"; + exit $ERRORS{"OK"}; +} + +if ($global_status==2) { + print $output." : WARNING\n"; + exit $ERRORS{"WARNING"}; +} + +if ($global_status==3) { + print $output." : CRITICAL\n"; + exit $ERRORS{"CRITICAL"}; +} + +print $output." : UNKNOWN\n"; +exit $ERRORS{"UNKNOWN"}; + +} + +########### Cisco env checks ############## +if ($o_check_type eq "linux") { + + verb("Checking linux env"); + + print "Not implemented yet : UNKNOWN\n"; + exit $ERRORS{"UNKNOWN"}; +} + +print "Unknown check type : UNKNOWN\n"; +exit $ERRORS{"UNKNOWN"}; diff --git a/check_snmp/trunk/check_snmp_int.pl b/check_snmp/trunk/check_snmp_int.pl new file mode 100644 index 0000000..1647a9e --- /dev/null +++ b/check_snmp/trunk/check_snmp_int.pl @@ -0,0 +1,836 @@ +#!/usr/bin/perl -w +############################## check_snmp_int ############## +my $Version='1.24'; +# Date : Oct 10 2007 +# Author : Patrick Proy ( patrick at proy.org ) +# Help : http://nagios.manubulon.com +# Licence : GPL - http://www.fsf.org/licenses/gpl.txt +# Contrib : J. Jungmann, S. Probst, R. Leroy, M. Berger +# TODO : +# Maybe put base directory for performance as an option +################################################################# +# +# Help : ./check_snmp_int.pl -h +# +use strict; +use Net::SNMP; +use Getopt::Long; + +############### BASE DIRECTORY FOR TEMP FILE ######## +my $o_base_dir="/tmp/tmp_Nagios_int."; +my $file_history=200; # number of data to keep in files. + +# Nagios specific + +my $TIMEOUT = 15; +my %ERRORS=('OK'=>0,'WARNING'=>1,'CRITICAL'=>2,'UNKNOWN'=>3,'DEPENDENT'=>4); + +# SNMP Datas + +my $inter_table= '.1.3.6.1.2.1.2.2.1'; +my $index_table = '1.3.6.1.2.1.2.2.1.1'; +my $descr_table = '1.3.6.1.2.1.2.2.1.2'; +my $oper_table = '1.3.6.1.2.1.2.2.1.8.'; +my $admin_table = '1.3.6.1.2.1.2.2.1.7.'; +my $speed_table = '1.3.6.1.2.1.2.2.1.5.'; +my $speed_table_64 = '1.3.6.1.2.1.31.1.1.1.15.'; +my $in_octet_table = '1.3.6.1.2.1.2.2.1.10.'; +my $in_octet_table_64 = '1.3.6.1.2.1.31.1.1.1.6.'; +my $in_error_table = '1.3.6.1.2.1.2.2.1.14.'; +my $in_discard_table = '1.3.6.1.2.1.2.2.1.13.'; +my $out_octet_table = '1.3.6.1.2.1.2.2.1.16.'; +my $out_octet_table_64 = '1.3.6.1.2.1.31.1.1.1.10.'; +my $out_error_table = '1.3.6.1.2.1.2.2.1.20.'; +my $out_discard_table = '1.3.6.1.2.1.2.2.1.19.'; + +my %status=(1=>'UP',2=>'DOWN',3=>'TESTING',4=>'UNKNOWN',5=>'DORMANT',6=>'NotPresent',7=>'lowerLayerDown'); + +# Globals + + +# Standard options +my $o_host = undef; # hostname +my $o_port = 161; # port +my $o_descr = undef; # description filter +my $o_help= undef; # wan't some help ? +my $o_admin= undef; # admin status instead of oper +my $o_inverse= undef; # Critical when up +my $o_dormant= undef; # Dormant state is OK +my $o_verb= undef; # verbose mode +my $o_version= undef; # print version +my $o_noreg= undef; # Do not use Regexp for name +my $o_short= undef; # set maximum of n chars to be displayed +my $o_label= undef; # add label before speed (in, out, etc...). +# Performance data options +my $o_perf= undef; # Output performance data +my $o_perfe= undef; # Output discard/error also in perf data +my $o_perfs= undef; # include speed in performance output (-S) +my $o_perfp= undef; # output performance data in % of max speed (-y) +my $o_perfr= undef; # output performance data in bits/s or Bytes/s (-Y) +# Speed/error checks +my $o_checkperf= undef; # checks in/out/err/disc values +my $o_delta= 300; # delta of time of perfcheck (default 5min) +my $o_ext_checkperf= undef; # extended perf checks (+error+discard) +my $o_warn_opt= undef; # warning options +my $o_crit_opt= undef; # critical options +my $o_kbits= undef; # Warn and critical in Kbits instead of KBytes +my @o_warn= undef; # warning levels of perfcheck +my @o_crit= undef; # critical levels of perfcheck +my $o_highperf= undef; # Use 64 bits counters +my $o_meg= undef; # output in MBytes or Mbits (-M) +my $o_gig= undef; # output in GBytes or Gbits (-G) +my $o_prct= undef; # output in % of max speed (-u) + +my $o_timeout= undef; # Timeout (Default 5) +# SNMP Message size parameter (Makina Corpus contrib) +my $o_octetlength=undef; +# Login options specific +my $o_community = undef; # community +my $o_version2 = undef; #use snmp v2c +my $o_login= undef; # Login for snmpv3 +my $o_passwd= undef; # Pass for snmpv3 +my $v3protocols=undef; # V3 protocol list. +my $o_authproto='md5'; # Auth protocol +my $o_privproto='des'; # Priv protocol +my $o_privpass= undef; # priv password + +# Readable names for counters (M. Berger contrib) +my @countername = ( "in=" , "out=" , "errors-in=" , "errors-out=" , "discard-in=" , "discard-out=" ); +my $checkperf_out_desc; + +# functions + +sub read_file { + # Input : File, items_number + # Returns : array of value : [line][item] + my ($traffic_file,$items_number)=@_; + my ($ligne,$n_rows)=(undef,0); + my (@last_values,@file_values,$i); + open(FILE,"<".$traffic_file) || return (1,0,0); + + while($ligne = ) + { + chomp($ligne); + @file_values = split(":",$ligne); + #verb("@file_values"); + if ($#file_values >= ($items_number-1)) { + # check if there is enough data, else ignore line + for ( $i=0 ; $i< $items_number ; $i++ ) {$last_values[$n_rows][$i]=$file_values[$i];} + $n_rows++; + } + } + close FILE; + if ($n_rows != 0) { + return (0,$n_rows,@last_values); + } else { + return (1,0,0); + } +} + +sub write_file { + # Input : file , rows, items, array of value : [line][item] + # Returns : 0 / OK, 1 / error + my ($file_out,$rows,$item,@file_values)=@_; + my $start_line= ($rows > $file_history) ? $rows - $file_history : 0; + if ( open(FILE2,">".$file_out) ) { + for (my $i=$start_line;$i<$rows;$i++) { + for (my $j=0;$j<$item;$j++) { + print FILE2 $file_values[$i][$j]; + if ($j != ($item -1)) { print FILE2 ":" }; + } + print FILE2 "\n"; + } + close FILE2; + return 0; + } else { + return 1; + } +} + +sub p_version { print "check_snmp_int version : $Version\n"; } + +sub print_usage { + print "Usage: $0 [-v] -H -C [-2] | (-l login -x passwd [-X pass -L ,) [-p ] -n [-i -a -D] [-r] [-f[eSyY]] [-k[qBMGu] -g -w -c -d] [-o ] [-t ] [-s] --label [-V]\n"; +} + +sub isnnum { # Return true if arg is not a number + my $num = shift; + if ( $num =~ /^(\d+\.?\d*)|(^\.\d+)$/ ) { return 0 ;} + return 1; +} + +sub help { + print "\nSNMP Network Interface Monitor for Nagios version ",$Version,"\n"; + print "GPL licence, (c)2004-2007 Patrick Proy\n\n"; + print_usage(); + print <, + : Authentication protocol (md5|sha : default md5) + : Priv protocole (des|aes : default des) +-P, --port=PORT + SNMP port (Default 161) +-n, --name=NAME + Name in description OID (eth0, ppp0 ...). + This is treated as a regexp : -n eth will match eth0,eth1,... + Test it before, because there are known bugs (ex : trailling /) +-r, --noregexp + Do not use regexp to match NAME in description OID +-i, --inverse + Make critical when up +-a, --admin + Use administrative status instead of operational +-D, --dormant + Dormant state is an OK state +-o, --octetlength=INTEGER + max-size of the SNMP message, usefull in case of Too Long responses. + Be carefull with network filters. Range 484 - 65535, default are + usually 1472,1452,1460 or 1440. +-f, --perfparse + Perfparse compatible output (no output when interface is down). +-e, --error + Add error & discard to Perfparse output +-S, --intspeed + Include speed in performance output in bits/s +-y, --perfprct ; -Y, --perfspeed + -y : output performance data in % of max speed + -Y : output performance data in bits/s or Bytes/s (depending on -B) +-k, --perfcheck ; -q, --extperfcheck + -k check the input/ouput bandwidth of the interface + -q also check the error and discard input/output +--label + Add label before speed in output : in=, out=, errors-out=, etc... +-g, --64bits + Use 64 bits counters instead of the standard counters when checking + bandwidth & performance data for interface >= 1Gbps. + You must use snmp v2c or v3 to get 64 bits counters. +-d, --delta=seconds + make an average of seconds (default 300=5min) +-B, --kbits + Make the warning and critical levels in K|M|G Bits/s instead of K|M|G Bytes/s +-G, --giga ; -M, --mega ; -u, --prct + -G : Make the warning and critical levels in Gbps (with -B) or GBps + -M : Make the warning and critical levels in Mbps (with -B) or MBps + -u : Make the warning and critical levels in % of reported interface speed. +-w, --warning=input,output[,error in,error out,discard in,discard out] + warning level for input / output bandwidth (0 for no warning) + unit depends on B,M,G,u options + warning for error & discard input / output in error/min (need -q) +-c, --critical=input,output[,error in,error out,discard in,discard out] + critical level for input / output bandwidth (0 for no critical) + unit depends on B,M,G,u options + critical for error & discard input / output in error/min (need -q) +-s, --short=int + Make the output shorter : only the first chars of the interface(s) + If the number is negative, then get the LAST caracters. +-t, --timeout=INTEGER + timeout for SNMP in seconds (Default: 5) +-V, --version + prints version number +Note : when multiple interface are selected with regexp, + all be must be up (or down with -i) to get an OK result. +EOT +} + +# For verbose output +sub verb { my $t=shift; print $t,"\n" if defined($o_verb) ; } + +sub check_options { + Getopt::Long::Configure ("bundling"); + GetOptions( + 'v' => \$o_verb, 'verbose' => \$o_verb, + 'h' => \$o_help, 'help' => \$o_help, + 'H:s' => \$o_host, 'hostname:s' => \$o_host, + 'p:i' => \$o_port, 'port:i' => \$o_port, + 'n:s' => \$o_descr, 'name:s' => \$o_descr, + 'C:s' => \$o_community, 'community:s' => \$o_community, + '2' => \$o_version2, 'v2c' => \$o_version2, + 'l:s' => \$o_login, 'login:s' => \$o_login, + 'x:s' => \$o_passwd, 'passwd:s' => \$o_passwd, + 'X:s' => \$o_privpass, 'privpass:s' => \$o_privpass, + 'L:s' => \$v3protocols, 'protocols:s' => \$v3protocols, + 't:i' => \$o_timeout, 'timeout:i' => \$o_timeout, + 'i' => \$o_inverse, 'inverse' => \$o_inverse, + 'a' => \$o_admin, 'admin' => \$o_admin, + 'r' => \$o_noreg, 'noregexp' => \$o_noreg, + 'V' => \$o_version, 'version' => \$o_version, + 'f' => \$o_perf, 'perfparse' => \$o_perf, + 'e' => \$o_perfe, 'error' => \$o_perfe, + 'k' => \$o_checkperf, 'perfcheck' => \$o_checkperf, + 'q' => \$o_ext_checkperf, 'extperfcheck' => \$o_ext_checkperf, + 'w:s' => \$o_warn_opt, 'warning:s' => \$o_warn_opt, + 'c:s' => \$o_crit_opt, 'critical:s' => \$o_crit_opt, + 'B' => \$o_kbits, 'kbits' => \$o_kbits, + 's:i' => \$o_short, 'short:i' => \$o_short, + 'g' => \$o_highperf, '64bits' => \$o_highperf, + 'S' => \$o_perfs, 'intspeed' => \$o_perfs, + 'y' => \$o_perfp, 'perfprct' => \$o_perfp, + 'Y' => \$o_perfr, 'perfspeed' => \$o_perfr, + 'M' => \$o_meg, 'mega' => \$o_meg, + 'G' => \$o_gig, 'giga' => \$o_gig, + 'u' => \$o_prct, 'prct' => \$o_prct, + 'o:i' => \$o_octetlength, 'octetlength:i' => \$o_octetlength, + 'label' => \$o_label, + 'd:i' => \$o_delta, 'delta:i' => \$o_delta, + 'D' => \$o_dormant, 'dormant' => \$o_dormant + ); + if (defined ($o_help) ) { help(); exit $ERRORS{"UNKNOWN"}}; + if (defined($o_version)) { p_version(); exit $ERRORS{"UNKNOWN"}}; + if ( ! defined($o_descr) || ! defined($o_host) ) # check host and filter + { print_usage(); exit $ERRORS{"UNKNOWN"}} + # check snmp information + if ( !defined($o_community) && (!defined($o_login) || !defined($o_passwd)) ) + { print "Put snmp login info!\n"; print_usage(); exit $ERRORS{"UNKNOWN"}} + if ((defined($o_login) || defined($o_passwd)) && (defined($o_community) || defined($o_version2)) ) + { print "Can't mix snmp v1,2c,3 protocols!\n"; print_usage(); exit $ERRORS{"UNKNOWN"}} + if (defined ($v3protocols)) { + if (!defined($o_login)) { print "Put snmp V3 login info with protocols!\n"; print_usage(); exit $ERRORS{"UNKNOWN"}} + my @v3proto=split(/,/,$v3protocols); + if ((defined ($v3proto[0])) && ($v3proto[0] ne "")) {$o_authproto=$v3proto[0]; } # Auth protocol + if (defined ($v3proto[1])) {$o_privproto=$v3proto[1]; } # Priv protocol + if ((defined ($v3proto[1])) && (!defined($o_privpass))) { + print "Put snmp V3 priv login info with priv protocols!\n"; print_usage(); exit $ERRORS{"UNKNOWN"}} + } + if (defined($o_timeout) && (isnnum($o_timeout) || ($o_timeout < 2) || ($o_timeout > 60))) + { print "Timeout must be >1 and <60 !\n"; print_usage(); exit $ERRORS{"UNKNOWN"}} + if (!defined($o_timeout)) {$o_timeout=5;} + # Check snmpv2c or v3 with 64 bit counters + if ( defined ($o_highperf) && (!defined($o_version2) && defined($o_community))) + { print "Can't get 64 bit counters with snmp version 1\n"; print_usage(); exit $ERRORS{"UNKNOWN"}} + if (defined ($o_highperf)) { + if (eval "require bigint") { + use bigint; + } else { print "Need bigint module for 64 bit counters\n"; print_usage(); exit $ERRORS{"UNKNOWN"}} + } + + # check if -e without -f + if ( defined($o_perfe) && !defined($o_perf)) + { print "Cannot output error without -f option!\n"; print_usage(); exit $ERRORS{"UNKNOWN"}} + if (defined ($o_perfr) && defined($o_perfp) ) { + print "-Y and -y options are exclusives\n"; print_usage(); exit $ERRORS{"UNKNOWN"}} + if ((defined ($o_perfr) || defined($o_perfp) ) && !defined($o_checkperf)) { + print "Cannot put -Y or -y options without perf check option (-k) \n"; print_usage(); exit $ERRORS{"UNKNOWN"}} + if (defined ($o_short)) { + #TODO maybe some basic tests ? caracters return empty string + } + if (defined ($o_checkperf)) { + @o_warn=split(/,/,$o_warn_opt); + if (defined($o_ext_checkperf) && ($#o_warn != 5)) { + print "6 warning levels for extended checks \n"; print_usage(); exit $ERRORS{"UNKNOWN"} + } + if (!defined($o_ext_checkperf) &&($#o_warn !=1 )){ + print "2 warning levels for bandwidth checks \n"; print_usage(); exit $ERRORS{"UNKNOWN"} + } + @o_crit=split(/,/,$o_crit_opt); + #verb(" $o_crit_opt :: $#o_crit : @o_crit"); + if (defined($o_ext_checkperf) && ($#o_crit != 5)) { + print "6 critical levels for extended checks \n"; print_usage(); exit $ERRORS{"UNKNOWN"} + } + if (!defined($o_ext_checkperf) && ($#o_crit !=1 )) { + print "2 critical levels for bandwidth checks \n"; print_usage(); exit $ERRORS{"UNKNOWN"} + } + for (my $i=0;$i<=$#o_warn;$i++) { + if (($o_crit[$i]!=0)&&($o_warn[$i] > $o_crit[$i])) { + print "Warning must be < Critical level \n"; print_usage(); exit $ERRORS{"UNKNOWN"} + } + } + if ((defined ($o_meg) && defined($o_gig) ) || (defined ($o_meg) && defined($o_prct) )|| (defined ($o_gig) && defined($o_prct) )) { + print "-M -G and -u options are exclusives\n"; print_usage(); exit $ERRORS{"UNKNOWN"} + } + } + #### octet length checks + if (defined ($o_octetlength) && (isnnum($o_octetlength) || $o_octetlength > 65535 || $o_octetlength < 484 )) { + print "octet lenght must be < 65535 and > 484\n";print_usage(); exit $ERRORS{"UNKNOWN"}; + } +} + +########## MAIN ####### + +check_options(); + +# Check gobal timeout if snmp screws up +if (defined($TIMEOUT)) { + verb("Alarm at $TIMEOUT + 5"); + alarm($TIMEOUT+5); +} else { + verb("no timeout defined : $o_timeout + 10"); + alarm ($o_timeout+10); +} + +$SIG{'ALRM'} = sub { + print "No answer from host\n"; + exit $ERRORS{"UNKNOWN"}; +}; + +# Connect to host +my ($session,$error); +if ( defined($o_login) && defined($o_passwd)) { + # SNMPv3 login + if (!defined ($o_privpass)) { + verb("SNMPv3 AuthNoPriv login : $o_login, $o_authproto"); + ($session, $error) = Net::SNMP->session( + -hostname => $o_host, + -version => '3', + -port => $o_port, + -username => $o_login, + -authpassword => $o_passwd, + -authprotocol => $o_authproto, + -timeout => $o_timeout + ); + } else { + verb("SNMPv3 AuthPriv login : $o_login, $o_authproto, $o_privproto"); + ($session, $error) = Net::SNMP->session( + -hostname => $o_host, + -version => '3', + -username => $o_login, + -port => $o_port, + -authpassword => $o_passwd, + -authprotocol => $o_authproto, + -privpassword => $o_privpass, + -privprotocol => $o_privproto, + -timeout => $o_timeout + ); + } +} else { + if (defined ($o_version2)) { + # SNMPv2c Login + verb("SNMP v2c login"); + ($session, $error) = Net::SNMP->session( + -hostname => $o_host, + -version => 2, + -community => $o_community, + -port => $o_port, + -timeout => $o_timeout + ); + } else { + # SNMPV1 login + verb("SNMP v1 login"); + ($session, $error) = Net::SNMP->session( + -hostname => $o_host, + -community => $o_community, + -port => $o_port, + -timeout => $o_timeout + ); + } +} +if (!defined($session)) { + printf("ERROR opening session: %s.\n", $error); + exit $ERRORS{"UNKNOWN"}; +} + +if (defined($o_octetlength)) { + my $oct_resultat=undef; + my $oct_test= $session->max_msg_size(); + verb(" actual max octets:: $oct_test"); + $oct_resultat = $session->max_msg_size($o_octetlength); + if (!defined($oct_resultat)) { + printf("ERROR: Session settings : %s.\n", $session->error); + $session->close; + exit $ERRORS{"UNKNOWN"}; + } + $oct_test= $session->max_msg_size(); + verb(" new max octets:: $oct_test"); +} + +# Get desctiption table +my $resultat = $session->get_table( + Baseoid => $descr_table +); + +if (!defined($resultat)) { + printf("ERROR: Description table : %s.\n", $session->error); + $session->close; + exit $ERRORS{"UNKNOWN"}; +} +my @tindex = undef; +my @oids = undef; +my @descr = undef; +my (@oid_perf,@oid_perf_outoct,@oid_perf_inoct,@oid_perf_inerr,@oid_perf_outerr,@oid_perf_indisc,@oid_perf_outdisc)= + (undef,undef,undef,undef,undef,undef,undef); +my @oid_speed=undef; +my @oid_speed_high=undef; +my $num_int = 0; + +# Change to 64 bit counters if option is set : +if (defined($o_highperf)) { + $out_octet_table=$out_octet_table_64; + $in_octet_table=$in_octet_table_64; +} + + +# Select interface by regexp of exact match +# and put the oid to query in an array + +verb("Filter : $o_descr"); +foreach my $key ( keys %$resultat) { + verb("OID : $key, Desc : $$resultat{$key}"); + # test by regexp or exact match + my $test = defined($o_noreg) + ? $$resultat{$key} eq $o_descr + : $$resultat{$key} =~ /$o_descr/; + if ($test) { + # get the index number of the interface + my @oid_list = split (/\./,$key); + $tindex[$num_int] = pop (@oid_list); + # get the full description + $descr[$num_int]=$$resultat{$key}; + # Get rid of special caracters (specially for Windows) + $descr[$num_int] =~ s/[[:cntrl:]]//g; + # put the admin or oper oid in an array + $oids[$num_int]= defined ($o_admin) ? $admin_table . $tindex[$num_int] + : $oper_table . $tindex[$num_int] ; + # Put the performance oid + if (defined($o_perf) || defined($o_checkperf)) { + $oid_perf_inoct[$num_int]= $in_octet_table . $tindex[$num_int]; + $oid_perf_outoct[$num_int]= $out_octet_table . $tindex[$num_int]; + $oid_speed[$num_int]=$speed_table . $tindex[$num_int]; + $oid_speed_high[$num_int]=$speed_table_64 . $tindex[$num_int]; + if (defined($o_ext_checkperf) || defined($o_perfe)) { + $oid_perf_indisc[$num_int]= $in_discard_table . $tindex[$num_int]; + $oid_perf_outdisc[$num_int]= $out_discard_table . $tindex[$num_int]; + $oid_perf_inerr[$num_int]= $in_error_table . $tindex[$num_int]; + $oid_perf_outerr[$num_int]= $out_error_table . $tindex[$num_int]; + } + } + verb("Name : $descr[$num_int], Index : $tindex[$num_int]"); + $num_int++; + } +} +# No interface found -> error +if ( $num_int == 0 ) { print "ERROR : Unknown interface $o_descr\n" ; exit $ERRORS{"UNKNOWN"};} + +my $result=undef; +# Add performance oids if requested +if (defined($o_perf)||defined($o_checkperf)) { + @oids=(@oids,@oid_perf_outoct,@oid_perf_inoct,@oid_speed); + if (defined($o_highperf)) { + @oids=(@oids,@oid_speed_high); + } + if (defined ($o_ext_checkperf) || defined($o_perfe)) { + @oids=(@oids,@oid_perf_inerr,@oid_perf_outerr,@oid_perf_indisc,@oid_perf_outdisc); + } +} + +# Get the requested oid values +$result = $session->get_request( + Varbindlist => \@oids +); +if (!defined($result)) { printf("ERROR: Status/statistics table : %s.\n", $session->error); $session->close; + exit $ERRORS{"UNKNOWN"}; +} + +$session->close; + +my $num_ok=0; +my @checkperf_out=undef; +my @checkperf_out_raw=undef; +### Bandwidth test variables +my $temp_file_name; +my ($return,@file_values)=(undef,undef); +my $n_rows=0; +my $n_items_check=(defined($o_ext_checkperf))?7:3; +my $timenow=time; +my $trigger=$timenow - ($o_delta - ($o_delta/10)); +my $trigger_low=$timenow - 3*$o_delta; +my ($old_value,$old_time)=undef; +my $speed_unit=undef; +my $speed_real=undef; # speed of interface using either standard or highperf mib. + +# define the OK value depending on -i option +my $ok_val= defined ($o_inverse) ? 2 : 1; +my $final_status = 0; +my ($print_out,$perf_out)=(undef,undef); + +# make all checks and output for all interfaces +for (my $i=0;$i < $num_int; $i++) { + $print_out.=", " if (defined($print_out)); + $perf_out .= " " if (defined ($perf_out)) ; + my $usable_data=1; + # Get the status of the current interface + my $int_status= defined ($o_admin) ? $$result{$admin_table . $tindex[$i]} + : $$result{ $oper_table . $tindex[$i] }; + + # Make the bandwith & error checks if necessary + if (defined ($o_checkperf) && $int_status==1) { + $temp_file_name=$descr[$i]; + $temp_file_name =~ s/[ ;\/]/_/g; + $temp_file_name = $o_base_dir . $o_host ."." . $temp_file_name; + # First, read entire file + my @ret_array=read_file($temp_file_name,$n_items_check); + $return = shift(@ret_array); + $n_rows = shift(@ret_array); + if ($n_rows != 0) { @file_values = @ret_array }; + verb ("File read returns : $return with $n_rows rows"); + # Get the speed in normal or highperf speed counters + if ($$result{$oid_speed[$i]} == 4294967295) { # Too high for this counter (cf IF-MIB) + if (! defined($o_highperf) && (defined($o_prct) || defined ($o_perfs) || defined ($o_perfp))) { + print "Cannot get interface speed with standard MIB, use highperf mib (-g) : UNKNOWN\n"; + exit $ERRORS{"UNKNOWN"} + } + if (defined ($$result{$oid_speed_high[$i]}) && $$result{$oid_speed_high[$i]} != 0) { + $speed_real=$$result{$oid_speed_high[$i]} * 1000000; + } else { + print "Cannot get interface speed using highperf mib : UNKNOWN\n"; + exit $ERRORS{"UNKNOWN"} + } + } else { + $speed_real=$$result{$oid_speed[$i]}; + } + verb ("Interface speed : $speed_real"); + #make the checks if the file is OK + if ($return ==0) { + my $j=$n_rows-1; + @checkperf_out=undef; + @checkperf_out_raw=undef; + do { + if ($file_values[$j][0] < $trigger) { + if ($file_values[$j][0] > $trigger_low) { + # Define the speed metric ( K | M | G ) (Bits|Bytes) or % + my $speed_metric=undef; + if (defined($o_prct)) { # in % of speed + # Speed is in bits/s, calculated speed is in Bytes/s + $speed_metric=$speed_real/800; + $speed_unit="%"; + } else { + if (defined($o_kbits)) { # metric in bits + if (defined($o_meg)) { # in Mbit/s = 1000000 bit/s + $speed_metric=125000; # (1000/8) * 1000 + $speed_unit="Mbps"; + } elsif (defined($o_gig)) { # in Gbit/s = 1000000000 bit/s + $speed_metric=125000000; # (1000/8) * 1000 * 1000 + $speed_unit="Gbps"; + } else { # in Kbits + $speed_metric=125; # ( 1000/8 ) + $speed_unit="Kbps"; + } + } else { # metric in byte + if (defined($o_meg)) { # in Mbits + $speed_metric=1048576; # 1024^2 + $speed_unit="MBps"; + } elsif (defined($o_gig)) { # in Mbits + $speed_metric=1073741824; # 1024^3 + $speed_unit="GBps"; + } else { + $speed_metric=1024; # 1024^3 + $speed_unit="KBps"; + } + } + } + # check if the counter is back to 0 after 2^32 / 2^64. + # First set the modulus depending on highperf counters or not + my $overfl_mod = defined ($o_highperf) ? 18446744073709551616 : 4294967296; + # Check counter (s) + my $overfl = ($$result{$oid_perf_inoct[$i]} >= $file_values[$j][1] ) ? 0 : $overfl_mod; + $checkperf_out_raw[0] = ( ($overfl + $$result{$oid_perf_inoct[$i]} - $file_values[$j][1])/ + ($timenow - $file_values[$j][0] )); + $checkperf_out[0] = $checkperf_out_raw[0] / $speed_metric; + + $overfl = ($$result{$oid_perf_outoct[$i]} >= $file_values[$j][2] ) ? 0 : $overfl_mod; + $checkperf_out_raw[1] = ( ($overfl + $$result{$oid_perf_outoct[$i]} - $file_values[$j][2])/ + ($timenow - $file_values[$j][0] )); + $checkperf_out[1] = $checkperf_out_raw[1] / $speed_metric; + + if (defined($o_ext_checkperf)) { + $checkperf_out[2] = ( ($$result{$oid_perf_inerr[$i]} - $file_values[$j][3])/ + ($timenow - $file_values[$j][0] ))*60; + $checkperf_out[3] = ( ($$result{$oid_perf_outerr[$i]} - $file_values[$j][4])/ + ($timenow - $file_values[$j][0] ))*60; + $checkperf_out[4] = ( ($$result{$oid_perf_indisc[$i]} - $file_values[$j][5])/ + ($timenow - $file_values[$j][0] ))*60; + $checkperf_out[5] = ( ($$result{$oid_perf_outdisc[$i]} - $file_values[$j][6])/ + ($timenow - $file_values[$j][0] ))*60; + } + } + } + $j--; + } while ( ($j>=0) && (!defined($checkperf_out[0])) ); + } + # Put the new values in the array and write the file + $file_values[$n_rows][0]=$timenow; + $file_values[$n_rows][1]=$$result{$oid_perf_inoct[$i]}; + $file_values[$n_rows][2]=$$result{$oid_perf_outoct[$i]}; + if (defined($o_ext_checkperf)) { # Add other values (error & disc) + $file_values[$n_rows][3]=$$result{$oid_perf_inerr[$i]}; + $file_values[$n_rows][4]=$$result{$oid_perf_outerr[$i]}; + $file_values[$n_rows][5]=$$result{$oid_perf_indisc[$i]}; + $file_values[$n_rows][6]=$$result{$oid_perf_outdisc[$i]}; + } + $n_rows++; + $return=write_file($temp_file_name,$n_rows,$n_items_check,@file_values); + verb ("Write file returned : $return"); + # Print the basic status + if (defined ($o_short)) { + my $short_desc=undef; + if ($o_short < 0) {$short_desc=substr($descr[$i],$o_short);} + else {$short_desc=substr($descr[$i],0,$o_short);} + $print_out.=sprintf("%s:%s",$short_desc, $status{$int_status} ); + } else { + $print_out.=sprintf("%s:%s",$descr[$i], $status{$int_status} ); + } + if ($return !=0) { # On error writing, return Unknown status + $final_status=3; + $print_out.= " !!Unable to write file ".$temp_file_name." !! "; + } + # print the other checks if it was calculated + if (defined($checkperf_out[0])) { + $print_out.= " ("; + # check 2 or 6 values depending on ext_check_perf + my $num_checkperf=(defined($o_ext_checkperf))?6:2; + for (my $l=0;$l < $num_checkperf;$l++) { + # Set labels if needed + $checkperf_out_desc= (defined($o_label)) ? $countername[$l] : ""; + verb("Interface $i, check $l : $checkperf_out[$l]"); + if ($l!=0) {$print_out.="/";} + if (($o_crit[$l]!=0) && ($checkperf_out[$l]>$o_crit[$l])) { + $final_status=2; + $print_out.= sprintf("CRIT %s%.1f",$checkperf_out_desc,$checkperf_out[$l]); + } elsif (($o_warn[$l]!=0) && ($checkperf_out[$l]>$o_warn[$l])) { + $final_status=($final_status==2)?2:1; + $print_out.= sprintf("WARN %s%.1f",$checkperf_out_desc,$checkperf_out[$l]); + } else { + $print_out.= sprintf("%s%.1f",$checkperf_out_desc,$checkperf_out[$l]); + } + if ( $l==0 || $l == 1) { $print_out.= $speed_unit; } + } + $print_out .= ")"; + } else { # Return unknown when no data + $print_out.= " No usable data on file (".$n_rows." rows) "; + $final_status=3;$usable_data=0; + } + } else { + if (defined ($o_short)) { + my $short_desc=undef; + if ($o_short < 0) {$short_desc=substr($descr[$i],$o_short);} + else {$short_desc=substr($descr[$i],0,$o_short);} + $print_out.=sprintf("%s:%s",$short_desc, $status{$int_status} ); + } else { + $print_out.=sprintf("%s:%s",$descr[$i], $status{$int_status} ); + } + } + # Get rid of special caracters for performance in description + $descr[$i] =~ s/'\/\(\)/_/g; + if (( $int_status == $ok_val)||(defined($o_dormant) && $int_status == 5)) { + $num_ok++; + } + if (( $int_status == 1 ) && defined ($o_perf)) { + if (defined ($o_perfp)) { # output in % of speed + if ($usable_data==1) { + my $warn_factor=1; + if (!defined($o_prct)) { # warn&crit in K|M|G B|bps -> put warn_factor to make % + $warn_factor = (defined($o_meg)) ? 1000000 : (defined($o_gig)) ? 1000000000 : 1000; + if (!defined($o_kbits)) { $warn_factor*=8;} + $warn_factor/=$speed_real; + $warn_factor*=100; # now turn into displayed % : 0,1 = 10% + } + $perf_out .= "'" . $descr[$i] ."_in_prct'="; + $perf_out .= sprintf("%.0f",$checkperf_out_raw[0] * 800 / $speed_real) ."%;"; + $perf_out .= ($o_warn[0]!=0) ? sprintf("%.0f",$o_warn[0]*$warn_factor) . ";" : ";"; + $perf_out .= ($o_crit[0]!=0) ? sprintf("%.0f",$o_crit[0]*$warn_factor) . ";" : ";"; + $perf_out .= "0;100 "; + $perf_out .= "'" . $descr[$i] ."_out_prct'="; + $perf_out .= sprintf("%.0f",$checkperf_out_raw[1] * 800 / $speed_real) ."%;"; + $perf_out .= ($o_warn[1]!=0) ? sprintf("%.0f",$o_warn[1]*$warn_factor) . ";" : ";"; + $perf_out .= ($o_crit[1]!=0) ? sprintf("%.0f",$o_crit[1]*$warn_factor) . ";" : ";"; + $perf_out .= "0;100 "; + } + } elsif (defined ($o_perfr)) { # output in bites or Bytes /s + if ($usable_data==1) { + if (defined($o_kbits)) { # bps + # put warning and critical levels into bps or Bps + my $warn_factor; + if (defined($o_prct)) { # warn&crit in % -> put warn_factor to 1% of speed in bps + $warn_factor=$speed_real/100; + } else { # just convert from K|M|G bps + $warn_factor = (defined($o_meg)) ? 1000000 : (defined($o_gig)) ? 1000000000 : 1000; + } + $perf_out .= "'" . $descr[$i] ."_in_bps'="; + $perf_out .= sprintf("%.0f",$checkperf_out_raw[0] * 8) .";"; + $perf_out .= ($o_warn[0]!=0) ? $o_warn[0]*$warn_factor . ";" : ";"; + $perf_out .= ($o_crit[0]!=0) ? $o_crit[0]*$warn_factor . ";" : ";"; + $perf_out .= "0;". $speed_real ." "; + $perf_out .= "'" . $descr[$i] ."_out_bps'="; + $perf_out .= sprintf("%.0f",$checkperf_out_raw[1] * 8) .";"; + $perf_out .= ($o_warn[1]!=0) ? $o_warn[1]*$warn_factor . ";" : ";"; + $perf_out .= ($o_crit[1]!=0) ? $o_crit[1]*$warn_factor . ";" : ";"; + $perf_out .= "0;". $speed_real ." "; + } else { # Bps + my $warn_factor; + if (defined($o_prct)) { # warn&crit in % -> put warn_factor to 1% of speed in Bps + $warn_factor=$speed_real/800; + } else { # just convert from K|M|G bps + $warn_factor = (defined($o_meg)) ? 1048576 : (defined($o_gig)) ? 1073741824 : 1024; + } + $perf_out .= "'" . $descr[$i] ."_in_Bps'=" . sprintf("%.0f",$checkperf_out_raw[0]) .";"; + $perf_out .= ($o_warn[0]!=0) ? $o_warn[0]*$warn_factor . ";" : ";"; + $perf_out .= ($o_crit[0]!=0) ? $o_crit[0]*$warn_factor . ";" : ";"; + $perf_out .= "0;". $speed_real / 8 ." "; + $perf_out .= "'" . $descr[$i] ."_out_Bps'=" . sprintf("%.0f",$checkperf_out_raw[1]) .";" ; + $perf_out .= ($o_warn[1]!=0) ? $o_warn[1]*$warn_factor . ";" : ";"; + $perf_out .= ($o_crit[1]!=0) ? $o_crit[1]*$warn_factor . ";" : ";"; + $perf_out .= "0;". $speed_real / 8 ." "; + } + } + } else { # output in octet counter + $perf_out .= "'" . $descr[$i] ."_in_octet'=". $$result{$oid_perf_inoct[$i]} ."c "; + $perf_out .= "'" . $descr[$i] ."_out_octet'=". $$result{$oid_perf_outoct[$i]} ."c "; + } + if (defined ($o_perfe)) { + $perf_out .= "'" . $descr[$i] ."_in_error'=". $$result{$oid_perf_inerr[$i]} ."c "; + $perf_out .= "'" . $descr[$i] ."_in_discard'=". $$result{$oid_perf_indisc[$i]} ."c "; + $perf_out .= "'" . $descr[$i] ."_out_error'=". $$result{$oid_perf_outerr[$i]} ."c "; + $perf_out .= "'" . $descr[$i] ."_out_discard'=". $$result{$oid_perf_outdisc[$i]} ."c "; + } + if (defined ($o_perfs)) { + $perf_out .= "'" . $descr[$i] ."_speed_bps'=".$speed_real; + } + } +} + +# Only a few ms left... +alarm(0); + +# Check if all interface are OK +if ($num_ok == $num_int) { + if ($final_status==0) { + print $print_out,":", $num_ok, " UP: OK"; + if (defined ($o_perf)) { print " | ",$perf_out; } + print "\n"; + exit $ERRORS{"OK"}; + } elsif ($final_status==1) { + print $print_out,":(", $num_ok, " UP): WARNING"; + if (defined ($o_perf)) { print " | ",$perf_out; } + print "\n"; + exit $ERRORS{"WARNING"}; + } elsif ($final_status==2) { + print $print_out,":(", $num_ok, " UP): CRITICAL"; + if (defined ($o_perf)) { print " | ",$perf_out; } + print "\n"; + exit $ERRORS{"CRITICAL"}; + } else { + print $print_out,":(", $num_ok, " UP): UNKNOWN"; + if (defined ($perf_out)) { print " | ",$perf_out; } + print "\n"; + exit $ERRORS{"UNKNOWN"}; + } +} + +# else print the not OK interface number and exit (return is always critical if at least one int is down). + +print $print_out,": ", $num_int-$num_ok, " int NOK : CRITICAL"; +if (defined ($perf_out)) { print " | ",$perf_out; } +print "\n"; +exit $ERRORS{"CRITICAL"}; + diff --git a/check_snmp/trunk/check_snmp_interfaces b/check_snmp/trunk/check_snmp_interfaces new file mode 100755 index 0000000..e8f3662 --- /dev/null +++ b/check_snmp/trunk/check_snmp_interfaces @@ -0,0 +1,779 @@ +#!/usr/bin/perl +# +# +# AUTHORS: +# Copyright (C) 2003-2010 Opsera Limited. All rights reserved +# +# This file is part of Opsview +# +# Opsview is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# Opsview is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Opsview; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +# + +use lib qw ( /usr/local/nagios/perl/lib ); +use Net::SNMP; +use Getopt::Std; + +$script = "check_snmp_cisco_ifstatus"; +$script_version = "2.1.0"; + +# SNMP options +$version = "2c"; +$timeout = 2; + +$number_of_interfaces = 0; +$target_interface_index = 0; + +@list_interfaces=undef; # List of inappropriate interfaces; + +$oid_base = ".1.3.6.1.2.1.2.2.1.1."; +$oid_sysdescr = ".1.3.6.1.2.1.1.1.0"; +$oid_ifnumber = ".1.3.6.1.2.1.2.1.0"; # number of interfaces on device +$oid_ifdescr = ".1.3.6.1.2.1.2.2.1.2."; # need to append integer for specific interface +$oid_iftype = ".1.3.6.1.2.1.2.2.1.3."; # need to append integer for specific interface +$oid_ifmtu = ".1.3.6.1.2.1.2.2.1.4."; # need to append integer for specific interface +$oid_ifspeed = ".1.3.6.1.2.1.2.2.1.5."; # need to append integer for specific interface +$oid_ifphysaddress = ".1.3.6.1.2.1.2.2.1.6."; # need to append integer for specific interface +$oid_ifadminstatus = ".1.3.6.1.2.1.2.2.1.7."; # need to append integer for specific interface +$oid_ifoperstatus = ".1.3.6.1.2.1.2.2.1.8."; # need to append integer for specific interface +$oid_iflastchange = ".1.3.6.1.2.1.2.2.1.9."; # need to append integer for specific interface +$oid_ifinerrors = ".1.3.6.1.2.1.2.2.1.14."; # need to append integer for specific interface +$oid_ifouterrors = ".1.3.6.1.2.1.2.2.1.20."; # need to append integer for specific interface +$oid_ifoutqlen = ".1.3.6.1.2.1.2.2.1.21."; # need to append integer for specific interface +my $realbitssec; # Perf data is always in bps, save this data here + +# Cisco Specific + +$oid_locIfIntBitsSec = "1.3.6.1.4.1.9.2.2.1.1.6."; # need to append integer for specific interface +$oid_locIfOutBitsSec = "1.3.6.1.4.1.9.2.2.1.1.8."; # need to append integer for specific interface + +$ifdescr = "n/a"; +$iftype = "n/a"; +$ifmtu = "n/a"; +$ifspeed = "n/a"; +$ifphysaddress = "n/a"; +$ifadminstatus = "n/a"; +$ifoperstatus = "n/a"; +$iflastchange = "n/a"; +$ifinerrors = "n/a"; +$ifouterrors = "n/a"; +$ifoutqlen = "n/a"; +$ifoutbitssec = "n/a"; + +$warning = 100000000; # Warning threshold +$critical = 100000000; # Critical threshold + +$hostname = "192.168.10.21"; + +#$hostname = "212.113.28.134"; +$returnstring = ""; + +$community = "public"; # Default community string +$configfilepath = "/usr/local/nagios/etc"; + +# Do we have enough information? +if ( @ARGV < 1 ) { + print "Too few arguments\n"; + usage(); +} + +getopts("hH:C:i:w:c:"); +if ($opt_h) { + usage(); + exit(0); +} +if ($opt_H) { + $hostname = $opt_H; + + # print "Hostname $opt_H\n"; +} +else { + print "No hostname specified\n"; + usage(); + exit(0); +} +if ($opt_C) { + $community = $opt_C; +} +if ($opt_i) { + $target_interface = $opt_i; +} +if ($opt_w) { + $warning = $opt_w; +} +if ($opt_c) { + $critical = $opt_c; +} +else { + + # print "Using community $community\n"; +} + +# Create the SNMP session + +$oid_sysDescr = ".1.3.6.1.2.1.1.1.0"; # Used to check whether SNMP is actually responding + +$version = "1"; +( $s, $e ) = Net::SNMP->session( + -community => $community, + -hostname => $hostname, + -version => $version, + -timeout => $timeout, +); + +if ( !defined( $s->get_request($oid_sysDescr) ) ) { + + # If we can't connect using SNMPv1 lets try as SNMPv2 + $s->close(); + sleep 0.5; + $version = "2c"; + ( $s, $e ) = Net::SNMP->session( + -community => $community, + -hostname => $hostname, + -version => $version, + -timeout => $timeout, + ); + if ( !defined( $s->get_request($oid_sysDescr) ) ) { + print "Agent not responding, tried SNMP v1 and v2\n"; + exit(1); + } +} + +if ( find_match() == 0 ) { + probe_interface(); +} +else { + $status = 2; + print "Interface $target_interface not found on device $hostname\n"; + exit $status; +} + +# Close the session +$s->close(); + +if ( $status == 0 ) { + print "Status is OK - $returnstring\n"; + exit $status; +} +elsif ( $status == 1 ) { + print "Status is a Warning Level - $returnstring\n"; + exit $status; +} +elsif ( $status == 2 ) { + print "Status is CRITICAL - $returnstring\n"; + exit $status; +} +else { + print "Plugin error! SNMP status unknown\n"; + exit $status; +} + +exit 2; + +################################################# +# Finds match for supplied interface name +################################################# + +sub find_match { + +my $resultat = $s->get_table($oid_base); + +if (!defined($resultat)) { + printf("ERROR: NHR table : %s.\n", $s->error); + $s->close; + exit 3; +} + +my @keys=undef; +my $oidindex=0; +foreach my $key ( keys %$resultat) { + #verb("OID : $key, Desc : $$resultat{$key}" ); + #print $$resultat{$key} + "\n"; + $key =~ s/$oid_base//; + push(@keys, $key); + #print "$key \n"; +} + +#print $resultat ; +#exit 0; + + + if ( !defined( $s->get_request($oid_ifnumber) ) ) { + if ( !defined( $s->get_request($oid_sysdescr) ) ) { + print "Status is a Warning Level - SNMP agent not responding\n"; + exit 1; + } + else { + print "Status is a Warning Level - SNMP OID does not exist\n"; + exit 1; + } + } + else { + foreach ( $s->var_bind_names() ) { + $number_of_interfaces = $s->var_bind_list()->{$_}; + if ( $number_of_interfaces == 0 ) { + return 1; + } + } + } + + #$index = 1; + #while ( $index <= $number_of_interfaces ) { + foreach $index ( @keys ) { + my $target_interface_index = $index; + $oid_temp = $oid_ifdescr . $index; + if ( !defined( $s->get_request($oid_temp) ) ) { + } + else { + foreach ( $s->var_bind_names() ) { + $temp_interface_descr = $s->var_bind_list()->{$_}; + } + next if ($temp_interface_descr !~ m/$target_interface/); + if ( lc($temp_interface_descr) eq lc($target_interface) ) { + $target_interface_index = $index; + } + } + + ############################ + $oid_temp = $oid_ifadminstatus . $target_interface_index; + if ( !defined( $s->get_request($oid_temp) ) ) { + } + else { + foreach ( $s->var_bind_names() ) { + $ifadminstatus = $s->var_bind_list()->{$_}; + } + } + ############################ + + $oid_temp = $oid_ifoperstatus . $target_interface_index; + if ( !defined( $s->get_request($oid_temp) ) ) { + } + else { + foreach ( $s->var_bind_names() ) { + $ifoperstatus = $s->var_bind_list()->{$_}; + } + } + ############################ + if ( $ifoperstatus != $ifadminstatus ) { + push(@list_interfaces, $temp_interface_descr); + #print ": $temp_interface_descr: $ifoperstatus / $ifadminstatus \n"; + } + + + + # $index++; + } + my $list_interfaces = @list_interfaces; + my $keys = @keys; + if ($list_interfaces > 0) { + print "$list_interfaces out of $keys in inappropriate state: @list_interfaces \n"; + exit 1 + } + else { + print "All $keys interfaces in appropriate state\n"; + exit 0 + } + print "@list_interfaces \n"; + if ( $target_interface_index == 0 ) { + return 1; + } + else { + return 0; + } +} + +#################################################################### +# Gathers data about target interface # +#################################################################### + +sub probe_interface { + + $oid_temp = $oid_ifdescr . $target_interface_index; + if ( !defined( $s->get_request($oid_temp) ) ) { + } + else { + foreach ( $s->var_bind_names() ) { + $ifdescr = $s->var_bind_list()->{$_}; + } + } + ############################ + + $oid_temp = $oid_iftype . $target_interface_index; + if ( !defined( $s->get_request($oid_temp) ) ) { + } + else { + foreach ( $s->var_bind_names() ) { + $iftype = $s->var_bind_list()->{$_}; + } + } + ############################ + + $oid_temp = $oid_ifmtu . $target_interface_index; + if ( !defined( $s->get_request($oid_temp) ) ) { + } + else { + foreach ( $s->var_bind_names() ) { + $ifmtu = $s->var_bind_list()->{$_}; + } + } + ############################ + + $oid_temp = $oid_ifspeed . $target_interface_index; + if ( !defined( $s->get_request($oid_temp) ) ) { + } + else { + foreach ( $s->var_bind_names() ) { + $ifspeed = $s->var_bind_list()->{$_}; + } + } + ############################ + + $oid_temp = $oid_ifadminstatus . $target_interface_index; + if ( !defined( $s->get_request($oid_temp) ) ) { + } + else { + foreach ( $s->var_bind_names() ) { + $ifadminstatus = $s->var_bind_list()->{$_}; + } + } + ############################ + + $oid_temp = $oid_ifoperstatus . $target_interface_index; + if ( !defined( $s->get_request($oid_temp) ) ) { + } + else { + foreach ( $s->var_bind_names() ) { + $ifoperstatus = $s->var_bind_list()->{$_}; + } + } + ############################ + + $oid_temp = $oid_iflastchange . $target_interface_index; + if ( !defined( $s->get_request($oid_temp) ) ) { + } + else { + foreach ( $s->var_bind_names() ) { + $iflastchange = $s->var_bind_list()->{$_}; + } + } + ############################ + + $oid_temp = $oid_ifinerrors . $target_interface_index; + if ( !defined( $s->get_request($oid_temp) ) ) { + } + else { + foreach ( $s->var_bind_names() ) { + $ifinerrors = $s->var_bind_list()->{$_}; + } + } + ############################ + + $oid_temp = $oid_ifouterrors . $target_interface_index; + if ( !defined( $s->get_request($oid_temp) ) ) { + } + else { + foreach ( $s->var_bind_names() ) { + $ifouterrors = $s->var_bind_list()->{$_}; + } + } + ############################ + + $oid_temp = $oid_ifoutqlen . $target_interface_index; + if ( !defined( $s->get_request($oid_temp) ) ) { + } + else { + foreach ( $s->var_bind_names() ) { + $ifoutqlen = $s->var_bind_list()->{$_}; + } + } + ############################ + + $oid_temp = $oid_locIfOutBitsSec . $target_interface_index; + if ( !defined( $s->get_request($oid_temp) ) ) { + $ifoutbitssec = -1; + } + else { + foreach ( $s->var_bind_names() ) { + $ifoutbitssec = $s->var_bind_list()->{$_}; + } + } + ############################ + + $errorstring = ""; + + # Sets warning / critical levels if interface down + + if ( $ifadminstatus eq "1" ) { + } + else { + $status = 1; + $errorstring = "INTERFACE ADMINISTRATIVELY DOWN:"; + } + + if ( $ifoperstatus eq "1" ) { + } + else { + $status = 2; + $errorstring = "INTERFACE DOWN:"; + } + + # Sets warning / critical levels if ifoutbitssec exceeds threshold + + if ( $status < 1 ) { + + # Don't bother is status is down + if ( $ifoutbitssec > $critical ) { + $errorstring = "HIGH THROUGHPUT:"; + $status = 2; + } + elsif ( $ifoutbitssec > $warning ) { + $errorstring = "HIGH THROUGHPUT:"; + $status = 1; + } + } + + # Mangles interface speed + + my $mbps = $ifspeed / 1000000; + if ( $mbps < 1 ) { + $ifspeed = $ifspeed / 1000; + $ifspeed = "$ifspeed Kbps"; + } + else { + $ifspeed = "$mbps Mbps"; + } + + $realbitssec = $ifoutbitssec; + + # Mangles IfOutBitsSec stat to bits / kbits + if ( $ifoutbitssec > 0 ) { + my $mbps = $ifoutbitssec / 1000000; + if ( $mbps < 1 ) { + $ifoutbitssec = $ifoutbitssec / 1000; + $ifoutbitssec = "$ifoutbitssec Kbps"; + } + else { + $ifoutbitssec = "$mbps Mbps"; + } + } + elsif ( $ifoutbitssec < 0 ) { + $ifoutbitssec = "N/A"; + } + else { + $ifoutbitssec = "0 bps"; + } + + # Returns string relating to interface media + my $iftype_string = return_interfacetype($iftype); + + if ( $status == 0 ) { + $temp = sprintf "$ifdescr ($iftype_string) - Current: $ifoutbitssec, Limit: $ifspeed, MTU: $ifmtu, Last change: $iflastchange, STATS:(in errors: $ifinerrors, out errors: $ifouterrors, queue length: $ifoutqlen)"; + append($temp); + } + else { + $temp = sprintf "$errorstring $ifdescr ($iftype_string) - Current: $ifoutbitssec, Limit: $ifspeed, MTU: $ifmtu, Last change: $iflastchange, STATS:(in errors: $ifinerrors, out errors: $ifouterrors, queue length: $ifoutqlen)"; + append($temp); + } + $perfinfo = sprintf "|bits/sec=$realbitssec"; + append($perfinfo); +} + +#################################################################### +# help and usage information # +#################################################################### + +sub usage { + print << "USAGE"; +-------------------------------------------------------------------- +$script v$script_version + +Monitors status of specific Ethernet interface. + +Usage: $script -H -c [...] + +Options: -H Hostname or IP address + -C Community (default is public) + -i Target interface name + Eg: Serial0/0, FastEthernet0/12 + -w Warning threshold - Out bits / sec + -c Critical threshold - Out bits / sec + +-------------------------------------------------------------------- +Copyright (C) 2003-2010 Opsera Limited. All rights reserved + +This program is free software; you can redistribute it or modify +it under the terms of the GNU General Public License +-------------------------------------------------------------------- + +USAGE + exit 1; +} + +#################################################################### +# Appends string to existing $returnstring # +#################################################################### + +sub append { + my $appendstring = @_[0]; + $returnstring = "$returnstring$appendstring"; +} + +#################################################################### +# Returns the interface type for given IANA metric # +#################################################################### + +sub return_interfacetype { + my $iftype_int = @_[0]; + my @iana = (); + my $returnstring = $iftype_int; + + $iana[0] = ""; + $iana[1] = "other"; + $iana[2] = "regular1822"; + $iana[3] = "hdh1822"; + $iana[4] = "ddnX25"; + $iana[5] = "rfc877x25"; + $iana[6] = "ethernet"; + $iana[7] = ""; + $iana[8] = "TokenBus"; + $iana[9] = "TokenRing"; + $iana[10] = "iso88026Man"; + $iana[11] = "starLan"; + $iana[12] = "proteon10Mbit"; + $iana[13] = "proteon80Mbit"; + $iana[14] = "hyperchannel"; + $iana[15] = "fddi"; + $iana[16] = "lapb"; + $iana[17] = "sdlc"; + $iana[18] = "DSL"; + $iana[19] = "E1"; + $iana[20] = "basicISDN"; + $iana[21] = "primaryISDN"; + $iana[22] = "propritory PointToPointSerial"; + $iana[23] = "PPP"; + $iana[24] = "softwareLoopback"; + $iana[25] = "CLNP over IP "; + $iana[26] = "ethernet3Mbit"; + $iana[27] = "XNS over IP"; + $iana[28] = "SLIP"; + $iana[29] = "ultra"; + $iana[30] = "DS3"; + $iana[31] = "SMDS"; + $iana[32] = "frameRelay DTE"; + $iana[33] = "RS232"; + $iana[34] = "Parallel port"; + $iana[35] = "arcnet"; + $iana[36] = "arcnetPlus"; + $iana[37] = "ATM"; + $iana[38] = "miox25"; + $iana[39] = "SONET / SDH "; + $iana[40] = "X25PLE"; + $iana[41] = "iso88022llc"; + $iana[42] = "localTalk"; + $iana[43] = "SMDSDxi"; + $iana[44] = "frameRelayService"; + $iana[45] = "v35"; + $iana[46] = "hssi"; + $iana[47] = "hippi"; + $iana[48] = "Generic MODEM"; + $iana[49] = ""; + $iana[50] = "sonetPath"; + $iana[51] = "sonetVT"; + $iana[52] = "SMDSIcip"; + $iana[53] = "propVirtual"; + $iana[54] = "propMultiplexor"; + $iana[55] = "ieee80212 100BaseVG"; + $iana[56] = "fibreChannel"; + $iana[57] = "HIPPI interface"; + $iana[58] = ""; + $iana[59] = "ATM Emulated LAN for 802.3"; + $iana[60] = "ATM Emulated LAN for 802.5"; + $iana[61] = "ATM Emulated circuit "; + $iana[62] = ""; + $iana[63] = "ISDN / X.25 "; + $iana[64] = "CCITT V.11/X.21 "; + $iana[65] = "CCITT V.36 "; + $iana[66] = "CCITT G703 at 64Kbps"; + $iana[67] = "G703 at 2Mb"; + $iana[68] = "SNA QLLC "; + $iana[69] = ""; + $iana[70] = "channel "; + $iana[71] = "ieee80211 radio spread spectrum "; + $iana[72] = "IBM System 360/370 OEMI Channel"; + $iana[73] = "IBM Enterprise Systems Connection"; + $iana[74] = "Data Link Switching"; + $iana[75] = "ISDN S/T interface"; + $iana[76] = "ISDN U interface"; + $iana[77] = "Link Access Protocol D"; + $iana[78] = "IP Switching Objects"; + $iana[79] = "Remote Source Route Bridging"; + $iana[80] = "ATM Logical Port"; + $iana[81] = "Digital Signal Level 0"; + $iana[82] = "ds0 Bundle (group of ds0s on the same ds1)"; + $iana[83] = "Bisynchronous Protocol"; + $iana[84] = "Asynchronous Protocol"; + $iana[85] = "Combat Net Radio"; + $iana[86] = "ISO 802.5r DTR"; + $iana[87] = "Ext Pos Loc Report Sys"; + $iana[88] = "Appletalk Remote Access Protocol"; + $iana[89] = "Proprietary Connectionless Protocol"; + $iana[90] = "CCITT-ITU X.29 PAD Protocol"; + $iana[91] = "CCITT-ITU X.3 PAD Facility"; + $iana[92] = "frameRelay MPI"; + $iana[93] = "CCITT-ITU X213"; + $iana[94] = "ADSL"; + $iana[95] = "Rate-Adapt. DSL"; + $iana[96] = "SDSL"; + $iana[97] = "Very High-Speed DSL"; + $iana[98] = "ISO 802.5 CRFP"; + $iana[99] = "Myricom Myrinet"; + $iana[100] = "voiceEM voice recEive and transMit"; + $iana[101] = "voiceFXO voice Foreign Exchange Office"; + $iana[102] = "voiceFXS voice Foreign Exchange Station"; + $iana[103] = "voiceEncap voice encapsulation"; + $iana[104] = "VoIP"; + $iana[105] = "ATM DXI"; + $iana[106] = "ATM FUNI"; + $iana[107] = "ATM IMA"; + $iana[108] = "PPP Multilink Bundle"; + $iana[109] = "IBM ipOverCdlc"; + $iana[110] = "IBM Common Link Access to Workstn"; + $iana[111] = "IBM stackToStack"; + $iana[112] = "IBM VIPA"; + $iana[113] = "IBM multi-protocol channel support"; + $iana[114] = "IBM IP over ATM"; + $iana[115] = "ISO 802.5j Fiber Token Ring"; + $iana[116] = "IBM twinaxial data link control"; + $iana[117] = ""; + $iana[118] = "HDLC"; + $iana[119] = "LAP F"; + $iana[120] = "V.37"; + $iana[121] = "X25 Multi-Link Protocol"; + $iana[122] = "X25 Hunt Group"; + $iana[123] = "Transp HDLC"; + $iana[124] = "Interleave channel"; + $iana[125] = "Fast channel"; + $iana[126] = "IP (for APPN HPR in IP networks)"; + $iana[127] = "CATV Mac Layer"; + $iana[128] = "CATV Downstream interface"; + $iana[129] = "CATV Upstream interface"; + $iana[130] = "Avalon Parallel Processor"; + $iana[131] = "Encapsulation interface"; + $iana[132] = "Coffee pot (no, really)"; + $iana[133] = "Circuit Emulation Service"; + $iana[134] = "ATM Sub Interface"; + $iana[135] = "Layer 2 Virtual LAN using 802.1Q"; + $iana[136] = "Layer 3 Virtual LAN using IP"; + $iana[137] = "Layer 3 Virtual LAN using IPX"; + $iana[138] = "IP over Power Lines"; + $iana[139] = "Multimedia Mail over IP"; + $iana[140] = "Dynamic Synchronous Transfer Mode"; + $iana[141] = "Data Communications Network"; + $iana[142] = "IP Forwarding Interface"; + $iana[143] = "Multi-rate Symmetric DSL"; + $iana[144] = "IEEE1394 High Performance Serial Bus"; + $iana[145] = "HIPPI-6400 "; + $iana[146] = "DVB-RCC MAC Layer"; + $iana[147] = "DVB-RCC Downstream Channel"; + $iana[148] = "DVB-RCC Upstream Channel"; + $iana[149] = "ATM Virtual Interface"; + $iana[150] = "MPLS Tunnel Virtual Interface"; + $iana[151] = "Spatial Reuse Protocol"; + $iana[152] = "Voice Over ATM"; + $iana[153] = "Voice Over Frame Relay "; + $iana[154] = "Digital Subscriber Loop over ISDN"; + $iana[155] = "Avici Composite Link Interface"; + $iana[156] = "SS7 Signaling Link "; + $iana[157] = "Prop. P2P wireless interface"; + $iana[158] = "Frame Forward Interface"; + $iana[159] = "Multiprotocol over ATM AAL5"; + $iana[160] = "USB Interface"; + $iana[161] = "IEEE 802.3ad Link Aggregate"; + $iana[162] = "BGP Policy Accounting"; + $iana[163] = "FRF .16 Multilink Frame Relay "; + $iana[164] = "H323 Gatekeeper"; + $iana[165] = "H323 Voice and Video Proxy"; + $iana[166] = "MPLS"; + $iana[167] = "Multi-frequency signaling link"; + $iana[168] = "High Bit-Rate DSL - 2nd generation"; + $iana[169] = "Multirate HDSL2"; + $iana[170] = "Facility Data Link 4Kbps on a DS1"; + $iana[171] = "Packet over SONET/SDH Interface"; + $iana[172] = "DVB-ASI Input"; + $iana[173] = "DVB-ASI Output "; + $iana[174] = "Power Line Communtications"; + $iana[175] = "Non Facility Associated Signaling"; + $iana[176] = "TR008"; + $iana[177] = "Remote Digital Terminal"; + $iana[178] = "Integrated Digital Terminal"; + $iana[179] = "ISUP"; + $iana[180] = "Cisco proprietary MAC layer"; + $iana[181] = "Cisco proprietary Downstream"; + $iana[182] = "Cisco proprietary Upstream"; + $iana[183] = "HIPERLAN Type 2 Radio Interface"; + $iana[184] = "PropBroadbandWirelessAccesspt2multipt"; + $iana[185] = "SONET Overhead Channel"; + $iana[186] = "Digital Wrapper"; + $iana[187] = "ATM adaptation layer 2"; + $iana[188] = "MAC layer over radio links"; + $iana[189] = "ATM over radio links "; + $iana[190] = "Inter Machine Trunks"; + $iana[191] = "Multiple Virtual Lines DSL"; + $iana[192] = "Long Reach DSL"; + $iana[193] = "Frame Relay DLCI End Point"; + $iana[194] = "ATM VCI End Point"; + $iana[195] = "Optical Channel"; + $iana[196] = "Optical Transport"; + $iana[197] = "Proprietary ATM "; + $iana[198] = "Voice Over Cable Interface"; + $iana[199] = "Infiniband"; + $iana[200] = "TE Link"; + $iana[201] = "Q.2931"; + $iana[202] = "Virtual Trunk Group"; + $iana[203] = "SIP Trunk Group"; + $iana[204] = "SIP Signaling "; + $iana[205] = "CATV Upstream Channel"; + $iana[206] = "Acorn Econet"; + $iana[207] = "FSAN 155Mb Symetrical PON interface"; + $iana[208] = "FSAN622Mb Symetrical PON interface"; + $iana[209] = "Transparent bridge interface"; + $iana[210] = "Interface common to multiple lines"; + $iana[211] = "voice E&M Feature Group D"; + $iana[212] = "voice FGD Exchange Access North American"; + $iana[213] = "voice Direct Inward Dialing"; + $iana[214] = "MPEG transport interface"; + $iana[215] = "6to4 interface"; + $iana[216] = "GTP (GPRS Tunneling Protocol)"; + $iana[217] = "Paradyne EtherLoop 1"; + $iana[218] = "Paradyne EtherLoop 2"; + $iana[219] = "Optical Channel Group"; + $iana[220] = "HomePNA ITU-T G.989"; + $iana[221] = "Generic Framing Procedure (GFP)"; + $iana[222] = "Layer 2 Virtual LAN using Cisco ISL"; + $iana[223] = "Acteleis proprietary MetaLOOP High Speed Link "; + $iana[224] = "FCIP Link "; + $iana[225] = "Resilient Packet Ring Interface Type"; + $iana[226] = "RF Qam Interface"; + $iana[227] = "Link Management Protocol"; + + if ( $iftype_int > 227 ) { + $returnstring = "$iftype_int"; + } + else { + $returnstring = $iana[$iftype_int]; + } + + return ($returnstring); + +} diff --git a/check_snmp/trunk/check_snmp_load.pl b/check_snmp/trunk/check_snmp_load.pl new file mode 100755 index 0000000..9771c1a --- /dev/null +++ b/check_snmp/trunk/check_snmp_load.pl @@ -0,0 +1,792 @@ +#!/usr/bin/perl -w +############################## check_snmp_load ################# +my $Version='1.12'; +# Date : Oct 12 2007 +# Author : Patrick Proy ( patrick at proy.org) +# Help : http://nagios.manubulon.com/ +# Licence : GPL - http://www.fsf.org/licenses/gpl.txt +# Contributors : F. Lacroix and many others !!! +# 2010-03-13 - Modified by Pall Sigurdsson Added support for cisco asa +################################################################# +# +# Help : ./check_snmp_load.pl -h +# + +use strict; +use Net::SNMP; +use Getopt::Long; + +# Nagios specific + +my $TIMEOUT = 15; +my %ERRORS=('OK'=>0,'WARNING'=>1,'CRITICAL'=>2,'UNKNOWN'=>3,'DEPENDENT'=>4); + +# SNMP Datas + +# Generic with host-ressource-mib +my $base_proc = "1.3.6.1.2.1.25.3.3.1"; # oid for all proc info +my $proc_id = "1.3.6.1.2.1.25.3.3.1.1"; # list of processors (product ID) +my $proc_load = "1.3.6.1.2.1.25.3.3.1.2"; # %time the proc was not idle over last minute + +# Linux load + +my $linload_table= "1.3.6.1.4.1.2021.10.1"; # net-snmp load table +my $linload_name = "1.3.6.1.4.1.2021.10.1.2"; # text 'Load-1','Load-5', 'Load-15' +my $linload_load = "1.3.6.1.4.1.2021.10.1.3"; # effective load table + +# Cisco cpu/load + +my $cisco_cpu_5m = "1.3.6.1.4.1.9.2.1.58.0"; # Cisco CPU load (5min %) +my $cisco_cpu_1m = "1.3.6.1.4.1.9.2.1.57.0"; # Cisco CPU load (1min %) +my $cisco_cpu_5s = "1.3.6.1.4.1.9.2.1.56.0"; # Cisco CPU load (5sec %) + +# Ciscoasa cpu/load +# Added by palli@ok.is - 2010-03-13 +my $casa_cpu_5m = ".1.3.6.1.4.1.9.9.109.1.1.1.1.5.1"; # Cisco CPU load (5min %) +my $casa_cpu_1m = ".1.3.6.1.4.1.9.9.109.1.1.1.1.4.1"; # Cisco CPU load (1min %) +my $casa_cpu_5s = ".1.3.6.1.4.1.9.9.109.1.1.1.1.3.1"; # Cisco CPU load (5sec %) + +# Cisco catalyst cpu/load + +my $ciscocata_cpu_5m = ".1.3.6.1.4.1.9.9.109.1.1.1.1.5.9"; # Cisco CPU load (5min %) +my $ciscocata_cpu_1m = ".1.3.6.1.4.1.9.9.109.1.1.1.1.3.9"; # Cisco CPU load (1min %) +my $ciscocata_cpu_5s = ".1.3.6.1.4.1.9.9.109.1.1.1.1.4.9"; # Cisco CPU load (5sec %) + +# Netscreen cpu/load + +my $nsc_cpu_5m = "1.3.6.1.4.1.3224.16.1.4.0"; # NS CPU load (5min %) +my $nsc_cpu_1m = "1.3.6.1.4.1.3224.16.1.2.0"; # NS CPU load (1min %) +my $nsc_cpu_5s = "1.3.6.1.4.1.3224.16.1.3.0"; # NS CPU load (5sec %) + +# AS/400 CPU + +my $as400_cpu = "1.3.6.1.4.1.2.6.4.5.1.0"; # AS400 CPU load (10000=100%); + +# Net-SNMP CPU + +my $ns_cpu_idle = "1.3.6.1.4.1.2021.11.11.0"; # Net-snmp cpu idle +my $ns_cpu_user = "1.3.6.1.4.1.2021.11.9.0"; # Net-snmp user cpu usage +my $ns_cpu_system = "1.3.6.1.4.1.2021.11.10.0"; # Net-snmp system cpu usage + +# Procurve CPU +my $procurve_cpu = "1.3.6.1.4.1.11.2.14.11.5.1.9.6.1.0"; # Procurve CPU Counter + +# Nokia CPU +my $nokia_cpu = "1.3.6.1.4.1.94.1.21.1.7.1.0"; # Nokia CPU % usage + +# Bluecoat Appliance +my $bluecoat_cpu = "1.3.6.1.4.1.3417.2.4.1.1.1.4.1"; # Bluecoat %cpu usage. + +# Fortigate CPU +my $fortigate_cpu = ".1.3.6.1.4.1.12356.1.8.0"; # Fortigate CPU % usage + +# Linkproof Appliance +my $linkproof_cpu= "1.3.6.1.4.1.89.35.1.55.0"; # CPU RE (Routing Engine Tasks) +# 1.3.6.1.4.1.89.35.1.53.0 : Ressource utilisation (%) Considers network utilization and internal CPU utilization +# 1.3.6.1.4.1.89.35.1.54 : CPU only (%) +# 1.3.6.1.4.1.89.35.1.55 : network only (%) + +# HP-UX cpu usage (thanks to krizb for the OIDs). +my $hpux_load_1_min="1.3.6.1.4.1.11.2.3.1.1.3.0"; +my $hpux_load_5_min="1.3.6.1.4.1.11.2.3.1.1.4.0"; +my $hpux_load_15_min="1.3.6.1.4.1.11.2.3.1.1.5.0"; + +# valid values +my @valid_types = ("stand","netsc","netsl","as400","cisco","casa","cata","nsc","fg","bc","nokia","hp","lp","hpux"); +# CPU OID array +my %cpu_oid = ("netsc",$ns_cpu_idle,"as400",$as400_cpu,"bc",$bluecoat_cpu,"nokia",$nokia_cpu,"hp",$procurve_cpu,"lp",$linkproof_cpu,"fg",$fortigate_cpu); + +# Globals + + +my $o_host = undef; # hostname +my $o_community = undef; # community +my $o_port = 161; # port +my $o_help= undef; # wan't some help ? +my $o_verb= undef; # verbose mode +my $o_version= undef; # print version +# check type : stand | netsc | netsl | as400 | cisco | cata | nsc | fg | bc | nokia | hp | lp | hpux +my $o_check_type= "stand"; +# End compatibility +my $o_warn= undef; # warning level +my @o_warnL= undef; # warning levels for Linux Load or Cisco CPU +my $o_crit= undef; # critical level +my @o_critL= undef; # critical level for Linux Load or Cisco CPU +my $o_timeout= undef; # Timeout (Default 5) +my $o_perf= undef; # Output performance data +my $o_version2= undef; # use snmp v2c +# SNMPv3 specific +my $o_login= undef; # Login for snmpv3 +my $o_passwd= undef; # Pass for snmpv3 +my $v3protocols=undef; # V3 protocol list. +my $o_authproto='md5'; # Auth protocol +my $o_privproto='des'; # Priv protocol +my $o_privpass= undef; # priv password + +# functions + +sub p_version { print "check_snmp_load version : $Version\n"; } + +sub print_usage { + print "Usage: $0 [-v] -H -C [-2] | (-l login -x passwd [-X pass -L ,]) [-p ] -w -c -T=[stand|netsl|netsc|as400|cisco|casa|cata|nsc|fg|bc|nokia|hp|lp|hpux] [-f] [-t ] [-V]\n"; +} + +sub isnnum { # Return true if arg is not a number + my $num = shift; + if ( $num =~ /^(\d+\.?\d*)|(^\.\d+)$/ ) { return 0 ;} + return 1; +} + +sub help { + print "\nSNMP Load & CPU Monitor for Nagios version ",$Version,"\n"; + print "GPL licence, (c)2004-2007 Patrick Proy\n\n"; + print_usage(); + print <, + : Authentication protocol (md5|sha : default md5) + : Priv protocole (des|aes : default des) +-P, --port=PORT + SNMP port (Default 161) +-w, --warn=INTEGER | INT,INT,INT + 1 value check : warning level for cpu in percent (on one minute) + 3 value check : comma separated level for load or cpu for 1min, 5min, 15min +-c, --crit=INTEGER | INT,INT,INT + critical level for cpu in percent (on one minute) + 1 value check : critical level for cpu in percent (on one minute) + 3 value check : comma separated level for load or cpu for 1min, 5min, 15min +-T, --type=stand|netsl|netsc|as400|cisco|casa|bc|nokia|hp|lp + CPU check : + stand : standard MIBII (works with Windows), + can handle multiple CPU. + netsl : linux load provided by Net SNMP (1,5 & 15 minutes values) + netsc : cpu usage given by net-snmp (100-idle) + as400 : as400 CPU usage + cisco : Cisco CPU usage + casa : Cisco ASA CPU usage + cata : Cisco catalyst CPU usage + nsc : NetScreen CPU usage + fg : Fortigate CPU usage + bc : Bluecoat CPU usage + nokia : Nokia CPU usage + hp : HP procurve switch CPU usage + lp : Linkproof CPU usage + hpux : HP-UX load (1,5 & 15 minutes values) +-f, --perfparse + Perfparse compatible output +-t, --timeout=INTEGER + timeout for SNMP in seconds (Default: 5) +-V, --version + prints version number +EOT +} + +# For verbose output +sub verb { my $t=shift; print $t,"\n" if defined($o_verb) ; } + +sub check_options { + Getopt::Long::Configure ("bundling"); + GetOptions( + 'v' => \$o_verb, 'verbose' => \$o_verb, + 'h' => \$o_help, 'help' => \$o_help, + 'H:s' => \$o_host, 'hostname:s' => \$o_host, + 'p:i' => \$o_port, 'port:i' => \$o_port, + 'C:s' => \$o_community, 'community:s' => \$o_community, + 'l:s' => \$o_login, 'login:s' => \$o_login, + 'x:s' => \$o_passwd, 'passwd:s' => \$o_passwd, + 'X:s' => \$o_privpass, 'privpass:s' => \$o_privpass, + 'L:s' => \$v3protocols, 'protocols:s' => \$v3protocols, + 't:i' => \$o_timeout, 'timeout:i' => \$o_timeout, + 'V' => \$o_version, 'version' => \$o_version, + '2' => \$o_version2, 'v2c' => \$o_version2, + 'c:s' => \$o_crit, 'critical:s' => \$o_crit, + 'w:s' => \$o_warn, 'warn:s' => \$o_warn, + 'f' => \$o_perf, 'perfparse' => \$o_perf, + 'T:s' => \$o_check_type, 'type:s' => \$o_check_type + ); + # check the -T option + my $T_option_valid=0; + foreach (@valid_types) { if ($_ eq $o_check_type) {$T_option_valid=1} }; + if ( $T_option_valid == 0 ) + {print "Invalid check type (-T)!\n"; print_usage(); exit $ERRORS{"UNKNOWN"}} + # Basic checks + if (defined($o_timeout) && (isnnum($o_timeout) || ($o_timeout < 2) || ($o_timeout > 60))) + { print "Timeout must be >1 and <60 !\n"; print_usage(); exit $ERRORS{"UNKNOWN"}} + if (!defined($o_timeout)) {$o_timeout=5;} + if (defined ($o_help) ) { help(); exit $ERRORS{"UNKNOWN"}}; + if (defined($o_version)) { p_version(); exit $ERRORS{"UNKNOWN"}}; + if ( ! defined($o_host) ) # check host and filter + { print_usage(); exit $ERRORS{"UNKNOWN"}} + # check snmp information + if ( !defined($o_community) && (!defined($o_login) || !defined($o_passwd)) ) + { print "Put snmp login info!\n"; print_usage(); exit $ERRORS{"UNKNOWN"}} + if ((defined($o_login) || defined($o_passwd)) && (defined($o_community) || defined($o_version2)) ) + { print "Can't mix snmp v1,2c,3 protocols!\n"; print_usage(); exit $ERRORS{"UNKNOWN"}} + if (defined ($v3protocols)) { + if (!defined($o_login)) { print "Put snmp V3 login info with protocols!\n"; print_usage(); exit $ERRORS{"UNKNOWN"}} + my @v3proto=split(/,/,$v3protocols); + if ((defined ($v3proto[0])) && ($v3proto[0] ne "")) {$o_authproto=$v3proto[0]; } # Auth protocol + if (defined ($v3proto[1])) {$o_privproto=$v3proto[1]; } # Priv protocol + if ((defined ($v3proto[1])) && (!defined($o_privpass))) { + print "Put snmp V3 priv login info with priv protocols!\n"; print_usage(); exit $ERRORS{"UNKNOWN"}} + } + # Check warnings and critical + if (!defined($o_warn) || !defined($o_crit)) + { print "put warning and critical info!\n"; print_usage(); exit $ERRORS{"UNKNOWN"}} + # Get rid of % sign + $o_warn =~ s/\%//g; + $o_crit =~ s/\%//g; + # Check for multiple warning and crit in case of -L + if (($o_check_type eq "netsl") || ($o_check_type eq "cisco") || ($o_check_type eq "cata") || + ($o_check_type eq "nsc") || ($o_check_type eq "casa") || ($o_check_type eq "hpux")) { + @o_warnL=split(/,/ , $o_warn); + @o_critL=split(/,/ , $o_crit); + if (($#o_warnL != 2) || ($#o_critL != 2)) + { print "3 warnings and critical !\n";print_usage(); exit $ERRORS{"UNKNOWN"}} + for (my $i=0;$i<3;$i++) { + if ( isnnum($o_warnL[$i]) || isnnum($o_critL[$i])) + { print "Numeric value for warning or critical !\n";print_usage(); exit $ERRORS{"UNKNOWN"}} + if ($o_warnL[$i] > $o_critL[$i]) + { print "warning <= critical ! \n";print_usage(); exit $ERRORS{"UNKNOWN"}} + } + } else { + if (($o_warn =~ /,/) || ($o_crit =~ /,/)) { + { print "Multiple warning/critical levels not available for this check\n";print_usage(); exit $ERRORS{"UNKNOWN"}} + } + if ( isnnum($o_warn) || isnnum($o_crit) ) + { print "Numeric value for warning or critical !\n";print_usage(); exit $ERRORS{"UNKNOWN"}} + if ($o_warn > $o_crit) + { print "warning <= critical ! \n";print_usage(); exit $ERRORS{"UNKNOWN"}} + } +} + +########## MAIN ####### + +check_options(); + +# Check gobal timeout if snmp screws up +if (defined($TIMEOUT)) { + verb("Alarm at $TIMEOUT + 5"); + alarm($TIMEOUT+5); +} else { + verb("no global timeout defined : $o_timeout + 10"); + alarm ($o_timeout+10); +} + +$SIG{'ALRM'} = sub { + print "No answer from host\n"; + exit $ERRORS{"UNKNOWN"}; +}; + +# Connect to host +my ($session,$error); +if ( defined($o_login) && defined($o_passwd)) { + # SNMPv3 login + verb("SNMPv3 login"); + if (!defined ($o_privpass)) { + verb("SNMPv3 AuthNoPriv login : $o_login, $o_authproto"); + ($session, $error) = Net::SNMP->session( + -hostname => $o_host, + -version => '3', + -username => $o_login, + -authpassword => $o_passwd, + -authprotocol => $o_authproto, + -timeout => $o_timeout + ); + } else { + verb("SNMPv3 AuthPriv login : $o_login, $o_authproto, $o_privproto"); + ($session, $error) = Net::SNMP->session( + -hostname => $o_host, + -version => '3', + -username => $o_login, + -authpassword => $o_passwd, + -authprotocol => $o_authproto, + -privpassword => $o_privpass, + -privprotocol => $o_privproto, + -timeout => $o_timeout + ); + } +} else { + if (defined ($o_version2)) { + # SNMPv2 Login + verb("SNMP v2c login"); + ($session, $error) = Net::SNMP->session( + -hostname => $o_host, + -version => 2, + -community => $o_community, + -port => $o_port, + -timeout => $o_timeout + ); + } else { + # SNMPV1 login + verb("SNMP v1 login"); + ($session, $error) = Net::SNMP->session( + -hostname => $o_host, + -community => $o_community, + -port => $o_port, + -timeout => $o_timeout + ); + } +} +if (!defined($session)) { + printf("ERROR opening session: %s.\n", $error); + exit $ERRORS{"UNKNOWN"}; +} + +my $exit_val=undef; +########### Linux load check ############## + +if ($o_check_type eq "netsl") { + +verb("Checking linux load"); +# Get load table +my $resultat = (Net::SNMP->VERSION < 4) ? + $session->get_table($linload_table) + : $session->get_table(Baseoid => $linload_table); + +if (!defined($resultat)) { + printf("ERROR: Description table : %s.\n", $session->error); + $session->close; + exit $ERRORS{"UNKNOWN"}; +} +$session->close; + +my @load = undef; +my @iload = undef; +my @oid=undef; +my $exist=0; +foreach my $key ( keys %$resultat) { + verb("OID : $key, Desc : $$resultat{$key}"); + if ( $key =~ /$linload_name/ ) { + @oid=split (/\./,$key); + $iload[0]= pop(@oid) if ($$resultat{$key} eq "Load-1"); + $iload[1]= pop(@oid) if ($$resultat{$key} eq "Load-5"); + $iload[2]= pop(@oid) if ($$resultat{$key} eq "Load-15"); + $exist=1 + } +} + +if ($exist == 0) { + print "Can't find snmp information on load : UNKNOWN\n"; + exit $ERRORS{"UNKNOWN"}; +} + +for (my $i=0;$i<3;$i++) { $load[$i] = $$resultat{$linload_load . "." . $iload[$i]}}; + +print "Load : $load[0] $load[1] $load[2] :"; + +$exit_val=$ERRORS{"OK"}; +for (my $i=0;$i<3;$i++) { + if ( $load[$i] > $o_critL[$i] ) { + print " $load[$i] > $o_critL[$i] : CRITICAL"; + $exit_val=$ERRORS{"CRITICAL"}; + } + if ( $load[$i] > $o_warnL[$i] ) { + # output warn error only if no critical was found + if ($exit_val eq $ERRORS{"OK"}) { + print " $load[$i] > $o_warnL[$i] : WARNING"; + $exit_val=$ERRORS{"WARNING"}; + } + } +} +print " OK" if ($exit_val eq $ERRORS{"OK"}); +if (defined($o_perf)) { + print " | load_1_min=$load[0];$o_warnL[0];$o_critL[0] "; + print "load_5_min=$load[1];$o_warnL[1];$o_critL[1] "; + print "load_15_min=$load[2];$o_warnL[2];$o_critL[2]\n"; +} else { + print "\n"; +} +exit $exit_val; +} + +############## Cisco CPU check ################ + +if ($o_check_type eq "cisco") { +my @oidlists = ($cisco_cpu_5m, $cisco_cpu_1m, $cisco_cpu_5s); +my $resultat = (Net::SNMP->VERSION < 4) ? + $session->get_request(@oidlists) + : $session->get_request(-varbindlist => \@oidlists); + +if (!defined($resultat)) { + printf("ERROR: Description table : %s.\n", $session->error); + $session->close; + exit $ERRORS{"UNKNOWN"}; +} + +$session->close; + +if (!defined ($$resultat{$cisco_cpu_5s})) { + print "No CPU information : UNKNOWN\n"; + exit $ERRORS{"UNKNOWN"}; +} + +my @load = undef; + +$load[0]=$$resultat{$cisco_cpu_5s}; +$load[1]=$$resultat{$cisco_cpu_1m}; +$load[2]=$$resultat{$cisco_cpu_5m}; + +print "CPU : $load[0] $load[1] $load[2] :"; + +$exit_val=$ERRORS{"OK"}; +for (my $i=0;$i<3;$i++) { + if ( $load[$i] > $o_critL[$i] ) { + print " $load[$i] > $o_critL[$i] : CRITICAL"; + $exit_val=$ERRORS{"CRITICAL"}; + } + if ( $load[$i] > $o_warnL[$i] ) { + # output warn error only if no critical was found + if ($exit_val eq $ERRORS{"OK"}) { + print " $load[$i] > $o_warnL[$i] : WARNING"; + $exit_val=$ERRORS{"WARNING"}; + } + } +} +print " OK" if ($exit_val eq $ERRORS{"OK"}); +if (defined($o_perf)) { + print " | load_5_sec=$load[0]%;$o_warnL[0];$o_critL[0] "; + print "load_1_min=$load[1]%;$o_warnL[1];$o_critL[1] "; + print "load_5_min=$load[2]%;$o_warnL[2];$o_critL[2]\n"; +} else { + print "\n"; +} + +exit $exit_val; +} + +############## Cisco ASA CPU check ################ + +if ($o_check_type eq "casa") { +my @oidlists = ($casa_cpu_5m, $casa_cpu_1m, $casa_cpu_5s); +my $resultat = (Net::SNMP->VERSION < 4) ? + $session->get_request(@oidlists) + : $session->get_request(-varbindlist => \@oidlists); + +if (!defined($resultat)) { + printf("ERROR: Description table : %s.\n", $session->error); + $session->close; + exit $ERRORS{"UNKNOWN"}; +} + +$session->close; + +if (!defined ($$resultat{$casa_cpu_5s})) { + print "No CPU information : UNKNOWN\n"; + exit $ERRORS{"UNKNOWN"}; +} + +my @load = undef; + +$load[0]=$$resultat{$casa_cpu_5s}; +$load[1]=$$resultat{$casa_cpu_1m}; +$load[2]=$$resultat{$casa_cpu_5m}; + +print "CPU : $load[0] $load[1] $load[2] :"; + +$exit_val=$ERRORS{"OK"}; +for (my $i=0;$i<3;$i++) { + if ( $load[$i] > $o_critL[$i] ) { + print " $load[$i] > $o_critL[$i] : CRITICAL"; + $exit_val=$ERRORS{"CRITICAL"}; + } + if ( $load[$i] > $o_warnL[$i] ) { + # output warn error only if no critical was found + if ($exit_val eq $ERRORS{"OK"}) { + print " $load[$i] > $o_warnL[$i] : WARNING"; + $exit_val=$ERRORS{"WARNING"}; + } + } +} +print " OK" if ($exit_val eq $ERRORS{"OK"}); +if (defined($o_perf)) { + print " | load_5_sec=$load[0]%;$o_warnL[0];$o_critL[0] "; + print "load_1_min=$load[1]%;$o_warnL[1];$o_critL[1] "; + print "load_5_min=$load[2]%;$o_warnL[2];$o_critL[2]\n"; +} else { + print "\n"; +} + +exit $exit_val; +} + + + +############## Cisco Catalyst CPU check ################ + +if ($o_check_type eq "cata") { +my @oidlists = ($ciscocata_cpu_5m, $ciscocata_cpu_1m, $ciscocata_cpu_5s); +my $resultat = (Net::SNMP->VERSION < 4) ? + $session->get_request(@oidlists) + : $session->get_request(-varbindlist => \@oidlists); + +if (!defined($resultat)) { + printf("ERROR: Description table : %s.\n", $session->error); + $session->close; + exit $ERRORS{"UNKNOWN"}; +} + +$session->close; + +if (!defined ($$resultat{$ciscocata_cpu_5s})) { + print "No CPU information : UNKNOWN\n"; + exit $ERRORS{"UNKNOWN"}; +} + +my @load = undef; + +$load[0]=$$resultat{$ciscocata_cpu_5s}; +$load[1]=$$resultat{$ciscocata_cpu_1m}; +$load[2]=$$resultat{$ciscocata_cpu_5m}; + +print "CPU : $load[0] $load[1] $load[2] :"; + +$exit_val=$ERRORS{"OK"}; +for (my $i=0;$i<3;$i++) { + if ( $load[$i] > $o_critL[$i] ) { + print " $load[$i] > $o_critL[$i] : CRITICAL"; + $exit_val=$ERRORS{"CRITICAL"}; + } + if ( $load[$i] > $o_warnL[$i] ) { + # output warn error only if no critical was found + if ($exit_val eq $ERRORS{"OK"}) { + print " $load[$i] > $o_warnL[$i] : WARNING"; + $exit_val=$ERRORS{"WARNING"}; + } + } +} +print " OK" if ($exit_val eq $ERRORS{"OK"}); +if (defined($o_perf)) { + print " | load_5_sec=$load[0]%;$o_warnL[0];$o_critL[0] "; + print "load_1_min=$load[1]%;$o_warnL[1];$o_critL[1] "; + print "load_5_min=$load[2]%;$o_warnL[2];$o_critL[2]\n"; +} else { + print "\n"; +} + +exit $exit_val; +} + +############## Netscreen CPU check ################ + +if ($o_check_type eq "nsc") { +my @oidlists = ($nsc_cpu_5m, $nsc_cpu_1m, $nsc_cpu_5s); +my $resultat = (Net::SNMP->VERSION < 4) ? + $session->get_request(@oidlists) + : $session->get_request(-varbindlist => \@oidlists); + +if (!defined($resultat)) { + printf("ERROR: Description table : %s.\n", $session->error); + $session->close; + exit $ERRORS{"UNKNOWN"}; +} + +$session->close; + +if (!defined ($$resultat{$nsc_cpu_5s})) { + print "No CPU information : UNKNOWN\n"; + exit $ERRORS{"UNKNOWN"}; +} + +my @load = undef; + +$load[0]=$$resultat{$nsc_cpu_5s}; +$load[1]=$$resultat{$nsc_cpu_1m}; +$load[2]=$$resultat{$nsc_cpu_5m}; + +print "CPU : $load[0] $load[1] $load[2] :"; + +$exit_val=$ERRORS{"OK"}; +for (my $i=0;$i<3;$i++) { + if ( $load[$i] > $o_critL[$i] ) { + print " $load[$i] > $o_critL[$i] : CRITICAL"; + $exit_val=$ERRORS{"CRITICAL"}; + } + if ( $load[$i] > $o_warnL[$i] ) { + # output warn error only if no critical was found + if ($exit_val eq $ERRORS{"OK"}) { + print " $load[$i] > $o_warnL[$i] : WARNING"; + $exit_val=$ERRORS{"WARNING"}; + } + } +} +print " OK" if ($exit_val eq $ERRORS{"OK"}); +if (defined($o_perf)) { + print " | cpu_5_sec=$load[0]%;$o_warnL[0];$o_critL[0] "; + print "cpu_1_min=$load[1]%;$o_warnL[1];$o_critL[1] "; + print "cpu_5_min=$load[2]%;$o_warnL[2];$o_critL[2]\n"; +} else { + print "\n"; +} + +exit $exit_val; +} + +################## CPU for : AS/400 , Netsnmp, HP, Bluecoat, linkproof, fortigate ########### +if ( $o_check_type =~ /netsc|as400|bc|nokia|^hp$|lp|fg/ ) { + +# Get load table +my @oidlist = $cpu_oid{$o_check_type}; +verb("Checking OID : @oidlist"); +my $resultat = (Net::SNMP->VERSION < 4) ? + $session->get_request(@oidlist) + : $session->get_request(-varbindlist => \@oidlist); +if (!defined($resultat)) { + printf("ERROR: Description table : %s.\n", $session->error); + $session->close; + exit $ERRORS{"UNKNOWN"}; +} +$session->close; + +if (!defined ($$resultat{$cpu_oid{$o_check_type}})) { + print "No CPU information : UNKNOWN\n"; + exit $ERRORS{"UNKNOWN"}; +} + +my $load=$$resultat{$cpu_oid{$o_check_type}}; +verb("OID returned $load"); +# for AS400, divide by 100 +if ($o_check_type eq "as400") {$load /= 100; }; +# for Net-snmp : oid returned idle time so load = 100-idle. +if ($o_check_type eq "netsc") {$load = 100 - $load; }; + +printf("CPU used %.1f%% (",$load); + +$exit_val=$ERRORS{"OK"}; +if ($load > $o_crit) { + print ">$o_crit) : CRITICAL"; + $exit_val=$ERRORS{"CRITICAL"}; +} else { + if ($load > $o_warn) { + print ">$o_warn) : WARNING"; + $exit_val=$ERRORS{"WARNING"}; + } +} +print "<$o_warn) : OK" if ($exit_val eq $ERRORS{"OK"}); +(defined($o_perf)) ? + print " | cpu_prct_used=$load%;$o_warn;$o_crit\n" + : print "\n"; +exit $exit_val; + +} + +##### Checking hpux load +if ($o_check_type eq "hpux") { + +verb("Checking hpux load"); + +my @oidlists = ($hpux_load_1_min, $hpux_load_5_min, $hpux_load_15_min); +my $resultat = (Net::SNMP->VERSION < 4) ? + $session->get_request(@oidlists) + : $session->get_request(-varbindlist => \@oidlists); + +if (!defined($resultat)) { + printf("ERROR: Load table : %s.\n", $session->error); + $session->close; + exit $ERRORS{"UNKNOWN"}; +} + +$session->close; + +if (!defined ($$resultat{$hpux_load_1_min})) { + print "No Load information : UNKNOWN\n"; + exit $ERRORS{"UNKNOWN"}; +} + +my @load = undef; + +$load[0]=$$resultat{$hpux_load_1_min}/100; +$load[1]=$$resultat{$hpux_load_5_min}/100; +$load[2]=$$resultat{$hpux_load_15_min}/100; + +print "Load : $load[0] $load[1] $load[2] :"; + +$exit_val=$ERRORS{"OK"}; +for (my $i=0;$i<3;$i++) { + if ( $load[$i] > $o_critL[$i] ) { + print " $load[$i] > $o_critL[$i] : CRITICAL"; + $exit_val=$ERRORS{"CRITICAL"}; + } + if ( $load[$i] > $o_warnL[$i] ) { + # output warn error only if no critical was found + if ($exit_val eq $ERRORS{"OK"}) { + print " $load[$i] > $o_warnL[$i] : WARNING"; + $exit_val=$ERRORS{"WARNING"}; + } + } +} +print " OK" if ($exit_val eq $ERRORS{"OK"}); +if (defined($o_perf)) { + print " | load_1_min=$load[0]%;$o_warnL[0];$o_critL[0] "; + print "load_5_min=$load[1]%;$o_warnL[1];$o_critL[1] "; + print "load_15_min=$load[2]%;$o_warnL[2];$o_critL[2]\n"; +} else { + print "\n"; +} + +exit $exit_val; +} + +########## Standard cpu usage check ############ +# Get desctiption table +my $resultat = (Net::SNMP->VERSION < 4) ? + $session->get_table($base_proc) + : $session->get_table(Baseoid => $base_proc); + +if (!defined($resultat)) { + printf("ERROR: Description table : %s.\n", $session->error); + $session->close; + exit $ERRORS{"UNKNOWN"}; +} + +$session->close; + +my ($cpu_used,$ncpu)=(0,0); +foreach my $key ( keys %$resultat) { + verb("OID : $key, Desc : $$resultat{$key}"); + if ( $key =~ /$proc_load/) { + $cpu_used += $$resultat{$key}; + $ncpu++; + } +} + +if ($ncpu==0) { + print "Can't find CPU usage information : UNKNOWN\n"; + exit $ERRORS{"UNKNOWN"}; +} + +$cpu_used /= $ncpu; + +print "$ncpu CPU, ", $ncpu==1 ? "load" : "average load"; +printf(" %.1f%%",$cpu_used); +$exit_val=$ERRORS{"OK"}; + +if ($cpu_used > $o_crit) { + print " > $o_crit% : CRITICAL"; + $exit_val=$ERRORS{"CRITICAL"}; +} else { + if ($cpu_used > $o_warn) { + print " > $o_warn% : WARNING"; + $exit_val=$ERRORS{"WARNING"}; + } +} +print " < $o_warn% : OK" if ($exit_val eq $ERRORS{"OK"}); +(defined($o_perf)) ? + print " | cpu_prct_used=$cpu_used%;$o_warn;$o_crit\n" + : print "\n"; +exit $exit_val; + diff --git a/check_snmp/trunk/check_snmp_mem.pl b/check_snmp/trunk/check_snmp_mem.pl new file mode 100755 index 0000000..4cda8d2 --- /dev/null +++ b/check_snmp/trunk/check_snmp_mem.pl @@ -0,0 +1,525 @@ +#!/usr/bin/perl -w +############################## check_snmp_mem ############## +# Version : 1.1 +# Date : Jul 09 2006 +# Author : Patrick Proy (nagios at proy.org) +# Help : http://www.manubulon.com/nagios/ +# Licence : GPL - http://www.fsf.org/licenses/gpl.txt +# Contrib : Jan Jungmann +# TODO : +################################################################# +# +# Help : ./check_snmp_mem.pl -h +# + +use strict; +use Net::SNMP; +use Getopt::Long; + +# Nagios specific + +use lib "/usr/local/nagios/libexec"; +use utils qw(%ERRORS $TIMEOUT); +#my $TIMEOUT = 15; +#my %ERRORS=('OK'=>0,'WARNING'=>1,'CRITICAL'=>2,'UNKNOWN'=>3,'DEPENDENT'=>4); + +# SNMP Datas + +# Net-snmp memory + +my $nets_ram_free = "1.3.6.1.4.1.2021.4.6.0"; # Real memory free +my $nets_ram_total = "1.3.6.1.4.1.2021.4.5.0"; # Real memory total +my $nets_ram_cache = "1.3.6.1.4.1.2021.4.15.0"; # Real memory cached +my $nets_swap_free = "1.3.6.1.4.1.2021.4.4.0"; # swap memory free +my $nets_swap_total = "1.3.6.1.4.1.2021.4.3.0"; # Swap memory total +my @nets_oids = ($nets_ram_free,$nets_ram_total,$nets_swap_free,$nets_swap_total,$nets_ram_cache); + +# Cisco + +my $cisco_mem_pool = "1.3.6.1.4.1.9.9.48.1.1.1"; # Cisco memory pool +my $cisco_index = "1.3.6.1.4.1.9.9.48.1.1.1.2"; # memory pool name and index +my $cisco_valid = "1.3.6.1.4.1.9.9.48.1.1.1.4"; # Valid memory if 1 +my $cisco_used = "1.3.6.1.4.1.9.9.48.1.1.1.5"; # Used memory +my $cisco_free = "1.3.6.1.4.1.9.9.48.1.1.1.6"; # Free memory +# .1 : type, .2 : name, .3 : alternate, .4 : valid, .5 : used, .6 : free, .7 : max free + +# HP Procurve + +my $hp_mem_pool = "1.3.6.1.4.1.11.2.14.11.5.1.1.2.2.1.1"; # HP memory pool +my $hp_mem_index = "1.3.6.1.4.1.11.2.14.11.5.1.1.2.2.1.1.1"; # memory slot index +my $hp_mem_total = "1.3.6.1.4.1.11.2.14.11.5.1.1.2.2.1.1.5"; # Total Bytes +my $hp_mem_free = "1.3.6.1.4.1.11.2.14.11.5.1.1.2.2.1.1.6"; # Free Bytes +my $hp_mem_free_seg = "1.3.6.1.4.1.11.2.14.11.5.1.1.2.2.1.1.3"; # Free segments + +# AS/400 + +# Windows NT/2K/(XP?) + +# check_snmp_storage.pl -C -H -m "^Virtual Memory$" -w -c + + +# Globals + +my $Version='1.1'; + +my $o_host = undef; # hostname +my $o_community = undef; # community +my $o_port = 161; # port +my $o_help= undef; # wan't some help ? +my $o_verb= undef; # verbose mode +my $o_version= undef; # print version +my $o_netsnmp= 1; # Check with netsnmp (default) +my $o_cisco= undef; # Check cisco router mem +my $o_hp= undef; # Check hp procurve mem +my $o_warn= undef; # warning level option +my $o_warnR= undef; # warning level for Real memory +my $o_warnS= undef; # warning levels for swap +my $o_crit= undef; # Critical level option +my $o_critR= undef; # critical level for Real memory +my $o_critS= undef; # critical level for swap +my $o_perf= undef; # Performance data option +my $o_cache= undef; # Include cached memory as used memory +my $o_timeout= undef; # Timeout (Default 5) +my $o_version2= undef; # use snmp v2c +# SNMPv3 specific +my $o_login= undef; # Login for snmpv3 +my $o_passwd= undef; # Pass for snmpv3 +my $v3protocols=undef; # V3 protocol list. +my $o_authproto='md5'; # Auth protocol +my $o_privproto='des'; # Priv protocol +my $o_privpass= undef; # priv password + +# functions + +sub p_version { print "check_snmp_mem version : $Version\n"; } + +sub print_usage { + print "Usage: $0 [-v] -H -C [-2] | (-l login -x passwd [-X pass -L ,]) [-p ] -w -c [-I|-N|-E] [-f] [-m] [-t ] [-V]\n"; +} + +sub isnnum { # Return true if arg is not a number + my $num = shift; + if ( $num =~ /^(\d+\.?\d*)|(^\.\d+)$/ ) { return 0 ;} + return 1; +} + +sub round ($$) { + sprintf "%.$_[1]f", $_[0]; +} + +sub help { + print "\nSNMP Memory Monitor for Nagios version ",$Version,"\n"; + print "(c)2004-2006 to my cat Ratoune - Author: Patrick Proy\n\n"; + print_usage(); + print <, + : Authentication protocol (md5|sha : default md5) + : Priv protocole (des|aes : default des) +-P, --port=PORT + SNMP port (Default 161) +-w, --warn=INTEGER | INT,INT + warning level for memory in percent (0 for no checks) + Default (-N switch) : comma separated level for Real Memory and Swap + -I switch : warning level +-c, --crit=INTEGER | INT,INT + critical level for memory in percent (0 for no checks) + Default (-N switch) : comma separated level for Real Memory and Swap + -I switch : critical level +-N, --netsnmp (default) + check linux memory & swap provided by Net SNMP +-m, --memcache + include cached memory in used memory (only with Net-SNMP) +-I, --cisco + check cisco memory (sum of all memory pools) +-E, --hp + check HP proccurve memory +-f, --perfdata + Performance data output +-t, --timeout=INTEGER + timeout for SNMP in seconds (Default: 5) +-V, --version + prints version number +EOT +} + +# For verbose output +sub verb { my $t=shift; print $t,"\n" if defined($o_verb) ; } + +# Get the alarm signal (just in case snmp timout screws up) +$SIG{'ALRM'} = sub { + print ("ERROR: Alarm signal (Nagios time-out)\n"); + exit $ERRORS{"UNKNOWN"}; +}; + +sub check_options { + Getopt::Long::Configure ("bundling"); + GetOptions( + 'v' => \$o_verb, 'verbose' => \$o_verb, + 'h' => \$o_help, 'help' => \$o_help, + 'H:s' => \$o_host, 'hostname:s' => \$o_host, + 'p:i' => \$o_port, 'port:i' => \$o_port, + 'C:s' => \$o_community, 'community:s' => \$o_community, + 'l:s' => \$o_login, 'login:s' => \$o_login, + 'x:s' => \$o_passwd, 'passwd:s' => \$o_passwd, + 'X:s' => \$o_privpass, 'privpass:s' => \$o_privpass, + 'L:s' => \$v3protocols, 'protocols:s' => \$v3protocols, + 't:i' => \$o_timeout, 'timeout:i' => \$o_timeout, + 'V' => \$o_version, 'version' => \$o_version, + 'I' => \$o_cisco, 'cisco' => \$o_cisco, + 'N' => \$o_netsnmp, 'netsnmp' => \$o_netsnmp, + 'E' => \$o_hp, 'hp' => \$o_hp, + '2' => \$o_version2, 'v2c' => \$o_version2, + 'c:s' => \$o_crit, 'critical:s' => \$o_crit, + 'w:s' => \$o_warn, 'warn:s' => \$o_warn, + 'm' => \$o_cache, 'memcache' => \$o_cache, + 'f' => \$o_perf, 'perfdata' => \$o_perf + ); + if (defined ($o_help) ) { help(); exit $ERRORS{"UNKNOWN"}}; + if (defined($o_version)) { p_version(); exit $ERRORS{"UNKNOWN"}}; + if ( ! defined($o_host) ) # check host and filter + { print "No host defined!\n";print_usage(); exit $ERRORS{"UNKNOWN"}} + # check snmp information + if ( !defined($o_community) && (!defined($o_login) || !defined($o_passwd)) ) + { print "Put snmp login info!\n"; print_usage(); exit $ERRORS{"UNKNOWN"}} + if ((defined($o_login) || defined($o_passwd)) && (defined($o_community) || defined($o_version2)) ) + { print "Can't mix snmp v1,2c,3 protocols!\n"; print_usage(); exit $ERRORS{"UNKNOWN"}} + if (defined ($v3protocols)) { + if (!defined($o_login)) { print "Put snmp V3 login info with protocols!\n"; print_usage(); exit $ERRORS{"UNKNOWN"}} + my @v3proto=split(/,/,$v3protocols); + if ((defined ($v3proto[0])) && ($v3proto[0] ne "")) {$o_authproto=$v3proto[0]; } # Auth protocol + if (defined ($v3proto[1])) {$o_privproto=$v3proto[1]; } # Priv protocol + if ((defined ($v3proto[1])) && (!defined($o_privpass))) { + print "Put snmp V3 priv login info with priv protocols!\n"; print_usage(); exit $ERRORS{"UNKNOWN"}} + } + if (defined($o_timeout) && (isnnum($o_timeout) || ($o_timeout < 2) || ($o_timeout > 60))) + { print "Timeout must be >1 and <60 !\n"; print_usage(); exit $ERRORS{"UNKNOWN"}} + if (!defined($o_timeout)) {$o_timeout=5;} + #Check Warning and crit are present + if ( ! defined($o_warn) || ! defined($o_crit)) + { print "Put warning and critical values!\n"; print_usage(); exit $ERRORS{"UNKNOWN"}} + # Get rid of % sign + $o_warn =~ s/\%//g; + $o_crit =~ s/\%//g; + # if -N or -E switch , undef $o_netsnmp + if (defined($o_cisco) || defined($o_hp) ) { + $o_netsnmp=undef; + if ( isnnum($o_warn) || isnnum($o_crit)) + { print "Numeric value for warning or critical !\n";print_usage(); exit $ERRORS{"UNKNOWN"} } + if ( ($o_crit != 0) && ($o_warn > $o_crit) ) + { print "warning <= critical ! \n";print_usage(); exit $ERRORS{"UNKNOWN"}} + } + if (defined($o_netsnmp)) { + my @o_warnL=split(/,/ , $o_warn); + my @o_critL=split(/,/ , $o_crit); + if (($#o_warnL != 1) || ($#o_critL != 1)) + { print "2 warnings and critical !\n";print_usage(); exit $ERRORS{"UNKNOWN"}} + for (my $i=0;$i<2;$i++) { + if ( isnnum($o_warnL[$i]) || isnnum($o_critL[$i])) + { print "Numeric value for warning or critical !\n";print_usage(); exit $ERRORS{"UNKNOWN"} } + if (($o_critL[$i]!= 0) && ($o_warnL[$i] > $o_critL[$i])) + { print "warning <= critical ! \n";print_usage(); exit $ERRORS{"UNKNOWN"}} + if ( $o_critL[$i] > 100) + { print "critical percent must be < 100 !\n";print_usage(); exit $ERRORS{"UNKNOWN"}} + } + $o_warnR=$o_warnL[0];$o_warnS=$o_warnL[1]; + $o_critR=$o_critL[0];$o_critS=$o_critL[1]; + } + +} + +########## MAIN ####### + +check_options(); + +# Check gobal timeout if snmp screws up +if (defined($TIMEOUT)) { + verb("Alarm at $TIMEOUT"); + alarm($TIMEOUT); +} else { + verb("no timeout defined : $o_timeout + 10"); + alarm ($o_timeout+10); +} + +# Connect to host +my ($session,$error); +if ( defined($o_login) && defined($o_passwd)) { + # SNMPv3 login + if (!defined ($o_privpass)) { + verb("SNMPv3 AuthNoPriv login : $o_login, $o_authproto"); + ($session, $error) = Net::SNMP->session( + -hostname => $o_host, + -version => '3', + -username => $o_login, + -authpassword => $o_passwd, + -authprotocol => $o_authproto, + -timeout => $o_timeout + ); + } else { + verb("SNMPv3 AuthPriv login : $o_login, $o_authproto, $o_privproto"); + ($session, $error) = Net::SNMP->session( + -hostname => $o_host, + -version => '3', + -username => $o_login, + -authpassword => $o_passwd, + -authprotocol => $o_authproto, + -privpassword => $o_privpass, + -privprotocol => $o_privproto, + -timeout => $o_timeout + ); + } +} else { + if (defined ($o_version2)) { + # SNMPv2 Login + verb("SNMP v2c login"); + ($session, $error) = Net::SNMP->session( + -hostname => $o_host, + -version => 2, + -community => $o_community, + -port => $o_port, + -timeout => $o_timeout + ); + } else { + # SNMPV1 login + verb("SNMP v1 login"); + ($session, $error) = Net::SNMP->session( + -hostname => $o_host, + -community => $o_community, + -port => $o_port, + -timeout => $o_timeout + ); + } +} +if (!defined($session)) { + printf("ERROR opening session: %s.\n", $error); + exit $ERRORS{"UNKNOWN"}; +} + +# Global variable +my $resultat=undef; + +########### Cisco memory check ############ +if (defined ($o_cisco)) { + + # Get Cisco memory table + $resultat = (Net::SNMP->VERSION < 4) ? + $session->get_table($cisco_mem_pool) + :$session->get_table(Baseoid => $cisco_mem_pool); + + if (!defined($resultat)) { + printf("ERROR: Description table : %s.\n", $session->error); + $session->close; + exit $ERRORS{"UNKNOWN"}; + } + my (@oid,@index)=(undef,undef); + my $nindex=0; + foreach my $key ( keys %$resultat) { + verb("OID : $key, Desc : $$resultat{$key}"); + if ( $key =~ /$cisco_index/ ) { + @oid=split (/\./,$key); + $index[$nindex++] = pop(@oid); + } + } + + # Check if at least 1 memory pool exists + if ($nindex == 0) { + printf("ERROR: No memory pools found"); + $session->close; + exit $ERRORS{"UNKNOWN"}; + } + + # Test every memory pool + my ($c_output,$prct_free)=(undef,undef); + my ($warn_s,$crit_s)=(0,0); + my ($used,$free)=(0,0); + foreach (@index) { + $c_output .="," if defined ($c_output); + if ( $$resultat{$cisco_valid . "." . $_} == 1 ) { + $used += $$resultat{$cisco_used . "." . $_}; + $free += $$resultat{$cisco_free . "." . $_}; + $prct_free=round($$resultat{$cisco_used . "." . $_}*100/($$resultat{$cisco_free . "." . $_}+$$resultat{$cisco_used . "." . $_}) ,0); + $c_output .= $$resultat{$cisco_index . "." . $_} . ":" . $prct_free . "%"; + if (($o_crit!=0)&&($o_crit <= $prct_free)) { + $crit_s =1; + } elsif (($o_warn!=0)&&($o_warn <= $prct_free)) { + $warn_s=1; + } + } else { + $c_output .= $$resultat{$cisco_index . "." . $_} . ": INVALID"; + $crit_s =1; + } + } + my $total=$used+$free; + $prct_free=round($used*100/($total),0); + verb("Total used : $used, free: $free, output : $c_output"); + my $c_status="OK"; + $c_output .=" : " . $prct_free ."% : "; + if ($crit_s == 1 ) { + $c_output .= " > " . $o_crit ; + $c_status="CRITICAL"; + } else { + if ($warn_s == 1 ) { + $c_output.=" > " . $o_warn; + $c_status="WARNING"; + } + } + $c_output .= " ; ".$c_status; + if (defined ($o_perf)) { + $c_output .= " | ram_used=" . $used.";"; + $c_output .= ($o_warn ==0)? ";" : round($o_warn * $total/100,0).";"; + $c_output .= ($o_crit ==0)? ";" : round($o_crit * $total/100,0).";"; + $c_output .= "0;" . $total ; + } + $session->close; + print "$c_output \n"; + exit $ERRORS{$c_status}; +} + +########### HP Procurve memory check ############ +if (defined ($o_hp)) { + + # Get hp memory table + $resultat = (Net::SNMP->VERSION < 4) ? + $session->get_table($hp_mem_pool) + :$session->get_table(Baseoid => $hp_mem_pool); + + if (!defined($resultat)) { + printf("ERROR: Description table : %s.\n", $session->error); + $session->close; + exit $ERRORS{"UNKNOWN"}; + } + my (@oid,@index)=(undef,undef); + my $nindex=0; + foreach my $key ( keys %$resultat) { + verb("OID : $key, Desc : $$resultat{$key}"); + if ( $key =~ /$hp_mem_index/ ) { + @oid=split (/\./,$key); + $index[$nindex++] = pop(@oid); + } + } + + # Check if at least 1 memory slots exists + if ($nindex == 0) { + printf("ERROR: No memory slots found"); + $session->close; + exit $ERRORS{"UNKNOWN"}; + } + + # Consolidate the datas + my ($total,$free)=(0,0); + my ($c_output,$prct_free)=(undef,undef); + foreach (@index) { + $c_output .="," if defined ($c_output); + $total += $$resultat{$hp_mem_total . "." . $_}; + $free += $$resultat{$hp_mem_free . "." . $_}; + $c_output .= "Slot " . $$resultat{$hp_mem_index . "." . $_} . ":" + .round( + 100 - ($$resultat{$hp_mem_free . "." . $_} *100 / + $$resultat{$hp_mem_total . "." . $_}) ,0) + . "%"; + } + my $used = $total - $free; + $prct_free=round($used*100/($total),0); + verb("Used : $used, Free: $free, Output : $c_output"); + my $c_status="OK"; + $c_output .=" : " . $prct_free ."% : "; + if (($o_crit!=0)&&($o_crit <= $prct_free)) { + $c_output .= " > " . $o_crit ; + $c_status="CRITICAL"; + } else { + if (($o_warn!=0)&&($o_warn <= $prct_free)) { + $c_output.=" > " . $o_warn; + $c_status="WARNING"; + } + } + $c_output .= " ; ".$c_status; + if (defined ($o_perf)) { + $c_output .= " | ram_used=" . $used.";"; + $c_output .= ($o_warn ==0)? ";" : round($o_warn * $total/100,0).";"; + $c_output .= ($o_crit ==0)? ";" : round($o_crit * $total/100,0).";"; + $c_output .= "0;" . $total ; + } + $session->close; + print "$c_output \n"; + exit $ERRORS{$c_status}; +} + +########### Net snmp memory check ############ +if (defined ($o_netsnmp)) { + + # Get NetSNMP memory values + $resultat = (Net::SNMP->VERSION < 4) ? + $session->get_request(@nets_oids) + :$session->get_request(-varbindlist => \@nets_oids); + + if (!defined($resultat)) { + printf("ERROR: netsnmp : %s.\n", $session->error); + $session->close; + exit $ERRORS{"UNKNOWN"}; + } + + my ($realused,$swapused)=(undef,undef); + + $realused= defined($o_cache) ? + ($$resultat{$nets_ram_total}-$$resultat{$nets_ram_free})/$$resultat{$nets_ram_total} + : + ($$resultat{$nets_ram_total}-($$resultat{$nets_ram_free}+$$resultat{$nets_ram_cache}))/$$resultat{$nets_ram_total}; + + if($$resultat{$nets_ram_total} == 0) { $realused = 0; } + + $swapused= ($$resultat{$nets_swap_total} == 0) ? 0 : + ($$resultat{$nets_swap_total}-$$resultat{$nets_swap_free})/$$resultat{$nets_swap_total}; + $realused=round($realused*100,0); + $swapused=round($swapused*100,0); + defined($o_cache) ? + verb ("Ram : $$resultat{$nets_ram_free} / $$resultat{$nets_ram_total} : $realused") + : + verb ("Ram : $$resultat{$nets_ram_free} ($$resultat{$nets_ram_cache} cached) / $$resultat{$nets_ram_total} : $realused"); + verb ("Swap : $$resultat{$nets_swap_free} / $$resultat{$nets_swap_total} : $swapused"); + + my $n_status="OK"; + my $n_output="Ram : " . $realused . "%, Swap : " . $swapused . "% :"; + if ((($o_critR!=0)&&($o_critR <= $realused)) || (($o_critS!=0)&&($o_critS <= $swapused))) { + $n_output .= " > " . $o_critR . ", " . $o_critS; + $n_status="CRITICAL"; + } else { + if ((($o_warnR!=0)&&($o_warnR <= $realused)) || (($o_warnS!=0)&&($o_warnS <= $swapused))) { + $n_output.=" > " . $o_warnR . ", " . $o_warnS; + $n_status="WARNING"; + } + } + $n_output .= " ; ".$n_status; + if (defined ($o_perf)) { + if (defined ($o_cache)) { + $n_output .= " | ram_used=" . ($$resultat{$nets_ram_total}-$$resultat{$nets_ram_free}).";"; + } + else { + $n_output .= " | ram_used=" . ($$resultat{$nets_ram_total}-$$resultat{$nets_ram_free}-$$resultat{$nets_ram_cache}).";"; + } + $n_output .= ($o_warnR ==0)? ";" : round($o_warnR * $$resultat{$nets_ram_total}/100,0).";"; + $n_output .= ($o_critR ==0)? ";" : round($o_critR * $$resultat{$nets_ram_total}/100,0).";"; + $n_output .= "0;" . $$resultat{$nets_ram_total}. " "; + $n_output .= "swap_used=" . ($$resultat{$nets_swap_total}-$$resultat{$nets_swap_free}).";"; + $n_output .= ($o_warnS ==0)? ";" : round($o_warnS * $$resultat{$nets_swap_total}/100,0).";"; + $n_output .= ($o_critS ==0)? ";" : round($o_critS * $$resultat{$nets_swap_total}/100,0).";"; + $n_output .= "0;" . $$resultat{$nets_swap_total}; + } + $session->close; + print "$n_output \n"; + exit $ERRORS{$n_status}; + +} diff --git a/check_snmp/trunk/check_snmp_patchlevel.pl b/check_snmp/trunk/check_snmp_patchlevel.pl new file mode 100755 index 0000000..03fb954 --- /dev/null +++ b/check_snmp/trunk/check_snmp_patchlevel.pl @@ -0,0 +1,287 @@ +#! /usr/bin/perl -w +################################################################################ +# check_snmp_patchlevel.pl v1.2 +# +# Nagios plugin to check the OS version string through SNMP sysDescr value. +# Please adjust the line setting the "use lib" path so utils.pm can be found. +# @2009 public[at]frank4dd[dot]com +# +# updates: +# 20090228 v1.1 adds support for Cisco PIX +# 20091117 v1.2 adds support for selection of SNMP version 1 or 2 +################################################################################ + +use strict; +use Getopt::Long; +use Net::SNMP; + +use vars qw($opt_V $opt_v $opt_h $opt_H $opt_g $opt_C $opt_f $PROGNAME @raw_data $output); +use lib "/usr/lib/nagios/plugins" ; +use utils qw(%ERRORS &print_revision &support &usage); + +$PROGNAME = "check_snmp_patchlevel.pl"; + +sub print_help (); +sub print_usage (); + +$ENV{'PATH'}=''; +$ENV{'BASH_ENV'}=''; +$ENV{'ENV'}=''; + +#print("Args: $#ARGV\n"); +if ($#ARGV == -1) { usage("Missing arguments\.\nUsage: $PROGNAME -H [-v snmp version 1|2] -g [-C community] [-f ]\n"); } + +Getopt::Long::Configure('bundling'); +GetOptions + ("V" => \$opt_V, "plugin-version"=> \$opt_V, + "v=s" => \$opt_v, "snmp-version=s"=> \$opt_v, + "h" => \$opt_h, "help" => \$opt_h, + "H=s" => \$opt_H, "hostname=s" => \$opt_H, + "C=s" => \$opt_C, "community=s" => \$opt_C, + "f=s" => \$opt_f, "configfile=s" => \$opt_f, + "g=s" => \$opt_g, "devicegroup=s" => \$opt_g); + +if ($opt_V) { + print_revision($PROGNAME,'$Revision: 120 $'); + exit $ERRORS{'OK'}; +} + +if ($opt_h) { print_help(); } + +# The SNMP port defaults to 161. It is not made a commandline option yet. +my $opt_p = 161; +# The SNMP timeout is set to 5 seconds. It is not made a commandline option yet. +my $opt_t = 5; + +################################################################################ +# Check for the "required" options -H , -g +################################################################################ + +($opt_H) || usage("Host name/address not specified\. Use $PROGNAME -h for help\.\n"); +my $host = $1 if ($opt_H =~ /([-.A-Za-z0-9]+)/); +($host) || usage("Invalid host: $opt_H\n"); + +($opt_g) || usage("Device type not specified\. Use $PROGNAME -h for help\.\n"); +# no sanity chck here, it is done below where $opt_g is parsed. + +################################################################################ +# Check for the "optional" options -v -C, -f, -s +################################################################################ +# set the SNMP version or assume it is "1" (default) +($opt_v) || ($opt_v = 1) ; +if ( $opt_v ne 1 && $opt_v ne 2) { + printf("UNKNOWN: SNMP version $opt_v.\n"); + exit $ERRORS{'UNKNOWN'}; +} + +# set the SNMP community or assume it is "public" (default) +($opt_C) || ($opt_C = "public") ; + +# load config file +if($opt_f) { &read_config(); } + +################################################################################ +# We fetch the system description via SNMP. It should contain the OS version. +# The SNMP OID we query is .1.3.6.1.2.1.1.1.0 = SNMPv2-MIB::sysDescr.0 +# $version = `/usr/bin/snmpget -OQv -v 1 -c $opt_C $host .1.3.6.1.2.1.1.1.0`; +################################################################################ +my $snmpdata=""; +my $response=""; +my $sysdesc_oid = ".1.3.6.1.2.1.1.1.0"; + +my ($session, $error) = Net::SNMP->session( + -hostname => $opt_H, + -community => $opt_C, + -port => $opt_p, + -timeout => $opt_t, + -version => $opt_v +); + +if(!defined($session)) { printf("UNKNOWN: %s.\n", $error); exit $ERRORS{'UNKNOWN'}; } + +$response = $session->get_request( -varbindlist => [$sysdesc_oid]); + +if(!defined($response)) { + printf("UNKNOWN: %s.\n", $session->error); + $session->close; + exit $ERRORS{'UNKNOWN'}; +} + +$snmpdata = $response->{$sysdesc_oid}; +$session->close; + +################################################################################ +# There is no standardized way for displaying OS version and patch levels. +# Depending on the vendor and OS, we need to parse this data differently. +# We don't have a switch statement yet (coming in perl 5.10), so we need +# to cascade the if-thens +################################################################################ + +################################################################################ +# Example response for Cisco Routers, here a from a Cat-6506: +# Version: Cisco Internetwork Operating System Software +# IOS (tm) MSFC2 Software (C6MSFC2-JSV-M), Version 12.1(27b)E3, RELEASE SOFTWARE (fc1) +# ^^^^^^^^^^^ +# Technical Support: http://www.cisco.com/techsupport +# Copyright (c) 1986-2007 by cisco Systems, Inc. +# Compiled Tue 07-Aug-0 +# Example response for Cisco Routers, here a from a Cat-3750: +# Cisco IOS Software, C3750 Software (C3750-IPBASE-M), Version 12.2(25)SEE2, RELEASE SOFTWARE (fc1) +# ^^^^^^^^^^^^ +# Copyright (c) 1986-2006 by Cisco Systems, Inc. +# Compiled Fri 28-Jul-06 08:46 by yenanh +################################################################################ +my $version=""; + +if ($opt_g =~ /ios/) { + my $line=""; + my @lines = split ('\n', $snmpdata); + foreach $line (@lines) { + if($line =~ /IOS .*/) { + (my @fields) = split(', ', $line); + foreach my $field (@fields) { + if($field =~ /Version/) { (my $txt, $version) = split('Version ', $field); } + } + } + } +} + +################################################################################ +# Example response for Cisco ASA 5520: +# "Cisco Adaptive Security Appliance Version 8.0(4)" +# ^^^^^^ +################################################################################ +elsif ($opt_g =~ /asa/) { + if($snmpdata =~ /^Cisco Adaptive Security Appliance.*/) { + (my $os, $version) = split('Version ', $snmpdata); + } +} + +############################################################################### +# Example response for Cisco PIX 525: +# "Cisco PIX Firewall Version 6.3(5)" +# "Cisco Cisco PIX Security Appliance Version 7.2(2)" +# "Cisco Cisco PIX Security Appliance Version 8.0(2)" +############################################################################### +elsif ($opt_g =~ /pix/) { + if($snmpdata =~ /.* PIX .*/) { + (my $os, $version) = split('Version ', $snmpdata); + } +} + +else { usage("Unknown option parameter: $opt_g\. Use $PROGNAME -h for help\.\n"); } + +################################################################################ +# If the SNMP data cannot be parsed, we generate the exit code and finish. +################################################################################ +if($version eq "") { + printf("UNKNOWN: cannot find version string in SNMP response. Either -t is incorrect or the Version string is unreadable.\n"); + exit $ERRORS{'UNKNOWN'}; +} +################################################################################ +# We are in 'discovery' mode, we report the OS Version, return 'OK' and finish. +################################################################################ +elsif (! $opt_f) { + printf (uc($opt_g)." Version: $version | $snmpdata\n"); + exit $ERRORS{'OK'}; +} +################################################################################ +# We are in 'compliance' mode, we check the OS Version against the config file +################################################################################ +else { + foreach my $line (@raw_data) { + # skip comment lines + next if($line =~ /^#.*$/); + chomp($line); + + (my $required, my $osgroup, my $osversion, my $remarks)=split(/\|/,$line); + + if( ($opt_g eq $osgroup) && ($version eq $osversion) ) { + + if($required eq "approved") { + $output = uc($opt_g)." Version: $version approved"; + if ($remarks ne "") { $output = $output." | Remarks: ".$remarks." Data: $snmpdata\n"; } + else { $output = $output." | $snmpdata\n"; } + printf $output; exit $ERRORS{'OK'}; + } + + if($required eq "obsolete") { + $output = uc($opt_g)." Version: $version obsolete"; + if ($remarks ne "") { $output = $output." | Remarks: ".$remarks." Data: $snmpdata\n"; } + else { $output = $output." | $snmpdata\n"; } + printf $output; exit $ERRORS{'WARNING'}; + } + + if($required eq "med-vuln") { + $output = uc($opt_g)." Version: $version vulnerable (low-medium)"; + if ($remarks ne "") { $output = $output." | Remarks: ".$remarks." Data: $snmpdata\n"; } + else { $output = $output." | $snmpdata\n"; } + printf $output; exit $ERRORS{'WARNING'}; + } + + if($required eq "crit-vuln") { + $output = uc($opt_g)." Version: $version vulnerable (high risk)"; + if ($remarks ne "") { $output = $output." | Remarks: ".$remarks." Data: $snmpdata\n"; } + else { $output = $output." | $snmpdata\n"; } + printf $output; exit $ERRORS{'CRITICAL'}; + } + } + } + # the OS version is not listed, we don't know exactly if its good or bad. + printf (uc($opt_g)." Version: $version unverified | $snmpdata\n"); + exit $ERRORS{'UNKNOWN'}; +} +################################################################################ +# End of main. Subroutine definitions below. +################################################################################ +sub read_config () { + + if (! -e $opt_f) { usage("Cannot find file $opt_f\. Check file name and path\.\n"); } + open(DATFILE, $opt_f) || usage("Cannot read file $opt_f\. Check permissions\.\n"); + @raw_data=; + close(DATFILE); +} + +sub print_usage () { + print "Usage: $PROGNAME -H [-v snmp version 1|2] -g [-C community] [-f ]\n"; + exit $ERRORS{'OK'}; +} + +sub print_help () { + print_revision($PROGNAME,'$Revision: 1.0.0 $'); + print "Copyright (c) 2009 Frank4DD + +This plugin intends to report the OS version string of a supported vendor. +Currently it is parsing Cisco IOS, PIX and ASA versions through SNMP sysDescr polls. + +In 'discovery mode' without using the option '-f', this plugin returns the OS +version string with 'OK' if the version could be fetched, or 'UNKNOWN' if not. +Useful if you need a view on what is out there in a enterprise environment. + +In 'compliance mode' by specifying '-f', this plugin compares the device OS +version string against a list of categorized (approved) OS versions. It is +meant to identify devices running a rogue, obsolete or vulnerable OS version. + +Usually this check runs only once in a couple of hours or even longer periods. +The configuration file format is in the check_snmp_patchlevel.cfg template. + +"; + print_usage(); + print " +-H, --hostname=HOST + Name or IP address of host to check +-v, --snmp-version [1|2] + Specify the SNMP version to use: 1 or 2c +-g, --devicegroup=[ios|asa] + OS version string to expect: ios = Cisco IOS Routers + asa = Cisco ASA Appliances + pix = Cisco PIX Firewalls +-C, --community=community + SNMP community (default public) +-f, --configfile=STRING + Version file and path, contains a list of approved versions + +"; + support(); + exit $ERRORS{'OK'}; +} diff --git a/check_snmp/trunk/check_snmp_temperature.pl b/check_snmp/trunk/check_snmp_temperature.pl new file mode 100644 index 0000000..674855d --- /dev/null +++ b/check_snmp/trunk/check_snmp_temperature.pl @@ -0,0 +1,714 @@ +#!/usr/bin/perl -w +# +# ============================== SUMMARY ===================================== +# +# Program : check_snmp_temperature.pl +# Version : 0.33 +# Date : Aug 08 2008 +# Author : William Leibzon - william@leibzon.org +# Summary : This is a nagios plugin that checks temperature sensors +# using SNMP. Dell, HP, Cisco and other types are supported +# and for other systems OIDs can be easily specified too +# Licence : GPL - summary below, text at http://www.fsf.org/licenses/gpl.txt +# +# =========================== PROGRAM LICENSE ================================= +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +# +# ===================== INFORMATION ABOUT THIS PLUGIN ========================= +# +# This Temperature check plugin that retreives temperature sensor values from +# SNMP and can issue alerts if selected parameters are above given number +# It also returns performance data for further nagios 2.0 post-processing +# +# This program is written and maintained by: +# William Leibzon - william(at)leibzon.org +# It is partially based on check_snmp_* plugins by: +# Patrick Proy (patrick at proy.org) +# +# ============================= SETUP NOTES ==================================== +# +# Make sure to check and if necessary adjust the the path to utils.pm +# Make sure you have Net::SNMP perl module installed +# +# If you want to check Dell servers, HP server, Juniper routers or +# Cisco Switches/Routers (cisco 7500, 5500, 2948) then you may skip +# much of the configuration hassles and use pre-programmed settings +# by using "--type" (or -T) parameter, you do still need to specify +# though if you want output as C or F with '-o' option (see examples). +# The plugin currently does not support finding critical & warning +# thresholds which most systems also report in SNMP, so actual thresholds +# you will need to specify as well. +# +# NOTE: If you've previously used 0.2x version of this plugin to +# check HP equipment, beware that 0.3 version has "incompatible" +# change in that it returns human-readable sensor names rather +# then using HP locale ids to enumerate sensors. If you need +# old behavior then instead of using '-T hp' as parameter +# use '-N 1.3.6.1.4.1.232.6.2.6.8.1.3 -D 1.3.6.1.4.1.232.6.2.6.8.1.4' +# +# If you're using some other device then you need to check documentation to +# figure out correct parameters for this plugin, then specify base temperature +# sensor names table OID with '-N' and values table OID with '-D. You also need +# to specify what base sensor temperature data type is with "-i" (see below). +# +# The way plugin works is to walk the snmp tree from base names OID and find +# all the sensor names. Then it compares names given with '-a' (names are +# seperated by ',') to those found in the snmp tree (in '-a' you're expected +# to specify one word which would be found in the full sensor name and +# is unique for thaqt `sensor) and uses OID ending (i.e. part of OID after +# the base) and adds it to base value table OID to create OID to be retrieved +# (similar to how you find ethernet statistics OIDs based on name of the +# interface and in fact many of SNMP parameters are like that). +# +# Note: If you don't know temperature sensor names on your system do: +# check_snmp_temperature -v -A '*' ... +# (using '-v' option forces debugging output that should further help) +# +# If your system does not have table with sensor names you can still use +# this plugin if you know exact temperature data OIDs. Then you specify list +# of names sensors should be known by with '-n' option and list of data OIDs +# with '-d' option (this can also be useful if you want to avoid having plugin +# do snmp table walk each time as retrieving specific list of OIDs is faster). +# You will still need to specify what is likely the same sensor names you +# you put in '-n' with '-a' or '-A' option. +# +# Request: If you have an new type of device and as per above you figured +# out SNMP parameters that work, please send me email with this +# information so that I can add it as a new system type. +# +# The values retrieved are compared to specified warning and critical values, +# but first the temperature has to be converted from base measurement units to +# measurement units you want. These units are Celsius (C) or Fahrenheit (F) +# or Kelvin (K) with input measurement unit specified with '-i' and output +# specified with '-o'. For input you sometimes have situation where sensor +# reports 10xRealValue, i.e. 33.5C is reported as 335 - this is supported +# too and then input type is specified as '-i 10C'. +# +# Warning and critical values are specified with '-w' and '-c' and each +# one must have exact same number of values (separated by ',') as number +# of sensor names specified with '-a'. Any values you dont want to compare +# you specify as 0 or just not specify (i.e. -w ',50,'). In some cases you +# might not get data for specific sensor and want to substitute default +# value - this is supported with '-u' option (note that default values +# is in fact compared against -w and -c). +# +# Additionally if you want performance output then use '-f' option to get all +# the sensors specified in '-a' or specify particular list of sensors for +# performance data with '-A' (this list can include names not found in '-a'). +# A special option of -A '*' will allow to get data from all sensors found +# and is this very useful to find what sensors you have with manual run. +# +# ========================= SETUP EXAMPLES ================================== +# +# define command { +# command_name check_cisco_temperature +# command_line $USER1$/check_snmp_temperature.pl -f -H $HOSTADDRESS$ --type=cisco1 -o F -C $ARG1$ -a $ARG2$ -w $ARG3$ -c $ARG4$ +# } +# +# define service{ +# use std-service +# hostgroup_name cs2948 +# service_description Temperature +# check_command check_cisco_temperature!foo!Chassis!160!190 +# } +# +# define command{ +# command_name check_dell_temperature +# command_line $USER1$/check_snmp_temperature.pl -H $HOSTADDRESS$ -C public \ +# -N .1.3.6.1.4.1.674.10892.1.700.20.1.8 \ +# -D .1.3.6.1.4.1.674.10892.1.700.20.1.6 -i 10C -o F -u 0 \ +# -a ARG1$ -w $ARG2$ -c $ARG3$ -f +# } +# +# define service { +# use std-service +# hostgroup_name dell_1750 +# service_description Temperature +# check_command check_dell_temperature!CPU,Ambient,Bottom!110,90,0!135,110,0 +# } +# +# For some dell systems with all sensors enabled you can replace the above with: +# check_command check_temperature!'CPU,PROC_1,PROC_2,Ambient,Bottom,BMC Planar,BMC Riser'!110,120,120,90,90,105,105!135,140,140,110,110,125,125 +# +# ==================== CHANGES/RELEASE, TODO ================================== +# +# 0.33 - Aug 2008 : Full SNMPv3 support (contrib patch by Nicolas Deffayet) +# 0.33 - May 2008 : Minor bug fixes. Added baytech pdu SNMP OIDs +# 0.31 - Feb 2008 : Bug fix due to report by Michael Timmers. The issue +# was with sensor list that contains a name which matches +# by regex with some other later sensor name. In this +# case it was Juniper with "Routing Engine" which was +# followed by "Routing Engine PCMCIA Card 0" sensor. +# 0.3 - Jan 2008 : Added '-n' and '-d' options to specify exact list of +# sensor names and oids. +# Also when you specify 'hp' type, the plugin will now +# provide human-readable sensor names rather then purely +# an id of their sensor locale (this is basicly special +# hack just for HP since I don't know anyone else who +# hard-coded sensor names by ids into SNMP MIB). +# 0.23 - Dec 2007 : Bug Fixes (especially one involving F as input format) +# +# TODO and older revision history: +# +# 1. [DONE - Aug 2006] To support multiple types of equipment add config +# array/hash and --type parameter +# 2. More plugin types for various other equipment need to be added ... +# [DONE - Dec 2006] - added Juniper & HP +# 3. Need to update warn & crit parameters parsing code so it would support +# both low and high values with '<' and '>' prefixed and using '~' for +# don't check rather then 0 +# [DONE - Dec 2006] - added quick hack to interpret empty values +# (i.e. -w ",90,") as dont check instead of specifying '0' directly +# Note: Low temperature value checks are rarely needed for network +# equipment so this is not high priority right now and will +# be done together with #4 most likely as part of some general +# library that would be shared with check_snmp_table and quite +# likely other plugins where multiple "attributes" are specified +# 4. Support specifying table OIDs for temperature threashold values. +# I'll do it only after adding optional file caching so these values +# can be retrieved about once every day rather then for each check. +# +# Note: if you want #3 or #4 done faster for specific application, +# contact me privately to discuss +# +# ========================== START OF PROGRAM CODE ============================ + +use strict; +use Net::SNMP; +use Getopt::Long; + +# use lib "/usr/lib/nagios/plugins"; +# use utils qw(%ERRORS $TIMEOUT); +# uncomment two lines below and comment out two above lines if you do not have nagios' utils.pm +my $TIMEOUT = 20; +my %ERRORS=('OK'=>0,'WARNING'=>1,'CRITICAL'=>2,'UNKNOWN'=>3,'DEPENDENT'=>4); + +# Below is hash array for several types of equipment, format here is that +# key is name you can specify in "--type" and data for that key is 3-value +# array with 1st value sensor names table OID (-N option), 2nd is sensor +# data table OID (-D option) and 3rd is type of temperature reading (-i) +# Additionally instead of specifying sensor names table OID and sensor data +# root table OID, the first two arguments to array can be "" and then 4th and +# 5th argument should be arrays first with list of sensor names and 2nd with +# list of OIDs for data to be retrieved (see below for how its done for Alteon) +my %system_types = ( "dell" => [ "1.3.6.1.4.1.674.10892.1.700.20.1.8", "1.3.6.1.4.1.674.10892.1.700.20.1.6", "10C" ], + "cisco1" => [ "1.3.6.1.4.1.9.9.13.1.3.1.2", "1.3.6.1.4.1.9.9.13.1.3.1.3", "C" ], + "cisco" => [ "1.3.6.1.4.1.9.9.13.1.3.1.2", "1.3.6.1.4.1.9.9.13.1.3.1.3", "C" ], # same as cisco 1 for now, this may change + "juniper" => [ "1.3.6.1.4.1.2636.3.1.13.1.5", "1.3.6.1.4.1.2636.3.1.13.1.7", "C" ], # somebody verify it, dont have juniper right now + "hp" => [ "1.3.6.1.4.1.232.6.2.6.8.1.3", "1.3.6.1.4.1.232.6.2.6.8.1.4", "C" ], + "alteon" => [ "", "", "C", ['RearLeftSensor', 'RearMiddleSensor', 'FrontMiddleSensor', 'FrontRightSensor'], ['1.3.6.1.4.1.1872.2.1.1.6.0','1.3.6.1.4.1.1872.2.1.1.7.0','1.3.6.1.4.1.1872.2.1.1.8.0','1.3.6.1.4.1.1872.2.1.1.9.0'] ], # why do they need to make these alteons so proprietory and hard to deal with? + "baytech" => [ "1.3.6.1.4.1.4779.1.3.5.2.1.2", "1.3.6.1.4.1.4779.1.3.5.2.1.8", "10C" ], # baytech pdu + ); +# APC OID for the temperature is .1.3.6.1.4.1.318.1.1.2.1.1.0 +# APC OID for the humidity is .1.3.6.1.4.1.318.1.1.2.1.2.0 +# Cisco fans: .1.3.6.1.4.1.9.9.13.1.4.1.3 +# HP switch temperature : .1.3.6.1.4.1.11.2.14.11.1.2.6.1.4.4 +# HP switch fan: .1.3.6.1.4.1.11.2.14.11.1.2.6.1.4.1 + +my $Version='0.33'; + +my $o_host= undef; # hostname +my $o_community= undef; # community +my $o_port= 161; # SNMP port +my $o_help= undef; # help option +my $o_verb= undef; # verbose mode +my $o_version= undef; # version info option +my $o_warn= undef; # warning level option +my @o_warnL= (); # array for above list +my $o_crit= undef; # Critical level option +my @o_critL= (); # array for above list +my $o_perf= undef; # Performance data option +my $o_timeout= 5; # Default 5s Timeout +my $o_version2= undef; # use snmp v2c +# SNMPv3 specific +my $o_login= undef; # Login for snmpv3 +my $o_passwd= undef; # Pass for snmpv3 +my $v3protocols=undef; # V3 protocol list. +my $o_authproto='md5'; # Auth protocol +my $o_privproto='des'; # Priv protocol +my $o_privpass= undef; # priv password + +my $o_attr= undef; # What attribute(s) to check (specify more then one separated by '.') +my @o_attrL= (); # array for above list +my $o_perfattr= undef; # List of attributes to only provide values in performance data but no checking +my @o_perfattrL=(); # array for above list +my $o_ounit= 'C'; # Output Temperature Measurement Units - can be 'C', 'F' or 'K' +my $o_iunit= 'C'; # Incoming Temperature Measurement Units - can prefix with number if its n*temp +my $oid_names= undef; # OID for base of sensor attribute names +my $oid_data= undef; # OID for base of actual data for those attributes found when walking name base +my $o_names= undef; # List of sensor names (as opposed to specifying names table) +my $o_unkdef= undef; # Default value to report for unknown attributes +my $o_type= undef; # Type of system to check (predefined values for $oid_names, $oid_data, $oid_iunit) +my $o_sensornames=undef; # Option specifying list of sensor names that then go into @ar_sensornames array +my $o_sensoroids=undef; # Option specifying list of sensor oids that then go into @ar_sensoroids array +my @ar_sensornames=(); # List of sensor names if specified in the sensor_types array +my @ar_sensoroids=(); # List of sensor data oids if specified in sensor_types array + +# This is hack for HP based on cpqHeTemperatureLocale OID from cpqhlth.mib to map reported locale id to real name +my %hp_locale = ( 1=> ['OTHER',1], 2=> ['UNKNOWN',1], 3=> ['System', 1], 4=> ['SystemBoard',1], 5=> ['ioBoard',1], + 6=> ['CPU',1], 7=> ['Memory',1], 8=> ['Storage',1], 9=> ['RemovableMedia',1], + 10=> ['PowerSupply',1], 11=> ['Ambient',1], 12=> ['Chassis',1], 13=> ['BridgeCard',1] ); + +sub print_version { print "$0: $Version\n" }; + +sub print_usage { + print "Usage: $0 [-v] -H -C [-2] | (-l login -x passwd [-X pass -L ,]) [-p ] [-t ] -T dell|hp|cisco1|juniper|alteon | [-N -D ] | [-n -d ] [-a -w -c [-f]] [-A ] [-o ] [-i ] [-u ] [-V]\n"; +} + +# Return true if arg is a number +sub isnum { + my $num = shift; + if ( $num =~ /^(\d+\.?\d*)|(^\.\d+)$/ ) { return 1 ;} + return 0; +} + +sub help { + print "\nSNMP Temperature Monitor for Nagios version ",$Version,"\n"; + print " by William Leibzon - william(at)leibzon.org\n\n"; + print_usage(); + print <, + : Authentication protocol (md5|sha : default md5) + : Priv protocole (des|aes : default des) +-P, --port=PORT + SNMP port (Default 161) +-w, --warn=INT[,INT[,INT[..]]] + warning temperature level(s) (if more then one attribute is checked, must have multiple values) +-c, --crit=INT[,INT[,INT[..]]] + critical temperature level(s) (if more then one attribute is checked, must have multiple values) +-f, --perfdata + Perfparse compatible output +-t, --timeout=INTEGER + timeout for SNMP in seconds (Default: 5) +-V, --version + prints version number +-N, --oidtable_attribnames=OID_STRING + Base table OID to walk through to find names of those attributes supported and from that corresponding data OIDs +-D, --oidtable_attribdata=OID_STRING + Base table OID for sensor attribute data, one number is added to that to make up full attribute OID +-n, --sensor_names=STRING[,STRING[..]] + List of sensor names when -N is not used and sensors are specified with exeact oids +-d, --sensor_oids=OID_STRING[,OID_STRING[..]] + List of exact data OIDs for sensors specified with -n (specify this when -N and -D are not used) +-a, --attributes=STRING[,STRING[..]] + Which attribute(s) to check. This is used as regex to check if attribute is found in sensor names. + As an example for Dell the attribute names to use are: PROC_1, PROC_2, Ambient, Planar, Riser +-A, --perf_attributes=STRING[,STRING[..]] + Which attribute(s) to add to as part of performance data output. These names can be different then the + ones listed in '-a' to only output attributes in perf data but not check. Special value of '*' gets them all. +-f, --perfparse + Used only with '-a'. Causes to output data not only in main status line but also as perfparse output +-o --out_temp_unit=C|F|K + What temperature measurement units are used for output and warning/critical - 'C', 'F' or 'K' - default is 'C' +-i --in_temp_unit=[num]C|F|K + What temperature measurement reported by data OID - format is C|F|K (default is 'C') + where num is used if data is num*realdata, i.e. if reported data of 330 means 33C, then it is: -i 10C +-u, --unknown_default=INT + If attribute is not found then report the output as this number (i.e. -u 0) +-T, --type=dell|hp|cisco1|juniper|alteon + This allows to use pre-defined system type to set Base, Data OIDs and incoming temperature measurement type + Currently support systems types are: dell, hp, cisco1 (7500, 5500, 2948, etc), juniper, alteon +EOD +} + +# For verbose output - don't use it right now +sub verb { my $t=shift; print $t,"\n" if defined($o_verb) ; } + +# Get the alarm signal (just in case snmp timout screws up) +$SIG{'ALRM'} = sub { + print ("ERROR: Alarm signal (Nagios time-out)\n"); + exit $ERRORS{"UNKNOWN"}; +}; + +# converts temperature from input format unit into output format units +sub convert_temp { + my ($temp, $in_unit, $out_unit) = @_; + + # that is not super great algorithm if both input and output are F + my $in_mult = 1; + my $ctemp = undef; + $in_mult = $1 if $in_unit =~ /(\d+)\w/; + $in_unit =~ s/\d+//; + $ctemp = $temp / $in_mult if $in_unit eq 'C'; + $ctemp = ($temp / $in_mult - 32) / 1.8 if $in_unit eq 'F'; + $ctemp = $temp / $in_mult - 273.15 if $in_unit eq 'K'; + $ctemp = $temp / $in_mult if !defined($ctemp); + return $ctemp if $out_unit eq "C"; + return $ctemp * 1.8 + 32 if $out_unit eq "F"; + return $ctemp + 273.15 if $out_unit eq "K"; + return $ctemp; # should not get here +} + +sub check_options { + Getopt::Long::Configure ("bundling"); + GetOptions( + 'v' => \$o_verb, 'verbose' => \$o_verb, + 'h' => \$o_help, 'help' => \$o_help, + 'H:s' => \$o_host, 'hostname:s' => \$o_host, + 'P:i' => \$o_port, 'port:i' => \$o_port, + 'C:s' => \$o_community, 'community:s' => \$o_community, + 'l:s' => \$o_login, 'login:s' => \$o_login, + 'x:s' => \$o_passwd, 'passwd:s' => \$o_passwd, + 'X:s' => \$o_privpass, 'privpass:s' => \$o_privpass, + 'L:s' => \$v3protocols, 'protocols:s' => \$v3protocols, + 't:i' => \$o_timeout, 'timeout:i' => \$o_timeout, + 'V' => \$o_version, 'version' => \$o_version, + '2' => \$o_version2, 'v2c' => \$o_version2, + 'c:s' => \$o_crit, 'critical:s' => \$o_crit, + 'w:s' => \$o_warn, 'warn:s' => \$o_warn, + 'f' => \$o_perf, 'perfparse' => \$o_perf, + 'a:s' => \$o_attr, 'attributes:s' => \$o_attr, + 'A:s' => \$o_perfattr, 'perf_attributes:s' => \$o_perfattr, + 'o:s' => \$o_ounit, 'out_temp_unit:s' => \$o_ounit, + 'i:s' => \$o_iunit, 'in_temp_unit:s' => \$o_iunit, + 'u:i' => \$o_unkdef, 'unknown_default:i' => \$o_unkdef, + 'N:s' => \$oid_names, 'oid_attribnames:s' => \$oid_names, 'oidtable_attribnames:s' => \$oid_names, + 'D:s' => \$oid_data, 'oid_attribdata:s' => \$oid_data, 'oidtable_attribdata:s' => \$oid_data, + 'n:s' => \$o_sensornames, 'sensor_names:s' => \$o_sensornames, + 'd:s' => \$o_sensoroids, 'sensor_oids:s' => \$o_sensoroids, + 'T:s' => \$o_type, 'type:s' => \$o_type + ); + if (defined($o_help) ) { help(); exit $ERRORS{"UNKNOWN"}; } + if (defined($o_version)) { print_version(); exit $ERRORS{"UNKNOWN"}; } + if (! defined($o_host) ) # check host and filter + { print "No host defined!\n";print_usage(); exit $ERRORS{"UNKNOWN"}; } + # check snmp information + if ( !defined($o_community) && (!defined($o_login) || !defined($o_passwd)) ) + { print "Put snmp login info!\n"; print_usage(); exit $ERRORS{"UNKNOWN"}} + if ((defined($o_login) || defined($o_passwd)) && (defined($o_community) || defined($o_version2)) ) + { print "Can't mix snmp v1,2c,3 protocols!\n"; print_usage(); exit $ERRORS{"UNKNOWN"}} + if (defined ($v3protocols)) { + if (!defined($o_login)) { print "Put snmp V3 login info with protocols!\n"; print_usage(); exit $ERRORS{"UNKNOWN"}} + my @v3proto=split(/,/,$v3protocols); + if ((defined ($v3proto[0])) && ($v3proto[0] ne "")) {$o_authproto=$v3proto[0]; } # Auth protocol + if (defined ($v3proto[1])) {$o_privproto=$v3proto[1]; } # Priv protocol + if ((defined ($v3proto[1])) && (!defined($o_privpass))) { + print "Put snmp V3 priv login info with priv protocols!\n"; print_usage(); exit $ERRORS{"UNKNOWN"}} + } + $o_ounit =~ tr/[a-z]/[A-Z]/; + if ($o_ounit ne 'C' && $o_ounit ne 'F' && $o_ounit ne 'K') + { print "Invalid output measurement unit specified!\n"; print_usage(); exit $ERRORS{"UNKNOWN"}; } + $o_iunit =~ tr/[a-z]/[A-Z]/; + if ($o_iunit !~ /\d*[C|K|F]/) + { print "Invalid input measurement unit specified!\n"; print_usage(); exit $ERRORS{"UNKNOWN"}; } + if (defined ($o_type)) { + if (defined($oid_names) || defined($oid_data) || defined($o_sensornames) || defined($o_sensoroids)) + { print "Please either specify specify system type (-T) OR base SNMP OIDs for name (-N) and data (-D) tables OR exact list of sensor names (-n) and data OIDs (-d) !\n"; print_usage(); exit $ERRORS{"UNKNOWN"}; } + if (defined($system_types{$o_type})) { + $oid_names = $system_types{$o_type}[0]; + $oid_data = $system_types{$o_type}[1]; + $o_iunit = $system_types{$o_type}[2]; + @ar_sensornames= @{$system_types{$o_type}[3]} if defined($system_types{$o_type}[3]) && !$oid_names; + @ar_sensoroids= @{$system_types{$o_type}[4]} if defined($system_types{$o_type}[4]) && !$oid_data; + } + else { print "Unknown system type $o_type !\n"; print_usage(); exit $ERRORS{"UNKNOWN"}; } + } + if (defined($o_sensornames) && defined($o_sensoroids)) { + if (defined($oid_names) || defined($oid_data)) { + print "You can not combine -n / -d options with -N / -D\n"; print_usage(); exit $ERRORS{"UNKNOWN"}; + } + else { + @ar_sensornames = split(/,/, $o_sensornames); + @ar_sensoroids = split(/,/, $o_sensoroids); + if (scalar(@ar_sensornames) != scalar(@ar_sensoroids)) { + printf "Number of sensor names specified at -n (%d) must be equal to number of data OIDs specified with -d (%d)\n", + scalar(@ar_sensornames), scalar(@ar_sensoroids); + print_usage(); + exit $ERRORS{"UNKNOWN"}; + } + } + } + if (scalar(@ar_sensornames)==0 && scalar(@ar_sensoroids)==0 && !(defined($oid_names) && defined($oid_data))) + { print "Specify system type (-T) OR base SNMP OIDs for names (-N) and data (-D) tables OR exact list of sensor names (-n) and data OIDs (-d) !\n"; print_usage(); exit $ERRORS{"UNKNOWN"}; } + + if (defined($o_perfattr)) { + @o_perfattrL=split(/,/ ,$o_perfattr) if defined($o_perfattr); + } + if (defined($o_warn) || defined($o_crit) || defined($o_attr)) { + if (defined($o_attr)) { + @o_attrL=split(/,/, $o_attr); + @o_warnL=split(/,/ ,$o_warn) if defined($o_warn); + @o_critL=split(/,/ ,$o_crit) if defined($o_crit); + } + else { + print "Specifying warning and critical levels requires '-a' parameter with attribute names\n"; + print_usage(); + exit $ERRORS{"UNKNOWN"}; + } + if (scalar(@o_warnL)!=scalar(@o_attrL) || scalar(@o_critL)!=scalar(@o_attrL)) { + printf "Number of spefied warning levels (%d) and critical levels (%d) must be equal to the number of attributes specified at '-a' (%d). If you need to ignore some attribute specify it as '0'\n", scalar(@o_warnL), scalar(@o_critL), scalar(@o_attrL); + print_usage(); + exit $ERRORS{"UNKNOWN"}; + } + for (my $i=0; $i $o_critL[$i] && $o_critL[$i]!=0) { + print "warning must be <= critical !\n"; + print_usage(); + exit $ERRORS{"UNKNOWN"}; + } + } + } + if (scalar(@o_attrL)==0 && scalar(@o_perfattrL)==0) { + print "You must specify list of attributes with either '-a' or '-A'\n"; + print_usage(); + exit $ERRORS{"UNKNOWN"}; + } +} + +########## MAIN ####### + +check_options(); + +# Check global timeout if something goes wrong +if (defined($TIMEOUT)) { + verb("Alarm at $TIMEOUT"); + alarm($TIMEOUT); +} else { + verb("no global timeout defined : $o_timeout + 10"); + alarm ($o_timeout+10); +} + +# Connect to host +my ($session,$error); +if ( defined($o_login) && defined($o_passwd)) { + # SNMPv3 login + verb("SNMPv3 login"); + if (!defined ($o_privpass)) { + verb("SNMPv3 AuthNoPriv login : $o_login, $o_authproto"); + ($session, $error) = Net::SNMP->session( + -hostname => $o_host, + -version => '3', + -username => $o_login, + -authpassword => $o_passwd, + -authprotocol => $o_authproto, + -timeout => $o_timeout + ); + } else { + verb("SNMPv3 AuthPriv login : $o_login, $o_authproto, $o_privproto"); + ($session, $error) = Net::SNMP->session( + -hostname => $o_host, + -version => '3', + -username => $o_login, + -authpassword => $o_passwd, + -authprotocol => $o_authproto, + -privpassword => $o_privpass, + -privprotocol => $o_privproto, + -timeout => $o_timeout + ); + } +} else { + if (defined ($o_version2)) { + # SNMPv2 Login + verb("SNMP v2c login"); + ($session, $error) = Net::SNMP->session( + -hostname => $o_host, + -version => 2, + -community => $o_community, + -port => $o_port, + -timeout => $o_timeout + ); + } else { + # SNMPV1 login + verb("SNMP v1 login"); + ($session, $error) = Net::SNMP->session( + -hostname => $o_host, + -community => $o_community, + -port => $o_port, + -timeout => $o_timeout + ); + } +} +if (!defined($session)) { + printf("ERROR opening session: %s.\n", $error); + exit $ERRORS{"UNKNOWN"}; +} + +# next part of the code builds list of attributes to be retrieved +my $i; +my $oid; +my $line; +my $attr; +my @varlist = (); +my %dataresults; +my $result; + +for ($i=0;$iget_table( -baseoid => $oid_names ); + if (!defined($result)) { + printf("ERROR: Problem retrieving OID %s table: %s.\n", $oid_names, $session->error); + $session->close(); + exit $ERRORS{"UNKNOWN"}; + } + L1: foreach $oid (Net::SNMP::oid_lex_sort(keys %{$result})) { + $line=$result->{$oid}; + verb("got $oid : $line"); + # special hack for HP + if (defined($o_type) && $o_type eq 'hp' && exists($hp_locale{$line})) { + $line = $hp_locale{$result->{$oid}}[0] ."_". $hp_locale{$result->{$oid}}[1]; + $hp_locale{$result->{$oid}}[1]++; + verb("HP hack: interpreting ".$result->{$oid}." as $line"); + } + if (defined($o_perfattr) && $o_perfattr eq '*') { + $oid =~ s/$oid_names/$oid_data/; + $dataresults{$line} = ["perf", $oid, undef]; + unshift(@varlist,$oid); + verb("match found based on -A '*', now set to retrieve $oid"); + } + foreach $attr (keys %dataresults) { + if ($line =~ /$attr/ && !defined($dataresults{$attr}[1])) { + $oid =~ s/$oid_names/$oid_data/; + $dataresults{$attr}[1] = $oid; + unshift(@varlist,$oid) if !defined($varlist[0]) || +$varlist[0] ne $oid; + verb("match found for $attr, now set to retrieve $oid"); + next L1; + } + } + } +} +else { + my $i; + for ($i=0;$iget_request( + -Varbindlist => \@varlist +); +if (!defined($result)) { + printf("ERROR: Can not retrieve OID(s) %s: %s.\n", join(" ",@varlist), $session->error); + $session->close(); + exit $ERRORS{"UNKNOWN"}; +} +else { + foreach $attr (keys %dataresults) { + if (defined($dataresults{$attr}[1]) && defined($$result{$dataresults{$attr}[1]})) { + $dataresults{$attr}[2]=convert_temp($$result{$dataresults{$attr}[1]},$o_iunit,$o_ounit); + verb("got $dataresults{$attr}[1] : $attr = $dataresults{$attr}[2]"); + } + else { + if (defined($o_unkdef)) { + $dataresults{$attr}[2]=$o_unkdef; + verb("could not find snmp data for $attr, setting to to default value $o_unkdef"); + } + else { + verb("could not find snmp data for $attr"); + } + } + } +} + +# loop to check if warning & critical attributes are ok +for ($i=0;$i$o_critL[$i] && $o_critL[$i]>0) { + $statuscode="CRITICAL"; + $statusinfo .= " " . $o_attrL[$i] . " Temperature is " . $dataresults{$o_attrL[$i]}[2] . $o_ounit . " > ". $o_critL[$i] . $o_ounit; + } + elsif ($dataresults{$o_attrL[$i]}[2]>$o_warnL[$i] && $o_warnL[$i]>0) { + $statuscode="WARNING" if $statuscode eq "OK"; + $statusinfo .= " " . $o_attrL[$i] . " Temperature is " . $dataresults{$o_attrL[$i]}[2] . $o_ounit . " > ". $o_warnL[$i] . $o_ounit; + } + else { + $statusdata .= "," if ($statusdata); + $statusdata .= " " . $o_attrL[$i] . " Temperature is " . $dataresults{$o_attrL[$i]}[2] . $o_ounit; + } + $perfdata .= " " . $o_attrL[$i] . "=" . $dataresults{$o_attrL[$i]}[2] if defined($o_perf) && $dataresults{$o_attrL[$i]}[0] ne "perf"; + } + else { + $statusdata .= "," if ($statusdata); + $statusdata .= " $o_attrL[$i] data is missing"; + } +} + +# add data for performance-only attributes +if (defined($o_perfattr) && $o_perfattr eq '*') { + foreach $attr (keys %dataresults) { + if ($dataresults{$attr}[0] eq "perf" && defined($dataresults{$attr}[2])) { + $perfdata .= " " . $attr . "=" . $dataresults{$attr}[2]; + } + } +} +else { + for ($i=0;$i