#!/usr/bin/perl
###
### -- Nagios plugin for checking Barracuda Spam Firewall Queue sizes via SNMP
###
### -- Based on Nagios check_disk_snmp.pl plugin
###
 
use strict;
use warnings;
use vars qw($VERSION $VERBOSE $PROGNAME $OID_BASE);
use lib "/usr/local/nagios/libexec";
use utils qw(%ERRORS $TIMEOUT &print_revision);		## - nagios helpers
use Socket qw(inet_aton);				## - hostname lookup
use Net::SNMP;

$VERSION	= 0.01;
$PROGNAME	= 'check_cuda';
$OID_BASE	= '1.3.6.1.4.1.2021.8.1.101'; # .1=in, .2=out, .3=bounce
$VERBOSE	= 0;

sub print_version ();
sub print_usage ();
sub print_help ();
sub croak (;$);
sub commify ($);
sub shift_argv ($);

my $snmp	= q{};					## - snmp methods
my $resp	= q{};					## - snmp response
my $host	= q{};					## - host address
my $port	= 161;					## - snmp port
my $comm	= 'public';				## - snmp community
my $index	= q{};					## - device index
my $warn	= '500';				## - warning threshold
my $crit	= '1000';				## - critical threshold
my $state	= q{};					## - nagios state
my %queue_t	= (					## - queues table
  'in'		=> '.1',
  'out'         => '.2',
  'bounce'      => '.3'
);
my $queue       = 'in';                                 ## - queue

sub print_version () {
###
### -- display plugin revision

  print STDOUT "$PROGNAME $VERSION\n";
}

sub print_usage () {
###
### -- display usage help

  print "\nUsage: ${PROGNAME} -H host_address [-s snmp_community]\n",
             "\t[-p snmp_udp_port] [-q queue]\n",
             "\t[-w warning_threshold] [-c critical_threshold]\n",
	     "\n",
        "Extended help: ${PROGNAME} -h\n",
             "\n";
}

sub print_help () {
###
### -- display extended usage help

  print_revision($PROGNAME, $VERSION);

  print	"\nThis plugin checks the queue size on a Barracuda Spam Firewall\n",
	"via snmp query of UCD-SNMP-MIB::extResult\n";

  print_usage;

  print	"Options:\n",
    "  -h\n",
    "\tPrint help detailed help screen\n",
    "  -V\n",
    "\tPrint version information\n",
    "  -H STRING\n",
    "\tDotted decimal IP address or fully qualified domain name of host\n",
    "  -p INTEGER\n",
    "\tUDP port number for SNMP access (default: 161)\n",
    "  -s STRING\n",
    "\tSNMP community string for host (default: public)\n",
    "  -w INTEGER\n",
    "\tExit with WARNING if more than INTEGER messages are in the queue (default 500)\n",
    "  -c INTEGER\n",
    "\tExit with CRITICAL if more than INTEGER messages are in the queue (default: 1000)\n",
    "  -q QUEUE\n",
    "\tName of queue to check (default: 'in', others are 'out', and 'bounce')\n",
  "\n";

}

sub croak (;$) {
###
### -- display error message and exit

  print "$_\n" if $_ = shift; exit $ERRORS{'UNKNOWN'};
}

sub shift_argv ($) {
###
### -- get next command line argument
  
  my $opt	= shift(@_) || return;
  my $arg	= shift(@ARGV);
  
  return $arg if defined($arg);
  croak("CONFIG: missing argument for option: -${opt}");
}

sub commify ($) {
###
### -- pretty print numbers as from the perl cookbook

  my $num	= shift;
  $num		= reverse(sprintf('%u', $num));
  $num		=~ s/(\d\d\d)(?=\d)(?!\d*\.)/$1,/g;

  scalar reverse $num;
}


### parse and qualify arguments
###--------------------------------------------------------------------------###

if ($#ARGV == -1) {
  print_usage();
  croak();
}
while($_ = shift(@ARGV)){	
  if ($_ !~ s/^\-//o) {unshift(@ARGV, $_); last}	## - well formed arg?
  if ($_ eq "H") {$host		= shift_argv($_); next}
  if ($_ eq "p") {$port		= shift_argv($_); next}
  if ($_ eq "s") {$comm		= shift_argv($_); next}
  if ($_ eq "w") {$warn		= shift_argv($_); next}
  if ($_ eq "c") {$crit		= shift_argv($_); next}
  if ($_ eq "v") {$VERBOSE++;      next}
  if ($_ eq "V") {print_version(); croak()}
  if ($_ eq "h") {print_help();	   croak()}
  if ($_ eq "q") {$queue        = shift_argv($_); next}
  croak("CONFIG: unknown option -${_}");
}
if ($port !~ /^[0-9]+$/o || $port < 1 || $port > 65535) {
  croak("CONFIG: invalid port number: ${port}");
}
if (! $host)			{croak("CONFIG: missing host address")}
if (! inet_aton($host))		{croak("CONFIG: bad host address: ${host}")}
if (! $queue_t{$queue})         {croak("CONFIG: bad queue specified: ${queue}")}
if ($VERBOSE)			{print "\n"}

### create snmp object
###--------------------------------------------------------------------------###

$snmp		= Net::SNMP->session(
  -hostname	=> $host,
  -port		=> $port,
  -community	=> $comm,
  -timeout	=> int(($TIMEOUT / 3) + 1),
  -retries	=> 2,
  -version	=> '1',
  -nonblocking	=> 0x0
);
if ($VERBOSE) {
  print "HOST\t$host\nPORT\t$port\nCOMM\t$comm\n";
}
if (!defined($snmp)) {
  croak("create snmp session failed: ${!}")
}

$index=$OID_BASE.$queue_t{$queue};

### create snmp query
###--------------------------------------------------------------------------###

if ($VERBOSE) {
  print "Getting information for extResult${queue_t{$queue}}\n";
}
$resp		= $snmp->get_request(
  -varbindlist => [$index]
);
$snmp->close();

croak("SNMP query failed for index: ${index}") if ! defined($resp);
croak("Invalid data returned for index: ${index}") if $resp->{$index} < 0;
if ($VERBOSE > 1) {
    print "index => $resp->{$index}\n";
}
if ($VERBOSE) {
  print "\n";
}

### process snmp response
###--------------------------------------------------------------------------###

# count of messages in queue
my $messages = $resp->{$index};

$state = 'OK';
if ($messages >= $crit) {
    $state = 'CRITICAL';
}
elsif ($messages >= $warn) {
    $state = 'WARNING';
}

print	"SNMP $state - ",
	"$resp->{$index} messages in queue '$queue'\n";

exit $ERRORS{$state};

### -- EOF
