1#!/usr/local/bin/perl -w 2############################## check_snmp_int ############## 3my $Version='1.24'; 4# Date : Oct 10 2007 5# Author : Patrick Proy ( patrick at proy.org ) 6# Help : http://nagios.manubulon.com 7# Licence : GPL - http://www.fsf.org/licenses/gpl.txt 8# Contrib : J. Jungmann, S. Probst, R. Leroy, M. Berger 9# TODO : 10# Maybe put base directory for performance as an option 11################################################################# 12# 13# Help : ./check_snmp_int.pl -h 14# 15use strict; 16use Net::SNMP; 17use Getopt::Long; 18 19############### BASE DIRECTORY FOR TEMP FILE ######## 20my $o_base_dir="/var/tmp/tmp_Nagios_int."; 21my $file_history=200; # number of data to keep in files. 22 23# Nagios specific 24 25my $TIMEOUT = 15; 26my %ERRORS=('OK'=>0,'WARNING'=>1,'CRITICAL'=>2,'UNKNOWN'=>3,'DEPENDENT'=>4); 27 28# SNMP Datas 29 30my $inter_table= '.1.3.6.1.2.1.2.2.1'; 31my $index_table = '1.3.6.1.2.1.2.2.1.1'; 32my $descr_table = '1.3.6.1.2.1.2.2.1.2'; 33my $oper_table = '1.3.6.1.2.1.2.2.1.8.'; 34my $admin_table = '1.3.6.1.2.1.2.2.1.7.'; 35my $speed_table = '1.3.6.1.2.1.2.2.1.5.'; 36my $speed_table_64 = '1.3.6.1.2.1.31.1.1.1.15.'; 37my $in_octet_table = '1.3.6.1.2.1.2.2.1.10.'; 38my $in_octet_table_64 = '1.3.6.1.2.1.31.1.1.1.6.'; 39my $in_error_table = '1.3.6.1.2.1.2.2.1.14.'; 40my $in_discard_table = '1.3.6.1.2.1.2.2.1.13.'; 41my $out_octet_table = '1.3.6.1.2.1.2.2.1.16.'; 42my $out_octet_table_64 = '1.3.6.1.2.1.31.1.1.1.10.'; 43my $out_error_table = '1.3.6.1.2.1.2.2.1.20.'; 44my $out_discard_table = '1.3.6.1.2.1.2.2.1.19.'; 45 46my %status=(1=>'UP',2=>'DOWN',3=>'TESTING',4=>'UNKNOWN',5=>'DORMANT',6=>'NotPresent',7=>'lowerLayerDown'); 47 48# Globals 49 50 51# Standard options 52my $o_host = undef; # hostname 53my $o_port = 161; # port 54my $o_descr = undef; # description filter 55my $o_help= undef; # wan't some help ? 56my $o_admin= undef; # admin status instead of oper 57my $o_inverse= undef; # Critical when up 58my $o_dormant= undef; # Dormant state is OK 59my $o_verb= undef; # verbose mode 60my $o_version= undef; # print version 61my $o_noreg= undef; # Do not use Regexp for name 62my $o_short= undef; # set maximum of n chars to be displayed 63my $o_label= undef; # add label before speed (in, out, etc...). 64# Performance data options 65my $o_perf= undef; # Output performance data 66my $o_perfe= undef; # Output discard/error also in perf data 67my $o_perfs= undef; # include speed in performance output (-S) 68my $o_perfp= undef; # output performance data in % of max speed (-y) 69my $o_perfr= undef; # output performance data in bits/s or Bytes/s (-Y) 70# Speed/error checks 71my $o_checkperf= undef; # checks in/out/err/disc values 72my $o_delta= 300; # delta of time of perfcheck (default 5min) 73my $o_ext_checkperf= undef; # extended perf checks (+error+discard) 74my $o_warn_opt= undef; # warning options 75my $o_crit_opt= undef; # critical options 76my $o_kbits= undef; # Warn and critical in Kbits instead of KBytes 77my @o_warn= undef; # warning levels of perfcheck 78my @o_crit= undef; # critical levels of perfcheck 79my $o_highperf= undef; # Use 64 bits counters 80my $o_meg= undef; # output in MBytes or Mbits (-M) 81my $o_gig= undef; # output in GBytes or Gbits (-G) 82my $o_prct= undef; # output in % of max speed (-u) 83 84my $o_timeout= undef; # Timeout (Default 5) 85# SNMP Message size parameter (Makina Corpus contrib) 86my $o_octetlength=undef; 87# Login options specific 88my $o_community = undef; # community 89my $o_version2 = undef; #use snmp v2c 90my $o_login= undef; # Login for snmpv3 91my $o_passwd= undef; # Pass for snmpv3 92my $v3protocols=undef; # V3 protocol list. 93my $o_authproto='md5'; # Auth protocol 94my $o_privproto='des'; # Priv protocol 95my $o_privpass= undef; # priv password 96 97# Readable names for counters (M. Berger contrib) 98my @countername = ( "in=" , "out=" , "errors-in=" , "errors-out=" , "discard-in=" , "discard-out=" ); 99my $checkperf_out_desc; 100 101# functions 102 103sub read_file { 104 # Input : File, items_number 105 # Returns : array of value : [line][item] 106 my ($traffic_file,$items_number)=@_; 107 my ($ligne,$n_rows)=(undef,0); 108 my (@last_values,@file_values,$i); 109 open(FILE,"<".$traffic_file) || return (1,0,0); 110 111 while($ligne = <FILE>) 112 { 113 chomp($ligne); 114 @file_values = split(":",$ligne); 115 #verb("@file_values"); 116 if ($#file_values >= ($items_number-1)) { 117 # check if there is enough data, else ignore line 118 for ( $i=0 ; $i< $items_number ; $i++ ) {$last_values[$n_rows][$i]=$file_values[$i];} 119 $n_rows++; 120 } 121 } 122 close FILE; 123 if ($n_rows != 0) { 124 return (0,$n_rows,@last_values); 125 } else { 126 return (1,0,0); 127 } 128} 129 130sub write_file { 131 # Input : file , rows, items, array of value : [line][item] 132 # Returns : 0 / OK, 1 / error 133 my ($file_out,$rows,$item,@file_values)=@_; 134 my $start_line= ($rows > $file_history) ? $rows - $file_history : 0; 135 if ( open(FILE2,">".$file_out) ) { 136 for (my $i=$start_line;$i<$rows;$i++) { 137 for (my $j=0;$j<$item;$j++) { 138 print FILE2 $file_values[$i][$j]; 139 if ($j != ($item -1)) { print FILE2 ":" }; 140 } 141 print FILE2 "\n"; 142 } 143 close FILE2; 144 return 0; 145 } else { 146 return 1; 147 } 148} 149 150sub p_version { print "check_snmp_int version : $Version\n"; } 151 152sub print_usage { 153 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"; 154} 155 156sub isnnum { # Return true if arg is not a number 157 my $num = shift; 158 if ( $num =~ /^(\d+\.?\d*)|(^\.\d+)$/ ) { return 0 ;} 159 return 1; 160} 161 162sub help { 163 print "\nSNMP Network Interface Monitor for Nagios version ",$Version,"\n"; 164 print "GPL licence, (c)2004-2007 Patrick Proy\n\n"; 165 print_usage(); 166 print <<EOT; 167-v, --verbose 168 print extra debugging information (including interface list on the system) 169-h, --help 170 print this help message 171-H, --hostname=HOST 172 name or IP address of host to check 173-C, --community=COMMUNITY NAME 174 community name for the host's SNMP agent (implies v1 protocol) 175-l, --login=LOGIN ; -x, --passwd=PASSWD, -2, --v2c 176 Login and auth password for snmpv3 authentication 177 If no priv password exists, implies AuthNoPriv 178 -2 : use snmp v2c 179-X, --privpass=PASSWD 180 Priv password for snmpv3 (AuthPriv protocol) 181-L, --protocols=<authproto>,<privproto> 182 <authproto> : Authentication protocol (md5|sha : default md5) 183 <privproto> : Priv protocole (des|aes : default des) 184-P, --port=PORT 185 SNMP port (Default 161) 186-n, --name=NAME 187 Name in description OID (eth0, ppp0 ...). 188 This is treated as a regexp : -n eth will match eth0,eth1,... 189 Test it before, because there are known bugs (ex : trailling /) 190-r, --noregexp 191 Do not use regexp to match NAME in description OID 192-i, --inverse 193 Make critical when up 194-a, --admin 195 Use administrative status instead of operational 196-D, --dormant 197 Dormant state is an OK state 198-o, --octetlength=INTEGER 199 max-size of the SNMP message, usefull in case of Too Long responses. 200 Be carefull with network filters. Range 484 - 65535, default are 201 usually 1472,1452,1460 or 1440. 202-f, --perfparse 203 Perfparse compatible output (no output when interface is down). 204-e, --error 205 Add error & discard to Perfparse output 206-S, --intspeed 207 Include speed in performance output in bits/s 208-y, --perfprct ; -Y, --perfspeed 209 -y : output performance data in % of max speed 210 -Y : output performance data in bits/s or Bytes/s (depending on -B) 211-k, --perfcheck ; -q, --extperfcheck 212 -k check the input/ouput bandwidth of the interface 213 -q also check the error and discard input/output 214--label 215 Add label before speed in output : in=, out=, errors-out=, etc... 216-g, --64bits 217 Use 64 bits counters instead of the standard counters when checking 218 bandwidth & performance data for interface >= 1Gbps. 219 You must use snmp v2c or v3 to get 64 bits counters. 220-d, --delta=seconds 221 make an average of <delta> seconds (default 300=5min) 222-B, --kbits 223 Make the warning and critical levels in K|M|G Bits/s instead of K|M|G Bytes/s 224-G, --giga ; -M, --mega ; -u, --prct 225 -G : Make the warning and critical levels in Gbps (with -B) or GBps 226 -M : Make the warning and critical levels in Mbps (with -B) or MBps 227 -u : Make the warning and critical levels in % of reported interface speed. 228-w, --warning=input,output[,error in,error out,discard in,discard out] 229 warning level for input / output bandwidth (0 for no warning) 230 unit depends on B,M,G,u options 231 warning for error & discard input / output in error/min (need -q) 232-c, --critical=input,output[,error in,error out,discard in,discard out] 233 critical level for input / output bandwidth (0 for no critical) 234 unit depends on B,M,G,u options 235 critical for error & discard input / output in error/min (need -q) 236-s, --short=int 237 Make the output shorter : only the first <n> chars of the interface(s) 238 If the number is negative, then get the <n> LAST caracters. 239-t, --timeout=INTEGER 240 timeout for SNMP in seconds (Default: 5) 241-V, --version 242 prints version number 243Note : when multiple interface are selected with regexp, 244 all be must be up (or down with -i) to get an OK result. 245EOT 246} 247 248# For verbose output 249sub verb { my $t=shift; print $t,"\n" if defined($o_verb) ; } 250 251sub check_options { 252 Getopt::Long::Configure ("bundling"); 253 GetOptions( 254 'v' => \$o_verb, 'verbose' => \$o_verb, 255 'h' => \$o_help, 'help' => \$o_help, 256 'H:s' => \$o_host, 'hostname:s' => \$o_host, 257 'p:i' => \$o_port, 'port:i' => \$o_port, 258 'n:s' => \$o_descr, 'name:s' => \$o_descr, 259 'C:s' => \$o_community, 'community:s' => \$o_community, 260 '2' => \$o_version2, 'v2c' => \$o_version2, 261 'l:s' => \$o_login, 'login:s' => \$o_login, 262 'x:s' => \$o_passwd, 'passwd:s' => \$o_passwd, 263 'X:s' => \$o_privpass, 'privpass:s' => \$o_privpass, 264 'L:s' => \$v3protocols, 'protocols:s' => \$v3protocols, 265 't:i' => \$o_timeout, 'timeout:i' => \$o_timeout, 266 'i' => \$o_inverse, 'inverse' => \$o_inverse, 267 'a' => \$o_admin, 'admin' => \$o_admin, 268 'r' => \$o_noreg, 'noregexp' => \$o_noreg, 269 'V' => \$o_version, 'version' => \$o_version, 270 'f' => \$o_perf, 'perfparse' => \$o_perf, 271 'e' => \$o_perfe, 'error' => \$o_perfe, 272 'k' => \$o_checkperf, 'perfcheck' => \$o_checkperf, 273 'q' => \$o_ext_checkperf, 'extperfcheck' => \$o_ext_checkperf, 274 'w:s' => \$o_warn_opt, 'warning:s' => \$o_warn_opt, 275 'c:s' => \$o_crit_opt, 'critical:s' => \$o_crit_opt, 276 'B' => \$o_kbits, 'kbits' => \$o_kbits, 277 's:i' => \$o_short, 'short:i' => \$o_short, 278 'g' => \$o_highperf, '64bits' => \$o_highperf, 279 'S' => \$o_perfs, 'intspeed' => \$o_perfs, 280 'y' => \$o_perfp, 'perfprct' => \$o_perfp, 281 'Y' => \$o_perfr, 'perfspeed' => \$o_perfr, 282 'M' => \$o_meg, 'mega' => \$o_meg, 283 'G' => \$o_gig, 'giga' => \$o_gig, 284 'u' => \$o_prct, 'prct' => \$o_prct, 285 'o:i' => \$o_octetlength, 'octetlength:i' => \$o_octetlength, 286 'label' => \$o_label, 287 'd:i' => \$o_delta, 'delta:i' => \$o_delta, 288 'D' => \$o_dormant, 'dormant' => \$o_dormant 289 ); 290 if (defined ($o_help) ) { help(); exit $ERRORS{"UNKNOWN"}}; 291 if (defined($o_version)) { p_version(); exit $ERRORS{"UNKNOWN"}}; 292 if ( ! defined($o_descr) || ! defined($o_host) ) # check host and filter 293 { print_usage(); exit $ERRORS{"UNKNOWN"}} 294 # check snmp information 295 if ( !defined($o_community) && (!defined($o_login) || !defined($o_passwd)) ) 296 { print "Put snmp login info!\n"; print_usage(); exit $ERRORS{"UNKNOWN"}} 297 if ((defined($o_login) || defined($o_passwd)) && (defined($o_community) || defined($o_version2)) ) 298 { print "Can't mix snmp v1,2c,3 protocols!\n"; print_usage(); exit $ERRORS{"UNKNOWN"}} 299 if (defined ($v3protocols)) { 300 if (!defined($o_login)) { print "Put snmp V3 login info with protocols!\n"; print_usage(); exit $ERRORS{"UNKNOWN"}} 301 my @v3proto=split(/,/,$v3protocols); 302 if ((defined ($v3proto[0])) && ($v3proto[0] ne "")) {$o_authproto=$v3proto[0]; } # Auth protocol 303 if (defined ($v3proto[1])) {$o_privproto=$v3proto[1]; } # Priv protocol 304 if ((defined ($v3proto[1])) && (!defined($o_privpass))) { 305 print "Put snmp V3 priv login info with priv protocols!\n"; print_usage(); exit $ERRORS{"UNKNOWN"}} 306 } 307 if (defined($o_timeout) && (isnnum($o_timeout) || ($o_timeout < 2) || ($o_timeout > 60))) 308 { print "Timeout must be >1 and <60 !\n"; print_usage(); exit $ERRORS{"UNKNOWN"}} 309 if (!defined($o_timeout)) {$o_timeout=5;} 310 # Check snmpv2c or v3 with 64 bit counters 311 if ( defined ($o_highperf) && (!defined($o_version2) && defined($o_community))) 312 { print "Can't get 64 bit counters with snmp version 1\n"; print_usage(); exit $ERRORS{"UNKNOWN"}} 313 if (defined ($o_highperf)) { 314 if (eval "require bigint") { 315 use bigint; 316 } else { print "Need bigint module for 64 bit counters\n"; print_usage(); exit $ERRORS{"UNKNOWN"}} 317 } 318 319 # check if -e without -f 320 if ( defined($o_perfe) && !defined($o_perf)) 321 { print "Cannot output error without -f option!\n"; print_usage(); exit $ERRORS{"UNKNOWN"}} 322 if (defined ($o_perfr) && defined($o_perfp) ) { 323 print "-Y and -y options are exclusives\n"; print_usage(); exit $ERRORS{"UNKNOWN"}} 324 if ((defined ($o_perfr) || defined($o_perfp) ) && !defined($o_checkperf)) { 325 print "Cannot put -Y or -y options without perf check option (-k) \n"; print_usage(); exit $ERRORS{"UNKNOWN"}} 326 if (defined ($o_short)) { 327 #TODO maybe some basic tests ? caracters return empty string 328 } 329 if (defined ($o_checkperf)) { 330 @o_warn=split(/,/,$o_warn_opt); 331 if (defined($o_ext_checkperf) && ($#o_warn != 5)) { 332 print "6 warning levels for extended checks \n"; print_usage(); exit $ERRORS{"UNKNOWN"} 333 } 334 if (!defined($o_ext_checkperf) &&($#o_warn !=1 )){ 335 print "2 warning levels for bandwidth checks \n"; print_usage(); exit $ERRORS{"UNKNOWN"} 336 } 337 @o_crit=split(/,/,$o_crit_opt); 338 #verb(" $o_crit_opt :: $#o_crit : @o_crit"); 339 if (defined($o_ext_checkperf) && ($#o_crit != 5)) { 340 print "6 critical levels for extended checks \n"; print_usage(); exit $ERRORS{"UNKNOWN"} 341 } 342 if (!defined($o_ext_checkperf) && ($#o_crit !=1 )) { 343 print "2 critical levels for bandwidth checks \n"; print_usage(); exit $ERRORS{"UNKNOWN"} 344 } 345 for (my $i=0;$i<=$#o_warn;$i++) { 346 if (($o_crit[$i]!=0)&&($o_warn[$i] > $o_crit[$i])) { 347 print "Warning must be < Critical level \n"; print_usage(); exit $ERRORS{"UNKNOWN"} 348 } 349 } 350 if ((defined ($o_meg) && defined($o_gig) ) || (defined ($o_meg) && defined($o_prct) )|| (defined ($o_gig) && defined($o_prct) )) { 351 print "-M -G and -u options are exclusives\n"; print_usage(); exit $ERRORS{"UNKNOWN"} 352 } 353 } 354 #### octet length checks 355 if (defined ($o_octetlength) && (isnnum($o_octetlength) || $o_octetlength > 65535 || $o_octetlength < 484 )) { 356 print "octet lenght must be < 65535 and > 484\n";print_usage(); exit $ERRORS{"UNKNOWN"}; 357 } 358} 359 360########## MAIN ####### 361 362check_options(); 363 364# Check gobal timeout if snmp screws up 365if (defined($TIMEOUT)) { 366 verb("Alarm at $TIMEOUT + 5"); 367 alarm($TIMEOUT+5); 368} else { 369 verb("no timeout defined : $o_timeout + 10"); 370 alarm ($o_timeout+10); 371} 372 373$SIG{'ALRM'} = sub { 374 print "No answer from host\n"; 375 exit $ERRORS{"UNKNOWN"}; 376}; 377 378# Connect to host 379my ($session,$error); 380if ( defined($o_login) && defined($o_passwd)) { 381 # SNMPv3 login 382 if (!defined ($o_privpass)) { 383 verb("SNMPv3 AuthNoPriv login : $o_login, $o_authproto"); 384 ($session, $error) = Net::SNMP->session( 385 -hostname => $o_host, 386 -version => '3', 387 -port => $o_port, 388 -username => $o_login, 389 -authpassword => $o_passwd, 390 -authprotocol => $o_authproto, 391 -timeout => $o_timeout 392 ); 393 } else { 394 verb("SNMPv3 AuthPriv login : $o_login, $o_authproto, $o_privproto"); 395 ($session, $error) = Net::SNMP->session( 396 -hostname => $o_host, 397 -version => '3', 398 -username => $o_login, 399 -port => $o_port, 400 -authpassword => $o_passwd, 401 -authprotocol => $o_authproto, 402 -privpassword => $o_privpass, 403 -privprotocol => $o_privproto, 404 -timeout => $o_timeout 405 ); 406 } 407} else { 408 if (defined ($o_version2)) { 409 # SNMPv2c Login 410 verb("SNMP v2c login"); 411 ($session, $error) = Net::SNMP->session( 412 -hostname => $o_host, 413 -version => 2, 414 -community => $o_community, 415 -port => $o_port, 416 -timeout => $o_timeout 417 ); 418 } else { 419 # SNMPV1 login 420 verb("SNMP v1 login"); 421 ($session, $error) = Net::SNMP->session( 422 -hostname => $o_host, 423 -community => $o_community, 424 -port => $o_port, 425 -timeout => $o_timeout 426 ); 427 } 428} 429if (!defined($session)) { 430 printf("ERROR opening session: %s.\n", $error); 431 exit $ERRORS{"UNKNOWN"}; 432} 433 434if (defined($o_octetlength)) { 435 my $oct_resultat=undef; 436 my $oct_test= $session->max_msg_size(); 437 verb(" actual max octets:: $oct_test"); 438 $oct_resultat = $session->max_msg_size($o_octetlength); 439 if (!defined($oct_resultat)) { 440 printf("ERROR: Session settings : %s.\n", $session->error); 441 $session->close; 442 exit $ERRORS{"UNKNOWN"}; 443 } 444 $oct_test= $session->max_msg_size(); 445 verb(" new max octets:: $oct_test"); 446} 447 448# Get desctiption table 449my $resultat = $session->get_table( 450 Baseoid => $descr_table 451); 452 453if (!defined($resultat)) { 454 printf("ERROR: Description table : %s.\n", $session->error); 455 $session->close; 456 exit $ERRORS{"UNKNOWN"}; 457} 458my @tindex = undef; 459my @oids = undef; 460my @descr = undef; 461my (@oid_perf,@oid_perf_outoct,@oid_perf_inoct,@oid_perf_inerr,@oid_perf_outerr,@oid_perf_indisc,@oid_perf_outdisc)= 462 (undef,undef,undef,undef,undef,undef,undef); 463my @oid_speed=undef; 464my @oid_speed_high=undef; 465my $num_int = 0; 466 467# Change to 64 bit counters if option is set : 468if (defined($o_highperf)) { 469 $out_octet_table=$out_octet_table_64; 470 $in_octet_table=$in_octet_table_64; 471} 472 473 474# Select interface by regexp of exact match 475# and put the oid to query in an array 476 477verb("Filter : $o_descr"); 478foreach my $key ( keys %$resultat) { 479 verb("OID : $key, Desc : $$resultat{$key}"); 480 # test by regexp or exact match 481 my $test = defined($o_noreg) 482 ? $$resultat{$key} eq $o_descr 483 : $$resultat{$key} =~ /$o_descr/; 484 if ($test) { 485 # get the index number of the interface 486 my @oid_list = split (/\./,$key); 487 $tindex[$num_int] = pop (@oid_list); 488 # get the full description 489 $descr[$num_int]=$$resultat{$key}; 490 # Get rid of special caracters (specially for Windows) 491 $descr[$num_int] =~ s/[[:cntrl:]]//g; 492 # put the admin or oper oid in an array 493 $oids[$num_int]= defined ($o_admin) ? $admin_table . $tindex[$num_int] 494 : $oper_table . $tindex[$num_int] ; 495 # Put the performance oid 496 if (defined($o_perf) || defined($o_checkperf)) { 497 $oid_perf_inoct[$num_int]= $in_octet_table . $tindex[$num_int]; 498 $oid_perf_outoct[$num_int]= $out_octet_table . $tindex[$num_int]; 499 $oid_speed[$num_int]=$speed_table . $tindex[$num_int]; 500 $oid_speed_high[$num_int]=$speed_table_64 . $tindex[$num_int]; 501 if (defined($o_ext_checkperf) || defined($o_perfe)) { 502 $oid_perf_indisc[$num_int]= $in_discard_table . $tindex[$num_int]; 503 $oid_perf_outdisc[$num_int]= $out_discard_table . $tindex[$num_int]; 504 $oid_perf_inerr[$num_int]= $in_error_table . $tindex[$num_int]; 505 $oid_perf_outerr[$num_int]= $out_error_table . $tindex[$num_int]; 506 } 507 } 508 verb("Name : $descr[$num_int], Index : $tindex[$num_int]"); 509 $num_int++; 510 } 511} 512# No interface found -> error 513if ( $num_int == 0 ) { print "ERROR : Unknown interface $o_descr\n" ; exit $ERRORS{"UNKNOWN"};} 514 515my $result=undef; 516# Add performance oids if requested 517if (defined($o_perf)||defined($o_checkperf)) { 518 @oids=(@oids,@oid_perf_outoct,@oid_perf_inoct,@oid_speed); 519 if (defined($o_highperf)) { 520 @oids=(@oids,@oid_speed_high); 521 } 522 if (defined ($o_ext_checkperf) || defined($o_perfe)) { 523 @oids=(@oids,@oid_perf_inerr,@oid_perf_outerr,@oid_perf_indisc,@oid_perf_outdisc); 524 } 525} 526 527# Get the requested oid values 528$result = $session->get_request( 529 Varbindlist => \@oids 530); 531if (!defined($result)) { printf("ERROR: Status/statistics table : %s.\n", $session->error); $session->close; 532 exit $ERRORS{"UNKNOWN"}; 533} 534 535$session->close; 536 537my $num_ok=0; 538my @checkperf_out=undef; 539my @checkperf_out_raw=undef; 540### Bandwidth test variables 541my $temp_file_name; 542my ($return,@file_values)=(undef,undef); 543my $n_rows=0; 544my $n_items_check=(defined($o_ext_checkperf))?7:3; 545my $timenow=time; 546my $trigger=$timenow - ($o_delta - ($o_delta/10)); 547my $trigger_low=$timenow - 3*$o_delta; 548my ($old_value,$old_time)=undef; 549my $speed_unit=undef; 550my $speed_real=undef; # speed of interface using either standard or highperf mib. 551 552# define the OK value depending on -i option 553my $ok_val= defined ($o_inverse) ? 2 : 1; 554my $final_status = 0; 555my ($print_out,$perf_out)=(undef,undef); 556 557# make all checks and output for all interfaces 558for (my $i=0;$i < $num_int; $i++) { 559 $print_out.=", " if (defined($print_out)); 560 $perf_out .= " " if (defined ($perf_out)) ; 561 my $usable_data=1; 562 # Get the status of the current interface 563 my $int_status= defined ($o_admin) ? $$result{$admin_table . $tindex[$i]} 564 : $$result{ $oper_table . $tindex[$i] }; 565 566 # Make the bandwith & error checks if necessary 567 if (defined ($o_checkperf) && $int_status==1) { 568 $temp_file_name=$descr[$i]; 569 $temp_file_name =~ s/[ ;\/]/_/g; 570 $temp_file_name = $o_base_dir . $o_host ."." . $temp_file_name; 571 # First, read entire file 572 my @ret_array=read_file($temp_file_name,$n_items_check); 573 $return = shift(@ret_array); 574 $n_rows = shift(@ret_array); 575 if ($n_rows != 0) { @file_values = @ret_array }; 576 verb ("File read returns : $return with $n_rows rows"); 577 # Get the speed in normal or highperf speed counters 578 if ($$result{$oid_speed[$i]} == 4294967295) { # Too high for this counter (cf IF-MIB) 579 if (! defined($o_highperf) && (defined($o_prct) || defined ($o_perfs) || defined ($o_perfp))) { 580 print "Cannot get interface speed with standard MIB, use highperf mib (-g) : UNKNOWN\n"; 581 exit $ERRORS{"UNKNOWN"} 582 } 583 if (defined ($$result{$oid_speed_high[$i]}) && $$result{$oid_speed_high[$i]} != 0) { 584 $speed_real=$$result{$oid_speed_high[$i]} * 1000000; 585 } else { 586 print "Cannot get interface speed using highperf mib : UNKNOWN\n"; 587 exit $ERRORS{"UNKNOWN"} 588 } 589 } else { 590 $speed_real=$$result{$oid_speed[$i]}; 591 } 592 verb ("Interface speed : $speed_real"); 593 #make the checks if the file is OK 594 if ($return ==0) { 595 my $j=$n_rows-1; 596 @checkperf_out=undef; 597 @checkperf_out_raw=undef; 598 do { 599 if ($file_values[$j][0] < $trigger) { 600 if ($file_values[$j][0] > $trigger_low) { 601 # Define the speed metric ( K | M | G ) (Bits|Bytes) or % 602 my $speed_metric=undef; 603 if (defined($o_prct)) { # in % of speed 604 # Speed is in bits/s, calculated speed is in Bytes/s 605 $speed_metric=$speed_real/800; 606 $speed_unit="%"; 607 } else { 608 if (defined($o_kbits)) { # metric in bits 609 if (defined($o_meg)) { # in Mbit/s = 1000000 bit/s 610 $speed_metric=125000; # (1000/8) * 1000 611 $speed_unit="Mbps"; 612 } elsif (defined($o_gig)) { # in Gbit/s = 1000000000 bit/s 613 $speed_metric=125000000; # (1000/8) * 1000 * 1000 614 $speed_unit="Gbps"; 615 } else { # in Kbits 616 $speed_metric=125; # ( 1000/8 ) 617 $speed_unit="Kbps"; 618 } 619 } else { # metric in byte 620 if (defined($o_meg)) { # in Mbits 621 $speed_metric=1048576; # 1024^2 622 $speed_unit="MBps"; 623 } elsif (defined($o_gig)) { # in Mbits 624 $speed_metric=1073741824; # 1024^3 625 $speed_unit="GBps"; 626 } else { 627 $speed_metric=1024; # 1024^3 628 $speed_unit="KBps"; 629 } 630 } 631 } 632 # check if the counter is back to 0 after 2^32 / 2^64. 633 # First set the modulus depending on highperf counters or not 634 my $overfl_mod = defined ($o_highperf) ? 18446744073709551616 : 4294967296; 635 # Check counter (s) 636 my $overfl = ($$result{$oid_perf_inoct[$i]} >= $file_values[$j][1] ) ? 0 : $overfl_mod; 637 $checkperf_out_raw[0] = ( ($overfl + $$result{$oid_perf_inoct[$i]} - $file_values[$j][1])/ 638 ($timenow - $file_values[$j][0] )); 639 $checkperf_out[0] = $checkperf_out_raw[0] / $speed_metric; 640 641 $overfl = ($$result{$oid_perf_outoct[$i]} >= $file_values[$j][2] ) ? 0 : $overfl_mod; 642 $checkperf_out_raw[1] = ( ($overfl + $$result{$oid_perf_outoct[$i]} - $file_values[$j][2])/ 643 ($timenow - $file_values[$j][0] )); 644 $checkperf_out[1] = $checkperf_out_raw[1] / $speed_metric; 645 646 if (defined($o_ext_checkperf)) { 647 $checkperf_out[2] = ( ($$result{$oid_perf_inerr[$i]} - $file_values[$j][3])/ 648 ($timenow - $file_values[$j][0] ))*60; 649 $checkperf_out[3] = ( ($$result{$oid_perf_outerr[$i]} - $file_values[$j][4])/ 650 ($timenow - $file_values[$j][0] ))*60; 651 $checkperf_out[4] = ( ($$result{$oid_perf_indisc[$i]} - $file_values[$j][5])/ 652 ($timenow - $file_values[$j][0] ))*60; 653 $checkperf_out[5] = ( ($$result{$oid_perf_outdisc[$i]} - $file_values[$j][6])/ 654 ($timenow - $file_values[$j][0] ))*60; 655 } 656 } 657 } 658 $j--; 659 } while ( ($j>=0) && (!defined($checkperf_out[0])) ); 660 } 661 # Put the new values in the array and write the file 662 $file_values[$n_rows][0]=$timenow; 663 $file_values[$n_rows][1]=$$result{$oid_perf_inoct[$i]}; 664 $file_values[$n_rows][2]=$$result{$oid_perf_outoct[$i]}; 665 if (defined($o_ext_checkperf)) { # Add other values (error & disc) 666 $file_values[$n_rows][3]=$$result{$oid_perf_inerr[$i]}; 667 $file_values[$n_rows][4]=$$result{$oid_perf_outerr[$i]}; 668 $file_values[$n_rows][5]=$$result{$oid_perf_indisc[$i]}; 669 $file_values[$n_rows][6]=$$result{$oid_perf_outdisc[$i]}; 670 } 671 $n_rows++; 672 $return=write_file($temp_file_name,$n_rows,$n_items_check,@file_values); 673 verb ("Write file returned : $return"); 674 # Print the basic status 675 if (defined ($o_short)) { 676 my $short_desc=undef; 677 if ($o_short < 0) {$short_desc=substr($descr[$i],$o_short);} 678 else {$short_desc=substr($descr[$i],0,$o_short);} 679 $print_out.=sprintf("%s:%s",$short_desc, $status{$int_status} ); 680 } else { 681 $print_out.=sprintf("%s:%s",$descr[$i], $status{$int_status} ); 682 } 683 if ($return !=0) { # On error writing, return Unknown status 684 $final_status=3; 685 $print_out.= " !!Unable to write file ".$temp_file_name." !! "; 686 } 687 # print the other checks if it was calculated 688 if (defined($checkperf_out[0])) { 689 $print_out.= " ("; 690 # check 2 or 6 values depending on ext_check_perf 691 my $num_checkperf=(defined($o_ext_checkperf))?6:2; 692 for (my $l=0;$l < $num_checkperf;$l++) { 693 # Set labels if needed 694 $checkperf_out_desc= (defined($o_label)) ? $countername[$l] : ""; 695 verb("Interface $i, check $l : $checkperf_out[$l]"); 696 if ($l!=0) {$print_out.="/";} 697 if (($o_crit[$l]!=0) && ($checkperf_out[$l]>$o_crit[$l])) { 698 $final_status=2; 699 $print_out.= sprintf("CRIT %s%.1f",$checkperf_out_desc,$checkperf_out[$l]); 700 } elsif (($o_warn[$l]!=0) && ($checkperf_out[$l]>$o_warn[$l])) { 701 $final_status=($final_status==2)?2:1; 702 $print_out.= sprintf("WARN %s%.1f",$checkperf_out_desc,$checkperf_out[$l]); 703 } else { 704 $print_out.= sprintf("%s%.1f",$checkperf_out_desc,$checkperf_out[$l]); 705 } 706 if ( $l==0 || $l == 1) { $print_out.= $speed_unit; } 707 } 708 $print_out .= ")"; 709 } else { # Return unknown when no data 710 $print_out.= " No usable data on file (".$n_rows." rows) "; 711 $final_status=3;$usable_data=0; 712 } 713 } else { 714 if (defined ($o_short)) { 715 my $short_desc=undef; 716 if ($o_short < 0) {$short_desc=substr($descr[$i],$o_short);} 717 else {$short_desc=substr($descr[$i],0,$o_short);} 718 $print_out.=sprintf("%s:%s",$short_desc, $status{$int_status} ); 719 } else { 720 $print_out.=sprintf("%s:%s",$descr[$i], $status{$int_status} ); 721 } 722 } 723 # Get rid of special caracters for performance in description 724 $descr[$i] =~ s/'\/\(\)/_/g; 725 if (( $int_status == $ok_val)||(defined($o_dormant) && $int_status == 5)) { 726 $num_ok++; 727 } 728 if (( $int_status == 1 ) && defined ($o_perf)) { 729 if (defined ($o_perfp)) { # output in % of speed 730 if ($usable_data==1) { 731 my $warn_factor=1; 732 if (!defined($o_prct)) { # warn&crit in K|M|G B|bps -> put warn_factor to make % 733 $warn_factor = (defined($o_meg)) ? 1000000 : (defined($o_gig)) ? 1000000000 : 1000; 734 if (!defined($o_kbits)) { $warn_factor*=8;} 735 $warn_factor/=$speed_real; 736 $warn_factor*=100; # now turn into displayed % : 0,1 = 10% 737 } 738 $perf_out .= "'" . $descr[$i] ."_in_prct'="; 739 $perf_out .= sprintf("%.0f",$checkperf_out_raw[0] * 800 / $speed_real) ."%;"; 740 $perf_out .= ($o_warn[0]!=0) ? sprintf("%.0f",$o_warn[0]*$warn_factor) . ";" : ";"; 741 $perf_out .= ($o_crit[0]!=0) ? sprintf("%.0f",$o_crit[0]*$warn_factor) . ";" : ";"; 742 $perf_out .= "0;100 "; 743 $perf_out .= "'" . $descr[$i] ."_out_prct'="; 744 $perf_out .= sprintf("%.0f",$checkperf_out_raw[1] * 800 / $speed_real) ."%;"; 745 $perf_out .= ($o_warn[1]!=0) ? sprintf("%.0f",$o_warn[1]*$warn_factor) . ";" : ";"; 746 $perf_out .= ($o_crit[1]!=0) ? sprintf("%.0f",$o_crit[1]*$warn_factor) . ";" : ";"; 747 $perf_out .= "0;100 "; 748 } 749 } elsif (defined ($o_perfr)) { # output in bites or Bytes /s 750 if ($usable_data==1) { 751 if (defined($o_kbits)) { # bps 752 # put warning and critical levels into bps or Bps 753 my $warn_factor; 754 if (defined($o_prct)) { # warn&crit in % -> put warn_factor to 1% of speed in bps 755 $warn_factor=$speed_real/100; 756 } else { # just convert from K|M|G bps 757 $warn_factor = (defined($o_meg)) ? 1000000 : (defined($o_gig)) ? 1000000000 : 1000; 758 } 759 $perf_out .= "'" . $descr[$i] ."_in_bps'="; 760 $perf_out .= sprintf("%.0f",$checkperf_out_raw[0] * 8) .";"; 761 $perf_out .= ($o_warn[0]!=0) ? $o_warn[0]*$warn_factor . ";" : ";"; 762 $perf_out .= ($o_crit[0]!=0) ? $o_crit[0]*$warn_factor . ";" : ";"; 763 $perf_out .= "0;". $speed_real ." "; 764 $perf_out .= "'" . $descr[$i] ."_out_bps'="; 765 $perf_out .= sprintf("%.0f",$checkperf_out_raw[1] * 8) .";"; 766 $perf_out .= ($o_warn[1]!=0) ? $o_warn[1]*$warn_factor . ";" : ";"; 767 $perf_out .= ($o_crit[1]!=0) ? $o_crit[1]*$warn_factor . ";" : ";"; 768 $perf_out .= "0;". $speed_real ." "; 769 } else { # Bps 770 my $warn_factor; 771 if (defined($o_prct)) { # warn&crit in % -> put warn_factor to 1% of speed in Bps 772 $warn_factor=$speed_real/800; 773 } else { # just convert from K|M|G bps 774 $warn_factor = (defined($o_meg)) ? 1048576 : (defined($o_gig)) ? 1073741824 : 1024; 775 } 776 $perf_out .= "'" . $descr[$i] ."_in_Bps'=" . sprintf("%.0f",$checkperf_out_raw[0]) .";"; 777 $perf_out .= ($o_warn[0]!=0) ? $o_warn[0]*$warn_factor . ";" : ";"; 778 $perf_out .= ($o_crit[0]!=0) ? $o_crit[0]*$warn_factor . ";" : ";"; 779 $perf_out .= "0;". $speed_real / 8 ." "; 780 $perf_out .= "'" . $descr[$i] ."_out_Bps'=" . sprintf("%.0f",$checkperf_out_raw[1]) .";" ; 781 $perf_out .= ($o_warn[1]!=0) ? $o_warn[1]*$warn_factor . ";" : ";"; 782 $perf_out .= ($o_crit[1]!=0) ? $o_crit[1]*$warn_factor . ";" : ";"; 783 $perf_out .= "0;". $speed_real / 8 ." "; 784 } 785 } 786 } else { # output in octet counter 787 $perf_out .= "'" . $descr[$i] ."_in_octet'=". $$result{$oid_perf_inoct[$i]} ."c "; 788 $perf_out .= "'" . $descr[$i] ."_out_octet'=". $$result{$oid_perf_outoct[$i]} ."c "; 789 } 790 if (defined ($o_perfe)) { 791 $perf_out .= "'" . $descr[$i] ."_in_error'=". $$result{$oid_perf_inerr[$i]} ."c "; 792 $perf_out .= "'" . $descr[$i] ."_in_discard'=". $$result{$oid_perf_indisc[$i]} ."c "; 793 $perf_out .= "'" . $descr[$i] ."_out_error'=". $$result{$oid_perf_outerr[$i]} ."c "; 794 $perf_out .= "'" . $descr[$i] ."_out_discard'=". $$result{$oid_perf_outdisc[$i]} ."c "; 795 } 796 if (defined ($o_perfs)) { 797 $perf_out .= "'" . $descr[$i] ."_speed_bps'=".$speed_real; 798 } 799 } 800} 801 802# Only a few ms left... 803alarm(0); 804 805# Check if all interface are OK 806if ($num_ok == $num_int) { 807 if ($final_status==0) { 808 print $print_out,":", $num_ok, " UP: OK"; 809 if (defined ($o_perf)) { print " | ",$perf_out; } 810 print "\n"; 811 exit $ERRORS{"OK"}; 812 } elsif ($final_status==1) { 813 print $print_out,":(", $num_ok, " UP): WARNING"; 814 if (defined ($o_perf)) { print " | ",$perf_out; } 815 print "\n"; 816 exit $ERRORS{"WARNING"}; 817 } elsif ($final_status==2) { 818 print $print_out,":(", $num_ok, " UP): CRITICAL"; 819 if (defined ($o_perf)) { print " | ",$perf_out; } 820 print "\n"; 821 exit $ERRORS{"CRITICAL"}; 822 } else { 823 print $print_out,":(", $num_ok, " UP): UNKNOWN"; 824 if (defined ($perf_out)) { print " | ",$perf_out; } 825 print "\n"; 826 exit $ERRORS{"UNKNOWN"}; 827 } 828} 829 830# else print the not OK interface number and exit (return is always critical if at least one int is down). 831 832print $print_out,": ", $num_int-$num_ok, " int NOK : CRITICAL"; 833if (defined ($perf_out)) { print " | ",$perf_out; } 834print "\n"; 835exit $ERRORS{"CRITICAL"}; 836 837