1#!/usr/local/bin/perl -w 2############################## check_snmp_boostedge.pl ################# 3# Version : 1.0 4# Date : Jan 16 2007 5# Author : Patrick Proy ( patrick at proy.org) 6# Help : http://www.manubulon.com/nagios/ 7# Licence : GPL - http://www.fsf.org/licenses/gpl.txt 8# Changelog : 9# Contributors : 10################################################################# 11# 12# Help : ./check_snmp_boostedge.pl -h 13# 14 15use strict; 16use Net::SNMP; 17use Getopt::Long; 18 19# Nagios specific 20 21use lib "/usr/local/libexec/nagios"; 22use utils qw(%ERRORS $TIMEOUT); 23#my $TIMEOUT = 15; 24#my %ERRORS=('OK'=>0,'WARNING'=>1,'CRITICAL'=>2,'UNKNOWN'=>3,'DEPENDENT'=>4); 25 26# SNMP Datas 27 28my $be_global_status= "1.3.6.1.4.1.4185.12.1.1.3.0"; # boostedge global status (stop(0), start(1)) 29 30my $be_service_number= "1.3.6.1.4.1.4185.12.1.5.1.0"; # beServiceNumber 31 32my $be_service_table= "1.3.6.1.4.1.4185.12.1.5"; # beServices 33my $be_service_name= "1.3.6.1.4.1.4185.12.1.5.2.1.2"; # beServiceName 34my $be_service_status= "1.3.6.1.4.1.4185.12.1.5.2.1.4"; # status ("RUNNING") 35my $be_service_mode= "1.3.6.1.4.1.4185.12.1.5.2.1.5"; # beServiceMode (disabled(0), enabled(1)) 36my $be_service_datain= "1.3.6.1.4.1.4185.12.1.5.2.1.6"; # beServiceDataIn (Not populated for now : HTTP/S - V5.2.16.0) 37my $be_service_dataout= "1.3.6.1.4.1.4185.12.1.5.2.1.7"; # beServiceDataOut (Not populated for now : HTTP/S - V5.2.16.0) 38my $be_service_connect= "1.3.6.1.4.1.4185.12.1.5.2.1.8"; # beServiceConnect (Not populated for now : HTTP/S - V5.2.16.0) 39 40 41# Globals 42 43my $Version='1.0'; 44 45my $o_host = undef; # hostname 46my $o_community = undef; # community 47my $o_port = 161; # port 48my $o_help= undef; # wan't some help ? 49my $o_verb= undef; # verbose mode 50my $o_version= undef; # print version 51my $o_timeout= undef; # Timeout (Default 5) 52my $o_perf= undef; # Output performance data 53my $o_version2= undef; # use snmp v2c 54# Specific 55my $o_service= undef; # service regexp selection 56my $o_nservice= undef; # service number expected 57 58# SNMPv3 specific 59my $o_login= undef; # Login for snmpv3 60my $o_passwd= undef; # Pass for snmpv3 61my $v3protocols=undef; # V3 protocol list. 62my $o_authproto='md5'; # Auth protocol 63my $o_privproto='des'; # Priv protocol 64my $o_privpass= undef; # priv password 65 66# functions 67 68sub p_version { print "check_snmp_boostedge version : $Version\n"; } 69 70sub print_usage { 71 print "Usage: $0 [-v] -H <host> -C <snmp_community> [-2] | (-l login -x passwd [-X pass -L <authp>,<privp>]) -s <service> -n <number> [-p <port>] [-f] [-t <timeout>] [-V]\n"; 72} 73 74sub isnnum { # Return true if arg is not a number 75 my $num = shift; 76 if ( $num =~ /^(\d+\.?\d*)|(^\.\d+)$/ ) { return 0 ;} 77 return 1; 78} 79 80sub set_status { # return worst status with this order : OK, unknwonw, warning, critical 81 my $new_status=shift; 82 my $cur_status=shift; 83 if (($cur_status == 0)|| ($new_status==$cur_status)){ return $new_status; } 84 if ($new_status==3) { return $cur_status; } 85 if ($new_status > $cur_status) {return $new_status;} 86 return $cur_status; 87} 88 89sub is_pattern_valid { # Test for things like "<I\s*[^>" or "+5-i" 90 my $pat = shift; 91 if (!defined($pat)) { $pat=" ";} # Just to get rid of compilation time warnings 92 return eval { "" =~ /$pat/; 1 } || 0; 93} 94 95sub help { 96 print "\nSNMP Boostedge service monitor for Nagios version ",$Version,"\n"; 97 print "GPL Licensen, (c)2006-2007 Patrick Proy\n\n"; 98 print_usage(); 99 print <<EOT; 100-v, --verbose 101 print extra debugging information 102-h, --help 103 print this help message 104-H, --hostname=HOST 105 name or IP address of host to check 106-C, --community=COMMUNITY NAME 107 community name for the host's SNMP agent (implies v1 protocol) 108-s, --service=<service> 109 Regexp of service to select 110-n, --number=<number> 111 Number of services selected that must be in running & enabled state 112-2, --v2c 113 Use snmp v2c 114-l, --login=LOGIN ; -x, --passwd=PASSWD 115 Login and auth password for snmpv3 authentication 116 If no priv password exists, implies AuthNoPriv 117-X, --privpass=PASSWD 118 Priv password for snmpv3 (AuthPriv protocol) 119-L, --protocols=<authproto>,<privproto> 120 <authproto> : Authentication protocol (md5|sha : default md5) 121 <privproto> : Priv protocole (des|aes : default des) 122-P, --port=PORT 123 SNMP port (Default 161) 124-f, --perfparse 125 Perfparse compatible output 126-t, --timeout=INTEGER 127 timeout for SNMP in seconds (Default: 5) 128-V, --version 129 prints version number 130EOT 131} 132 133# For verbose output 134sub verb { my $t=shift; print $t,"\n" if defined($o_verb) ; } 135 136sub check_options { 137 Getopt::Long::Configure ("bundling"); 138 GetOptions( 139 'v' => \$o_verb, 'verbose' => \$o_verb, 140 'h' => \$o_help, 'help' => \$o_help, 141 'H:s' => \$o_host, 'hostname:s' => \$o_host, 142 'p:i' => \$o_port, 'port:i' => \$o_port, 143 'C:s' => \$o_community, 'community:s' => \$o_community, 144 'l:s' => \$o_login, 'login:s' => \$o_login, 145 'x:s' => \$o_passwd, 'passwd:s' => \$o_passwd, 146 'X:s' => \$o_privpass, 'privpass:s' => \$o_privpass, 147 'L:s' => \$v3protocols, 'protocols:s' => \$v3protocols, 148 't:i' => \$o_timeout, 'timeout:i' => \$o_timeout, 149 'V' => \$o_version, 'version' => \$o_version, 150 '2' => \$o_version2, 'v2c' => \$o_version2, 151 'f' => \$o_perf, 'perfparse' => \$o_perf, 152 's:s' => \$o_service, 'service:s' => \$o_service, 153 'n:i' => \$o_nservice, 'number:i' => \$o_nservice 154 ); 155 # Basic checks 156 if (defined($o_timeout) && (isnnum($o_timeout) || ($o_timeout < 2) || ($o_timeout > 60))) 157 { print "Timeout must be >1 and <60 !\n"; print_usage(); exit $ERRORS{"UNKNOWN"}} 158 if (!defined($o_timeout)) {$o_timeout=5;} 159 if (defined ($o_help) ) { help(); exit $ERRORS{"UNKNOWN"}}; 160 if (defined($o_version)) { p_version(); exit $ERRORS{"UNKNOWN"}}; 161 if ( ! defined($o_host) ) # check host and filter 162 { print_usage(); exit $ERRORS{"UNKNOWN"}} 163 # check snmp information 164 if ( !defined($o_community) && (!defined($o_login) || !defined($o_passwd)) ) 165 { print "Put snmp login info!\n"; print_usage(); exit $ERRORS{"UNKNOWN"}} 166 if ((defined($o_login) || defined($o_passwd)) && (defined($o_community) || defined($o_version2)) ) 167 { print "Can't mix snmp v1,2c,3 protocols!\n"; print_usage(); exit $ERRORS{"UNKNOWN"}} 168 if (defined ($v3protocols)) { 169 if (!defined($o_login)) { print "Put snmp V3 login info with protocols!\n"; print_usage(); exit $ERRORS{"UNKNOWN"}} 170 my @v3proto=split(/,/,$v3protocols); 171 if ((defined ($v3proto[0])) && ($v3proto[0] ne "")) {$o_authproto=$v3proto[0]; } # Auth protocol 172 if (defined ($v3proto[1])) {$o_privproto=$v3proto[1]; } # Priv protocol 173 if ((defined ($v3proto[1])) && (!defined($o_privpass))) { 174 print "Put snmp V3 priv login info with priv protocols!\n"; print_usage(); exit $ERRORS{"UNKNOWN"}} 175 } 176 if (!defined($o_service) || !(is_pattern_valid($o_service))) 177 { print "Service selection must be set and be a valid regexp\n"; print_usage(); exit $ERRORS{"UNKNOWN"}} 178 if (!defined($o_nservice) || isnnum($o_nservice)) 179 { print "Service number must be set and be an integer\n"; print_usage(); exit $ERRORS{"UNKNOWN"}} 180} 181 182########## MAIN ####### 183 184check_options(); 185 186# Check gobal timeout if snmp screws up 187if (defined($TIMEOUT)) { 188 verb("Alarm at $TIMEOUT + 5"); 189 alarm($TIMEOUT+5); 190} else { 191 verb("no global timeout defined : $o_timeout + 10"); 192 alarm ($o_timeout+10); 193} 194 195# Connect to host 196my ($session,$error); 197if ( defined($o_login) && defined($o_passwd)) { 198 # SNMPv3 login 199 verb("SNMPv3 login"); 200 if (!defined ($o_privpass)) { 201 verb("SNMPv3 AuthNoPriv login : $o_login, $o_authproto"); 202 ($session, $error) = Net::SNMP->session( 203 -hostname => $o_host, 204 -version => '3', 205 -username => $o_login, 206 -authpassword => $o_passwd, 207 -authprotocol => $o_authproto, 208 -timeout => $o_timeout 209 ); 210 } else { 211 verb("SNMPv3 AuthPriv login : $o_login, $o_authproto, $o_privproto"); 212 ($session, $error) = Net::SNMP->session( 213 -hostname => $o_host, 214 -version => '3', 215 -username => $o_login, 216 -authpassword => $o_passwd, 217 -authprotocol => $o_authproto, 218 -privpassword => $o_privpass, 219 -privprotocol => $o_privproto, 220 -timeout => $o_timeout 221 ); 222 } 223} else { 224 if (defined ($o_version2)) { 225 # SNMPv2 Login 226 verb("SNMP v2c login"); 227 ($session, $error) = Net::SNMP->session( 228 -hostname => $o_host, 229 -version => 2, 230 -community => $o_community, 231 -port => $o_port, 232 -timeout => $o_timeout 233 ); 234 } else { 235 # SNMPV1 login 236 verb("SNMP v1 login"); 237 ($session, $error) = Net::SNMP->session( 238 -hostname => $o_host, 239 -community => $o_community, 240 -port => $o_port, 241 -timeout => $o_timeout 242 ); 243 } 244} 245if (!defined($session)) { 246 printf("ERROR opening session: %s.\n", $error); 247 exit $ERRORS{"UNKNOWN"}; 248} 249 250# Get global status 251my @oidlist=($be_global_status); 252my $resultat = (Net::SNMP->VERSION < 4) ? 253 $session->get_request(@oidlist) 254 : $session->get_request(-varbindlist => \@oidlist); 255 256if (!defined($resultat)) { 257 printf("ERROR: Gloabal status table : %s.\n", $session->error); 258 $session->close; 259 exit $ERRORS{"UNKNOWN"}; 260} 261 262if ($$resultat{$be_global_status} != 1) { 263 print "Global service is stopped (",$$resultat{$be_global_status},") : CRITICAL\n"; 264 exit $ERRORS{"CRITICAL"}; 265} 266 267$resultat=undef; 268# Get service table 269$resultat = (Net::SNMP->VERSION < 4) ? 270 $session->get_table($be_service_table) 271 : $session->get_table(Baseoid => $be_service_table); 272 273if (!defined($resultat)) { 274 printf("ERROR: Description table : %s.\n", $session->error); 275 $session->close; 276 exit $ERRORS{"UNKNOWN"}; 277} 278$session->close; 279 280my $output=""; 281my $output_perf=""; 282my $global_status=0; 283my ($nservice,$nservice_ok)=(0,0); 284my (@found_service,@service_state)=undef; 285 286foreach my $key ( keys %$resultat) { 287 verb("OID : $key, Desc : $$resultat{$key}"); 288 if ( ($key =~ /$be_service_name\./) && ($$resultat{$key} =~ /$o_service/ )) { # Get index of service with name 289 $found_service[$nservice]=$$resultat{$key}; 290 $key =~ s/$be_service_name//; 291 $service_state[$nservice]=$$resultat{$be_service_status.$key}; 292 if (($service_state[$nservice] ne "RUNNING") || ($$resultat{$be_service_mode.$key}!=1)) { 293 $service_state[$nservice].="(".$$resultat{$be_service_mode.$key}.")"; 294 $global_status=2; 295 } else { 296 $nservice_ok++ 297 } 298 $nservice++; 299 verb ("Found service $found_service[$nservice-1]"); 300 } 301} 302 303if ($o_nservice > $nservice_ok) { 304 for (my $i=0;$i<$nservice;$i++) { 305 if ($output ne "") { $output .= ", "; } 306 $output .= $found_service[$i] . ":" . $service_state[$i]; 307 } 308 if ($output ne "") { $output .= ", "; } 309 $output .= ":" . $nservice_ok . " services OK < ".$o_nservice; 310 print $output, " : CRITICAL\n"; 311 exit $ERRORS{"CRITICAL"}; 312} 313 314$output = $nservice_ok . " services OK"; 315if ($o_nservice < $nservice_ok) { 316 print $output," > $o_nservice : WARNING\n"; 317 exit $ERRORS{"WARNING"}; 318} 319print $output," : OK\n"; 320exit $ERRORS{"OK"}; 321