1#!/usr/local/bin/perl -w 2############################## check_snmp_nsbox ################# 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_nsbox.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 27my $ns_service_status= "1.3.6.1.4.1.14020.2.2.1.3.0"; # service status 1= ok ?? 28 29my $ns_service_table= "1.3.6.1.4.1.14020.2.3"; # vhost & diode table 30my $ns_vhost_table= "1.3.6.1.4.1.14020.2.3.1"; # vhost table 31my $ns_vhost_name= "1.0"; # GUI Vhost Name 32my $ns_vhost_requests= "2.0"; # Instant Vhost Requests per Second : NOT POPULATED IN V 2.0.8 33my $ns_vhost_Trequests= "2.0"; # Total Vhost Requests : NOT POPULATED IN V 2.0.8 34my $ns_diode_table= "1.3.6.1.4.1.14020.2.3.2"; # diode table 35my $ns_diode_name= "1.0"; # GUI Diode Name 36my $ns_diode_status= "2.0"; # Last diode Status (" " = OK?) (undocumented) 37 38my $ns_rsa_prct_usage= ".1.3.6.1.4.1.14020.1.1.1.3.0"; # % usage of RSA operations. (undocumented) 39my $ns_rsa_oper_second= ".1.3.6.1.4.1.14020.1.1.3.4.0;"; # number of RSA operations/s (undocumented) 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_vhost= undef; # vhost regexp 56my $o_diode= undef; # diode regexp 57my $o_nvhost= undef; # vhost number 58my $o_ndiode= undef; # diode number 59 60# SNMPv3 specific 61my $o_login= undef; # Login for snmpv3 62my $o_passwd= undef; # Pass for snmpv3 63my $v3protocols=undef; # V3 protocol list. 64my $o_authproto='md5'; # Auth protocol 65my $o_privproto='des'; # Priv protocol 66my $o_privpass= undef; # priv password 67 68# functions 69 70sub p_version { print "check_snmp_nsbox version : $Version\n"; } 71 72sub print_usage { 73 print "Usage: $0 [-v] -H <host> -C <snmp_community> [-2] | (-l login -x passwd [-X pass -L <authp>,<privp>]) -d <diode> -s <vhost> -n <ndiode>,<nvhost> [-p <port>] [-f] [-t <timeout>] [-V]\n"; 74} 75 76sub isnnum { # Return true if arg is not a number 77 my $num = shift; 78 if ( $num =~ /^(\d+\.?\d*)|(^\.\d+)$/ ) { return 0 ;} 79 return 1; 80} 81 82sub set_status { # return worst status with this order : OK, unknwonw, warning, critical 83 my $new_status=shift; 84 my $cur_status=shift; 85 if (($cur_status == 0)|| ($new_status==$cur_status)){ return $new_status; } 86 if ($new_status==3) { return $cur_status; } 87 if ($new_status > $cur_status) {return $new_status;} 88 return $cur_status; 89} 90 91sub is_pattern_valid { # Test for things like "<I\s*[^>" or "+5-i" 92 my $pat = shift; 93 if (!defined($pat)) { $pat=" ";} # Just to get rid of compilation time warnings 94 return eval { "" =~ /$pat/; 1 } || 0; 95} 96 97sub help { 98 print "\nSNMP NetSecureOne Netbox monitor for Nagios version ",$Version,"\n"; 99 print "(c)2004-2006 Patrick Proy\n\n"; 100 print_usage(); 101 print <<EOT; 102Check that diode and vhost selected by regexp are active. 103-v, --verbose 104 print extra debugging information 105-h, --help 106 print this help message 107-H, --hostname=HOST 108 name or IP address of host to check 109-C, --community=COMMUNITY NAME 110 community name for the host's SNMP agent (implies v1 protocol) 111-2, --v2c 112 Use snmp v2c 113-l, --login=LOGIN ; -x, --passwd=PASSWD 114 Login and auth password for snmpv3 authentication 115 If no priv password exists, implies AuthNoPriv 116-X, --privpass=PASSWD 117 Priv password for snmpv3 (AuthPriv protocol) 118-L, --protocols=<authproto>,<privproto> 119 <authproto> : Authentication protocol (md5|sha : default md5) 120 <privproto> : Priv protocole (des|aes : default des) 121-d, --diode=<diode> 122 Diode selection by regexp 123-s, --vhost=<vhost> 124 Vhost selection by regexp 125-n, --number=<ndiode>,<nvhost> 126 number of diode and vhost that must be up. 127-P, --port=PORT 128 SNMP port (Default 161) 129-f, --perfparse 130 Perfparse compatible output 131-t, --timeout=INTEGER 132 timeout for SNMP in seconds (Default: 5) 133-V, --version 134 prints version number 135EOT 136} 137 138# For verbose output 139sub verb { my $t=shift; print $t,"\n" if defined($o_verb) ; } 140 141sub check_options { 142 Getopt::Long::Configure ("bundling"); 143 GetOptions( 144 'v' => \$o_verb, 'verbose' => \$o_verb, 145 'h' => \$o_help, 'help' => \$o_help, 146 'H:s' => \$o_host, 'hostname:s' => \$o_host, 147 'p:i' => \$o_port, 'port:i' => \$o_port, 148 'C:s' => \$o_community, 'community:s' => \$o_community, 149 'l:s' => \$o_login, 'login:s' => \$o_login, 150 'x:s' => \$o_passwd, 'passwd:s' => \$o_passwd, 151 'X:s' => \$o_privpass, 'privpass:s' => \$o_privpass, 152 'L:s' => \$v3protocols, 'protocols:s' => \$v3protocols, 153 't:i' => \$o_timeout, 'timeout:i' => \$o_timeout, 154 'V' => \$o_version, 'version' => \$o_version, 155 '2' => \$o_version2, 'v2c' => \$o_version2, 156 'f' => \$o_perf, 'perfparse' => \$o_perf, 157 'd:s' => \$o_diode, 'diode:s' => \$o_diode, 158 's:s' => \$o_vhost, 'vhost:s' => \$o_vhost, 159 'n:s' => \$o_nvhost, 'number:s' => \$o_nvhost 160 ); 161 # Basic checks 162 if (defined($o_timeout) && (isnnum($o_timeout) || ($o_timeout < 2) || ($o_timeout > 60))) 163 { print "Timeout must be >1 and <60 !\n"; print_usage(); exit $ERRORS{"UNKNOWN"}} 164 if (!defined($o_timeout)) {$o_timeout=5;} 165 if (defined ($o_help) ) { help(); exit $ERRORS{"UNKNOWN"}}; 166 if (defined($o_version)) { p_version(); exit $ERRORS{"UNKNOWN"}}; 167 if ( ! defined($o_host) ) # check host and filter 168 { print_usage(); exit $ERRORS{"UNKNOWN"}} 169 # check snmp information 170 if ( !defined($o_community) && (!defined($o_login) || !defined($o_passwd)) ) 171 { print "Put snmp login info!\n"; print_usage(); exit $ERRORS{"UNKNOWN"}} 172 if ((defined($o_login) || defined($o_passwd)) && (defined($o_community) || defined($o_version2)) ) 173 { print "Can't mix snmp v1,2c,3 protocols!\n"; print_usage(); exit $ERRORS{"UNKNOWN"}} 174 if (defined ($v3protocols)) { 175 if (!defined($o_login)) { print "Put snmp V3 login info with protocols!\n"; print_usage(); exit $ERRORS{"UNKNOWN"}} 176 my @v3proto=split(/,/,$v3protocols); 177 if ((defined ($v3proto[0])) && ($v3proto[0] ne "")) {$o_authproto=$v3proto[0]; } # Auth protocol 178 if (defined ($v3proto[1])) {$o_privproto=$v3proto[1]; } # Priv protocol 179 if ((defined ($v3proto[1])) && (!defined($o_privpass))) { 180 print "Put snmp V3 priv login info with priv protocols!\n"; print_usage(); exit $ERRORS{"UNKNOWN"}} 181 } 182 if (!defined($o_vhost) || !(is_pattern_valid($o_vhost))) 183 { print "Vhost selection must be set and be a valid regexp (-s)\n"; print_usage(); exit $ERRORS{"UNKNOWN"}} 184 if (!defined($o_diode) || !(is_pattern_valid($o_diode))) 185 { print "Diode selection must be set and be a valid regexp (-d)\n"; print_usage(); exit $ERRORS{"UNKNOWN"}} 186 if (!defined($o_nvhost)) 187 { print "Diode and vhost number must be set (-n)\n"; print_usage(); exit $ERRORS{"UNKNOWN"}} 188 my @nsbox_number=split(/,/,$o_nvhost); 189 if ($#nsbox_number != 1) 190 { print "2 numbers must be set with -n option\n"; print_usage(); exit $ERRORS{"UNKNOWN"}} 191 if (isnnum($nsbox_number[0]) || isnnum($nsbox_number[1])) 192 { print "2 numbers must be set with -n option\n"; print_usage(); exit $ERRORS{"UNKNOWN"}} 193 $o_ndiode=$nsbox_number[0]; 194 $o_nvhost=$nsbox_number[1]; 195} 196 197########## MAIN ####### 198 199check_options(); 200 201# Check gobal timeout if snmp screws up 202if (defined($TIMEOUT)) { 203 verb("Alarm at $TIMEOUT + 5"); 204 alarm($TIMEOUT+5); 205} else { 206 verb("no global timeout defined : $o_timeout + 10"); 207 alarm ($o_timeout+10); 208} 209 210# Connect to host 211my ($session,$error); 212if ( defined($o_login) && defined($o_passwd)) { 213 # SNMPv3 login 214 verb("SNMPv3 login"); 215 if (!defined ($o_privpass)) { 216 verb("SNMPv3 AuthNoPriv login : $o_login, $o_authproto"); 217 ($session, $error) = Net::SNMP->session( 218 -hostname => $o_host, 219 -version => '3', 220 -username => $o_login, 221 -authpassword => $o_passwd, 222 -authprotocol => $o_authproto, 223 -timeout => $o_timeout 224 ); 225 } else { 226 verb("SNMPv3 AuthPriv login : $o_login, $o_authproto, $o_privproto"); 227 ($session, $error) = Net::SNMP->session( 228 -hostname => $o_host, 229 -version => '3', 230 -username => $o_login, 231 -authpassword => $o_passwd, 232 -authprotocol => $o_authproto, 233 -privpassword => $o_privpass, 234 -privprotocol => $o_privproto, 235 -timeout => $o_timeout 236 ); 237 } 238} else { 239 if (defined ($o_version2)) { 240 # SNMPv2 Login 241 verb("SNMP v2c login"); 242 ($session, $error) = Net::SNMP->session( 243 -hostname => $o_host, 244 -version => 2, 245 -community => $o_community, 246 -port => $o_port, 247 -timeout => $o_timeout 248 ); 249 } else { 250 # SNMPV1 login 251 verb("SNMP v1 login"); 252 ($session, $error) = Net::SNMP->session( 253 -hostname => $o_host, 254 -community => $o_community, 255 -port => $o_port, 256 -timeout => $o_timeout 257 ); 258 } 259} 260if (!defined($session)) { 261 printf("ERROR opening session: %s.\n", $error); 262 exit $ERRORS{"UNKNOWN"}; 263} 264 265 266########### check global status ############## 267my @oidlist=($ns_service_status); 268my $resultat = (Net::SNMP->VERSION < 4) ? 269 $session->get_request(@oidlist) 270 : $session->get_request(-varbindlist => \@oidlist); 271 272if (!defined($resultat) || ($$resultat{$ns_service_status} eq "noSuchObject")) { 273 printf("ERROR: Global status oid not found : %s.\n", $session->error); 274 $session->close; 275 exit $ERRORS{"UNKNOWN"}; 276} 277 278if ($$resultat{$ns_service_status} != 1) { 279 print "Global service is in state ",$$resultat{$ns_service_status}," : CRITICAL\n"; 280 exit $ERRORS{"CRITICAL"}; 281} 282 283########### check vhost & diode status ############## 284$resultat=undef; 285$resultat = (Net::SNMP->VERSION < 4) ? 286 $session->get_table($ns_service_table) 287 : $session->get_table(Baseoid => $ns_service_table); 288 289if (!defined($resultat)) { 290 printf("ERROR: vhost and diode status table : %s.\n", $session->error); 291 $session->close; 292 exit $ERRORS{"UNKNOWN"}; 293} 294$session->close; 295 296my $output=""; 297my $output_perf=""; 298my ($index,$name)=undef; 299my ($nvhost,$ndiode)=(0,0); 300my (@found_vhost,@found_diode)=(undef,undef); 301 302foreach my $key ( keys %$resultat) { 303 verb("OID : $key, Desc : $$resultat{$key}"); 304 if ( $key =~ /($ns_vhost_table)\.(\d+)\.($ns_vhost_name)/ ) { # Get index of vhost with name 305 $index=$2;$name=$$resultat{$key}; 306 if ($name =~ /$o_vhost/) { 307 $found_vhost[$nvhost++]=$name; 308 verb ("found vhost $name"); 309 } 310 } 311 if ( $key =~ /($ns_diode_table)\.(\d+)\.($ns_diode_name)/ ) { # Get index of diode with name 312 $index=$2;$name=$$resultat{$key}; 313 if ($name =~ /$o_diode/) { 314 # TODO Check diode status : undocumented for now. 315 $found_diode[$ndiode++]=$name; 316 verb ("found diode $name"); 317 } 318 } 319} 320 321if (($ndiode<$o_ndiode) || ($nvhost<$o_nvhost)) { 322 $output = "Diode"; 323 if ($ndiode == 0 ) { $output.= ": none ";} 324 else { 325 $output.= "(".$ndiode."): :"; 326 for (my $i=0;$i<$ndiode;$i++) { 327 $output.=$found_diode[$i]." "; 328 } 329 } 330 $output .= "Vhost"; 331 if ($nvhost == 0 ) { $output.= ": none ";} 332 else { 333 $output.= "(".$nvhost."): :"; 334 for (my $i=0;$i<$nvhost;$i++) { 335 $output.=$found_vhost[$i]." "; 336 } 337 } 338 $output .= " < " . $o_ndiode .",". $o_nvhost ." : CRITICAL"; 339 print $output,"\n"; 340 exit $ERRORS{"CRITICAL"}; 341} 342 343$output = $ndiode . " diodes, " .$nvhost." vhosts :"; 344if (($ndiode>$o_ndiode) || ($nvhost>$o_nvhost)) { 345 $output .= " > " . $o_ndiode .",". $o_nvhost ." : WARNING"; 346} else { 347 $output .= " OK"; 348} 349print $output,"\n"; 350exit $ERRORS{"OK"}; 351 352