#!/usr/bin/perl -w

# Copyright (c) 2009 
# Written by Nathan Butcher
#
# Released under the GNU Public License
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
#
# Version: 1.0
#
# This plugin does the following : 
# Checks sysctl oid statistics in the FreeBSD kernel!
#
# Select a specific sysctl to monitor. The oid and it's value will be shown in
# Nagios' report window.
#
# Optionally, specify a value modifier for a value comparison against the oid's
# current value. These modifiers can be one of the following:-
# lt - less than, gt - greater than, eq - equal to, ne - not equal to
# and follow this with a value/string to compare against.
# When an oid's value does not match the specified range given, a CRITICAL
# error will be produced.
#
# Usage:   check_sysctl <sysctl oid> [lt/gt/eq/ne <value/string>]
#
# Example: check_sysctl kern.maxnvodes
#          OK kern.maxvnodes: 69131
# Example: check_sysctl kern.maxnvodes gt 70000 
#          CRITICAL kern.maxvnodes: 69131 (less than 70000)

use strict;

my %ERRORS=('DEPENDENT'=>4,'UNKNOWN'=>3,'OK'=>0,'WARNING'=>1,'CRITICAL'=>2);
my $state="UNKNOWN";
my $msg="FAILURE";

if ($#ARGV < 0) {
	print "Not enough arguments!\nUsage: $0 <sysctl oid> [lt/gt/eq/ne <value/string>]\n";
	exit $ERRORS{$state};
}

if ($^O ne 'freebsd') {
	print "This plugin is only applicable on FreeBSD.\n";
	exit $ERRORS{$state};
}

my $ctl=$ARGV[0];
my $mod="";
if ($ARGV[1]) {
	$mod=$ARGV[1];
}
my $val="";
if ($ARGV[2]) {
	$val=$ARGV[2];
}
my $output;
my $valout;
my $comment;
my $validmod=0;

if ($mod && ! $val) {
	print "Not enough arguments! Missing value for comparison !\n";
	exit ($ERRORS{$state});
}

my $statcommand="sysctl -h $ctl";
if (! open STAT, "$statcommand|") {
	print ("$state $statcommand returns no result!\n");
	exit ($ERRORS{$state});
}

while (<STAT>) {
	$output = $_;
}
if ( ! $output ) {
	print ("$state The sysctl oid $ctl does not exist!\n");
	exit ($ERRORS{$state});
}

chomp $output;

if ($mod) {
	$_=$output;
	($valout) = /\:\s(.*)$/;
	chomp $valout;

	if ($mod eq "lt") {
		$validmod=1;
		if ($valout <= $val) {
			$comment = "less than";
			$state = "OK";
		} else {
			$comment = "greater than";
			$state = "CRITICAL";
		}
	}
	if ($mod eq "gt") {
		$validmod=1;
		if ($valout >= $val) {
			$comment = "greater than";
			$state = "OK";
		} else {
			$comment = "less than";
			$state = "CRITICAL";
		}
	}
	if ($mod eq "eq") {
		$validmod=1;
		if ($valout == $val) {
			$comment = "equal to";
			$state = "OK";
		} else {
			$comment = "not equal to";
			$state = "CRITICAL";
		}
	}
	if ($mod eq "ne") {
		$validmod=1;
		if ($valout != $val) {
			$comment = "not equal to";
			$state = "OK";
		} else {
			$comment = "equal to";
			$state = "CRITICAL";
		}
	}
	if ($validmod == 0) {
		print "Invalid value comparison modifier! (lt,gt,eq,ne are valid)\n";
		exit ($ERRORS{$state});
	}

	$msg = sprintf "%s (%s %s)\n", $output , $comment, $val;

} else {
	$state = "OK";
	$msg = sprintf "%s\n", $output;
}

#goats away!
print $state, " ", $msg;
exit ($ERRORS{$state});
