#!/usr/bin/perl
#Written by Lane Williams
#01-10-2012
#Script is used to check values of snmp enabled devices.  Yes another one...the others do not do what I like..so I wrote Yet another SNMP check.
#My programming is not the best nor do I strive to be perfect.  The code is simple an easily read and/or change to meet your needs. 
#There is no warranty or guarantee this will do what you would like, but you can always add or change it.
#Thanks to Stephan Hradek for input on port option and giving the idea which lead to the expanded first line output.

use Getopt::Std;
use Net::SNMP;
getopts('hH:C:V:O:t:p:');

if ($opt_h){
        print "\nUSAGE: check_snmp.pl -H hostname -C community -V snmp version -t Title -O label:oid:warn:crit:[(l)less than|(g)greater than]:[(a)alpha|(n)number\n";
        print "The -O option must have all of the values in order for it to work.\n";
        print "The last 2 options are if the value should be greater than or less than, and/or whether the check output will be numeric or alphabet\n\n";
        exit;
        }

$host=$opt_H;
$community=$opt_C;
$version=$opt_V;
@oids=$opt_O;
$title=$opt_t;
$port=$opt_p;

$STATE_OK = 0;
$STATE_WARNING = 1;
$STATE_CRITICAL = 2;
$STATE_UNKNOWN = 3;

$crit_exit = 0;
$warn_exit = 0;
#split the input for use
foreach $oid (@oids){
	@oid2 = split (',',$oid);
	foreach $obj (@oid2){
		($label,$oid,$warn,$crit,$v,$an)=split (/:/,$obj);
#Connect to host and collect data
		($session,$error) = Net::SNMP->session(Hostname => $host,
                                       		Community => $community,
						Port => $port);
		if (!defined $session){
			print "Error: %s.\n", $error;
			exit $STATE_UNKNOWN;
		}
		$get = $session->get_request("$oid");
		if (!defined $get) {
      			printf "ERROR: %s.\n", $session->error();
      			$session->close();
     			exit $STATE_UNKNOWN;
  		 }
		$session->close;
		$value = $get->{$oid};
#Load the hash with data
		push @{ $results{$label} },($value,$warn,$crit,$v,$an);
	}
}
#format the first line of output and prime the pump
$banner = $title." Status:";
$string eq "";
$perf = " | ";
$count = 0;

foreach $element (sort keys %results){
#If you need the check to be value based, then you should enter a 'n' in the last option.
    if ($results{$element}[4] eq "n"){
        $results{$element}[0] =~ tr/0-9.-//cd;
        if ($results{$element}[3] eq "g"){
#if you wish the output to be greater than the warning and critical levels than enter a 'g' in the fifth postion of the option.
                if ($results{$element}[0] >= $results{$element}[2]){
                        $crit_exit = 1;
                        $string .= "CRITICAL: $element = $results{$element}[0]"."\n";
			$banner .= " [$element=$results{$element}[0] CRITICAL]";
                        $perf .= "$element=$results{$element}[0];$results{$element}[1];$results{$element}[2];0; ";
                }
                elsif ($results{$element}[0] >= $results{$element}[1]){
                        $warn_exit = 1;
                        $string .= "WARNING: $element = $results{$element}[0]"."\n";
			$banner .= " [$element=$results{$element}[0] WARNING]";
                        $perf .= "$element=$results{$element}[0];$results{$element}[1];$results{$element}[2];0; ";
                }
                else {  $string .= "OK: $element = $results{$element}[0]"."\n";
			$count++;
                        $perf .= "$element=$results{$element}[0];$results{$element}[1];$results{$element}[2];0; ";}
        }
#if you wish the output to be less than the warning and critical levels than enter a 'l' in the fifth postion of the option.
        elsif ($results{$element}[3] eq "l"){
                if ($results{$element}[0] <= $results{$element}[2]){
                        $crit_exit = 1;
                        $string .= "CRITICAL: $element = $results{$element}[0]"."\n";
			$banner .= " [$element=$results{$element}[0] CRITICAL]";
                        $perf .= "$element=$results{$element}[0];$results{$element}[1];$results{$element}[2];0; ";
                }
                elsif ($results{$element}[0] <= $results{$element}[1]){
                        $warn_exit = 1;
                        $string .= "WARNING: $element = $results{$element}[0]"."\n";
			$banner .= " [$element=$results{$element}[0] WARNING]";
                        $perf .= "$element=$results{$element}[0];$results{$element}[1];$results{$element}[2];0; ";
                }
                else {  $string .= "OK: $element = $results{$element}[0]"."\n";
			$count++;
                        $perf .= "$element=$results{$element}[0];$results{$element}[1];$results{$element}[2];0; ";}
        }
        else {print "You left out an option: -O label:oid:warn:crit:[(l)less than|(g)greater than]:[(a)alpha|(n)number\n";
                exit $STATE_UNKNOWN;}
        }
#If you need to check text and not numerical values, then you should enter an 'a' in the last option.  I am not sure if I have tackled this properly.
#You may enter what you expect for critical or warning, else everything else is OK.  I may change the OK to an 'elsif' and 'else' an Unknown.
#You can place a 'x', or whatever you wish, in the fifth position of the options.
   elsif ($results{$element}[4] eq "a"){
                if ($results{$element}[0] =~ /($results{$element}[2])/i){
                        $crit_exit = 1;
                        $string .= "CRITICAL: $element = $results{$element}[0]"."\n";
			$banner .= " [$element=$results{$element}[0] CRITICAL]";
		}
                elsif ($results{$element}[0] =~ /($results{$element}[1])/i){
                        $warn_exit = 1;
                        $string .= "WARNING: $element = $results{$element}[0]"."\n";
			$banner .= " [$element=$results{$element}[0] WARNING]";
                }
                else {  $count++;
			$string .= "OK: $element = $results{$element}[0]"."\n";}
   }
  else {print "You left out an option: -O label:oid:warn:crit:[(l)less than|(g)greater than]:[(a)alpha|(n)number]\n";
                exit $STATE_UNKNOWN;}
 }


if ($crit_exit != 0){
        chomp $string;
        print "$banner [$count OK]\n$string $perf \n";
        exit $STATE_CRITICAL;
}

elsif($warn_exit != 0){
        chomp $string;
        print "$banner [$count OK]\n$string $perf \n";
        exit $STATE_WARNING;
}

else {  chomp $string;
        print "$banner [$count OK]\n$string $perf\n";
        exit $STATE_OK; }
