#!/usr/bin/perl -w
#
# bulk checker for net-snmp, to be used with Nagios
#
# alex@2e-systems.com, Sep 2006
#

use strict;
use Getopt::Long;

my $SNMPWALK = "snmpwalk";
my $SNMPWALK_OPTS = "-On -Oa -t 15";


my $debug=0;
my $silent=0;
my $help=0;
my $snmpver="2c";
my $user="twoe";
my $community="twoe";

GetOptions('help'  => \$help, 'debug' => \$debug, 'snmpver=s' => \$snmpver, 'user=s' => \$user, 'community=s' => \$community, 'silent' =>\$silent );

if ($help || $#ARGV < 1 ) {

print<<EOF

Check all OIDs specified in the command line and all objects underneath
Anything other than zero under .101.x is considered an error

usage: $0 [options] host oid1 [,oid2] ...
usage: ./snmp-bulk-check.pl hostname .1.3.6.1.4.1.2021.8.1 .1.3.6.1.4.1.2021.2.1 .1.3.6.1.4.1.2021.10 .1.3.6.1.4.1.2021.9

Options:

  --help		this help
  --debug		be verbose
  --snmpver=s           SNMP version (default: $snmpver)
  --user=s              SNMP user (default: $user)
  --community=s         SNMP comimunity (default: $community)
  --silent		do not print anything unless errors

Interesting OIDs:

.1.3.6.1.4.1.2021.2.1 = processes
.1.3.6.1.4.1.2021.10  = load average
.1.3.6.1.4.1.2021.9   = disk usage
.1.3.6.1.4.1.2021.8.1 = custom scripts


EOF
;
   exit;
}

my $host=shift;
my @oids=@ARGV;

$SNMPWALK_OPTS="$SNMPWALK_OPTS -v $snmpver -u $user -c $community";

print "Host: $host\n" if $debug;

my (%oidmap);

# fill oidmap

for my $oid (@oids) {
  my $cmd="$SNMPWALK $SNMPWALK_OPTS $host $oid";
  print "Running: $cmd\n" if $debug;
  my @walk_output = `$cmd`;
  for (@walk_output) {
     my $index="";
     my $type="";
     my $value="";
     print "Got  : $_" if $debug;
     if (/^(.*?)\s=\s(.*?):\s(.*?)$/) {
       $index=$1;
       $type=$2;
       $value=$3;
     } elsif (/^(.*?)\s=\s(.*?)$/) {
       $index=$1;
       $type="UNK";
       $value=$2;
     } else {
       print "Malformed output: $_";
     }
     # remove quotes, blank spaces
     $value =~ s/^\"//;
     $value =~ s/\"$//;
     $value =~ s/^\s+//;
     $value =~ s/\s+$//;
     print "Parsed: index: $index, type=$type, value=$value\n" if $debug;
     $oidmap{$index} = $value;
  }
}

# in net-snmp exit codes are in .100.x, so get them
my @errors = grep (/\.100\..*?\d+$/, keys %oidmap);
my $exitcode = 0;

# now check for exitcodes > 0
if ($#errors == -1 ) {
  print "CRITICAL: Nothing reported!";
  exit 2;
} else {
  for (grep (/\.100\..*?\d+$/, keys %oidmap)) {
    # print "Checking: $_ = $oidmap{$_}\n";
    if ( $oidmap{$_} > 0 ) { # exit code not zero!

       #get just MSB, as this is the exit from the shell
       $oidmap{$_} >>= 8 if $oidmap{$_} > 255;

       # increase the global exit code if needed
       $exitcode = $oidmap{$_} if $oidmap{$_} > $exitcode;

       print "OID in error: $_:$exitcode\n" if $debug;

       # get the service name and error text
       my @bytes=split /\./;
       $bytes[$#bytes-1]=2;
       print $oidmap{join('.',@bytes)} . ":";
       $bytes[$#bytes-1]=101;

       # if its a custom script there can be more than one line of output
       if (/2021\.8\.1\./) {
         $bytes[$#bytes]=1;
         while (defined $oidmap{join('.',@bytes)} ) {
            print "joining OID: " . join('.',@bytes) . "\n" if $debug;
            print (( 1 < $bytes[$#bytes] ? ", " : "" ) . $oidmap{join('.',@bytes)} );
            $bytes[$#bytes]++;
         }
       } else {
         print $oidmap{join('.',@bytes)} if defined $oidmap{join('.',@bytes)};
       }
       print "\n";
    }
  }
}
print (($#errors+1) . " OIDs tested OK on " . localtime() . "\n") if (! $silent) && $exitcode==0;
exit $exitcode;

