#!/usr/bin/perl
#
# check_nomadix_esp
# 
# A nagios plugin that monitors the IPSec tunnel status on 
# NOMADIX Enterprise devices.
#
# Espen Braastad, Linpro AS (2006)
# Bugfixed by: Erik Bolsoe, Linpro AS
# Funded by Oslo Airport
#
# Supported MIBs:
#  -ag5000.mib
#  -ag3000.mib
#  -USGII.mib

use strict;
use Net::SNMP;
use Getopt::Long;

my $snmpwalk="/usr/bin/snmpwalk";	# Path to the snmpwalk executable
my $mibpath="/usr/lib/nagios/mibs/";	# Path to the directory where the MIBs are located
my $timeout=1;				# snmp timeout
my $debug=0;				# Enable/disable debugging

my $status=2;

my($s,$help,$target,$community,$mib);
sub syntax {
        $s = shift;
        unless ($s =~ m/Help:/) {
                $s = "Error: (".$s.")" or $s = 'Unknown';
        }
        print "$s\n" unless ($help);
        print "Syntax: $0 -m <mib> -h <host> -c <community>\n";
        print "  --host -h         Target SNMP host\n";
        print "  --mib -m          MIB filename (in " . $mibpath . ")\n";
        print "  --community -c    SNMP community\n";
        print "  --help -h         This help\n";
        exit(3);
}

Getopt::Long::Configure('bundling');
GetOptions
        ("h=s"        => \$target,      "host=s"       => \$target,
         "m=s"        => \$mib,         "mib=s"        => \$mib,
         "c=s"        => \$community,   "community=s"  => \$community);

syntax("Help:") if ($help);
syntax("Missing host") unless (defined($target));
syntax("Missing mib") unless (defined($mib));
syntax("Missing community") unless (defined($community));

# Checking if snmpwalk is found and executable
if(! -x ${snmpwalk}){
	${status}=2;
	print "Error: " . ${snmpwalk} . " not found.\n";	
	if(${debug}){
		print "Exit code: " . ${status} . "\n";
	}
	exit ${status};
}

# Let's see if we are able to talk to the SNMP host
my $fullmib=$mibpath . $mib;
my @{response}=split("\n",`${snmpwalk} -v 1 -c ${community} -t ${timeout} -m "${fullmib}" ${target} NOMADIX-MIB::ipsecSaStatusState -Cp -OQv 2>/dev/null`);
my ${snmpexit}=$?;
if(${snmpexit}!=0){
	${status}=2;
	print "Error: Unable to connect to ${target}. Exit code was " . ${snmpexit} . ".\n";
	if(${debug}){
		print "Exit code: " . ${status} . "\n";
	}
	# We could use 3/Unknown here, but the connection problem may mean
	# that the device is down so report it as critical.
	exit ${status};
}

# Number of interfaces to look for
my ${interfaces}=(split(" ",${response[-1]}))[-1];
if(${debug}){
	print "Interfaces found: " . ${interfaces} . "\n";
}

# Checking if the number of interfaces is a numeric value
if (${interfaces} =~ /^-?\d/) {
	# Check if any interfaces were found
	if(${interfaces}==0){
		${status}=2;
		print "Error: No interfaces found! Unable to monitor correctly. (" . ${interfaces} . ")\n";
		if(${debug}){
			print "Exit code: " . ${status} . "\n";
		}
		exit ${status};
	exit ${status};
	}

	# Loop through the interfaces, extract status
	my ${OK}=0;
	my ${FAIL}=0;
	my ${output}="";
	for(my ${i}=1 ; ${i}<=${interfaces} ; ${i}++){
		my ${state}=${response[${i}-1]};
                # bugfiks 20070227 knan ... eq, ikke == ... vi sammenligner strenger her.
                if(${state} eq "ipsecUp"){
			${output}.="SP" . ${i} . " is up. ";
			${OK}+=1;
		} else {
			${output}.="SP" . ${i} . " is " . ${state} . "! ";
			${FAIL}+=1;
		}
		if(${debug}){
			print "Interface " . ${i} . " is in state: " . ${state} . "\n";
		}
	}

	# Write human readable output
	if(${FAIL}>0){
		${status}=2;
		print "CRITICAL! " . ${FAIL} . " tunnel(s) down, " . ${OK} . " up: "
	} else {
		${status}=0;
		print "OK, " . ${OK} . " tunnel(s) up: "
	}
	print ${output} . "\n";

	if(${debug}){
		print "Exit code: " . ${status} . "\n";
	}
	exit ${status};
} else {
	${status}=2;
	print "Error: The number of interfaces found is not a numerical value. Unable to monitor correctly.\n";
	if(${debug}){
		print "Exit code: " . ${status} . "\n";
	}
	exit ${status};
}

# Obs!
print "This is not supposed to happen. Debugging is needed!\n";
${status}=2;
if(${debug}){
	print "Exit code: " . ${status} . "\n";
}
exit ${status};

