Plugin:check snmp win


 * 1) !/usr/bin/perl -w
 * 2) check_snmp_win ##############
 * 3) Version : 0.5
 * 4) Date : Aug 22 2005
 * 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) TODO :
 * 9) help : ./check_snmp_win.pl -h
 * 1) help : ./check_snmp_win.pl -h
 * 1) help : ./check_snmp_win.pl -h

use strict; use Getopt::Long; require "/usr/lib/nagios/plugins/Centreon/SNMP/Utils.pm";


 * 1) Nagios specific

use lib "/usr/lib/nagios/plugins"; use utils qw(%ERRORS $TIMEOUT); my %OPTION = (   "host" => undef,    "snmp-community" => "public", "snmp-version" => 1, "snmp-port" => 161,     "snmp-auth-key" => undef, "snmp-auth-user" => undef, "snmp-auth-password" => undef, "snmp-auth-protocol" => "MD5",    "snmp-priv-key" => undef, "snmp-priv-password" => undef, "snmp-priv-protocol" => "DES",    "maxrepetitions" => undef, "snmptimeout" => undef,    "64-bits" => undef, ); my $session_params;
 * 1) my %ERRORS=('OK'=>0,'WARNING'=>1,'CRITICAL'=>2,'UNKNOWN'=>3,'DEPENDENT'=>4);

my $process_table= '1.3.6.1.2.1.25.4.2.1'; my $index_table = '1.3.6.1.2.1.25.4.2.1.1'; my $run_name_table = '1.3.6.1.2.1.25.4.2.1.2'; my $run_path_table = '1.3.6.1.2.1.25.4.2.1.4'; my $proc_mem_table = '1.3.6.1.2.1.25.5.1.1.2'; # Kbytes my $proc_cpu_table = '1.3.6.1.2.1.25.5.1.1.1'; # Centi sec of CPU my $proc_run_state = '1.3.6.1.2.1.25.4.2.1.7';
 * 1) SNMP Datas for processes (MIB II)


 * 1) Windows SNMP DATA

my $win_serv_table = '1.3.6.1.4.1.77.1.2.3.1'; # Windows services table my $win_serv_name = '1.3.6.1.4.1.77.1.2.3.1.1'; # Name of the service my $win_serv_inst = '1.3.6.1.4.1.77.1.2.3.1.2'; my $win_serv_state = '1.3.6.1.4.1.77.1.2.3.1.3'; my %win_serv_state_label = ( 1 => 'active', 2=> 'continue-pending', 3=> 'pause-pending', 4=> 'paused'); my $win_serv_uninst = '1.3.6.1.4.1.77.1.2.3.1.4';
 * 1) Install state : uninstalled(1), install-pending(2), uninstall-pending(3), installed(4)
 * 1) Operating state : active(1),  continue-pending(2),  pause-pending(3),  paused(4)
 * 1) Can be uninstalled : cannot-be-uninstalled(1), can-be-uninstalled(2)


 * 1) Globals

my $Version='0.5'; my $Name='check_snmp_win';

my $o_descr = 	undef; 		# description filter my @o_descrL = 	undef;		# Service descriprion list. my $o_showall = undef;	# Show all services even if OK my $o_type = "service";	# Check type (service, ...) my $o_number = undef; # Number of service for warn and crit levels my $o_help=	undef; 		# wan't some help ? my $o_verb=	undef;		# verbose mode my $o_version=  undef;         # print version my $o_noreg=	undef;		# Do not use Regexp for name


 * 1) functions

sub p_version { print "$Name version : $Version\n"; }

sub print_usage { print "Usage: $Name [-v] -H -C  | (-l login -x passwd) [-p ] -n [,] [-t ] [-V]\n"; }

sub isnotnum { # Return true if arg is not a number my $num = shift; if ( $num =~ /^-?(\d+\.?\d*)|(^\.\d+)$/ ) { return 0 ;} return 1; }

sub is_pattern_valid { # Test for things like "" or "+5-i" my $pat = shift; if (!defined($pat)) { $pat=" ";} # Just to get rid of compilation time warnings return eval { "" =~ /$pat/; 1 } || 0; }

sub help { print "\nSNMP Windows Monitor for Nagios version ",$Version,"\n"; print "GPL licence, (c)2004-2005 Patrick Proy\n\n"; print_usage; print <<EOT; -v, --verbose print extra debugging information (and lists all services) -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 SNMP v1 or v2c with option) -l, --login=LOGIN Login for snmpv3 authentication (implies v3 protocol with MD5) -x, --passwd=PASSWD Password for snmpv3 authentication -p, --port=PORT SNMP port (Default 161) -T, --type=service Check type : - service (default) checks service -n, --name=NAME[,NAME2...] Comma separated names of services (perl regular expressions can be used for every one). By default, it is not case sensitive. -N, --number= Compare matching services with  instead of the number of names provided. -s, --showall Show all services in the output, instead of only the non-active ones. -r, --noregexp Do not use regexp to match NAME in service description. -t, --timeout=INTEGER timeout for SNMP in seconds (Default: 5) -V, --version prints version number Note : The script will return OK if ALL services are in active state, WARNING if there is more than specified (ex 2 service specified, 3 active services matching), CRITICAL if at least one of them is non active. The -n option will allows regexp in perl format -n "service" will match 'service WINS' 'sevice DNS' etc... It is not case sensitive by default : WINS = wins EOT }

sub verb { my $t=shift; print $t,"\n" if defined($o_verb) ; }

sub decode_utf8 { # just replaces UFT8 caracters by "." my $utfstr=shift; if (substr($utfstr,0,2) ne "0x") { return $utfstr; } my @stringL=split(//,$utfstr); my $newstring=""; for (my $i=2;$i<$#stringL;$i+=2) { if ( ($stringL[$i]. $stringL[$i+1]) eq "c3") { $i+=2;$newstring .= "."; } else { $newstring .= chr(hex($stringL[$i]. $stringL[$i+1])); }   }    return $newstring; }

sub check_options { Getopt::Long::Configure ("bundling"); GetOptions(       "H|hostname|host=s"         => \$OPTION{'host'},        "C|community=s"             => \$OPTION{'snmp-community'},        "snmp|snmp-version=s"       => \$OPTION{'snmp-version'},        "p|port|P|snmpport|snmp-port=i"    => \$OPTION{'snmp-port'},        "l|login|username=s"        => \$OPTION{'snmp-auth-user'},        "x|passwd|authpassword|password=s" => \$OPTION{'snmp-auth-password'},        "k|authkey=s"               => \$OPTION{'snmp-auth-key'},        "authprotocol=s"            => \$OPTION{'snmp-auth-protocol'},        "privpassword=s"            => \$OPTION{'snmp-priv-password'},        "privkey=s"                 => \$OPTION{'snmp-priv-key'},        "privprotocol=s"            => \$OPTION{'snmp-priv-protocol'},        "maxrepetitions=s"          => \$OPTION{'maxrepetitions'},        "t|timeout|snmp-timeout=i"  => \$OPTION{'snmptimeout'},        "64-bits"                   => \$OPTION{'64-bits'}, 'v'    => \$o_verb,		'verbose'	=> \$o_verb, 'h'    => \$o_help,    	'help'        	=> \$o_help, 'n:s'  => \$o_descr,		'name:s'	=> \$o_descr, 'r'    => \$o_noreg,           'noregexp'      => \$o_noreg, 'T:s'  => \$o_type,           	'type:s'      	=> \$o_type, 'N:i'  => \$o_number,          'number:i'      => \$o_number, 's'    => \$o_showall,  	'showall'       => \$o_showall, 'V'    => \$o_version,         'version'       => \$o_version );   if (defined ($o_help)) { help; exit $ERRORS{"UNKNOWN"}};    if (defined($o_version)) { p_version; exit $ERRORS{"UNKNOWN"}};    # check snmp information    ($session_params) = Centreon::SNMP::Utils::check_snmp_options($ERRORS{'UNKNOWN'}, \%OPTION);    # Check compulsory attributes    if ( $o_type ne "service" ) {      print "Invalid check type !\n"; print_usage; exit $ERRORS{"UNKNOWN"}    }    if ( ! defined($o_descr) ) { print_usage; exit $ERRORS{"UNKNOWN"}};   @o_descrL=split(/,/,$o_descr);    foreach my $List (@o_descrL) {      if ( ! is_pattern_valid ($List) ) { print "Invalid pattern ! ";print_usage; exit $ERRORS{"UNKNOWN"} }   }    if (defined ($o_number)) {      if (isnotnum($o_number) || ($o_number<0) )        { print "Invalid number of services!\n";print_usage; exit $ERRORS{"UNKNOWN"}}    }

}


 * 1) MAIN #######

check_options;

my $session = Centreon::SNMP::Utils::connection($ERRORS{'UNKNOWN'}, $session_params); $session->translate(Net::SNMP->TRANSLATE_OCTET_STRING);
 * 1) Connect to host

my $resultat = Centreon::SNMP::Utils::get_snmp_table($win_serv_name, $session, $ERRORS{'UNKNOWN'}, \%OPTION);
 * 1) Look for process in name or path name table

my @tindex = undef; my @oids = undef; my @descr = undef; my $num_int = 0; my $count_oid = 0;
 * 1) Select storage by regexp of exact match
 * 2) and put the oid to query in an array

verb("Filter : $o_descr");

foreach my $key ( keys %$resultat) { my $descr_d=decode_utf8($$resultat{$key}); verb("Desc : $descr_d"); # test by regexp or exact match my $test=undef; foreach my $List (@o_descrL) { if (!($test)) { $test = defined($o_noreg) ? $descr_d eq $List : $descr_d =~ /$List/i; }   }    if ($test) { # get the full description $descr[$num_int]=$descr_d; # get the index number of the process $key =~ s/$win_serv_name\.//; $tindex[$num_int] = $key; # put the oid of running state in an array. $oids[$count_oid++]=$win_serv_state. "." . $tindex[$num_int]; verb("Name : $descr[$num_int], Index : $tindex[$num_int]"); $num_int++; } }

if ( $num_int == 0) { if (defined ($o_number) && ($o_number ==0)) { print "No services ",(defined ($o_noreg)) ? "named \"" : "matching \"", $o_descr, "\" found : OK\n";       exit $ERRORS{"OK"};    } else  {        print "No services ",(defined ($o_noreg)) ? "named \"" : "matching \"", $o_descr, "\" found : CRITICAL\n"; exit $ERRORS{"CRITICAL"}; } }

my $result = Centreon::SNMP::Utils::get_snmp_leef(\@oids, $session, $ERRORS{'UNKNOWN'}); my $num_int_ok=0;

my $output=undef; for (my $i=0; $i< $num_int; $i++) { my $state=$$result{$win_serv_state. "." . $tindex[$i]}; verb ("Process $tindex[$i] in state $state"); if ($state == 1) { $num_int_ok++ } else { $output .= ", " if defined($output); $output .= $descr[$i]. " : " . $win_serv_state_label{$state}; } }
 * 1) Check if service are in active state

my $force_critical=0;

foreach my $List (@o_descrL) { my $test=0; for (my $i=0; $i< $num_int; $i++) { if ( !defined($o_noreg) && ($descr[$i] =~ /$List/i) ) { $test++; } if ( defined($o_noreg) && ($descr[$i] eq $List) ) { $test++; } }   if ($test==0) { $output .= ", " if defined($output); $output .= "\"" . $List . "\" not active"; # Force a critical state (could otherwise lead to false OK) $force_critical=1; } elsif ( defined ($o_showall) ) { $output .= ", " if defined($output); $output .= "\"" . $List . "\" active"; if ($test != 1) { $output .= "(" .$test . " services)"; }   } }
 * 1) Show the services that are not present
 * 2) Or all of them with -s option

if (defined ($output) ) { print $output, " : "; } else { print $num_int_ok, " services active (", (defined ($o_noreg)) ? "named \"" : "matching \"", $o_descr, "\") : "; }

$o_number = $#o_descrL+1 if (!defined($o_number));

if (($num_int_ok < $o_number)||($force_critical == 1)) { print "CRITICAL\n"; exit $ERRORS{"CRITICAL"}; } elsif ($num_int_ok > $o_number) { print "WARNING\n"; exit $ERRORS{"WARNING"}; } print "OK\n"; exit $ERRORS{"OK"};