source from :http://nagios.manubulon.com/check_snmp_int.pl
Snmp interface check
| Snmp interface check | |||||||||||||||||||||||||||||||
|
Script : check_snmp_int.pl Last update : May 24 2007 |
|||||||||||||||||||||||||||||||
|
Description : Checks by snmp (v1, v2c or v3) host interface state and usage.
The script will check interface operationnal status using the MIB-II table. The interface is (are) selected by the -n option. The script will return OK if ALL interfaces selected are UP, or CRITICAL if at least one interface is down. You can make the same tests on administrative status instead with the -a option. If you have ISDN interface, and want that DORMANT state returns ok, put -D. To make output shorter, specially when you have multiple interface, you can put the -s option. Ex : EL20005 3Com Gigabit NIC (3C2000 Family) Usage check (-k) The unit for the check depends on the -B, -M and -G option :
It is possible to put warning and critical levels with -b option. When the extended checks are activated (-q option), the warning levels are -k : activates the standard usage feature T0 : value 1 : can't calculate usage The script will allow 10% less of the delta and 300% more than delta as a correct interval. Msg size option (-o option) In case you get a "ERROR: running table : Message size exceeded maxMsgSize" error, you may need to adjust the maxMsgSize, i.e. the maximum size of snmp message with the -o option. Try a value with the -o AND the -v option : the script will output the actual value so you can add some octets to it with the -o option. --label option This option just put label before the speed output : SNMP Login See snmp info page Requirements : - Perl in /usr/bin/perl - or just run 'perl script' Dowload latest version : 1.4.8 Examples :
If multiple interfaces are selected, all must be up to get an OK result
Changelog : On CVS repository on sourceforge : http://nagios-snmp.cvs.sourceforge.net/nagios-snmp/plugins/. Output of check_snmp_int.pl -h
|
#!/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 = <FILE>)
{
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 <host> -C <snmp_community> [-2] | (-l login -x passwd [-X pass -L <authp>,<privp>) [-p <port>] -n <name in desc_oid> [-i -a -D] [-r] [-f[eSyY]] [-k[qBMGu] -g -w<warn levels> -c<crit levels> -d<delta>] [-o <octet_length>] [-t <timeout>] [-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 <<EOT;
-v, --verbose
print extra debugging information (including interface list on the system)
-h, --help
print this help message
-H, --hostname=HOST
name or IP address of host to check
-C, --community=COMMUNITY NAME
community name for the host's SNMP agent (implies v1 protocol)
-l, --login=LOGIN ; -x, --passwd=PASSWD, -2, --v2c
Login and auth password for snmpv3 authentication
If no priv password exists, implies AuthNoPriv
-2 : use snmp v2c
-X, --privpass=PASSWD
Priv password for snmpv3 (AuthPriv protocol)
-L, --protocols=<authproto>,<privproto>
<authproto> : Authentication protocol (md5|sha : default md5)
<privproto> : 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 <delta> 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 <n> chars of the interface(s)
If the number is negative, then get the <n> 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"};