diff options
Diffstat (limited to 'contrib')
57 files changed, 7352 insertions, 0 deletions
diff --git a/contrib/aix/check_crit_dsk b/contrib/aix/check_crit_dsk new file mode 100644 index 00000000..566e07c1 --- /dev/null +++ b/contrib/aix/check_crit_dsk @@ -0,0 +1,66 @@ +#!/bin/sh + +#========================================================================= +# Critical Disk Checker utility +# +# This is the same as the disk checker utility but we use it as +# a seperate service in Nagios to report on partitions that +# have reached 100% capacity. +# +# We have excluded /dev/cd0 because the cdrom drive will always +# report 100% capacity if a CD is in the drive. +# +# Authors: TheRocker +# SpEnTBoY +# +# Email: therocker@pawprints.2y.net +# lonny@abyss.za.org +# +#======================================================================= + +NUMBER=`rsh $1 -l root df -kP | grep -vE ":|/dev/cd0" | grep -E "100%" | tr -s ' '| cut -d' ' -f5 | cut -c1-3 | line` +TMPFILE=/tmp/tmpcrit.hndl +TMPTOO=/tmp/twocrit.hndl + +if [ "$NUMBER" -eq 100 ] +then + + `rsh $1 -l root df -kP |grep -vE ":|/dev/cd0" | grep -E "100%" | tr -s ' '| cut -d' ' -f6,5 >> $TMPFILE` + + LINES=`wc -l /tmp/tmpcrit.hndl | cut -c8` + LINESCTL=`wc -l /tmp/tmpcrit.hndl | cut -c8 ` + echo "Filesystems over 99% --> \c" + +#=============================================================== +# Just a little bit to check for multiple occurances of the +# condition. +#=============================================================== + + while [ $LINESCTL != 0 ] + do + + cat $TMPFILE | tail -$LINESCTL > $TMPTOO + cat $TMPTOO > $TMPFILE + LINESCTL=$(( $LINESCTL -1 )) + LINES=$(( $LINES -1 )) + DATA=`head -1 /tmp/tmpcrit.hndl` + echo "( $DATA ) \c" + + + done + echo "\n" + +#=============================================================== +# File clean up. Always pick up after yourself. Disk space +# doesn't grow on trees you know. +#=============================================================== + + rm -f $TMPFILE + rm -f $TMPTOO + exit 2 + +else + + echo "No Filesystems over 99%... OK" + exit 0 +fi diff --git a/contrib/aix/check_dsk b/contrib/aix/check_dsk new file mode 100644 index 00000000..c8ddb3f8 --- /dev/null +++ b/contrib/aix/check_dsk @@ -0,0 +1,62 @@ +#! /bin/sh + +#====================================================================== +# Disk Checker utility +# +# Simple little script that checks the status of all partitions +# on a node's hard disks. It will produce a warning alert and list +# the offending filesystems in nagios. +# +# Authors: SpEnTBoY +# TheRocker +# +# Email: lonny@abyss.za.org +# therocker@pawprints.2y.net +#===================================================================== + +NUMBER=`rsh $1 -l root df -kP | grep -v ":" | grep -E "9[0-9]%" | tr -s ' '| cut -d' ' -f5 | cut -c1-2 | line` +TMPFILE=/tmp/tmp.hndl +TMPTOO=/tmp/two.hndl + +if [ "$NUMBER" -gt 90 ] +then + + `rsh $1 -l root df -kP |grep -v ":" | grep -E "9[0-9]%" | tr -s ' '| cut -d' ' -f6,5 >> $TMPFILE` + + LINES=`wc -l /tmp/tmp.hndl | cut -c8` + LINESCTL=`wc -l /tmp/tmp.hndl | cut -c8 ` + echo "Filesystems over 90% --> \c" + +#====================================================================== +# You'll see this one in a few our shell scripts. Just chcecking for +# multiple occurances of the warnign condition. We gotta list 'em all +#====================================================================== + + while [ $LINESCTL != 0 ] + do + + cat $TMPFILE | tail -$LINESCTL > $TMPTOO + cat $TMPTOO > $TMPFILE + LINESCTL=$(( $LINESCTL -1 )) + LINES=$(( $LINES -1 )) + DATA=`head -1 /tmp/tmp.hndl` + echo "( $DATA ) \c" + + + done + echo "\n" + +#=============================================================== +# Clean up all those nasty tmp files that suck up valuable +# disk realestate. +#=============================================================== + + rm -f $TMPFILE + rm -f $TMPTOO + exit 1 + +else + + echo "No Filesystems over 90%... OK" + exit 0 +fi diff --git a/contrib/aix/check_failed b/contrib/aix/check_failed new file mode 100644 index 00000000..50cdf7e1 --- /dev/null +++ b/contrib/aix/check_failed @@ -0,0 +1,48 @@ +#!/usr/bin/perl +#====================== +# Created May 25, 2000 +#====================== + +# This scripts is for checking for failed root login attempts on +# any machine running AIX which has a failedlogin file in /etc/security +# The purpose is to thwart (good word) any unauthorised people from +# even trying to log in as root. This plugin has been developed for Nagios +# running on AIX. +# Lonny Selinger SpEnTBoY lonny@abyss.za.org +# May + + +my $server = $ARGV[0]; + +if (!$ARGV[0]) { + print "You must specify a server to check\n"; + print "usage: ./check_failed <Server Name>\n"; + exit (-1); + } else { + open (DATE, "/bin/date '+%b %d' |"); + while (<DATE>) { + $dline = $_; + @dresults = $dline; + chop $dresults[0]; + } + open (SULOG, "rsh $server -l root who /etc/security/failedlogin | grep root |"); + while (<SULOG>) { + $line = $_; + @results = split (/\s+/,$line); + if ($line =~ /^root/) { + if (join(' ', @results[2,3]) eq $dresults[0]) { + print "FAILED root login on $dresults[0], node: $ARGV[0] from $results[5]\n"; + exit(2); + } + } + } +} +if (join(' ', @results[2,3]) ne $dresults[0]) { + print "No Failed Root Logins on This Node\n"; + exit(0); +} +exit(0); +close(SULOG); +close(DATE); + + diff --git a/contrib/aix/check_io b/contrib/aix/check_io new file mode 100644 index 00000000..58b25f6d --- /dev/null +++ b/contrib/aix/check_io @@ -0,0 +1,69 @@ +#! /bin/sh + +#================================================================= +# +# I/O Checker (KBPS) +# This Script uses iostat to monitor disk io +# Useful for notifications of disk thrashing. +# +# Authors: TheRocker +# SpEnTBoY +# +# Email: therocker@pawprints.2y.net +# lonny@abyss.za.org +# +#================================================================ + +NUMBER1=`rsh $1 -l root iostat -d | grep -e "hdisk" | tr -s ' ' | cut -d' ' -f2 | sort -2 -r | cut -c1 | line` +NUMBER2=`rsh $1 -l root iostat -d | grep -e "hdisk" | tr -s ' ' | cut -d' ' -f2 | sort -2 -r | cut -c2 | line` +TMPFILE=/tmp/iotest.hndl +TMPTOO=/tmp/iotwo.hndl + +#=========================================================== +# +# We do an evaluation on $NUMBER1 and $NUMBER2 to see if +# disk io is exceeding 40%. +# +#=========================================================== + +if [ "$NUMBER1" -gt 4 ] && [ "$NUMBER2" -gt 0 ] +then + + `rsh $1 -l root iostat -d | grep -v cd0 | tr -s ' '| cut -d' ' -f1,2 | grep -e "4[0-9]." >> $TMPFILE` + +#==================================================================== +# +# Of course, there may be more than one hard disk on the node +# so we use this bit of code to report on more than one instance +# of excessive disk IO. +# +#==================================================================== + + LINES=`wc -l /tmp/iotest.hndl | cut -c8` + LINESCTL=`wc -l /tmp/iotest.hndl | cut -c8 ` + echo "WARNING!!! Disk I/O Exceeding 40% on --> \c" + + while [ $LINESCTL != 0 ] + do + + cat $TMPFILE | tail -$LINESCTL > $TMPTOO + cat $TMPTOO > $TMPFILE + LINESCTL=$(( $LINESCTL -1 )) + LINES=$(( $LINES -1 )) + DATA=`head -1 /tmp/iotest.hndl` + echo "( $DATA ) " + + + done + echo "\n" + + rm -f $TMPFILE + rm -f $TMPTOO + exit 1 + +else + + print "No Disk I/O Exceeding 40%...OK" + exit 0 + +fi diff --git a/contrib/aix/check_kerberos b/contrib/aix/check_kerberos new file mode 100644 index 00000000..443ab109 --- /dev/null +++ b/contrib/aix/check_kerberos @@ -0,0 +1,49 @@ +#! /bin/sh + +#========================================================================= +# Kerberos Ticket Checker +# +# This script is handy if you allow kerberos tickets to expire +# on your nodes. The script will simply warn you when a node has +# kerberos tickets expiring on the current date. This will allow to +# re-initialize the tickets if you wish to do so. +# +# Nothing fancy here, all Nagios will show is the number of tickets +# that are going to (or already have) expired. +# +# An item of note: +# +# We made no provisions for the weekend. If tickets expire on the +# weekend and nobody is around, you won't see a warning on the +# Nagios console because we look for expired on the current day +# only. It's a good idea to have this warning emailed to the +# appropriate admin and if there is something critical that relies +# on Kerberos, you might want to send a page. +# +# Authors: TheRocker +# SpEnTBoY +# +# Email: therocker@pawprints.2y.net +# lonny@abyss.za.org +#========================================================================= + +TMPFILE=/tmp/kerbtmp.hndl +DATE=`date +%b' '%d` + +rsh $1 -l root /usr/lpp/ssp/kerberos/bin/klist | tr -s ' ' | cut -d' ' -f4,5,6 | grep -e "$DATE" > $TMPFILE + + +if [ -s $TMPFILE ] +then + + LINES=`wc -l /tmp/kerbtmp.hndl | cut -c7-8` + echo "Kerberos Tickets set to expire --> \c" + echo "$LINES \c" + echo "\n" + + rm -f $TMPFILE + exit 1 + +fi + echo "Kerberos Tickets are valid" + exit 0 diff --git a/contrib/aix/check_ping b/contrib/aix/check_ping new file mode 100644 index 00000000..aaa8c84e --- /dev/null +++ b/contrib/aix/check_ping @@ -0,0 +1,117 @@ +#!/usr/bin/perl -w + +#================================================================ +# +# This perl script will accept an argument and simply pass it +# to ping. It works by sending 2 ping to the specified host +# and evaluating on the average delta time of those 2 pings. +# +# Author: SpEnTBoY +# Email: lonny@abyss.za.org +# April 5,2000 +# +#================================================================ + +#============================ +# State predefined stuff and +# requirements +#============================ + +require 5.004; +use POSIX; +use strict; + +sub usage; + +my $ipaddr = $ARGV[0]; + +my $TIMEOUT = 15; + +my %ERRORS = ('UNKNOWN' , '-1', + 'OK' , '0', + 'WARNING', '1', + 'CRITICAL', '2'); + +my $remote = shift || &usage(%ERRORS); +my $warning = shift || 750; +my $critical = shift || 1000; + +my $state = "OK"; +my $answer = undef; +my $offset = undef; +my $line = undef; + +#============================================================ +# If theres no response we can exit the bloody thing cleanly +# last thing I want to do is hang an AIX system ;-) +#============================================================ + +$SIG{'ALRM'} = sub { + print ("ERROR: No response from PING! (alarm)\n"); + exit $ERRORS{"UNKNOWN"}; +}; +alarm($TIMEOUT); + +#================================================ +# Pass stddn from $ARGV to the command and parse +# the info we need (namely the value for "max" +#================================================ + + + +open(PING,"/usr/sbin/ping -c 2 '$ipaddr' >&1|"); +while (<PING>) { + $line = $_; + if (/round-trip min\/avg\/max = (.+)\/(.+)\/(.+) ms/) { + $offset = $3; + last; + } +} + +#================================================== +# Do some error checking on the output of the file +# and implement values for <crit> and <warn> +# deffinitions if they were specified by the user +# or sub in the predefined ones +#================================================== + +if (defined $offset) { + if (abs($offset) > $warning) { + if (abs($offset) > $critical) { + $state = "CRITICAL"; + $answer = ": Ping Time $offset MS greater than +/- $critical MS\n"; + } else { + $state = "WARNING"; + $answer = ": Ping Time $offset MS greater than +/- $warning MS\n"; + } + } else { + $state = "OK"; + $answer = ": Ping Time $offset MS\n"; + } +} else { + $state = "UNKNOWN"; + $answer = ": $line\n"; +} +print ("$state$answer"); +exit $ERRORS{$state}; + +sub usage { + print "\n"; + print "#=========================================\n"; + print "Check_Ping 0.02 script by Lonny Selinger\n"; + print "Made with AIX in mind ;-)\n"; + print "#=========================================\n"; + print "\n"; + print "#================================================\n"; + print " I'm going to need a few more arguments from you\n"; + print "#================================================\n"; + print "\n"; + print "#================================================\n"; + print "Usage: check_ping <host> [<warn> [<crit>]\n"; + print "#================================================\n"; + print "\n"; + print "<warn> = Ping in MS at which a warning message will be generated.\n Defaults to 750.\n"; + print "<crit> = Ping in MS at which a critical message will be generated.\n Defaults to 1000.\n\n"; + exit $ERRORS{"UNKNOWN"}; +} + diff --git a/contrib/aix/check_queue b/contrib/aix/check_queue new file mode 100644 index 00000000..9f709c54 --- /dev/null +++ b/contrib/aix/check_queue @@ -0,0 +1,67 @@ +#! /bin/sh + +#=============================================================== +# Print Queue Checker +# +# The print queue checker simply looks for an occurance of a +# DOWN queue. A note of warning, if you use remote queues in +# AIX to redirect print jobs from the AIX queue to an NT print +# server that print through DLC rather than IP, it will be very +# s - l - o - w. But it will work. +# +# Author: TheRocker +# Email: therocker@pawprints.2y.net +#=============================================================== + +TMPFILE=/tmp/qtmp.hndl +TMPTOO=/tmp/qtwo.hndl + +#======================================================================= +# +# This script will also work on AIX 4.2.1 BUT you have to change +# the following line. AIX 4.2.1 does not support the -W option +# with lpstat. For AIX 4.2.1 just remove the -W option and it should +# work just fine. +# +#======================================================================= + +`rsh $1 -l root lpstat -W | grep -e "DOWN" | tr -s ' ' | cut -d' ' -f1,3 > /tmp/qtmp.hndl 2> /tmp/q_err` + +if [ -s $TMPFILE ] +then + +#======================================================= +# +# If you've seen the other AIX scripts I wrote you may +# notice that I use this bit of code a lot. Well it +# works and appears to be all purpose. +# +#======================================================= + + LINES=`wc -l /tmp/qtmp.hndl | cut -c8` + LINESCTL=`wc -l /tmp/qtmp.hndl | cut -c8` + + echo "Print Queue DOWN --> \c" + + while [ $LINESCTL != 0 ] + do + + cat $TMPFILE | tail -$LINESCTL > $TMPTOO + cat $TMPTOO > $TMPFILE + LINESCTL=$(( $LINESCTL -1 )) + LINES=$(( $LINES -1 )) + DATA=`head -1 /tmp/qtmp.hndl` + echo "( $DATA ) \c" + + + done + + echo "\n" + + rm -f $TMPFILE + rm -f $TMPTOO + exit 2 + +fi + echo "Print Queues Running... OK" + exit 0 diff --git a/contrib/aix/pg_stat b/contrib/aix/pg_stat new file mode 100644 index 00000000..e0603ec4 --- /dev/null +++ b/contrib/aix/pg_stat @@ -0,0 +1,45 @@ +#!/bin/ksh + +#============================================================================== +# Script was originally created to collect stats and dump then to a log file +# every five minutes. But we like this better (the log file thing is still +# good if you want to track availability). +# +# Authors: SpEnTBoY +# TheRocker +# +# Email: lonny@abyss.za.org +# therocker@pawprints.2y.net +#============================================================================== + +#========================================================================================= +# +# The best way to do this is to use Kerberos but we use rsh here because our monitoring +# workstation doesn't have Kerberos installed. In order for this to work, the remote +# host ($1) must have a .rhosts file that contains a line like: +# +# monitorhost nagiosuser +# +#========================================================================================= + +PAGING2=`rsh $1 -l root lsps -a -s | grep -v Paging | tr -s ' '| cut -d' ' -f3 | cut -d'%' -f1` + + +if [ "$PAGING2" -gt "35" ] && [ "$PAGING2" -lt "50" ] +then + echo "Paging Space is over 35% ("$PAGING2")%" +exit 1 +fi + +if [ "$PAGING2" -gt "49" ] +then + echo "WARNING! Paging Space is over 50% ("$PAGING2")%" +exit 2 +fi + +if [ "$PAGING2" -lt "34" ] +then + echo "Paging Space is less than 34% ("$PAGING2")%" +exit 0 +fi + diff --git a/contrib/check_apache.pl b/contrib/check_apache.pl new file mode 100644 index 00000000..b9e69a0c --- /dev/null +++ b/contrib/check_apache.pl @@ -0,0 +1,283 @@ +#!/usr/bin/perl +# +# (c)2001 Sebastian Hetze, Linux Information Systems AG +# send bug reports to <S.Hetze@Linux-AG.com> +# +# 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 (or with Nagios); if not, write to the +# Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA +# +# +# Check apache status information provided by mod_status to find +# out about the load (number of servers working) and the +# performance (average response time for recent requests). +# +# Usage: +# check_apache -H <host> [-lhV] [-w <warn>] [-c <crit>] [-u <url>] +# +# check_apache <host> <warn> <crit> <url> (if you cannot avoid it) +# + +use LWP::UserAgent; +use URI::URL; +use Getopt::Long; +Getopt::Long::Configure('bundling'); + +$version=0.01; + +my %ERRORS = ('UNKNOWN' , '-1', + 'OK' , '0', + 'WARNING', '1', + 'CRITICAL', '2'); + + +# +# some default values +# +$perf_w=500; +$perf_c=1000; +$load_w=20; +$load_c=30; +$TIMEOUT=15; + +# +# get command line options the regular way +# +GetOptions + ("V" => \$opt_V, "version" => \$opt_V, + "h" => \$opt_h, "help" => \$opt_h, + "l" => \$opt_l, "load" => \$opt_l, + "v" => \$verbose, "verbose" => \$verbose, + "w=s" => \$opt_w, "warning=s" => \$opt_w, + "c=s" => \$opt_c, "critical=s" => \$opt_c, + "H=s" => \$opt_H, "hostname=s" => \$opt_H, + "u=s" => \$opt_u, "url=s" => \$opt_u); + +# +# handle the verbose stuff first +# +if ($opt_V) { + print "\n"; + print "check_apache nagios plugin version $version\n"; + print "\n"; + print "The nagios plugins come with ABSOLUTELY NO WARRANTY. You may redistribute\n"; + print "copies of the plugins under the terms of the GNU General Public License.\n"; + print "For more information about these matters, see the file named COPYING.\n"; + print "\n"; + print "Copyright (c) 2001 Sebastian Hetze Linux Information Systems AG\n"; + print "\n"; + print "\n"; + exit $ERRORS{'UNKNOWN'}; +} + +if ($opt_h) { + print_help(); + exit $ERRORS{'UNKNOWN'}; +} + +# +# now get options the weired way and set the defaults +# if nothing else is provided +# +$opt_H = shift unless ($opt_H); +print_usage() unless ($opt_H); + +if($opt_l) { + $autostring="?auto"; + ($opt_w) || ($opt_w = shift) || ($opt_w = $load_w); + $warn = $1 if ($opt_w =~ /([0-9]+)/); + ($opt_c) || ($opt_c = shift) || ($opt_c = $load_c); + $alert = $1 if ($opt_c =~ /([0-9]+)/); +} else { + $autostring=""; + ($opt_w) || ($opt_w = shift) || ($opt_w = $perf_w); + $warn = $1 if ($opt_w =~ /([0-9]+)/); + ($opt_c) || ($opt_c = shift) || ($opt_c = $perf_c); + $alert = $1 if ($opt_c =~ /([0-9]+)/); +} + +($opt_u) || ($opt_u = shift) || ($opt_u = "/server-status"); + + +# +# dont let us wait forever... +# +$SIG{'ALRM'} = sub { + print ("ERROR: No response from HTTP server (alarm)\n"); + exit $ERRORS{"UNKNOWN"}; +}; +alarm($TIMEOUT); + + +# +# now we set things up for the real work +# and fire up the request +# +$ua = new LWP::UserAgent; +$ua->agent("Nagios/0.1 " . $ua->agent); + + +$urlstring = "http://" . $opt_H . $opt_u . $autostring; +$url = url($urlstring); + +my $req = new HTTP::Request 'GET', $url; +my $res = $ua->request($req); + +# +# hopefully we´ve got something usefull +# +if ($res->is_success) { + if($opt_l) { + foreach $_ (split /^/m, $res->content) { + next if /^\s*$/; +# +# this is the load checking section +# we parse the whole content, just in case someone +# wants to use this some day in the future +# + if (/^Total Accesses:\s+([0-9.]+)/) { $accesses = $1; next; } + if (/^Total kBytes:\s+([0-9.]+)/) { $kbytes = $1; next; } + if (/^CPULoad:\s+([0-9.]+)\s+/) { $load = $1; next; } + if (/^Uptime:\s+([0-9.]+)\s+/) { $uptime = $1; next; } + if (/^ReqPerSec:\s+([0-9.]+)\s+/) { $rps = $1; next; } + if (/^BytesPerSec:\s+([0-9.]+)\s+/) { $bps = $1; next; } + if (/^BytesPerReq:\s+([0-9.]+)\s+/) { $bpr = $1; next; } + if (/^BusyServers:\s+([0-9.]+)\s+/) { $busy = $1; next; } + if (/^IdleServers:\s+([0-9.]+)\s+/) { $idle = $1; next; } + if (/^Scoreboard:\s+([SRWKDLG_.]+)\s+/) { $score = $1; next; } + print "Unknown Status\n"; + exit $ERRORS{"UNKNOWN"}; + } +# +# now we even parse the whole scoreboard, just for fun +# + foreach $scorepoint (split //m, $score) { + if($scorepoint eq '.') { $scores{'.'}+=1; next; } # Unused + if($scorepoint eq '_') { $scores{'_'}+=1; next; } # Waiting + if($scorepoint eq 'S') { $scores{'S'}+=1; next; } # Starting + if($scorepoint eq 'R') { $scores{'R'}+=1; next; } # Reading + if($scorepoint eq 'W') { $scores{'W'}+=1; next; } # Writing + if($scorepoint eq 'K') { $scores{'K'}+=1; next; } # Keepalive + if($scorepoint eq 'D') { $scores{'D'}+=1; next; } # DNS Lookup + if($scorepoint eq 'L') { $scores{'L'}+=1; next; } # Logging + if($scorepoint eq 'G') { $scores{'G'}+=1; next; } # Going + } + + if($busy>$alert) { + printf "HTTPD CRITICAL: %.0f servers running\n", $busy; + exit $ERRORS{"CRITICAL"}; + } + if($busy>$warn) { + printf "HTTPD WARNING: %.0f servers running\n", $busy; + exit $ERRORS{"WARNING"}; + } + printf "HTTPD ok: %.0f servers running, %d idle\n", $busy, $idle; + exit $ERRORS{"OK"}; + + } else { +# +# this is the performance check section +# We are a bit lazy here, no parsing of the initial data +# block and the scoreboard. +# However, you have the whole set of per server +# information to play with ;-) +# The actual performance is measured by adding up the +# milliseconds required to process the most recent +# requests of all instances and then taking the average. +# + foreach $tablerow (split /<tr>/m, $res->content) { + ($empty,$Srv,$PID,$Acc,$M,$CPU,$SS,$Req,$Conn,$Child,$Slot,$Client,$VHost,$Request) + = split /<td>/, $tablerow; + if($Req) { + $lines+=1; + $req_sum+=$Req; + } + undef $Req; + } + $average=$req_sum/$lines; + if($average>$alert) { + printf "HTTPD CRITICAL: average response time %.0f + milliseconds\n", $average; + exit $ERRORS{"CRITICAL"}; + } + if($average>$warn) { + printf "HTTPD WARNING: average response time %.0f + milliseconds\n", $average; + exit $ERRORS{"WARNING"}; + } + if($average>0) { + printf "HTTPD ok: average response time %.0f milliseconds\n", + $average; + exit $ERRORS{"OK"}; + } + print "Unknown Status\n"; + exit $ERRORS{"UNKNOWN"}; + } +} else { + print "HTTP request failed\n"; + exit $ERRORS{"CRITICAL"}; +} + + +# +# ok, now we are almost through +# These last subroutines do the things for those that do not +# read source code. +# +sub print_usage () { + print "Usage: $0 -H <host> [-lhV] [-w <warn>] [-c <crit>] [-u <url>]\n"; } + +sub print_help () { + print "\n"; + print "\n"; + print "check_apache nagios plugin version $version\n"; + print "\n"; + print "The nagios plugins come with ABSOLUTELY NO WARRANTY. You may redistribute\n"; + print "copies of the plugins under the terms of the GNU General Public License.\n"; + print "For more information about these matters, see the file named COPYING.\n"; + print "\n"; + print "Copyright (c) 2001 Sebastian Hetze Linux Information Systems AG\n"; + print "\n"; + print "\n"; + print "This plugin checks the apache HTTP service on the specified host.\n"; + print "It uses the mod_status facilities provided by the apache server.\n"; + print "The monitoring server must be authorized in httpd.conf.\n"; + print "\n"; + print "\n"; + print_usage(); + print "\n"; + print "Options:\n"; + print " -H, --hostname=ADDRESS\n"; + print " host name argument for server.\n"; + print " -l, --load\n"; + print " check load instead of performance.\n"; + print " -h, --help\n"; + print " print detailed help screen.\n"; + print " -V, --version\n"; + print " print version information.\n"; + print " -w, --warning=INTEGER\n"; + print " load / performance level at which a warning message will be gererated.\n"; + print " -c, --critical=INTEGER\n"; + print " load / performance level at which a critical message will be gererated.\n"; + print " -u, --url=PATH\n"; + print " location to call mod_status.\n"; + print "\n"; + print " Defaults for performance checking are $perf_w/$perf_c msec.\n"; + print " Defaults for load checking are $load_w/$load_c servers running.\n"; + print "\n"; + print "\n"; +} +# +# the end +# diff --git a/contrib/check_apc_ups.pl b/contrib/check_apc_ups.pl new file mode 100644 index 00000000..dd979f52 --- /dev/null +++ b/contrib/check_apc_ups.pl @@ -0,0 +1,314 @@ +#! /usr/bin/perl -wT +# +# Check_apc_ups - Check APC UPS status via SNMP +# Shamelessly copied from check_breeze.pl +# +# To do: +# - Send SNMP queries directly, instead of forking `snmpget`. +# - Make the status less verbose. Maybe we can send an "onLine, time +# remaining: hh:mm:ss" if all is well, and a list of specific problems +# if something is broken. + +BEGIN { + if ($0 =~ m/^(.*?)[\/\\]([^\/\\]+)$/) { + $runtimedir = $1; + $PROGNAME = $2; + } +} + +use strict; +use Getopt::Long; +use vars qw($opt_V $opt_h $opt_H $opt_T $opt_t $opt_R $opt_r + $opt_L $opt_l $PROGNAME); +use lib $main::runtimedir; +use utils qw(%ERRORS &print_revision &support &usage); + +sub print_help (); +sub print_usage (); +sub get_snmp_int_val ($); +sub escalate_exitval ($); + +$ENV{'PATH'}=''; +$ENV{'BASH_ENV'}=''; +$ENV{'ENV'}=''; + +Getopt::Long::Configure('bundling'); +GetOptions + ("V" => \$opt_V, "version" => \$opt_V, + "h" => \$opt_h, "help" => \$opt_h, + "T=s" => \$opt_T, "temp-critical" => \$opt_T, + "t=s" => \$opt_t, "temp-warning" => \$opt_t, + "R=s" => \$opt_R, "runtime-critical" => \$opt_R, + "r=s" => \$opt_r, "runtime-warning" => \$opt_r, + "L=s" => \$opt_L, "load-critical" => \$opt_L, + "l=s" => \$opt_l, "load-warning" => \$opt_l, + "H=s" => \$opt_H, "hostname=s" => \$opt_H); + +if ($opt_V) { + print_revision($PROGNAME,'$Revision$'); + exit $ERRORS{'OK'}; +} + +if ($opt_h) {print_help(); exit $ERRORS{'OK'};} + +($opt_H) || ($opt_H = shift) || usage("Host name/address not specified\n"); +my $host = $1 if ($opt_H =~ /([-.A-Za-z0-9]+)/); +($host) || usage("Invalid host: $opt_H\n"); + +# Defaults + +$opt_R *= 60 * 100 if (defined $opt_R); # Convert minutes to secs/100 +$opt_r *= 60 * 100 if (defined $opt_R); + +my $tempcrit = $opt_T || 60; +my $tempwarn = $opt_t || 40; +my $runtimecrit = $opt_R || 30 * 60 * 100; # Secs / 100 +my $runtimewarn = $opt_r || 60 * 60 * 100; +my $loadcrit = $opt_L || 85; +my $loadwarn = $opt_l || 50; + +if ($tempcrit !~ /\d+/) { usage ("Invalid critical temperature threshold.\n"); } +if ($tempwarn !~ /\d+/) { usage ("Invalid critical temperature threshold.\n"); } + +if ($runtimecrit !~ /\d+/) { + usage ("Invalid critical run time threshold.\n"); +} +if ($runtimewarn !~ /\d+/) { + usage ("Invalid warning run time threshold.\n"); +} + +if ($loadcrit !~ /\d+/ || $loadcrit < 0 || $loadcrit > 100) { + usage ("Invalid critical load threshold.\n"); +} +if ($loadwarn !~ /\d+/ || $loadwarn < 0 || $loadwarn > 100) { + usage ("Invalid warning load threshold.\n"); +} + + +# APC UPS OIDs +# APC MIBs are available at ftp://ftp.apcftp.com/software/pnetmib/mib +my $upsBasicOutputStatus = ".1.3.6.1.4.1.318.1.1.1.4.1.1.0"; +my $upsBasicBatteryStatus = ".1.3.6.1.4.1.318.1.1.1.2.1.1.0"; +my $upsAdvInputLineFailCause = ".1.3.6.1.4.1.318.1.1.1.3.2.5.0"; +my $upsAdvBatteryTemperature = ".1.3.6.1.4.1.318.1.1.1.2.2.2.0"; +my $upsAdvBatteryRunTimeRemaining = ".1.3.6.1.4.1.318.1.1.1.2.2.3.0"; +my $upsAdvBatteryReplaceIndicator = ".1.3.6.1.4.1.318.1.1.1.2.2.4.0"; +my $upsAdvOutputLoad = ".1.3.6.1.4.1.318.1.1.1.4.2.3.0"; +my $upsAdvTestDiagnosticsResults = ".1.3.6.1.4.1.318.1.1.1.7.2.3.0"; + +my @outputStatVals = ( + [ undef, undef ], # pad 0 + [ undef, undef ], # pad 1 + [ "onLine", $ERRORS{'OK'} ], # 2 + [ "onBattery", $ERRORS{'WARNING'} ], # 3 + [ "onSmartBoost", $ERRORS{'WARNING'} ], # 4 + [ "timedSleeping", $ERRORS{'WARNING'} ], # 5 + [ "softwareBypass", $ERRORS{'WARNING'} ], # 6 + [ "off", $ERRORS{'CRITICAL'} ], # 7 + [ "rebooting", $ERRORS{'WARNING'} ], # 8 + [ "switchedBypass", $ERRORS{'WARNING'} ], # 9 + [ "hardwareFailureBypass", $ERRORS{'CRITICAL'} ], # 10 + [ "sleepingUntilPowerReturn", $ERRORS{'CRITICAL'} ], # 11 + [ "onSmartTrim", $ERRORS{'WARNING'} ], # 12 +); + +my @failCauseVals = ( + undef, + "noTransfer", + "highLineVoltage", + "brownout", + "blackout", + "smallMomentarySag", + "deepMomentarySag", + "smallMomentarySpike", + "largeMomentarySpike", + "selfTest", + "rateOfVoltageChnage", +); + +my @battStatVals = ( + [ undef, undef ], # pad 0 + [ undef, undef ], # pad 1 + [ "batteryNormal", $ERRORS{'OK'} ], # 2 + [ "batteryLow", $ERRORS{'CRITICAL'} ], # 3 +); + +my @battReplVals = ( + [ undef, undef ], # pad 0 + [ "noBatteryNeedsReplacing", $ERRORS{'OK'} ], # 1 + [ "batteryNeedsReplacing", $ERRORS{'CRITICAL'} ], # 2 +); + +my @diagnosticsResultsVals = ( + [ undef, undef ], # pad 0 + [ "OK", $ERRORS{'OK'} ], # 1 + [ "failed", $ERRORS{'CRITICAL'} ], # 2 + [ "invalidTest", $ERRORS{'CRITICAL'} ], # 3 + [ "testInProgress", $ERRORS{'OK'} ], # 4 +); + +my $exitval = $ERRORS{'UNKNOWN'}; +my $data; +my $onbattery = 3; + +$data = get_snmp_int_val( $upsBasicOutputStatus ); + +print "Output status: "; +if (defined ($data) && defined ($outputStatVals[$data][0])) { + print "$outputStatVals[$data][0] | "; + escalate_exitval($outputStatVals[$data][1]); +} else { + print "unknown | "; +} + +$data = get_snmp_int_val( $upsAdvBatteryRunTimeRemaining ); + +print "Rem time: "; +if (defined ($data)) { + my $hrs = int($data / (60 * 60 * 100)); # Data is hundredths of a second + my $mins = int($data / (60 * 100)) % 60; + my $secs = ($data % 100) / 100; + printf "%d:%02d:%05.2f | ", $hrs, $mins, $secs; + if ($data <= $runtimecrit) { + escalate_exitval($ERRORS{'CRITICAL'}); + } elsif ($data <= $runtimewarn) { + escalate_exitval($ERRORS{'WARNING'}); + } else { + escalate_exitval($ERRORS{'OK'}); + } +} else { + print "unknown | "; +} + +$data = get_snmp_int_val( $upsBasicBatteryStatus ); + +print "Battery status: "; +if (defined ($data) && defined ($battStatVals[$data][0])) { + my $failcause = "unknown"; + my $fc = get_snmp_int_val( $upsAdvInputLineFailCause ); + if ($data == $onbattery) { + if (defined ($failCauseVals[$fc])) { $failcause = $failCauseVals[$fc]; } + print "$battStatVals[$data][0] ($failcause) | "; + } else { + print "$battStatVals[$data][0] | "; + } + escalate_exitval($battStatVals[$data][1]); +} else { + print "unknown | "; +} + +$data = get_snmp_int_val( $upsAdvBatteryTemperature ); + +print "Battery temp(C): "; +if (defined ($data)) { + print "$data | "; + if ($data >= $tempcrit) { + escalate_exitval($ERRORS{'CRITICAL'}); + } elsif ($data >= $tempwarn) { + escalate_exitval($ERRORS{'WARNING'}); + } else { + escalate_exitval($ERRORS{'OK'}); + } +} else { + print "unknown | "; +} + +$data = get_snmp_int_val( $upsAdvBatteryReplaceIndicator ); + +print "Battery repl: "; +if (defined ($data) && defined ($battReplVals[$data][0])) { + print "$battReplVals[$data][0] | "; + escalate_exitval($battReplVals[$data][1]); +} else { + print "unknown | "; +} + +$data = get_snmp_int_val( $upsAdvOutputLoad ); + +print "Output load (%): "; +if (defined ($data)) { + print "$data | "; + if ($data >= $loadcrit) { + escalate_exitval($ERRORS{'CRITICAL'}); + } elsif ($data >= $loadwarn) { + escalate_exitval($ERRORS{'WARNING'}); + } else { + escalate_exitval($ERRORS{'OK'}); + } +} else { + print "unknown | "; +} + +$data = get_snmp_int_val( $upsAdvTestDiagnosticsResults ); + +print "Diag result: "; +if (defined ($data) && defined ($diagnosticsResultsVals[$data][0])) { + print "$diagnosticsResultsVals[$data][0]\n"; + escalate_exitval($diagnosticsResultsVals[$data][1]); +} else { + print "unknown\n"; +} + + +exit $exitval; + + +sub print_usage () { + print "Usage: $PROGNAME -H <host> -T temp -t temp -R minutes -r minutes\n"; + print " -L percent -l percent\n"; +} + +sub print_help () { + print_revision($PROGNAME,'$Revision$'); + print "Copyright (c) 2001 Gerald Combs/Jeffrey Blank/Karl DeBisschop + +This plugin reports the status of an APC UPS equipped with an SNMP management +module. + +"; + print_usage(); + print " +-H, --hostname=HOST + Name or IP address of host to check +-T --temp-critical + Battery degrees C above which a CRITICAL status will result (default: 60) +-t --temp-warning + Battery degrees C above which a WARNING status will result (default: 40) +-R --runtime-critical + Minutes remaining below which a CRITICAL status will result (default: 30) +-r --runtime-warning + Minutes remaining below which a WARNING status will result (default: 60) +-L --load-critical + Output load pct above which a CRITICAL status will result (default: 85 +-l --load-warning + Output load pct above which a WARNING status will result (default: 50 + +"; + support(); +} + +sub get_snmp_int_val ($) { + my $val=0; + my $oid = shift(@_); + + $val = `/usr/bin/snmpget $host public $oid 2> /dev/null`; + my @test = split(/ /,$val,3); + + return undef unless (defined ($test[2])); + + if ($test[2] =~ /\(\d+\)/) { # Later versions of UCD SNMP + ($val) = ($test[2] =~ /\((\d+)\)/); + } elsif ($test[2] =~ /: \d+/) { + ($val) = ($test[2] =~ /: (\d+)/); + } else { + $val = $test[2]; + } + + return $val; +} + +sub escalate_exitval ($) { + my $newval = shift(@_); + + if ($newval > $exitval) { $exitval = $newval; } +} diff --git a/contrib/check_bgpstate.pl b/contrib/check_bgpstate.pl new file mode 100644 index 00000000..6658a0b8 --- /dev/null +++ b/contrib/check_bgpstate.pl @@ -0,0 +1,215 @@ +#!/usr/bin/perl -w +# +# check_bgpstate.pl - nagios plugin +# +# Copyright (C) 2000 Christoph Kron +# +# 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. +# +# +# Report bugs to: ck@zet.net +# +# 11.01.2000 Version 1.0 + + + +use strict; + +use Net::SNMP; +use Getopt::Long; +&Getopt::Long::config('auto_abbrev'); + + +# whois programm for RIPE database queries +my $whois = '/usr/bin/whois'; +my $status; +my $TIMEOUT = 30; + +# critical bgp sessions +my %uplinks = ( 1273, 'Uplink ECRC', + 1755, 'Uplink EBONE', + 3300, 'Uplink AUCS' + ); + +my %ERRORS = ('UNKNOWN' , '-1', + 'OK' , '0', + 'WARNING', '1', + 'CRITICAL', '2'); + + +my %bgpPeerState = ( + '1',"idle", + '2',"connect", + '3',"active", + '4',"opensent", + '5',"openconfirm", + '6',"established" + ); +my $state = "UNKNOWN"; +my $answer = ""; +my $snmpkey; +my $snmpoid; +my $key; +my $community = "public"; +my $port = 161; +my @snmpoids; +my $snmpbgpPeerState = '1.3.6.1.2.1.15.3.1.2'; +my $snmpbgpPeerLocalAddr = '1.3.6.1.2.1.15.3.1.5'; +my $snmpbgpPeerRemoteAddr = '1.3.6.1.2.1.15.3.1.7'; +my $snmpbgpPeerRemoteAs = '1.3.6.1.2.1.15.3.1.9'; +my $hostname; +my $session; +my $error; +my $response; +my %bgpStatus; +my $bgpestablished =0 ; +my $bgpcritical =0; +my $bgpdown =0; +my $bgpidle =0; +my $bgpmessage; +my $asname; +my $remoteas; +my @output; + +sub usage { + printf "\nMissing arguments!\n"; + printf "\n"; + printf "Perl bgpstate plugin for Nagios\n"; + printf "monitors all BGP sessions\n"; + printf "usage: \n"; + printf "check_bgpstate.pl -c <READCOMMUNITY> -p <PORT> <HOSTNAME>\n"; + printf "Copyright (C) 2000 Christoph Kron\n"; + printf "check_bgpstate.pl comes with ABSOLUTELY NO WARRANTY\n"; + printf "This programm is licensed under the terms of the "; + printf "GNU General Public License\n(check source code for details)\n"; + printf "\n\n"; + exit $ERRORS{"UNKNOWN"}; +} + +# Just in case of problems, let's not hang Nagios +$SIG{'ALRM'} = sub { + print ("ERROR: No snmp response from $hostname (alarm)\n"); + exit $ERRORS{"UNKNOWN"}; +}; +alarm($TIMEOUT); + + +$status = GetOptions("community=s",\$community, + "port=i",\$port); +if ($status == 0) +{ + &usage; +} + + #shift; + $hostname = shift || &usage; + + +push(@snmpoids, $snmpbgpPeerState); +push(@snmpoids, $snmpbgpPeerLocalAddr); +push(@snmpoids, $snmpbgpPeerRemoteAddr); +push(@snmpoids, $snmpbgpPeerRemoteAs); + +foreach $snmpoid (@snmpoids) { + + ($session, $error) = Net::SNMP->session( + -hostname => $hostname, + -community => $community, + -port => $port + ); + + if (!defined($session)) { + $state='UNKNOWN'; + $answer=$error; + print ("$state: $answer"); + exit $ERRORS{$state}; + } + + if (!defined($response = $session->get_table($snmpoid))) { + $answer=$session->error; + $session->close; + $state = 'CRITICAL'; + print ("$state: $answer,$community,$snmpkey"); + exit $ERRORS{$state}; + } + + foreach $snmpkey (keys %{$response}) { + $snmpkey =~ m/.*\.(\d+\.\d+\.\d+\.\d+$)/; + $key = $1; +# printf "debug: $snmpkey: $key -> $response->{$snmpkey}\n"; + $bgpStatus{$key}{$snmpoid} = $response->{$snmpkey}; + } + $session->close; +} + +foreach $key (keys %bgpStatus) { + if ($bgpStatus{$key}{$snmpbgpPeerState} == 6 ) { + $bgpestablished++; + } + elsif ($bgpStatus{$key}{$snmpbgpPeerState} == 1 ) { + $bgpidle++; + } + else { + $bgpdown++ ; + if (exists($uplinks{$bgpStatus{$key}{$snmpbgpPeerRemoteAs}}) ) { + $bgpcritical++; + } + @output = `$whois -T aut-num AS$bgpStatus{$key}{$snmpbgpPeerRemoteAs}`; + + $asname = ""; + foreach (@output) { + if (m/as-name/) { + $asname = $_; + $asname =~ s/as-name://; + last; + } + if ( $asname =~ "" && m/descr/ ) { + $asname = $_; + $asname =~ s/descr://; + } + } + $asname =~ s/^\s*//; + $asname =~ s/\s*$//; + $bgpmessage .= sprintf("Peering with AS%s not established -> %s<BR>", + $bgpStatus{$key}{$snmpbgpPeerRemoteAs}, + $asname); + } +} + + + if ($bgpdown > 0) { + if ($bgpcritical > 0) { + $state = 'CRITICAL'; + } + else { + $state = 'WARNING'; + } + $answer = sprintf("host '%s', sessions up: %d, down: %d, shutdown: %d<BR>", + $hostname, + $bgpestablished, + $bgpdown, $bgpidle); + $answer = $answer . $bgpmessage . "\n"; + } + else { + $state = 'OK'; + $answer = sprintf("host '%s', sessions up: %d, down: %d, shutdown: %d\n", + $hostname, + $bgpestablished, + $bgpdown,$bgpidle); + } + +print ("$state: $answer"); +exit $ERRORS{$state}; + diff --git a/contrib/check_dhcp.c b/contrib/check_dhcp.c new file mode 100644 index 00000000..8168b947 --- /dev/null +++ b/contrib/check_dhcp.c @@ -0,0 +1,992 @@ +/****************************************************************************** +* +* CHECK_DHCP.C +* +* Program: DHCP plugin for Nagios +* License: GPL +* Copyright (c) 2001 Ethan Galstad (nagios@nagios.org) +* +* License Information: +* +* 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., 675 Mass Ave, Cambridge, MA 02139, USA. +* +*****************************************************************************/ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <errno.h> +#include <unistd.h> +#include <sys/time.h> +#include <sys/ioctl.h> +#include <fcntl.h> +#include <features.h> +#include <linux/if_ether.h> +#include <getopt.h> +#include <net/if.h> +#include <sys/socket.h> +#include <sys/types.h> +#include <netinet/in.h> +#include <arpa/inet.h> +#include <netdb.h> + +#define PROGNAME "check_dhcp" + +/*#define DEBUG*/ +#define HAVE_GETOPT_H + + +/**** Common definitions ****/ + +#define STATE_OK 0 +#define STATE_WARNING 1 +#define STATE_CRITICAL 2 +#define STATE_UNKNOWN -1 + +#define OK 0 +#define ERROR -1 + +#define FALSE 0 +#define TRUE 1 + + +/**** DHCP definitions ****/ + +#define MAX_DHCP_CHADDR_LENGTH 16 +#define MAX_DHCP_SNAME_LENGTH 64 +#define MAX_DHCP_FILE_LENGTH 128 +#define MAX_DHCP_OPTIONS_LENGTH 312 + + +typedef struct dhcp_packet_struct{ + u_int8_t op; /* packet type */ + u_int8_t htype; /* type of hardware address for this machine (Ethernet, etc) */ + u_int8_t hlen; /* length of hardware address (of this machine) */ + u_int8_t hops; /* hops */ + u_int32_t xid; /* random transaction id number - chosen by this machine */ + u_int16_t secs; /* seconds used in timing */ + u_int16_t flags; /* flags */ + struct in_addr ciaddr; /* IP address of this machine (if we already have one) */ + struct in_addr yiaddr; /* IP address of this machine (offered by the DHCP server) */ + struct in_addr siaddr; /* IP address of DHCP server */ + struct in_addr giaddr; /* IP address of DHCP relay */ + unsigned char chaddr [MAX_DHCP_CHADDR_LENGTH]; /* hardware address of this machine */ + char sname [MAX_DHCP_SNAME_LENGTH]; /* name of DHCP server */ + char file [MAX_DHCP_FILE_LENGTH]; /* boot file name (used for diskless booting?) */ + char options[MAX_DHCP_OPTIONS_LENGTH]; /* options */ + }dhcp_packet; + + +typedef struct dhcp_offer_struct{ + struct in_addr server_address; /* address of DHCP server that sent this offer */ + struct in_addr offered_address; /* the IP address that was offered to us */ + u_int32_t lease_time; /* lease time in seconds */ + u_int32_t renewal_time; /* renewal time in seconds */ + u_int32_t rebinding_time; /* rebinding time in seconds */ + struct dhcp_offer_struct *next; + }dhcp_offer; + + +typedef struct requested_server_struct{ + struct in_addr server_address; + struct requested_server_struct *next; + }requested_server; + + +#define BOOTREQUEST 1 +#define BOOTREPLY 2 + +#define DHCPDISCOVER 1 +#define DHCPOFFER 2 +#define DHCPREQUEST 3 +#define DHCPDECLINE 4 +#define DHCPACK 5 +#define DHCPNACK 6 +#define DHCPRELEASE 7 + +#define DHCP_OPTION_MESSAGE_TYPE 53 +#define DHCP_OPTION_HOST_NAME 12 +#define DHCP_OPTION_BROADCAST_ADDRESS 28 +#define DHCP_OPTION_REQUESTED_ADDRESS 50 +#define DHCP_OPTION_LEASE_TIME 51 +#define DHCP_OPTION_RENEWAL_TIME 58 +#define DHCP_OPTION_REBINDING_TIME 59 + +#define DHCP_INFINITE_TIME 0xFFFFFFFF + +#define DHCP_BROADCAST_FLAG 32768 + +#define DHCP_SERVER_PORT 67 +#define DHCP_CLIENT_PORT 68 + +#define ETHERNET_HARDWARE_ADDRESS 1 /* used in htype field of dhcp packet */ +#define ETHERNET_HARDWARE_ADDRESS_LENGTH 6 /* length of Ethernet hardware addresses */ + +unsigned char client_hardware_address[MAX_DHCP_CHADDR_LENGTH]=""; + +char network_interface_name[8]="eth0"; + +u_int32_t packet_xid=0; + +u_int32_t dhcp_lease_time=0; +u_int32_t dhcp_renewal_time=0; +u_int32_t dhcp_rebinding_time=0; + +int dhcpoffer_timeout=2; + +dhcp_offer *dhcp_offer_list=NULL; +requested_server *requested_server_list=NULL; + +int valid_responses=0; /* number of valid DHCPOFFERs we received */ +int requested_servers=0; +int requested_responses=0; + +int request_specific_address=FALSE; +int received_requested_address=FALSE; +struct in_addr requested_address; + + +int process_arguments(int, char **); +int call_getopt(int, char **); +int validate_arguments(void); +void print_usage(void); +void print_help(void); + +int get_hardware_address(int,char *); + +int send_dhcp_discover(int); +int get_dhcp_offer(int); + +int get_results(void); + +int add_dhcp_offer(struct in_addr,dhcp_packet *); +int free_dhcp_offer_list(void); +int free_requested_server_list(void); + +int create_dhcp_socket(void); +int close_dhcp_socket(int); +int send_dhcp_packet(void *,int,int,struct sockaddr_in *); +int receive_dhcp_packet(void *,int,int,int,struct sockaddr_in *); + + + +int main(int argc, char **argv){ + int dhcp_socket; + int result; + + if(process_arguments(argc,argv)!=OK){ + /*usage("Invalid command arguments supplied\n");*/ + printf("Invalid command arguments supplied\n"); + exit(STATE_UNKNOWN); + } + + + /* create socket for DHCP communications */ + dhcp_socket=create_dhcp_socket(); + + /* get hardware address of client machine */ + get_hardware_address(dhcp_socket,network_interface_name); + + /* send DHCPDISCOVER packet */ + send_dhcp_discover(dhcp_socket); + + /* wait for a DHCPOFFER packet */ + get_dhcp_offer(dhcp_socket); + + /* close socket we created */ + close_dhcp_socket(dhcp_socket); + + /* determine state/plugin output to return */ + result=get_results(); + + /* free allocated memory */ + free_dhcp_offer_list(); + free_requested_server_list(); + + return result; + } + + + +/* determines hardware address on client machine */ +int get_hardware_address(int sock,char *interface_name){ + struct ifreq ifr; + + strncpy((char *)&ifr.ifr_name,interface_name,sizeof(ifr.ifr_name)); + + /* try and grab hardware address of requested interface */ + if(ioctl(sock,SIOCGIFHWADDR,&ifr)<0){ + printf("Error: Could not get hardware address of interface '%s'\n",interface_name); + exit(STATE_UNKNOWN); + } + + memcpy(&client_hardware_address[0],&ifr.ifr_hwaddr.sa_data,6); + +#ifdef DEBUG + printf("Hardware address: %02x:%02x:%02x:",client_hardware_address[0],client_hardware_address[1],client_hardware_address[2]); + printf("%02x:",client_hardware_address[3]); + printf("%02x:%02x\n",client_hardware_address[4],client_hardware_address[5]); + printf("\n"); +#endif + + return OK; + } + + +/* sends a DHCPDISCOVER broadcast message in an attempt to find DHCP servers */ +int send_dhcp_discover(int sock){ + dhcp_packet discover_packet; + struct sockaddr_in sockaddr_broadcast; + + + /* clear the packet data structure */ + bzero(&discover_packet,sizeof(discover_packet)); + + + /* boot request flag (backward compatible with BOOTP servers) */ + discover_packet.op=BOOTREQUEST; + + /* hardware address type */ + discover_packet.htype=ETHERNET_HARDWARE_ADDRESS; + + /* length of our hardware address */ + discover_packet.hlen=ETHERNET_HARDWARE_ADDRESS_LENGTH; + + discover_packet.hops=0; + + /* transaction id is supposed to be random */ + srand(time(NULL)); + packet_xid=random(); + discover_packet.xid=htonl(packet_xid); + + /**** WHAT THE HECK IS UP WITH THIS?!? IF I DON'T MAKE THIS CALL, ONLY ONE SERVER RESPONSE IS PROCESSED!!!! ****/ + /* downright bizzarre... */ + ntohl(discover_packet.xid); + + /*discover_packet.secs=htons(65535);*/ + discover_packet.secs=0xFF; + + /* tell server it should broadcast its response */ + discover_packet.flags=htons(DHCP_BROADCAST_FLAG); + + /* our hardware address */ + memcpy(discover_packet.chaddr,client_hardware_address,ETHERNET_HARDWARE_ADDRESS_LENGTH); + + /* first four bytes of options field is magic cookie (as per RFC 2132) */ + discover_packet.options[0]='\x63'; + discover_packet.options[1]='\x82'; + discover_packet.options[2]='\x53'; + discover_packet.options[3]='\x63'; + + /* DHCP message type is embedded in options field */ + discover_packet.options[4]=DHCP_OPTION_MESSAGE_TYPE; /* DHCP message type option identifier */ + discover_packet.options[5]='\x01'; /* DHCP message option length in bytes */ + discover_packet.options[6]=DHCPDISCOVER; + + /* the IP address we're requesting */ + if(request_specific_address==TRUE){ + discover_packet.options[7]=DHCP_OPTION_REQUESTED_ADDRESS; + discover_packet.options[8]='\x04'; + memcpy(&discover_packet.options[9],&requested_address,sizeof(requested_address)); + } + + /* send the DHCPDISCOVER packet to broadcast address */ + sockaddr_broadcast.sin_family=AF_INET; + sockaddr_broadcast.sin_port=htons(DHCP_SERVER_PORT); + sockaddr_broadcast.sin_addr.s_addr=INADDR_BROADCAST; + bzero(&sockaddr_broadcast.sin_zero,sizeof(sockaddr_broadcast.sin_zero)); + + +#ifdef DEBUG + printf("DHCPDISCOVER to %s port %d\n",inet_ntoa(sockaddr_broadcast.sin_addr),ntohs(sockaddr_broadcast.sin_port)); + printf("DHCPDISCOVER XID: %lu (0x%X)\n",ntohl(discover_packet.xid),ntohl(discover_packet.xid)); + printf("DHCDISCOVER ciaddr: %s\n",inet_ntoa(discover_packet.ciaddr)); + printf("DHCDISCOVER yiaddr: %s\n",inet_ntoa(discover_packet.yiaddr)); + printf("DHCDISCOVER siaddr: %s\n",inet_ntoa(discover_packet.siaddr)); + printf("DHCDISCOVER giaddr: %s\n",inet_ntoa(discover_packet.giaddr)); +#endif + + /* send the DHCPDISCOVER packet out */ + send_dhcp_packet(&discover_packet,sizeof(discover_packet),sock,&sockaddr_broadcast); + +#ifdef DEBUG + printf("\n\n"); +#endif + + return OK; + } + + + + +/* waits for a DHCPOFFER message from one or more DHCP servers */ +int get_dhcp_offer(int sock){ + dhcp_packet offer_packet; + struct sockaddr_in source; + int result=OK; + int timeout=1; + int responses=0; + int x; + time_t start_time; + time_t current_time; + + time(&start_time); + + /* receive as many responses as we can */ + for(responses=0,valid_responses=0;;){ + + time(¤t_time); + if((current_time-start_time)>=dhcpoffer_timeout) + break; + +#ifdef DEBUG + printf("\n\n"); +#endif + + bzero(&source,sizeof(source)); + bzero(&offer_packet,sizeof(offer_packet)); + + result=OK; + result=receive_dhcp_packet(&offer_packet,sizeof(offer_packet),sock,dhcpoffer_timeout,&source); + + if(result!=OK){ +#ifdef DEBUG + printf("Result=ERROR\n"); +#endif + continue; + } + else{ +#ifdef DEBUG + printf("Result=OK\n"); +#endif + responses++; + } + +#ifdef DEBUG + printf("DHCPOFFER from IP address %s\n",inet_ntoa(source.sin_addr)); + printf("DHCPOFFER XID: %lu (0x%X)\n",ntohl(offer_packet.xid),ntohl(offer_packet.xid)); +#endif + + /* check packet xid to see if its the same as the one we used in the discover packet */ + if(ntohl(offer_packet.xid)!=packet_xid){ +#ifdef DEBUG + printf("DHCPOFFER XID (%lu) did not match DHCPDISCOVER XID (%lu) - ignoring packet\n",ntohl(offer_packet.xid),packet_xid); +#endif + continue; + } + + /* check hardware address */ + result=OK; +#ifdef DEBUG + printf("DHCPOFFER chaddr: "); +#endif + for(x=0;x<ETHERNET_HARDWARE_ADDRESS_LENGTH;x++){ +#ifdef DEBUG + printf("%02X",(unsigned char)offer_packet.chaddr[x]); +#endif + if(offer_packet.chaddr[x]!=client_hardware_address[x]){ + result=ERROR; + } + } +#ifdef DEBUG + printf("\n"); +#endif + if(result==ERROR){ +#ifdef DEBUG + printf("DHCPOFFER hardware address did not match our own - ignoring packet\n"); +#endif + continue; + } + +#ifdef DEBUG + printf("DHCPOFFER ciaddr: %s\n",inet_ntoa(offer_packet.ciaddr)); + printf("DHCPOFFER yiaddr: %s\n",inet_ntoa(offer_packet.yiaddr)); + printf("DHCPOFFER siaddr: %s\n",inet_ntoa(offer_packet.siaddr)); + printf("DHCPOFFER giaddr: %s\n",inet_ntoa(offer_packet.giaddr)); +#endif + + add_dhcp_offer(source.sin_addr,&offer_packet); + + valid_responses++; + } + +#ifdef DEBUG + printf("Total responses seen on the wire: %d\n",responses); + printf("Valid responses for this machine: %d\n",valid_responses); +#endif + + return OK; + } + + + +/* sends a DHCP packet */ +int send_dhcp_packet(void *buffer, int buffer_size, int sock, struct sockaddr_in *dest){ + struct sockaddr_in myname; + int result; + + result=sendto(sock,(char *)buffer,buffer_size,0,(struct sockaddr_in *)dest,sizeof(*dest)); + +#ifdef DEBUG + printf("send_dhcp_packet result: %d\n",result); +#endif + + if(result<0) + return ERROR; + + return OK; + } + + + +/* receives a DHCP packet */ +int receive_dhcp_packet(void *buffer, int buffer_size, int sock, int timeout, struct sockaddr_in *address){ + struct timeval tv; + fd_set readfds; + int recv_result; + socklen_t address_size; + struct sockaddr_in source_address; + + + /* wait for data to arrive (up time timeout) */ + tv.tv_sec=timeout; + tv.tv_usec=0; + FD_ZERO(&readfds); + FD_SET(sock,&readfds); + select(sock+1,&readfds,NULL,NULL,&tv); + + /* make sure some data has arrived */ + if(!FD_ISSET(sock,&readfds)){ +#ifdef DEBUG + printf("No (more) data recieved\n"); +#endif + return ERROR; + } + + else{ + + /* why do we need to peek first? i don't know, its a hack. without it, the source address of the first packet received was + not being interpreted correctly. sigh... */ + bzero(&source_address,sizeof(source_address)); + recv_result=recvfrom(sock,(char *)buffer,buffer_size,MSG_PEEK,(struct sockaddr_in *)&source_address,&address_size); +#ifdef DEBUG + printf("recv_result_1: %d\n",recv_result); +#endif + recv_result=recvfrom(sock,(char *)buffer,buffer_size,0,(struct sockaddr_in *)&source_address,&address_size); +#ifdef DEBUG + printf("recv_result_2: %d\n",recv_result); +#endif + + if(recv_result==-1){ +#ifdef DEBUG + printf("recvfrom() failed, "); + printf("errno: (%d) -> %s\n",errno,strerror(errno)); +#endif + return ERROR; + } + else{ +#ifdef DEBUG + printf("receive_dhcp_packet() result: %d\n",recv_result); + printf("receive_dhcp_packet() source: %s\n",inet_ntoa(source_address.sin_addr)); +#endif + + memcpy(address,&source_address,sizeof(source_address)); + return OK; + } + } + + return OK; + } + + + +/* creates a socket for DHCP communication */ +int create_dhcp_socket(void){ + struct sockaddr_in myname; + int sock; + int flag=1; + + /* Set up the address we're going to bind to. */ + bzero(&myname,sizeof(myname)); + myname.sin_family=AF_INET; + myname.sin_port=htons(DHCP_CLIENT_PORT); + myname.sin_addr.s_addr=INADDR_ANY; /* listen on any address */ + bzero(&myname.sin_zero,sizeof(myname.sin_zero)); + + /* create a socket for DHCP communications */ + sock=socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP); + if(sock<0){ + printf("Error: Could not create socket!\n"); + exit(STATE_UNKNOWN); + } + +#ifdef DEBUG + printf("DHCP socket: %d\n",sock); +#endif + + /* set the reuse address flag so we don't get errors when restarting */ + flag=1; + if(setsockopt(sock,SOL_SOCKET,SO_REUSEADDR,(char *)&flag,sizeof(flag))<0){ + printf("Error: Could not set reuse address option on DHCP socket!\n"); + exit(STATE_UNKNOWN); + } + + /* set the broadcast option - we need this to listen to DHCP broadcast messages */ + if(setsockopt(sock,SOL_SOCKET,SO_BROADCAST,(char *)&flag,sizeof flag)<0){ + printf("Error: Could not set broadcast option on DHCP socket!\n"); + exit(STATE_UNKNOWN); + } + + /* bind the socket */ + if(bind(sock,(struct sockaddr *)&myname,sizeof(myname))<0){ + printf("Error: Could not bind to DHCP socket (port %d)! Check your privileges...\n",DHCP_CLIENT_PORT); + exit(STATE_UNKNOWN); + } + + return sock; + } + + + + + +/* closes DHCP socket */ +int close_dhcp_socket(int sock){ + + close(sock); + + return OK; + } + + + + +/* adds a requested server address to list in memory */ +int add_requested_server(struct in_addr server_address){ + requested_server *new_server; + + new_server=(requested_server *)malloc(sizeof(requested_server)); + if(new_server==NULL) + return ERROR; + + new_server->server_address=server_address; + + new_server->next=requested_server_list; + requested_server_list=new_server; + + requested_servers++; + +#ifdef DEBUG + printf("Requested server address: %s\n",inet_ntoa(new_server->server_address)); +#endif + + return OK; + } + + + + +/* adds a DHCP OFFER to list in memory */ +int add_dhcp_offer(struct in_addr source,dhcp_packet *offer_packet){ + dhcp_offer *new_offer; + int x; + int y; + unsigned option_type; + unsigned option_length; + + if(offer_packet==NULL) + return ERROR; + + /* process all DHCP options present in the packet */ + for(x=4;x<MAX_DHCP_OPTIONS_LENGTH;){ + + /* end of options (0 is really just a pad, but bail out anyway) */ + if((int)offer_packet->options[x]==-1 || (int)offer_packet->options[x]==0) + break; + + /* get option type */ + option_type=offer_packet->options[x++]; + + /* get option length */ + option_length=offer_packet->options[x++]; + +#ifdef DEBUG + printf("Option: %d (0x%02X)\n",option_type,option_length); +#endif + + /* get option data */ + if(option_type==DHCP_OPTION_LEASE_TIME) + dhcp_lease_time=ntohl(*((u_int32_t *)&offer_packet->options[x])); + if(option_type==DHCP_OPTION_RENEWAL_TIME) + dhcp_renewal_time=ntohl(*((u_int32_t *)&offer_packet->options[x])); + if(option_type==DHCP_OPTION_REBINDING_TIME) + dhcp_rebinding_time=ntohl(*((u_int32_t *)&offer_packet->options[x])); + + /* skip option data we're ignoring */ + else + for(y=0;y<option_length;y++,x++); + } + +#ifdef DEBUG + if(dhcp_lease_time==DHCP_INFINITE_TIME) + printf("Lease Time: Infinite\n"); + else + printf("Lease Time: %lu seconds\n",(unsigned long)dhcp_lease_time); + if(dhcp_renewal_time==DHCP_INFINITE_TIME) + printf("Renewal Time: Infinite\n"); + else + printf("Renewal Time: %lu seconds\n",(unsigned long)dhcp_renewal_time); + if(dhcp_rebinding_time==DHCP_INFINITE_TIME) + printf("Rebinding Time: Infinite\n"); + printf("Rebinding Time: %lu seconds\n",(unsigned long)dhcp_rebinding_time); +#endif + + new_offer=(dhcp_offer *)malloc(sizeof(dhcp_offer)); + + if(new_offer==NULL) + return ERROR; + + + new_offer->server_address=source; + new_offer->offered_address=offer_packet->yiaddr; + new_offer->lease_time=dhcp_lease_time; + new_offer->renewal_time=dhcp_renewal_time; + new_offer->rebinding_time=dhcp_rebinding_time; + + +#ifdef DEBUG + printf("Added offer from server @ %s",inet_ntoa(new_offer->server_address)); + printf(" of IP address %s\n",inet_ntoa(new_offer->offered_address)); +#endif + + /* add new offer to head of list */ + new_offer->next=dhcp_offer_list; + dhcp_offer_list=new_offer; + + return OK; + } + + + + +/* frees memory allocated to DHCP OFFER list */ +int free_dhcp_offer_list(void){ + dhcp_offer *this_offer; + dhcp_offer *next_offer; + + for(this_offer=dhcp_offer_list;this_offer!=NULL;this_offer=next_offer){ + next_offer=this_offer->next; + free(this_offer); + } + + return OK; + } + + + + +/* frees memory allocated to requested server list */ +int free_requested_server_list(void){ + requested_server *this_server; + requested_server *next_server; + + for(this_server=requested_server_list;this_server!=NULL;this_server=next_server){ + next_server=this_server->next; + free(this_server); + } + + return OK; + } + + +/* gets state and plugin output to return */ +int get_results(void){ + dhcp_offer *temp_offer; + requested_server *temp_server; + int result; + u_int32_t max_lease_time=0; + + received_requested_address=FALSE; + + /* checks responses from requested servers */ + requested_responses=0; + if(requested_servers>0){ + + for(temp_server=requested_server_list;temp_server!=NULL;temp_server=temp_server->next){ + + for(temp_offer=dhcp_offer_list;temp_offer!=NULL;temp_offer=temp_offer->next){ + + /* get max lease time we were offered */ + if(temp_offer->lease_time>max_lease_time || temp_offer->lease_time==DHCP_INFINITE_TIME) + max_lease_time=temp_offer->lease_time; + + /* see if we got the address we requested */ + if(!memcmp(&requested_address,&temp_offer->offered_address,sizeof(requested_address))) + received_requested_address=TRUE; + + /* see if the servers we wanted a response from talked to us or not */ + if(!memcmp(&temp_offer->server_address,&temp_server->server_address,sizeof(temp_server->server_address))){ +#ifdef DEBUG + printf("DHCP Server Match: Offerer=%s",inet_ntoa(temp_offer->server_address)); + printf(" Requested=%s\n",inet_ntoa(temp_server->server_address)); +#endif + requested_responses++; + } + } + } + + } + + /* else check and see if we got our requested address from any server */ + else{ + + for(temp_offer=dhcp_offer_list;temp_offer!=NULL;temp_offer=temp_offer->next){ + + /* get max lease time we were offered */ + if(temp_offer->lease_time>max_lease_time || temp_offer->lease_time==DHCP_INFINITE_TIME) + max_lease_time=temp_offer->lease_time; + + /* see if we got the address we requested */ + if(!memcmp(&requested_address,&temp_offer->offered_address,sizeof(requested_address))) + received_requested_address=TRUE; + } + } + + result=STATE_OK; + if(valid_responses==0) + result=STATE_CRITICAL; + else if(requested_servers>0 && requested_responses==0) + result=STATE_CRITICAL; + else if(requested_responses<requested_servers) + result=STATE_WARNING; + else if(request_specific_address==TRUE && received_requested_address==FALSE) + result=STATE_WARNING; + + + printf("DHCP %s: ",(result==STATE_OK)?"ok":"problem"); + + /* we didn't receive any DHCPOFFERs */ + if(dhcp_offer_list==NULL){ + printf("No DHCPOFFERs were received.\n"); + return result; + } + + printf("Received %d DHCPOFFER(s)",valid_responses); + + if(requested_servers>0) + printf(", %s%d of %d requested servers responded",((requested_responses<requested_servers) && requested_responses>0)?"only ":"",requested_responses,requested_servers); + + if(request_specific_address==TRUE) + printf(", requested address (%s) was %soffered",inet_ntoa(requested_address),(received_requested_address==TRUE)?"":"not "); + + printf(", max lease time = "); + if(max_lease_time==DHCP_INFINITE_TIME) + printf("Infinity"); + else + printf("%lu sec",(unsigned long)max_lease_time); + + printf(".\n"); + + return result; + } + + + + + + +/* print usage help */ +void print_help(void){ + + /*print_revision(PROGNAME,"$Revision$");*/ + + printf("Copyright (c) 2001 Ethan Galstad (nagios@nagios.org)\n\n"); + printf("This plugin tests the availability of DHCP servers on a network.\n\n"); + + print_usage(); + + printf + ("\nOptions:\n" + " -s, --serverip=IPADDRESS\n" + " IP address of DHCP server that we must hear from\n" + " -r, --requestedip=IPADDRESS\n" + " IP address that should be offered by at least one DHCP server\n" + " -t, --timeout=INTEGER\n" + " Seconds to wait for DHCPOFFER before timeout occurs\n" + " -i, --interface=STRING\n" + " Interface to to use for listening (i.e. eth0)\n" + " -v, --verbose\n" + " Print extra information (command-line use only)\n" + " -h, --help\n" + " Print detailed help screen\n" + " -V, --version\n" + " Print version information\n\n" + ); + + /*support();*/ + + return; + } + + +/* prints usage information */ +void print_usage(void){ + + printf("Usage: %s [-s serverip] [-r requestedip] [-t timeout] [-i interface]\n",PROGNAME); + printf(" %s --help\n",PROGNAME); + printf(" %s --version\n",PROGNAME); + + return; + } + + + + +/* process command-line arguments */ +int process_arguments(int argc, char **argv){ + int c; + + if(argc<1) + return ERROR; + + c=0; + while((c+=(call_getopt(argc-c,&argv[c])))<argc){ + + /* + if(is_option(argv[c])) + continue; + */ + } + + return validate_arguments(); + } + + + +int call_getopt(int argc, char **argv){ + int c=0; + int i=0; + struct in_addr ipaddress; + +#ifdef HAVE_GETOPT_H + int option_index = 0; + static struct option long_options[] = + { + {"serverip", required_argument,0,'s'}, + {"requestedip", required_argument,0,'r'}, + {"timeout", required_argument,0,'t'}, + {"interface", required_argument,0,'i'}, + {"verbose", no_argument, 0,'v'}, + {"version", no_argument, 0,'V'}, + {"help", no_argument, 0,'h'}, + {0,0,0,0} + }; +#endif + + while(1){ +#ifdef HAVE_GETOPT_H + c=getopt_long(argc,argv,"+hVvt:s:r:t:i:",long_options,&option_index); +#else + c=getopt(argc,argv,"+?hVvt:s:r:t:i:"); +#endif + + i++; + + if(c==-1||c==EOF||c==1) + break; + + switch(c){ + case 'w': + case 'r': + case 't': + case 'i': + i++; + break; + default: + break; + } + + switch(c){ + + case 's': /* DHCP server address */ + if(inet_aton(optarg,&ipaddress)) + add_requested_server(ipaddress); + /* + else + usage("Invalid server IP address\n"); + */ + break; + + case 'r': /* address we are requested from DHCP servers */ + if(inet_aton(optarg,&ipaddress)){ + requested_address=ipaddress; + request_specific_address=TRUE; + } + /* + else + usage("Invalid requested IP address\n"); + */ + break; + + case 't': /* timeout */ + + /* + if(is_intnonneg(optarg)) + */ + if(atoi(optarg)>0) + dhcpoffer_timeout=atoi(optarg); + /* + else + usage("Time interval must be a nonnegative integer\n"); + */ + break; + + case 'i': /* interface name */ + + strncpy(network_interface_name,optarg,sizeof(network_interface_name)-1); + network_interface_name[sizeof(network_interface_name)-1]='\x0'; + + break; + + case 'V': /* version */ + + /*print_revision(PROGNAME,"$Revision$");*/ + exit(STATE_OK); + + case 'h': /* help */ + + print_help(); + exit(STATE_OK); + + case '?': /* help */ + + /*usage("Invalid argument\n");*/ + break; + + default: + break; + } + } + + return i; + } + + + +int validate_arguments(void){ + + return OK; + } + diff --git a/contrib/check_dlswcircuit.pl b/contrib/check_dlswcircuit.pl new file mode 100755 index 00000000..f6ef9311 --- /dev/null +++ b/contrib/check_dlswcircuit.pl @@ -0,0 +1,221 @@ +#!/usr/bin/perl -w +# +# check_dlswcircuit.pl - nagios plugin +# +# Checks if a Cisco Dlsw circuit is connected. +# +# +# Copyright (C) 2000 Carsten Foss & Christoph Kron +# +# Basically this is an adapted version of Christoph Kron's (ck@zet.net) check_ifoperstatus.pl plugin. +# most of the thanks should go to him. +# +# 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. +# +# Arguments : -s <SourceMac> -d <DestMac> -c <READCOMMUNITY> -p <PORT> <HOSTNAME or IP-Addr> +# - +# Source & Dest Mac/Sap arguments must be given in Hex as this example : 40.00.01.37.45.01.ss (Where ss is the sap) +# +# Sample command line : check_dlswcircuit.pl -s 40.00.01.37.45.01.04 -d 40.00.02.37.45.02.04 -c secret 1.2.3.4 +# +# Sample host.cfg entry : +#service[Dlsw-xx]=NCP1-NCP2;0;24x7;3;5;1;router-admins;240;24x7;1;1;0;;check_dlswcircuit!-s 40.00.01.37.45.01.04!-d 40.00..01.37.45.02.04!-c secret!1.2.3.4 +# remember to add the service to commands.cfg , something like this: +# command[check_dlswcircuit]=$USER1$/check_dlswcircuit.pl $ARG1$ $ARG2$ $ARG3$ $ARG4$ $ARG5$ +# +# Report bugs to: cfo@dmdata.dk +# +# 11.03.2000 Version 1.0 + +use strict; + +use Net::SNMP; +use Getopt::Long; +&Getopt::Long::config('auto_abbrev'); + + +my $status; +my $TIMEOUT = 15; + +my %ERRORS = ('UNKNOWN' , '-1', + 'OK' , '0', + 'WARNING', '1', + 'CRITICAL', '2'); + +my %dlswCircuitStatus = ( + '1','disconnected', + '2','circuitStart', + '3','resolvePending', + '4','circuitPending', + '5','circuitEstablished', + '6','connectPending', + '7','contactPending', + '8','connected', + '9','disconnectPending', + '10','haltPending', + '11','haltPendingNoack', + '13','circuitRestart', + '14','restartPending'); + +my $state = "UNKNOWN"; +my $answer = ""; +my $smac = ""; +my $dmac = ""; +my $community = "public"; +my $port = 161; +#Dlsw Circuit Oid enterprises.9.10.9.1.5.2.1.17.6.0.96.148.47.230.166.4.6.64.0.1.55.69.2.4 = 8 +my $enterpriseOid = "1.3.6.1.4.1"; +my $ciscoDlswCircuitOid = ".9.10.9.1.5.2.1.17."; +my $unknownOid = "6."; +my $smacOid = ""; +my $dmacOid = ""; +my $tmpOid = ""; +my @tmparg; +my $snmpoid; +my @snmpoids; +my $hostname; +my $session; +my $error; +my $response; +my $p = ""; +my $q = ""; + +sub usage { + printf "\nMissing arguments!\n"; + printf "\n"; + printf "Perl Check Cisco Dlsw Circuit State plugin for Nagios\n"; + printf "checks operational status of specified DLSW Circuit\n"; + printf "usage: \n"; + printf "check_dlswcircuit.pl -s <SourceMac> -d <DestMac> -c <READCOMMUNITY> -p <PORT> <HOSTNAME>"; + printf "\nCopyright (C) 2000 Carsten Foss\n"; + printf "check_dlswcircuit.pl comes with ABSOLUTELY NO WARRANTY\n"; + printf "This programm is licensed under the terms of the "; + printf "GNU General Public License\n(check source code for details)\n"; + printf "\n\n"; + exit $ERRORS{"UNKNOWN"}; +} + +# Just in case of problems, let's not hang Nagios +$SIG{'ALRM'} = sub { + print ("ERROR: No snmp response from $hostname (alarm)\n"); + exit $ERRORS{"UNKNOWN"}; +}; +alarm($TIMEOUT); + + +$status = GetOptions("sourcemac=s",\$smac,"destmac=s",\$dmac, + "community=s",\$community, + "port=i",\$port); +if ($status == 0) +{ + &usage; +} + +# +#Convert Source Mac & Sap +# + @tmparg = split(/\./,$smac); + #print "-$smac-\n"; + #print "@tmparg\n"; + #print "$#tmparg\n"; + if($#tmparg != 6) + { + print "SourceMac/Sap format $smac not valid\n"; + &usage; + } + while($p = shift @tmparg) + { + $q = hex($p); + $smacOid = $smacOid.$q; + $smacOid = $smacOid.'.'; + } + + #print "@tmparg1\n"; + #print "$smacOid\n"; + +# +#Convert Dest Mac & Sap +# + @tmparg = split(/\./,$dmac); + #print "-$dmac-\n"; + #print "@tmparg\n"; + #print "$#tmparg\n"; + if($#tmparg != 6) + { + print "DestMac/Sap format $dmac not valid\n"; + &usage; + } + + while($p = shift @tmparg) + { + $q = hex($p); + $dmacOid = $dmacOid.$q; + $dmacOid = $dmacOid.'.'; + } +# Remove Trailing Dot + $dmacOid = substr($dmacOid,0,length($dmacOid)-1); + + + #print "@tmparg1\n"; + #print "$dmacOid\n"; +#Build the Dlsw Oic to use + $snmpoid = $enterpriseOid.$ciscoDlswCircuitOid.$unknownOid.$smacOid.$unknownOid.$dmacOid ; + #print "$snmpoid\n"; + + #shift; + $hostname = shift || &usage; + + ($session, $error) = Net::SNMP->session( + -hostname => $hostname, + -community => $community, + -port => $port + ); + + if (!defined($session)) { + $state='UNKNOWN'; + $answer=$error; + print ("$state: $answer"); + exit $ERRORS{$state}; + } + + push(@snmpoids,$snmpoid); + #push(@snmpoids,$snmpLocIfDescr); + + if (!defined($response = $session->get_request(@snmpoids))) { + $answer=$session->error; + $session->close; + $state = 'CRITICAL'; + print ("$state: $answer,$community,$smac - $dmac"); + exit $ERRORS{$state}; + } + + $answer = sprintf("dlsw circuit %s - %s at host '%s',is %s\n", + $smac, + $dmac, + $hostname, + $dlswCircuitStatus{$response->{$snmpoid}} + ); + + $session->close; + + if ( $response->{$snmpoid} == 8 ) { + $state = 'OK'; + } + else { + $state = 'CRITICAL'; + } + +print ("$state: $answer"); +exit $ERRORS{$state}; diff --git a/contrib/check_dns_random.pl b/contrib/check_dns_random.pl new file mode 100644 index 00000000..787d4644 --- /dev/null +++ b/contrib/check_dns_random.pl @@ -0,0 +1,75 @@ +#!/usr/bin/perl +# ------------------------------------------------------------------------------ +# File Name: check_dns_random.pl +# Author: Richard Mayhew - South Africa +# Date: 2000/01/26 +# Version: 1.0 +# Description: This script will check to see if dns resolves hosts +# randomly from a list using the check_dns plugin. +# Email: netsaint@splash.co.za +# ------------------------------------------------------------------------------ +# Copyright 1999 (c) Richard Mayhew +# Credits go to Ethan Galstad for coding Nagios +# If any changes are made to this script, please mail me a copy of the +# changes :) +# License GPL +# ------------------------------------------------------------------------------ +# Date Author Reason +# ---- ------ ------ +# 1999/09/26 RM Creation +# ------------------------------------------------------------------------------ + +# -----------------------------------------------------------------[ Require ]-- +require 5.004; + +# --------------------------------------------------------------------[ Uses ]-- +use Socket; +use strict; + +# --------------------------------------------------------------[ Enviroment ]-- +$ENV{PATH} = "/bin"; +$ENV{BASH_ENV} = ""; +$|=1; + +my $host = shift || &usage; + +my $domainfile = "/usr/local/nagios/etc/domains.list"; +my $wc = `/usr/bin/wc -l $domainfile`; +my $check = "/usr/local/nagios/libexec/check_dns"; +my $x = 0; +my $srv_file = ""; +my $z = ""; +my $y = ""; + +open(DOMAIN,"<$domainfile") or die "Error Opening $domainfile File!\n"; + while (<DOMAIN>) { + $srv_file .= $_; +} + close(DOMAIN); + my @data = split(/\n/,$srv_file); + +chomp $wc; +$wc =~ s/ //g; +$wc =~ s/domains//g; + +$x = rand $wc; +($z,$y) = split(/\./,$x); + +print `$check $data[$z] $host`; + + + +sub usage +{ + print "Minimum arguments not supplied!\n"; + print "\n"; + print "Perl Check Random DNS plugin for Nagios\n"; + print "Copyright (c) 2000 Richard Mayhew\n"; + print "\n"; + print "Usage: check_dns_random.pl <host>\n"; + print "\n"; + print "<host> = DNS server you would like to query.\n"; + exit -1; + +} + diff --git a/contrib/check_email_loop.pl b/contrib/check_email_loop.pl new file mode 100644 index 00000000..733406da --- /dev/null +++ b/contrib/check_email_loop.pl @@ -0,0 +1,268 @@ +#!/usr/bin/perl +# +# (c)2000 Benjamin Schmid, blueshift@gmx.net (emergency use only ;-) +# Copyleft by GNU GPL +# +# +# check_email_loop Nagios Plugin +# +# This script sends a mail with a specific id in the subject via +# an given smtp-server to a given email-adress. When the script +# is run again, it checks for this Email (with its unique id) on +# a given pop3 account and send another mail. +# +# +# Example: check_email_loop.pl -poph=mypop -popu=user -pa=password +# -smtph=mailer -from=returnadress@yoursite.com +# -to=remaileradress@friend.com -pendc=2 -lostc=0 +# +# This example will send eacht time this check is executed a new +# mail to remaileradress@friend.com using the SMTP-Host mailer. +# Then it looks for any back-forwarded mails in the POP3 host +# mypop. In this Configuration CRITICAL state will be reached if +# more than 2 Mails are pending (meaning that they did not came +# back till now) or if a mails got lost (meaning a mail, that was +# send later came back prior to another mail). +# + +use Net::POP3; +use Net::SMTP; +use strict; +use Getopt::Long; +&Getopt::Long::config('auto_abbrev'); + +# ---------------------------------------- + +my $TIMEOUT = 120; +my %ERRORS = ('UNKNOWN' , '-1', + 'OK' , '0', + 'WARNING', '1', + 'CRITICAL', '2'); + +my $state = "UNKNOWN"; +my ($sender,$receiver, $pophost, $popuser, $poppasswd, $smtphost); +my ($poptimeout,$smtptimeout,$pinginterval)=(60,60,5); +my ($lostwarn, $lostcrit,$pendwarn, $pendcrit); + +# Internal Vars +my ($pop,$msgcount,@msglines,$statinfo,@messageids,$newestid); +my ($matchcount,$statfile) = (0,"check_email_loop.stat"); + +# Subs declaration +sub usage; +sub messagematchs; +sub nsexit; + +# Just in case of problems, let's not hang Nagios +$SIG{'ALRM'} = sub { + print ("ERROR: $0 Time-Out $TIMEOUT s \n"); + exit $ERRORS{"UNKNOWN"}; +}; +alarm($TIMEOUT); + + +# Evaluate Command Line Parameters +my $status = GetOptions( + "from=s",\$sender, + "to=s",\$receiver, + "pophost=s",\$pophost, + "popuser=s",\$popuser, + "passwd=s",\$poppasswd, + "poptimeout=i",\$poptimeout, + "smtphost=s",\$smtphost, + "smtptimeout=i",\$smtptimeout, + "statfile=s",\$statfile, + "interval=i",\$pinginterval, + "lostwarr=i",\$lostwarn, + "lostcrit=i",\$lostcrit, + "pendwarn=i",\$pendwarn, + "pendcrit=i",\$pendcrit, + ); +usage() if ($status == 0 || ! ($pophost && $popuser && $poppasswd && + $smtphost && $receiver && $sender )); + +# Try to read the ids of the last send emails out of statfile +if (open STATF, "$statfile") { + @messageids = <STATF>; + chomp @messageids; + close STATF; +} + +# Try to open statfile for writing +if (!open STATF, ">$statfile") { + nsexit("Failed to open mail-ID database $statfile for writing",'CRITICAL'); +} + +# Ok - check if it's time to release another mail + +# ... + +# creating new serial id +my $serial = time(); +$serial = "ID#" . $serial . "#$$"; + +# sending new ping email +my $smtp = Net::SMTP->new($smtphost,Timeout=>$smtptimeout) + || nsexit("SMTP connect timeout ($smtptimeout s)",'CRITICAL'); +($smtp->mail($sender) && + $smtp->to($receiver) && + $smtp->data() && + $smtp->datasend("To: $receiver\nSubject: E-Mail Ping [$serial]\n\n". + "This is a automatically sended E-Mail.\n". + "It ist not intended for human reader.\n\n". + "Serial No: $serial\n") && + $smtp->dataend() && + $smtp->quit + ) || nsexit("Error delivering message",'CRITICAL'); + +# no the interessting part: let's if they are receiving ;-) + +$pop = Net::POP3->new( $pophost, + Timeout=>$poptimeout) + || nsexit("POP3 connect timeout (>$poptimeout s, host: $pophost)",'CRITICAL'); + +$msgcount=$pop->login($popuser,$poppasswd); + +$statinfo="$msgcount mails on POP3"; + +nsexit("POP3 login failed (user:$popuser)",'CRITICAL') if (!defined($msgcount)); + +# Count messages, that we are looking 4: +while ($msgcount > 0) { + @msglines = @{$pop->get($msgcount)}; + + for (my $i=0; $i < scalar @messageids; $i++) { + if (messagematchsid(\@msglines,$messageids[$i])) { + $matchcount++; + # newest received mail than the others, ok remeber id. + $newestid = $messageids[$i] if ($messageids[$i] > $newestid || !defined $newestid); + $pop->delete($msgcount); # remove E-Mail from POP3 server + splice @messageids, $i, 1;# remove id from List + last; # stop looking in list + } + } + + $msgcount--; +} + +$pop->quit(); # necessary for pop3 deletion! + +# traverse through the message list and mark the lost mails +# that mean mails that are older than the last received mail. +if (defined $newestid) { + $newestid =~ /\#(\d+)\#/; + $newestid = $1; + for (my $i=0; $i < scalar @messageids; $i++) { + $messageids[$i] =~ /\#(\d+)\#/; + my $akid = $1; + if ($akid < $newestid) { + $messageids[$i] =~ s/^ID/LI/; # mark lost + } + } +} + +# Write list to id-Database +foreach my $id (@messageids) { + print STATF "$id\n"; +} +print STATF "$serial\n"; # remember send mail of this session +close STATF; + +# ok - count lost and pending mails; +my @tmp = grep /^ID/, @messageids; +my $pendingm = scalar @tmp; +@tmp = grep /^LI/, @messageids; +my $lostm = scalar @tmp; + +# Evaluate the Warnin/Crit-Levels +if (defined $pendwarn && $pendingm > $pendwarn) { $state = 'WARNING'; } +if (defined $lostwarn && $lostm > $lostwarn) { $state = 'WARNING'; } +if (defined $pendcrit && $pendingm > $pendcrit) { $state = 'CRITICAL'; } +if (defined $lostcrit && $lostm > $lostcrit) { $state = 'CRITICAL'; } + +if ((defined $pendwarn || defined $pendcrit || defined $lostwarn + || defined $lostcrit) && ($state eq 'UNKNOWN')) {$state='OK';} + + +# Append Status info +$statinfo = $statinfo . ", $matchcount mail(s) came back,". + " $pendingm pending, $lostm lost."; + +# Exit in a Nagios-compliant way +nsexit($statinfo); + +# ---------------------------------------------------------------------- + +sub usage { + print "check_email_loop 1.0 Nagios Plugin - Real check of a E-Mail system\n"; + print "=" x 75,"\nERROR: Missing or wrong arguments!\n","=" x 75,"\n"; + print "This script sends a mail with a specific id in the subject via an given\n"; + print "smtp-server to a given email-adress. When the script is run again, it checks\n"; + print "for this Email (with its unique id) on a given pop3 account and sends \n"; + print "another mail.\n"; + print "\nThe following options are available:\n"; + print " -from=text email adress of send (for mail returnr on errors)\n"; + print " -to=text email adress to which the mails should send to\n"; + print " -pophost=text IP or name of the POP3-host to be checked\n"; + print " -popuser=text Username of the POP3-account\n"; + print " -passwd=text Password for the POP3-user\n"; + print " -poptimeout=num Timeout in seconds for the POP3-server\n"; + print " -smtphost=text IP oder name of the SMTP host\n"; + print " -smtptimeout=num Timeout in seconds for the SMTP-server\n"; + print " -statfile=text File to save ids of messages ($statfile)\n"; +# print " -interval=num Time (in minutes) that must pass by before sending\n" +# print " another Ping-mail (gibe a new try);\n"; + print " -lostwarn=num WARNING-state if more than num lost emails\n"; + print " -lostcrit=num CRITICAL \n"; + print " -pendwarn=num WARNING-state if more than num pending emails\n"; + print " -pendcrit=num CRITICAL \n"; + print " Options may abbreviated!\n"; + print " LOST mails are mails, being sent before the last mail arrived back.\n"; + print " PENDING mails are those, which are not. (supposed to be on the way)\n"; + print "\nExample: \n"; + print " $0 -poph=host -pa=pw -popu=popts -smtph=host -from=root\@me.com\n "; + print " -to=remailer\@testxy.com -lostc=0 -pendc=2\n"; + print "\nCopyleft 19.10.2000, Benjamin Schmid\n"; + print "This script comes with ABSOLUTELY NO WARRANTY\n"; + print "This programm is licensed under the terms of the "; + print "GNU General Public License\n\n"; + exit $ERRORS{"UNKNOWN"}; +} + +# --------------------------------------------------------------------- + +sub nsexit { + my ($msg,$code) = @_; + $code=$state if (!defined $code); + print "$code: $msg\n" if (defined $msg); + exit $ERRORS{$code}; +} + +# --------------------------------------------------------------------- + +sub messagematchsid { + my ($mailref,$id) = (@_); + my (@tmp); + my $match = 0; + + # ID + $id =~ s/^LI/ID/; # evtl. remove lost mail mark + @tmp = grep /Subject: E-Mail Ping \[/, @$mailref; + chomp @tmp; + if (($tmp[0] =~ /$id/)) + { $match = 1; } + + # Sender: +# @tmp = grep /^From:\s+/, @$mailref; +# if (@tmp && $sender ne "") +# { $match = $match && ($tmp[0]=~/$sender/); } + + # Receiver: +# @tmp = grep /^To: /, @$mailref; +# if (@tmp && $receiver ne "") +# { $match = $match && ($tmp[0]=~/$receiver/); } + + return $match; +} + +# --------------------------------------------------------------------- diff --git a/contrib/check_fping_in.c b/contrib/check_fping_in.c new file mode 100644 index 00000000..50fd5eea --- /dev/null +++ b/contrib/check_fping_in.c @@ -0,0 +1,430 @@ +/****************************************************************************** +* +* CHECK_INET_FPING.C +* +* Program: Fping plugin for Nagios +* License: GPL +* Copyright (c) 1999 Didi Rieder (adrieder@sbox.tu-graz.ac.at) +* $Id$ +* +* Modifications: +* +* 08-24-1999 Didi Rieder (adrieder@sbox.tu-graz.ac.at) +* Intial Coding +* 09-11-1999 Karl DeBisschop (kdebiss@alum.mit.edu) +* Change to spopen +* Fix so that state unknown is returned by default +* (formerly would give state ok if no fping specified) +* Add server_name to output +* Reformat to 80-character standard screen +* 11-18-1999 Karl DeBisschop (kdebiss@alum.mit.edu) +* set STATE_WARNING of stderr written or nonzero status returned +* 09-29-2000 Matthew Grant (matthewg@plain.co.nz) +* changes for monitoring multiple hosts for checking Internet +* reachibility +* +* Description: +* +* This plugin will use the /bin/fping command (from nagios) to ping +* the specified host for a fast check if the host is alive. Note that +* it is necessary to set the suid flag on fping. +******************************************************************************/ + +#include "config.h" +#include "common.h" +#include "popen.h" +#include "utils.h" + +#define PROGNAME "check_fping" +#define PACKET_COUNT 15 +#define PACKET_SIZE 56 +#define CRITICAL_COUNT 2 +#define WARNING_COUNT 1 +#define UNKNOWN_PACKET_LOSS 200 /* 200% */ +#define UNKNOWN_TRIP_TIME -1.0 /* -1 seconds */ + +#define STRSZ 100 + +int textscan(char *buf); +int process_arguments(int, char **); +int get_threshold (char *arg, char *rv[2]); +void print_usage(void); +void print_help(void); + +char *server_names=NULL; +char *name="INTERNET"; +int cthresh=CRITICAL_COUNT; +int wthresh=WARNING_COUNT; +int nnames=0; +int tpl=UNKNOWN_PACKET_LOSS; +double trta=UNKNOWN_TRIP_TIME; +int packet_size=PACKET_SIZE; +int packet_count=PACKET_COUNT; +int verbose=FALSE; +int fail = 0; +int not_found = 0; +int rta_fail = 0; +int pl_fail = 0; +int unreachable = 0; + +int main(int argc, char **argv){ + int result; + int status=STATE_UNKNOWN; + char *servers=NULL; + char *command_line=NULL; + char *input_buffer=NULL; + char *pl_buffer=NULL; + char *rta_buffer=NULL; + input_buffer=malloc(MAX_INPUT_BUFFER); + rta_buffer = malloc(80); + pl_buffer = malloc(80); + memset(rta_buffer, 0, 80); + memset(pl_buffer, 0, 80); + + if(process_arguments(argc,argv)==ERROR) + usage("Could not parse arguments\n"); + + servers=strscpy(servers,server_names); + + /* compose the command */ + command_line=ssprintf + (command_line,"%s -b %d -c %d %s", + PATH_TO_FPING, + packet_size, + packet_count, + servers); + + if (verbose) printf("%s\n",command_line); + + /* run the command */ + child_process=spopen(command_line); + if(child_process==NULL){ + printf("Unable to open pipe: %s\n",command_line); + return STATE_UNKNOWN; + } + + child_stderr=fdopen(child_stderr_array[fileno(child_process)],"r"); + if(child_stderr==NULL){ + printf("Could not open stderr for %s\n",command_line); + } + + while (fgets(input_buffer,MAX_INPUT_BUFFER-1,child_process)) { + if (verbose) printf("%s",input_buffer); + result = textscan(input_buffer); + status = max(status,result); + } + + while(fgets(input_buffer,MAX_INPUT_BUFFER-1,child_stderr)) { + if (verbose) printf("%s",input_buffer); + result = textscan(input_buffer); + status = max(status,result); + } + + (void)fclose(child_stderr); + + /* close the pipe */ + if(spclose(child_process)) + status=max(status,STATE_WARNING); + + /* Analyse fail count and produce results */ + if (fail >= wthresh) { + status = max(status, STATE_WARNING); + } + + if (fail >= cthresh) { + status = max(status, STATE_CRITICAL); + } + + if( tpl != UNKNOWN_PACKET_LOSS ) { + snprintf(pl_buffer, 80, ", %d PL", pl_fail); + } + + if( trta != UNKNOWN_TRIP_TIME ) { + snprintf(rta_buffer, 80, ", %d RTA", rta_fail); + + } + + printf("FPING %s - %s, %d of %d fail, %d NF, %d UR%s%s\n", + state_text(status), + (name != NULL ? name : server_names), + fail, + nnames, + not_found, + unreachable, + pl_buffer, + rta_buffer); + + return status; +} + + + +/* analyse fping output - each event resulting in an increment of fail + * must be mutually exclusive. packet loss and round trip time analysed + * together, both at once just results in one increment of fail + */ +int textscan(char *buf) +{ + char *rtastr=NULL; + char *losstr=NULL; + double loss; + double rta; + int status=STATE_OK; + + if (strstr(buf,"not found")) { + fail++; + not_found++; + } else if(strstr(buf,"xmt/rcv/%loss") + && strstr(buf,"min/avg/max")) { + losstr = strstr(buf,"="); + losstr = 1+strstr(losstr,"/"); + losstr = 1+strstr(losstr,"/"); + rtastr = strstr(buf,"min/avg/max"); + rtastr = strstr(rtastr,"="); + rtastr = 1+index(rtastr,'/'); + loss = strtod(losstr,NULL); + rta = strtod(rtastr,NULL); + /* Increment fail counter + */ + if (tpl!=UNKNOWN_PACKET_LOSS && loss>tpl) { + fail++; + } + else if (trta!=UNKNOWN_TRIP_TIME && rta>trta) { + fail++; + } + else if (loss >= 100) { + fail++; + } + /* Increment other counters + */ + if (trta!=UNKNOWN_TRIP_TIME && rta>trta) + rta_fail++; + if (tpl!=UNKNOWN_PACKET_LOSS && loss>tpl) + pl_fail++; + if (loss >= 100) + unreachable++; + } else if(strstr(buf,"xmt/rcv/%loss") ) { + losstr = strstr(buf,"="); + losstr = 1+strstr(losstr,"/"); + losstr = 1+strstr(losstr,"/"); + loss = strtod(losstr,NULL); + /* Increment fail counter + */ + if (tpl!=UNKNOWN_PACKET_LOSS && loss>tpl) { + fail++; + } + else if (loss >= 100) { + fail++; + } + /* Increment other counters + */ + if (tpl!=UNKNOWN_PACKET_LOSS && loss>tpl) + pl_fail++; + if (loss >= 100) + unreachable++; + } + + return status; +} + + + + +/* process command-line arguments */ +int process_arguments(int argc, char **argv) +{ + int c; + +#ifdef HAVE_GETOPT_H + int option_index = 0; + static struct option long_options[] = + { + {"hostname" ,required_argument,0,'H'}, + {"critical" ,required_argument,0,'c'}, + {"warning" ,required_argument,0,'w'}, + {"bytes" ,required_argument,0,'b'}, + {"number" ,required_argument,0,'n'}, + {"pl-threshold" ,required_argument,0,'p'}, + {"rta-threshold" ,required_argument,0,'r'}, + {"name" ,required_argument,0,'N'}, + {"verbose" ,no_argument, 0,'v'}, + {"version" ,no_argument, 0,'V'}, + {"help" ,no_argument, 0,'h'}, + {0,0,0,0} + }; +#else + + if(argc<2) return ERROR; + + if (!is_option(argv[1])){ + server_names=argv[1]; + argv[1]=argv[0]; + argv=&argv[1]; + argc--; + } +#endif + + while (1){ +#ifdef HAVE_GETOPT_H + c = getopt_long(argc,argv,"+hVvH:c:w:b:n:N:p:r:",long_options,&option_index); +#else + c = getopt(argc,argv,"+hVvH:c:w:b:n:N:p:r:"); +#endif + + if (c==-1||c==EOF||c==1) + break; + + switch (c) + { + case '?': /* print short usage statement if args not parsable */ + printf("%s: Unknown argument: %s\n\n",my_basename(argv[0]),optarg); + print_usage(); + exit(STATE_UNKNOWN); + case 'h': /* help */ + print_help(); + exit(STATE_OK); + case 'V': /* version */ + print_revision(my_basename(argv[0]),"$Revision$"); + exit(STATE_OK); + case 'v': /* verbose mode */ + verbose=TRUE; + break; + case 'H': /* hostname */ + if(is_host(optarg)==FALSE){ + printf("Invalid host name/address\n\n"); + print_usage(); + exit(STATE_UNKNOWN); + } + if (server_names != NULL) + server_names=strscat(server_names," "); + server_names=strscat(server_names,optarg); + nnames++; + break; + case 'c': + if (is_intpos(optarg)) + cthresh = atoi(optarg); + else + usage("Critical threshold must be a positive integer"); + break; + case 'w': + if (is_intpos(optarg)) + wthresh = atoi(optarg); + else + usage("Warning threshold must be a postive integer"); + break; + case 'r': + if (is_intpos(optarg)) { + trta=strtod(optarg,NULL); + } + else { + usage("RTA threshold must be a positive integer"); + } + break; + case 'p': + if (is_intpos(optarg)) { + tpl=strtod(optarg,NULL); + } + else { + usage("RTA threshold must be a positive integer"); + } + break; + case 'b': /* bytes per packet */ + if (is_intpos(optarg)) + packet_size=atoi(optarg); + else + usage("Packet size must be a positive integer"); + break; + case 'N': /* Name of service */ + name = optarg; + break; + case 'n': /* number of packets */ + if (is_intpos(optarg)) + packet_count=atoi(optarg); + else + usage("Packet count must be a positive integer"); + break; + } + } + + while (optind < argc) { + if(is_host(argv[optind])==FALSE) { + printf("Invalid host name/address\n\n"); + print_usage(); + exit(STATE_UNKNOWN); + } + if (server_names != NULL) + server_names=strscat(server_names," "); + server_names=strscat(server_names,argv[optind]); + nnames++; + optind++; + } + + if (server_names==NULL || nnames < 2) + usage("At least 2 hostnames must be supplied\n\n"); + + if (cthresh < 2) + usage("Critical threshold must be at least 2"); + if (cthresh > nnames) + usage("Critical threshold cannot be greater than number of hosts tested"); + if (wthresh < 1) + usage("Warning threshold must be at least 1"); + if (wthresh > nnames) + usage("Warning threshold cannot be greater than number of hosts tested"); + if(wthresh >= cthresh) + usage("Warning threshold must be less than the critical threshold"); + + return OK; +} + + +void print_usage(void) +{ + printf("Usage: %s <host_address> <host_address> [<host_address>] ...\n",PROGNAME); +} + + + + + +void print_help(void) +{ + + print_revision(PROGNAME,"$Revision$"); + + printf + ("Copyright (c) 1999 Didi Rieder (adrieder@sbox.tu-graz.ac.at)\n" + " (c) 2000 Matthew Grant (matthewg@plain.co.nz)\n" + "This plugin will use the /bin/fping command (from saint) to ping the\n" + "specified hosts for a fast check to see if the Internet is still \n" + "reachable, and the results of the testing aggregated. Note that it\n" + "is necessary to set the suid flag on fping.\n\n"); + + print_usage(); + + printf + ("\nOptions:\n" + "-b, --bytes=INTEGER\n" + " Size of ICMP packet (default: %d)\n" + "-c, --critical=INTEGER (default: %d)\n" + " critical threshold failure count\n" + "-n, --number=INTEGER\n" + " Number of ICMP packets to send (default: %d)\n" + "-H, --hostname=HOST\n" + " Name or IP Address of host to ping (IP Address bypasses name lookup,\n" + " reducing system load)\n" + "-h, --help\n" + " Print this help screen\n" + "-N, --name\n" + " Service name to print in results, defaults to INTERNET\n" + "-p, --pl-threshold\n" + " Packet loss threshold - specify to turn on packet loss testing\n" + "-r, --rta-threshold\n" + " Round trip average threshold - specify to turn on RTA testing\n" + "-V, --version\n" + " Print version information\n" + "-v, --verbose\n" + " Show details for command-line debugging (do not use with nagios server)\n" + "-w, --warning=INTEGER (default: %d)\n" + " warning threshold failure count\n", + PACKET_SIZE, CRITICAL_COUNT, PACKET_COUNT, WARNING_COUNT); +} diff --git a/contrib/check_ftpget.pl b/contrib/check_ftpget.pl new file mode 100755 index 00000000..de7e8242 --- /dev/null +++ b/contrib/check_ftpget.pl @@ -0,0 +1,48 @@ +#!/usr/bin/perl -w +## Written 12/5/00 Jeremy Hanmer +# $Id$ + +use strict; +use Net::FTP; +use Getopt::Std; + +use vars qw($opt_H $opt_u $opt_p $opt_f); +getopts("H:u:p:f:"); + +my $host = $opt_H || + die "usage: check_ftp.pl -h host [<-u user> <-p pass> <-f file>]\n"; + +my $username = $opt_u || 'anonymous'; +my $pass = $opt_p || "$ENV{'LOGNAME'}\@$ENV{'HOSTNAME'}" ; + +my $file = $opt_f; + +my $status = 0; +my $problem; +my $output = "ftp ok"; + +my $ftp = Net::FTP->new("$host") || + &crit("connect"); + +$ftp->login("$username", "$pass") || + &crit("login"); + +$ftp->get($file) || + &crit("get") if $file; + +sub crit() +{ + $problem = $_[0]; + $status = 2; + if ( $problem eq 'connect' ) { + $output = "can't connect"; + } elsif ( $problem eq 'login' ) { + $output = "can't log in"; + } elsif ( $problem eq 'get' ) { + $output = "cant get $file"; + } +} + +print "$output\n"; +exit $status; + diff --git a/contrib/check_ifoperstatus.pl b/contrib/check_ifoperstatus.pl new file mode 100644 index 00000000..3f21cddd --- /dev/null +++ b/contrib/check_ifoperstatus.pl @@ -0,0 +1,145 @@ +#!/usr/bin/perl -w +# +# check_ifoperstatus.pl - nagios plugin +# +# +# +# +# Copyright (C) 2000 Christoph Kron +# +# 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. +# +# +# Report bugs to: ck@zet.net +# +# 11.01.2000 Version 1.0 + +use strict; + +use Net::SNMP; +use Getopt::Long; +&Getopt::Long::config('auto_abbrev'); + + +my $status; +my $TIMEOUT = 15; + +my %ERRORS = ('UNKNOWN' , '-1', + 'OK' , '0', + 'WARNING', '1', + 'CRITICAL', '2'); + +my %ifOperStatus = ('1','up', + '2','down', + '3','testing', + '4','unknown', + '5','dormant', + '6','notPresent'); + +my $state = "UNKNOWN"; +my $answer = ""; +my $snmpkey = 1; +my $community = "public"; +my $port = 161; +my @snmpoids; +my $snmpIfOperStatus; +my $snmpLocIfDescr; +my $hostname; +my $session; +my $error; +my $response; + + +sub usage { + printf "\nMissing arguments!\n"; + printf "\n"; + printf "Perl Check IfOperStatus plugin for Nagios\n"; + printf "checks operational status of specified interface\n"; + printf "usage: \n"; + printf "ifoperstatus.pl -k <IF_KEY> -c <READCOMMUNITY> -p <PORT> <HOSTNAME>"; + printf "\nCopyright (C) 2000 Christoph Kron\n"; + printf "check_ifoperstatus.pl comes with ABSOLUTELY NO WARRANTY\n"; + printf "This programm is licensed under the terms of the "; + printf "GNU General Public License\n(check source code for details)\n"; + printf "\n\n"; + exit $ERRORS{"UNKNOWN"}; +} + +# Just in case of problems, let's not hang Nagios +$SIG{'ALRM'} = sub { + print ("ERROR: No snmp response from $hostname (alarm)\n"); + exit $ERRORS{"UNKNOWN"}; +}; +alarm($TIMEOUT); + + +$status = GetOptions("key=i",\$snmpkey, + "community=s",\$community, + "port=i",\$port); +if ($status == 0) +{ + &usage; +} + + #shift; + $hostname = shift || &usage; + + ($session, $error) = Net::SNMP->session( + -hostname => $hostname, + -community => $community, + -port => $port + ); + + if (!defined($session)) { + $state='UNKNOWN'; + $answer=$error; + print ("$state: $answer"); + exit $ERRORS{$state}; + } + + $snmpIfOperStatus = '1.3.6.1.2.1.2.2.1.8' . "." . $snmpkey; + $snmpLocIfDescr = '1.3.6.1.4.1.9.2.2.1.1.28' . "." . $snmpkey; + + + push(@snmpoids,$snmpIfOperStatus); + push(@snmpoids,$snmpLocIfDescr); + + if (!defined($response = $session->get_request(@snmpoids))) { + $answer=$session->error; + $session->close; + $state = 'CRITICAL'; + print ("$state: $answer,$community,$snmpkey"); + exit $ERRORS{$state}; + } + + $answer = sprintf("host '%s',%s(%s) is %s\n", + $hostname, + $response->{$snmpLocIfDescr}, + $snmpkey, + $ifOperStatus{$response->{$snmpIfOperStatus}} + ); + + $session->close; + + if ( $response->{$snmpIfOperStatus} == 1 ) { + $state = 'OK'; + } + else { + $state = 'CRITICAL'; + } + +print ("$state: $answer"); +exit $ERRORS{$state}; + diff --git a/contrib/check_ifstatus.pl b/contrib/check_ifstatus.pl new file mode 100644 index 00000000..a7ab39ec --- /dev/null +++ b/contrib/check_ifstatus.pl @@ -0,0 +1,178 @@ +#!/usr/bin/perl -w +# +# check_ifstatus.pl - nagios plugin +# +# +# Copyright (C) 2000 Christoph Kron +# +# 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. +# +# +# Report bugs to: ck@zet.net +# +# 11.01.2000 Version 1.0 + +use strict; + +use Net::SNMP; +use Getopt::Long; +&Getopt::Long::config('auto_abbrev'); + + +my $status; +my $TIMEOUT = 1500; + +my %ERRORS = ('UNKNOWN' , '-1', + 'OK' , '0', + 'WARNING', '1', + 'CRITICAL', '2'); + +my %ifOperStatus = ('1','up', + '2','down', + '3','testing', + '4','unknown', + '5','dormant', + '6','notPresent'); + +my $state = "UNKNOWN"; +my $answer = ""; +my $snmpkey; +my $snmpoid; +my $key; +my $community = "public"; +my $port = 161; +my @snmpoids; +my $snmpIfAdminStatus = '1.3.6.1.2.1.2.2.1.7'; +my $snmpIfDescr = '1.3.6.1.2.1.2.2.1.2'; +my $snmpIfOperStatus = '1.3.6.1.2.1.2.2.1.8'; +my $snmpLocIfDescr = '1.3.6.1.4.1.9.2.2.1.1.28'; +my $hostname; +my $session; +my $error; +my $response; +my %ifStatus; +my $ifup =0 ; +my $ifdown =0; +my $ifdormant = 0; +my $ifmessage; + +sub usage { + printf "\nMissing arguments!\n"; + printf "\n"; + printf "Perl Check IfStatus plugin for Nagios\n"; + printf "monitors operational status of each interface\n"; + printf "usage: \n"; + printf "check_ifstatus.pl -c <READCOMMUNITY> -p <PORT> <HOSTNAME>\n"; + printf "Copyright (C) 2000 Christoph Kron\n"; + printf "check_ifstatus.pl comes with ABSOLUTELY NO WARRANTY\n"; + printf "This programm is licensed under the terms of the "; + printf "GNU General Public License\n(check source code for details)\n"; + printf "\n\n"; + exit $ERRORS{"UNKNOWN"}; +} + +# Just in case of problems, let's not hang Nagios +$SIG{'ALRM'} = sub { + print ("ERROR: No snmp response from $hostname (alarm)\n"); + exit $ERRORS{"UNKNOWN"}; +}; +alarm($TIMEOUT); + + +$status = GetOptions("community=s",\$community, + "port=i",\$port); +if ($status == 0) +{ + &usage; +} + + #shift; + $hostname = shift || &usage; + + + + push(@snmpoids,$snmpIfOperStatus); + push(@snmpoids,$snmpLocIfDescr); + push(@snmpoids,$snmpIfAdminStatus); + push(@snmpoids,$snmpIfDescr); + +foreach $snmpoid (@snmpoids) { + + ($session, $error) = Net::SNMP->session( + -hostname => $hostname, + -community => $community, + -port => $port + ); + + if (!defined($session)) { + $state='UNKNOWN'; + $answer=$error; + print ("$state: $answer"); + exit $ERRORS{$state}; + } + + if (!defined($response = $session->get_table($snmpoid))) { + $answer=$session->error; + $session->close; + $state = 'CRITICAL'; + print ("$state: $answer,$community,$snmpkey"); + exit $ERRORS{$state}; + } + + foreach $snmpkey (keys %{$response}) { + $snmpkey =~ /.*\.(\d+)$/; + $key = $1; + $ifStatus{$key}{$snmpoid} = $response->{$snmpkey}; + } + $session->close; +} + + foreach $key (keys %ifStatus) { + # check only if interface is administratively up + if ($ifStatus{$key}{$snmpIfAdminStatus} == 1 ) { + if ($ifStatus{$key}{$snmpIfOperStatus} == 1 ) { $ifup++ ;} + if ($ifStatus{$key}{$snmpIfOperStatus} == 2 ) { + $ifdown++ ; + $ifmessage .= sprintf("%s: down -> %s<BR>", + $ifStatus{$key}{$snmpIfDescr}, + $ifStatus{$key}{$snmpLocIfDescr}); + + } + if ($ifStatus{$key}{$snmpIfOperStatus} == 5 ) { $ifdormant++ ;} + } + } + + + if ($ifdown > 0) { + $state = 'CRITICAL'; + $answer = sprintf("host '%s', interfaces up: %d, down: %d, dormant: %d<BR>", + $hostname, + $ifup, + $ifdown, + $ifdormant); + $answer = $answer . $ifmessage . "\n"; + } + else { + $state = 'OK'; + $answer = sprintf("host '%s', interfaces up: %d, down: %d, dormant: %d\n", + $hostname, + $ifup, + $ifdown, + $ifdormant); + } + +print ("$state: $answer"); +exit $ERRORS{$state}; + diff --git a/contrib/check_ipxping.c b/contrib/check_ipxping.c new file mode 100644 index 00000000..1ba10fe6 --- /dev/null +++ b/contrib/check_ipxping.c @@ -0,0 +1,200 @@ +/****************************************************************************************** + * + * CHECK_IPXPING.C + * + * Program: IPX ping plugin for Nagios + * License: GPL + * Copyright (c) 1999 Ethan Galstad (nagios@nagios.org) + * + * Last Modified: 09-24-1999 + * + * Command line: CHECK_IPXPING <dest_network> <dest_address> <wrtt> <crtt> + * + * Description: + * + * This plugin will use the /usr/bin/ipxping command to ping the specified host using the + * IPX protocol. Note: Linux users must have IPX support compiled into the kernerl and + * must have IPX configured correctly in order for this plugin to work. + * If the round trip time value is above the <wrtt> level, a STATE_WARNING is + * returned. If it exceeds the <crtt> level, a STATE_CRITICAL is returned. + * + * + * + * IMPORTANT!! + * + * This plugin will only work with the ipxping command that has been ported to Linux. + * The version for Sun takes different command line arguments and differs in its output. + * + *****************************************************************************************/ + +#include "../common/config.h" +#include "../common/common.h" +#include "netutils.h" + +/* this should be moved out to the configure script! */ +#define IPXPING_COMMAND "/tmp/ipxping/ipxping" + +/* these should be moved to the common header file */ +#define MAX_IPXNET_ADDRESS_LENGTH 12 +#define MAX_IPXHOST_ADDRESS_LENGTH 18 + +int socket_timeout=DEFAULT_SOCKET_TIMEOUT; +char dest_network[MAX_IPXNET_ADDRESS_LENGTH]; +char dest_address[MAX_IPXHOST_ADDRESS_LENGTH]; +int wrtt; +int crtt; + +int process_arguments(int,char **); + +FILE * spopen(const char *); +int spclose(FILE *); + +int main(int argc, char **argv){ + char command_line[MAX_INPUT_BUFFER]; + int rtt; + int bytes_returned; + int result=STATE_OK; + FILE *fp; + char input_buffer[MAX_INPUT_BUFFER]; + char *substr; + int current_line; + + if(process_arguments(argc,argv)!=OK){ + printf("Incorrect arguments supplied\n"); + printf("\n"); + printf("IPX ping plugin for Nagios\n"); + printf("Copyright (c) 1999 Ethan Galstad (nagios@nagios.org)\n"); + printf("Last Modified: 09-24-1999\n"); + printf("License: GPL\n"); + printf("\n"); + printf("Usage: %s <dest_network> <dest_address> <wrtt> <crtt> [-to to_sec]\n",argv[0]); + printf("\n"); + printf("Options:\n"); + printf(" <dest_network> = IPX network that the remote host lies on. (Hex Format - 00:00:00:00)\n"); + printf(" <dest_address> = MAC address of the remote host. (Hex Format - 00:00:00:00:00:00)\n"); + printf(" <wrtt> = Round trip time in milliseconds necessary to result in a WARNING state\n"); + printf(" <crtt> = Round trip time in milliseconds necessary to result in a CRITICAL state\n"); + printf(" [to_sec] = Seconds before we should timeout waiting for ping result. Default = %d sec\n",DEFAULT_SOCKET_TIMEOUT); + printf("\n"); + printf("Notes:\n"); + printf("This plugin will use the /usr/bin/ipxping command to ping the specified host using\n"); + printf("the IPX protocol. IPX support must be compiled into the kernel and your host must\n"); + printf("be correctly configured to use IPX before this plugin will work! An RPM package of\n"); + printf("the ipxping binary can be found at...\n"); + printf("http://www.rpmfind.net/linux/RPM/contrib/libc5/i386/ipxping-0.0-2.i386.shtml\n"); + printf("\n"); + return STATE_UNKNOWN; + } + + /* create the command line to use... */ + sprintf(command_line,"%s %s %s",IPXPING_COMMAND,dest_network,dest_address); + + /* initialize alarm signal handling */ + signal(SIGALRM,socket_timeout_alarm_handler); + + /* set socket timeout */ + alarm(socket_timeout); + + /* run the command */ + fp = spopen(command_line); + if(fp==NULL){ + printf("Unable to open pipe: %s",command_line); + return STATE_UNKNOWN; + } + + current_line=0; + while(fgets(input_buffer,MAX_INPUT_BUFFER-1,fp)){ + + current_line++; + + /* skip the first line of the output */ + if(current_line==1) + continue; + + /* we didn't get the "is alive" */ + if(current_line==2 && !strstr(input_buffer,"is alive")) + result=STATE_CRITICAL; + + /* get the round trip time */ + if(current_line==3){ + substr=strtok(input_buffer,":"); + substr=strtok(NULL,"\n"); + rtt=atoi(substr); + } + + /* get the number of bytes returned */ + if(current_line==4 && strstr(input_buffer,"bytes returned")){ + bytes_returned=atoi(input_buffer); + } + } + + /* close the pipe */ + spclose(fp); + + /* reset the alarm */ + alarm(0); + + if(current_line==1 || result==STATE_CRITICAL) + printf("IPX Ping problem - No response from host\n"); + else{ + + if(rtt>crtt) + result=STATE_CRITICAL; + else if(rtt>wrtt) + result=STATE_WARNING; + + printf("IPX Ping %s - RTT = %d ms, %d bytes returned from %s %s\n",(result==STATE_OK)?"ok":"problem",rtt,bytes_returned,dest_network,dest_address); + } + + + return result; + } + + + +/* process all arguments passed on the command line */ +int process_arguments(int argc, char **argv){ + int x; + + /* no options were supplied */ + if(argc<5) + return ERROR; + + /* get the destination network address */ + strncpy(dest_network,argv[1],sizeof(dest_network)-1); + dest_network[sizeof(dest_network)-1]='\x0'; + + /* get the destination host address */ + strncpy(dest_address,argv[2],sizeof(dest_address)-1); + dest_address[sizeof(dest_address)-1]='\x0'; + + /* get the round trip time variables */ + wrtt=atoi(argv[3]); + crtt=atoi(argv[4]); + + /* process remaining arguments */ + for(x=6;x<=argc;x++){ + + /* we got the timeout to use */ + if(!strcmp(argv[x-1],"-to")){ + if(x<argc){ + socket_timeout=atoi(argv[x]); + if(socket_timeout<=0) + return ERROR; + x++; + } + else + return ERROR; + } + + /* else we got something else... */ + else + return ERROR; + } + + return OK; + } + + + + diff --git a/contrib/check_joy.sh b/contrib/check_joy.sh new file mode 100755 index 00000000..cd076db9 --- /dev/null +++ b/contrib/check_joy.sh @@ -0,0 +1,69 @@ +#! /bin/sh + +PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin + +PROGNAME=`basename $0` +PROGPATH=`echo $0 | sed -e 's,[\\/][^\\/][^\\/]*$,,'` +REVISION=`echo '$Revision$' | sed -e 's/[^0-9.]//g'` +STATUS="" + +. $PROGPATH/utils.sh + + +print_usage() { + echo "Usage: $PROGNAME /dev/js<#> <button #>" +} + +print_help() { + print_revision $PROGNAME $REVISION + echo "" + print_usage + echo "" + echo "This plugin checks a joystick button status using the " + echo "joyreadbutton utility from the joyd package." + echo "" + support + exit 0 +} + +if [ $# -ne 2 ]; then + print_usage + exit 0 +fi + +case "$1" in + --help) + print_help + exit 0 + ;; + -h) + print_help + exit 0 + ;; + --version) + print_revision $PROGNAME $REVISION + exit 0 + ;; + -V) + print_revision $PROGNAME $REVISION + exit 0 + ;; + /dev/js*) + joyreadbutton $1 $2 1>&1 1>/dev/null + STATUS=$? + if [ "$STATUS" -eq 0 ]; then + echo OK + exit 0 + elif [ "$STATUS" -eq 1 ];then + echo CRITICAL + exit 2 + else + echo UNKNOWN + exit -1 + fi + ;; + *) + print_usage + exit 0 + ;; +esac diff --git a/contrib/check_maxchannels.pl b/contrib/check_maxchannels.pl new file mode 100644 index 00000000..a3ce525b --- /dev/null +++ b/contrib/check_maxchannels.pl @@ -0,0 +1,231 @@ +#!/usr/bin/perl -w +# +# check_maxchannels.pl - nagios plugin +# +# +# Copyright (C) 2000 Christoph Kron +# +# 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. +# +# +# Report bugs to: ck@zet.net +# +# 11.01.2000 Version 1.0 + +use strict; + +use Net::SNMP; +use Getopt::Long; +&Getopt::Long::config('auto_abbrev'); + + +my $status; +my $TIMEOUT = 15; + +my %ERRORS = ('UNKNOWN' , '-1', + 'OK' , '0', + 'WARNING', '1', + 'CRITICAL', '2'); + + +my $state = "UNKNOWN"; +my $answer = ""; +my $snmpkey; +my $snmpoid; +my $key; +my $community = "public"; +my $port = 161; +my @snmpoids; +# free channels +my $snmpWanAvailableChannels = '1.3.6.1.4.1.529.4.23.0'; +# maximum channels +my $snmpWanSwitchedChannels = '1.3.6.1.4.1.529.4.24.0'; +my $snmpWanDisabledChannels = '1.3.6.1.4.1.529.4.25.0'; +my $snmpWanActiveChannels = '1.3.6.1.4.1.529.4.26.0'; +my $snmpWanNailedChannels = '1.3.6.1.4.1.529.4.27.0'; +my $snmpWanOutOfServiceChannels = '1.3.6.1.4.1.529.4.28.0'; +my $snmpEventCurrentActiveSessions = '1.3.6.1.4.1.529.10.6.0'; +# since startup +my $snmpEventTotalNoModems = '1.3.6.1.4.1.529.10.15.0'; +# lan modem +my $snmpDeadLanModem = '1.3.6.1.4.1.529.15.7.0'; +my $snmpDisabledLanModem = '1.3.6.1.4.1.529.15.5.0'; +my $snmpSuspectLanModem = '1.3.6.1.4.1.529.15.3.0'; +my $snmpAvailLanModem = '1.3.6.1.4.1.529.15.1.0'; +my $snmpBusyLanModem = '1.3.6.1.4.1.529.15.9.0'; +# max modems +my $snmpMdmNumber = '1.3.6.1.2.1.38.1.1.0'; +my $hostname; +my $session; +my $error; +my $response; +my %wanStatus; + + +my $WanAvailableChannels; +my $WanSwitchedChannels; +my $WanDisabledChannels; +my $WanActiveChannels; +my $WanNailedChannels; +my $WanOutOfServiceChannels; +my $EventCurrentActiveSessions; +my $EventTotalNoModems; +my $DeadLanModem; +my $DisabledLanModem; +my $SuspectLanModem; +my $AvailLanModem; +my $BusyLanModem; +my $MdmNumber; + + +sub usage { + printf "\nMissing arguments!\n"; + printf "\n"; + printf "Perl Check maxchannels plugin for Nagios\n"; + printf "monitors ISDN lines and modems on Ascend MAX 2000/4000/6000/TNT\n"; + printf "usage: \n"; + printf "check_maxchannel.pl -c <READCOMMUNITY> -p <PORT> <HOSTNAME>\n"; + printf "Copyright (C) 2000 Christoph Kron\n"; + printf "check_maxchannels.pl comes with ABSOLUTELY NO WARRANTY\n"; + printf "This programm is licensed under the terms of the "; + printf "GNU General Public License\n(check source code for details)\n"; + printf "\n\n"; + exit $ERRORS{"UNKNOWN"}; +} + +# Just in case of problems, let's not hang Nagios +$SIG{'ALRM'} = sub { + print ("ERROR: No snmp response from $hostname (alarm)\n"); + exit $ERRORS{"UNKNOWN"}; +}; +alarm($TIMEOUT); + + +$status = GetOptions("community=s",\$community, + "port=i",\$port); +if ($status == 0) +{ + &usage; +} + + #shift; + $hostname = shift || &usage; + + + +push(@snmpoids,$snmpWanAvailableChannels); +push(@snmpoids,$snmpWanSwitchedChannels); +push(@snmpoids,$snmpWanDisabledChannels); +push(@snmpoids,$snmpWanActiveChannels); +push(@snmpoids,$snmpWanNailedChannels); +push(@snmpoids,$snmpWanOutOfServiceChannels); + +push(@snmpoids,$snmpEventCurrentActiveSessions); + +push(@snmpoids,$snmpEventTotalNoModems); +push(@snmpoids,$snmpDeadLanModem); +push(@snmpoids,$snmpDisabledLanModem); +push(@snmpoids,$snmpSuspectLanModem); +push(@snmpoids,$snmpAvailLanModem); +push(@snmpoids,$snmpBusyLanModem); +push(@snmpoids,$snmpMdmNumber); + + ($session, $error) = Net::SNMP->session( + -hostname => $hostname, + -community => $community, + -port => $port + ); + + if (!defined($session)) { + $state='UNKNOWN'; + $answer=$error; + print ("$state: $answer"); + exit $ERRORS{$state}; + } + + if (!defined($response = $session->get_request(@snmpoids))) { + $answer=$session->error; + $session->close; + $state = 'CRITICAL'; + print ("$state: $answer,$community"); + exit $ERRORS{$state}; + } + + +$WanAvailableChannels = $response->{$snmpWanAvailableChannels}; +$WanSwitchedChannels = $response->{$snmpWanSwitchedChannels}; +$WanDisabledChannels = $response->{$snmpWanDisabledChannels}; +$WanActiveChannels = $response->{$snmpWanActiveChannels}; +$WanNailedChannels = $response->{$snmpWanNailedChannels}; +$WanOutOfServiceChannels = $response->{$snmpWanOutOfServiceChannels}; +$EventCurrentActiveSessions = $response->{$snmpEventCurrentActiveSessions}; +$EventTotalNoModems = $response->{$snmpEventTotalNoModems}; +$DeadLanModem = $response->{$snmpDeadLanModem}; +$DisabledLanModem = $response->{$snmpDisabledLanModem}; +$SuspectLanModem = $response->{$snmpSuspectLanModem}; +$AvailLanModem = $response->{$snmpAvailLanModem}; +$BusyLanModem = $response->{$snmpBusyLanModem}; +$MdmNumber = $response->{$snmpMdmNumber}; + +# less than 50% -> WARNING +if ( 0 < $WanOutOfServiceChannels + && $WanOutOfServiceChannels < ($snmpWanSwitchedChannels * 0.5) ) { + $state = 'WARNING'; +} +elsif ($WanOutOfServiceChannels > 0) { + $state = 'CRITICAL'; +} +elsif ($DeadLanModem > 0) { + $state = 'CRITICAL'; +} +elsif ($SuspectLanModem > 0) { + $state = 'WARNING'; +} +elsif ($AvailLanModem == 0) { + $state = 'WARNING'; +} +else { + $state = 'OK'; +} + + +$answer = sprintf("active sessions: %d (%d), active modems: %d (%d)<BR>", + $EventCurrentActiveSessions, + $WanSwitchedChannels, + $BusyLanModem, + $MdmNumber); + +$answer .= sprintf("channels available: %d, disabled: %d", + $WanAvailableChannels, + $WanDisabledChannels); + +$answer .= sprintf(", out of service: %d, nailed: %d<BR>", + $WanOutOfServiceChannels, + $WanNailedChannels); + +$answer .= sprintf("modems avail.: %d, disabled: %d, suspect: %d, dead: %d<BR>", + $AvailLanModem, + $DisabledLanModem, + $SuspectLanModem, + $DeadLanModem); + +$answer .= sprintf("unserviced modem calls: %d (since startup)\n", + $EventTotalNoModems); + +$session->close; + +print ("$state: $answer"); +exit $ERRORS{$state}; + diff --git a/contrib/check_maxwanstate.pl b/contrib/check_maxwanstate.pl new file mode 100644 index 00000000..4fbb9da2 --- /dev/null +++ b/contrib/check_maxwanstate.pl @@ -0,0 +1,201 @@ +#!/usr/bin/perl -w +# +# check_maxwanstate.pl - nagios plugin +# +# +# Copyright (C) 2000 Christoph Kron +# +# 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. +# +# +# Report bugs to: ck@zet.net +# +# 11.01.2000 Version 1.0 + +use strict; + +use Net::SNMP; +use Getopt::Long; +&Getopt::Long::config('auto_abbrev'); + + +my $status; +my $TIMEOUT = 1500; + +my %ERRORS = ('UNKNOWN' , '-1', + 'OK' , '0', + 'WARNING', '1', + 'CRITICAL', '2'); + +my %wanLineState = ( + 1,'ls-unknown', + 2,'ls-does-not-exist', + 3,'ls-disabled', + 4,'ls-no-physical', + 5,'ls-no-logical', + 6,'ls-point-to-point', + 7,'ls-multipoint-1', + 8,'ls-multipoint-2', + 9,'ls-loss-of-sync', + 10,'ls-yellow-alarm', + 11,'ls-ais-receive', + 12,'ls-no-d-channel', + 13,'ls-active', + 14,'ls-maintenance'); + +my %wanLineType = ( + '1.3.6.1.4.1.529.4.1','Any', + '1.3.6.1.4.1.529.4.2','T1', + '1.3.6.1.4.1.529.4.3','E1', + '1.3.6.1.4.1.529.4.4','Dpnss', + '1.3.6.1.4.1.529.4.5','Bri', + '1.3.6.1.4.1.529.4.6','S562', + '1.3.6.1.4.1.529.4.7','S564', + '1.3.6.1.4.1.529.4.8','Sdsl', + '1.3.6.1.4.1.529.4.9','AdslCap'); + +my $state = "UNKNOWN"; +my $answer = ""; +my $snmpkey; +my $snmpoid; +my $key; +my $community = "public"; +my $port = 161; +my @snmpoids; +my $snmpWanLineName = '1.3.6.1.4.1.529.4.21.1.2'; +my $snmpWanLineType = '1.3.6.1.4.1.529.4.21.1.3'; +my $snmpWanLineState = '1.3.6.1.4.1.529.4.21.1.5'; +my $snmpWanLineUsage = '1.3.6.1.4.1.529.4.21.1.8'; + +my $hostname; +my $session; +my $error; +my $response; +my %wanStatus; +my $ifup =0 ; +my $ifdown =0; +my $ifdormant = 0; +my $ifmessage; + +sub usage { + printf "\nMissing arguments!\n"; + printf "\n"; + printf "Perl Check maxwanstate plugin for Nagios\n"; + printf "monitors E1/T1 interface status\n"; + printf "usage: \n"; + printf "check_maxwanstate.pl -c <READCOMMUNITY> -p <PORT> <HOSTNAME>"; + printf "Copyright (C) 2000 Christoph Kron\n"; + printf "check_maxwanstate.pl comes with ABSOLUTELY NO WARRANTY\n"; + printf "This programm is licensed under the terms of the "; + printf "GNU General Public License\n(check source code for details)\n"; + printf "\n\n"; + exit $ERRORS{"UNKNOWN"}; +} + +# Just in case of problems, let's not hang Nagios +$SIG{'ALRM'} = sub { + print ("ERROR: No snmp response from $hostname (alarm)\n"); + exit $ERRORS{"UNKNOWN"}; +}; +alarm($TIMEOUT); + + +$status = GetOptions("community=s",\$community, + "port=i",\$port); +if ($status == 0) +{ + &usage; +} + + #shift; + $hostname = shift || &usage; + + + +push(@snmpoids,$snmpWanLineUsage); +push(@snmpoids,$snmpWanLineState); +push(@snmpoids,$snmpWanLineName); +push(@snmpoids,$snmpWanLineType); + +foreach $snmpoid (@snmpoids) { + + ($session, $error) = Net::SNMP->session( + -hostname => $hostname, + -community => $community, + -port => $port + ); + + if (!defined($session)) { + $state='UNKNOWN'; + $answer=$error; + print ("$state: $answer"); + exit $ERRORS{$state}; + } + + if (!defined($response = $session->get_table($snmpoid))) { + $answer=$session->error; + $session->close; + $state = 'CRITICAL'; + print ("$state: $answer,$community,$snmpkey"); + exit $ERRORS{$state}; + } + + foreach $snmpkey (keys %{$response}) { + $snmpkey =~ /.*\.(\d+)$/; + $key = $1; + $wanStatus{$key}{$snmpoid} = $response->{$snmpkey}; + } + $session->close; +} + + foreach $key (keys %wanStatus) { + # look only at active Interfaces lu-trunk(5) + if ($wanStatus{$key}{$snmpWanLineUsage} == 5 ) { + + # 13 -> active + if ($wanStatus{$key}{$snmpWanLineState} == 13 ) { + $ifup++; + } + else { + $ifdown++ ; + $ifmessage .= sprintf("%s interface status : %s (%s)<BR>", + $wanLineType{$wanStatus{$key}{$snmpWanLineType}}, + $wanLineState{$wanStatus{$key}{$snmpWanLineState}}, + $wanStatus{$key}{$snmpWanLineName}); + + } + } + } + + + if ($ifdown > 0) { + $state = 'CRITICAL'; + $answer = sprintf("host '%s', interfaces up: %d, down: %d<BR>", + $hostname, + $ifup, + $ifdown); + $answer = $answer . $ifmessage . "\n"; + } + else { + $state = 'OK'; + $answer = sprintf("host '%s', interfaces up: %d, down: %d\n", + $hostname, + $ifup, + $ifdown); + } + +print ("$state: $answer"); +exit $ERRORS{$state}; + diff --git a/contrib/check_mem.pl b/contrib/check_mem.pl new file mode 100644 index 00000000..f0c82129 --- /dev/null +++ b/contrib/check_mem.pl @@ -0,0 +1,146 @@ +#!/usr/bin/perl -w +# $Id$ + +# check_mem.pl Copyright (C) 2000 Dan Larsson <dl@tyfon.net> +# +# 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 (or with Nagios); if not, write to the +# Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA + +# Tell Perl what we need to use +use strict; +use Getopt::Std; + +use vars qw($opt_c $opt_f $opt_u $opt_w + $free_memory $used_memory $total_memory + $crit_level $warn_level + %exit_codes @memlist + $percent $fmt_pct + $verb_err $command_line); + +# Predefined exit codes for Nagios +%exit_codes = ('UNKNOWN' ,-1, + 'OK' , 0, + 'WARNING' , 1, + 'CRITICAL', 2,); + +# Turn this to 1 to see reason for parameter errors (if any) +$verb_err = 0; + +# This the unix command string that brings Perl the data +$command_line = `vmstat | tail -1 | awk '{print \$4,\$5}'`; + +chomp $command_line; +@memlist = split(/ /, $command_line); + +# Define the calculating scalars +$used_memory = $memlist[0]; +$free_memory = $memlist[1]; +$total_memory = $used_memory + $free_memory; + +# Get the options +if ($#ARGV le 0) +{ + &usage; +} +else +{ + getopts('c:fuw:'); +} + +# Shortcircuit the switches +if (!$opt_w or $opt_w == 0 or !$opt_c or $opt_c == 0) +{ + print "*** You must define WARN and CRITICAL levels!" if ($verb_err); + &usage; +} +elsif (!$opt_f and !$opt_u) +{ + print "*** You must select to monitor either USED or FREE memory!" if ($verb_err); + &usage; +} + +# Check if levels are sane +if ($opt_w <= $opt_c and $opt_f) +{ + print "*** WARN level must not be less than CRITICAL when checking FREE memory!" if ($verb_err); + &usage; +} +elsif ($opt_w >= $opt_c and $opt_u) +{ + print "*** WARN level must not be greater than CRITICAL when checking USED memory!" if ($verb_err); + &usage; +} + +$warn_level = $opt_w; +$crit_level = $opt_c; + +if ($opt_f) +{ + $percent = $free_memory / $total_memory * 100; + $fmt_pct = sprintf "%.1f", $percent; + if ($percent <= $crit_level) + { + print "Memory CRITICAL - $fmt_pct% ($free_memory kB) free\n"; + exit $exit_codes{'CRITICAL'}; + } + elsif ($percent <= $warn_level) + { + print "Memory WARNING - $fmt_pct% ($free_memory kB) free\n"; + exit $exit_codes{'WARNING'}; + } + else + { + print "Memory OK - $fmt_pct% ($free_memory kB) free\n"; + exit $exit_codes{'OK'}; + } +} +elsif ($opt_u) +{ + $percent = $used_memory / $total_memory * 100; + $fmt_pct = sprintf "%.1f", $percent; + if ($percent >= $crit_level) + { + print "Memory CRITICAL - $fmt_pct% ($used_memory kB) used\n"; + exit $exit_codes{'CRITICAL'}; + } + elsif ($percent >= $warn_level) + { + print "Memory WARNING - $fmt_pct% ($used_memory kB) used\n"; + exit $exit_codes{'WARNING'}; + } + else + { + print "Memory OK - $fmt_pct% ($used_memory kB) used\n"; + exit $exit_codes{'OK'}; + } +} + +# Show usage +sub usage() +{ + print "\ncheck_mem.pl v1.0 - Nagios Plugin\n\n"; + print "usage:\n"; + print " check_mem.pl -<f|u> -w <warnlevel> -c <critlevel>\n\n"; + print "options:\n"; + print " -f Check FREE memory\n"; + print " -u Check USED memory\n"; + print " -w PERCENT Percent free/used when to warn\n"; + print " -c PERCENT Percent free/used when critical\n"; + print "\nCopyright (C) 2000 Dan Larsson <dl\@tyfon.net>\n"; + print "check_mem.pl comes with absolutely NO WARRANTY either implied or explicit\n"; + print "This program is licensed under the terms of the\n"; + print "GNU General Public License (check source code for details)\n"; + exit $exit_codes{'UNKNOWN'}; +} diff --git a/contrib/check_memory.tgz b/contrib/check_memory.tgz Binary files differnew file mode 100644 index 00000000..b0f80160 --- /dev/null +++ b/contrib/check_memory.tgz diff --git a/contrib/check_mysql.c b/contrib/check_mysql.c new file mode 100644 index 00000000..9abacf87 --- /dev/null +++ b/contrib/check_mysql.c @@ -0,0 +1,75 @@ +/***************************************************************** + * + * Program: check_mysql.c + * License: GPL + * + * Written by Tim Weippert + * (based on plugins by Ethan Galstad and MySQL example code) + * + * Command line: check_mysql <host> [user] [passwd] + * <host> can be the FQDN or the IP-Adress + * [user] and [passwd] are optional + * + * Description: + * + * This plugin attempts to connect to an MySQL Server + * with the optional specified parameters user and passwd. + * Normaly the host and a user HAVE to assigned. + * + * The plugin returns + * STATE_OK and the Version Number of the Server when all is fine + * STATE_CRITICAL if the Connection can't be esablished + * STATE_WARNING if the connection was established but the + * program can't get the Versoin Number + * STATE_UNKNOWN if to many parameters are given + * + * Copyright (c) 1999 by Tim Weippert + * + * Changes: + * 16.12.1999: Changed the return codes from numbers to statements + * + *******************************************************************/ + +#include "../common/config.h" +#include "../common/common.h" +#include "mysql.h" + +MYSQL mysql; + +int main(int argc, char **argv) +{ + uint i = 0; + char *host; + char *user; + char *passwd; + + char *status; + char *version; + + if ( argc > 4 ) { + printf("Too many Arguments supplied - %i .\n", argc); + printf("Usage: %s <host> [user] [passwd]\n", argv[0]); + return STATE_UNKNOWN; + } + + (host = argv[1]) || (host = NULL); + (user = argv[2]) || (user = NULL); + (passwd = argv[3]) || (passwd = NULL); + + if (!(mysql_connect(&mysql,host,user,passwd))) { + printf("Can't connect to Mysql on Host: %s\n", host); + return STATE_CRITICAL; + } + + if ( !(version = mysql_get_server_info(&mysql)) ) { + printf("Connect OK, but can't get Serverinfo ... something wrong !\n"); + return STATE_WARNING; + } + + printf("Mysql ok - Running Version: %s\n", version); + + mysql_close(&mysql); + return STATE_OK; +} + + diff --git a/contrib/check_mysql.pl b/contrib/check_mysql.pl new file mode 100644 index 00000000..143d5a5a --- /dev/null +++ b/contrib/check_mysql.pl @@ -0,0 +1,73 @@ +#!/nyet/bin/perl +# +# (c)1999 Mitch Wright, NetLine Corporation +# Read the GNU copyright stuff for all the legalese +# +# Check to see that our MySQL server(s) are up and running. +# This plugin requires that mysqladmin(1) is installed on the system. +# Since it is part of the MySQL distribution, that should be a problem. +# +# If no parameters are giving, a usage statement is output. +# +# Exit 0 on success, providing some informational output +# Exit 2 on failure, provide what we can... +# + +require 5.004; + +sub usage; + +my $TIMEOUT = 15; +my $MYSQLADMIN = "/usr/local/bin/mysqladmin"; + +my %ERRORS = ('UNKNOWN' , '-1', + 'OK' , '0', + 'WARNING', '1', + 'CRITICAL', '2'); + +my $host = shift || &usage(%ERRORS); +my $user = shift || &usage(%ERRORS); +my $pass = shift || ""; +my $warn = shift || 60; +my $crit = shift || 100; + +my $state = "OK"; + +# Just in case of problems, let's not hang Nagios +$SIG{'ALRM'} = sub { + print ("ERROR: No response from MySQL server (alarm)\n"); + exit $ERRORS{"UNKNOWN"}; +}; +alarm($TIMEOUT); + +open (OUTPUT, + "$MYSQLADMIN -h $host -u $user --password=\"$pass\" version 2>&1 + |"); + +while (<OUTPUT>) { + if (/failed/) { $state="CRITICAL"; s/.*://; $status=$_; last; } + next if /^\s*$/; + if (/^Server version\s+(\d+.*)/) { $version = $1; next; } + if (/^Uptime:\s+(\d.*)/) { $uptime = $1; next; } + if (/^Threads:\s+(\d+)\s+/) { $threads = $1; next; } +} + +$status = "Version $version -- $threads Threads <br>Uptime $uptime" if +$state ne "CRITICAL"; + +if ($threads >= $warn) { $state = "WARNING"; } +if ($threads >= $crit) { $state = "CRITICAL"; } + +print $status; +exit $ERRORS{$state}; + +sub usage { + print "Required arguments not given!\n\n"; + print "MySQL status checker plugin for Nagios, V1.01\n"; + print "Copyright (c) 1999-2000 Mitch Wright \n\n"; + print "Usage: check_mysql.pl <host> <user> [<pass> [<warn> + [<crit>]]]\n\n"; print " <pass> = password to use for <user> at + <host>\n"; print " <warn> = number of threads to warn us + about\n"; print " <crit> = number of threads to scream at us + about\n"; exit $ERRORS{"UNKNOWN"}; +} diff --git a/contrib/check_nagios.pl b/contrib/check_nagios.pl new file mode 100644 index 00000000..7d15d4db --- /dev/null +++ b/contrib/check_nagios.pl @@ -0,0 +1,48 @@ +#!/usr/bin/perl +# denao - denao@uol.com.br - Systems Engineering +# Universo Online - http://www.uol.com.br +use DBI; +use Time::Local; + +my $t_lambuja = 5; # (expire_minutes) +my $databasename = ""; # The name of nagios database (i.e.: nagios) +my $table = "programstatus"; +my $where = "localhost"; # The machine where the database +my $port = "3306"; +my $base = "DBI:mysql:$databasename:$where:$port"; +my $user = ""; # the user to connect to the database + # (needs permission to "select at programstatus table only" +my $password = ""; # the password (if any) +my %results; +my @fields = qw( last_update ); +my $dbh = DBI->connect($base,$user,$password); +my $fields = join(', ', @fields); +my $query = "SELECT $fields FROM $table"; + +my $sth = $dbh->prepare($query); +$sth->execute(); + +@results{@fields} = (); +$sth->bind_columns(map { \$results{$_} } @fields); + +$sth->fetch(); +$sth->finish(); +$dbh->disconnect(); + +check_update(); + +sub check_update { +($yea,$mon,$day,$hou,$min,$sec)=($results{last_update}=~/(\d+)\-(\d+)\-(\d+)\s(\d+)\:(\d+)\:(\d+)/); +($sec_now, $min_now, $hou_now, $day_now, $mon_now, $yea_now) = (localtime(time))[0,1,2,3,4,5]; +$mon_now+=1; $yea_now+=1900; +$unixdate=timelocal($sec,$min,$hou,$day,$mon,$yea); +$unixdate_now=timelocal($sec_now,$min_now,$hou_now,$day_now,$mon_now,$yea_now); + if (scalar($unixdate_now - $unixdate) > scalar($t_lambuja * 60)) { + print "Nagios problem: nagios is down, for at least " . scalar($t_lambuja) . " minutes.\n"; + exit(1); + } else { + print "Nagios ok: status data updated " . scalar($unixdate_now - $unixdate) . " seconds ago\n"; + exit(0); + } +} + diff --git a/contrib/check_netapp.pl b/contrib/check_netapp.pl new file mode 100755 index 00000000..d556e9da --- /dev/null +++ b/contrib/check_netapp.pl @@ -0,0 +1,178 @@ +#!/usr/bin/perl -wT +# check_netapp +# +# Copyright (C) 2000 Leland E. Vandervort <leland@mmania.com> +# +# 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 (or with Nagios); if not, write to the +# Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA +#################################### +# checks for overtemperature, fans, psu, and nfs operations/second on +# Network Appliance Filers. +# Returns: +# OK if temp, fans, psu OK and Ops/Sec below warning and critical +# Thresholds (default is warning=3500, critical=5000) +# ** Note: See the specifications for your Filer model for +# the thresholds ! +# Returns Warning if NFS Ops/Sec is above warning threshold +# (default 3500, or specified by -o command line option) +# Returns Critical if NFS Ops/Sec is above critical threshold +# ( -m option, or default 5000), or if overtem, psufault, or +# fanfault detected. +# +#################################### +# Notes on operational limits for NetApp Filers: +# Platform Maximum Ops/Second (recommended) +# ------------------------------------------------------------- +# F230 1000 +# F740 5500 +# F760 9000 +#################################### + +use Net::SNMP; +use Getopt::Long; +&Getopt::Long::config('auto_abbrev'); + +my $status; +my $response = ""; +my $TIMEOUT = 10; +my $community = "public"; +my $port = 161; +my $opsthresh = "3500"; +my $critical = "5000"; + +my $status_string = ""; + +my %OIDLIST = ( + overtemp => '1.3.6.1.4.1.789.1.2.4.1.0', + failedfan => '1.3.6.1.4.1.789.1.2.4.2.0', + failedpsu => '1.3.6.1.4.1.789.1.2.4.4.0', + nfsops => '1.3.6.1.4.1.789.1.2.2.1.0' + ); + + + +my %STATUSCODE = ( 'UNKNOWN' => '-1', + 'OK' => '0', + 'WARNING' => '1', + 'CRITICAL' => '2'); + +my $state = "UNKNOWN"; + + +$SIG{'ALRM'} = sub { + print "ERROR: No snmp response from $hostname (sigALRM)\n"; + exit($STATUSCODE{"UNKNOWN"}); +}; + +alarm($TIMEOUT); + +sub get_nfsops { + my $nfsops_start = &SNMPGET($OIDLIST{nfsops}); + sleep(1); + my $nfsops_end = &SNMPGET($OIDLIST{nfsops}); + my $nfsopspersec = $nfsops_end - $nfsops_start; + return($nfsopspersec); +} + + +sub show_help { + printf("\nPerl NetApp filer plugin for Nagios\n"); + printf("Usage:\n"); + printf(" + check_netapp [options] <hostname> + Options: + -c snmp-community + -p snmp-port + -o Operations per second warning threshold + -m Operations per second critical threshold + +"); + printf("Copyright (C)2000 Leland E. Vandervort\n"); + printf("check_netapp comes with absolutely NO WARRANTY either implied or explicit\n"); + printf("This program is licensed under the terms of the\n"); + printf("GNU General Public License\n(check source code for details)\n\n\n"); + exit($STATUSCODE{"UNKNOWN"}); +} + + +$status = GetOptions( "community=s", \$community, + "port=i", \$port, + "opsthresh=i", \$opsthresh, + "maxops=i", \$critical ); + +if($status == 0) { + &show_help; +} + +sub SNMPGET { + $OID = shift; + ($session,$error) = Net::SNMP->session( + Hostname => $hostname, + Community => $community, + Port => $port + ); + if(!defined($session)) { + printf("$state %s\n", $error); + exit($STATUSCODE{$state}); + } + if(!defined($response = $session->get_request($OID))) { + printf("$state %s\n", $session->error()); + $session->close(); + exit($STATUSCODE{$state}); + } + $session->close(); + return($response->{$OID}); +} + +$hostname = shift || &show_help; + +my $tempcheck = &SNMPGET($OIDLIST{overtemp}); +if($tempcheck == 1) { + $state = "OK"; + $status_string .= "Temp OK "; +} +else { + $state = "CRITICAL"; + $status_string .= "Temp CRIT"; +} + +foreach $element ('failedfan','failedpsu') { + my $my_return = &SNMPGET($OIDLIST{$element}); + if(($my_return =~ /no/) || ($my_return == 0)) { + $status_string .= "$element = $my_return "; + $state = "OK"; + } + else { + $status_string .= "$element = $my_return "; + $state = "CRITICAL"; + } +} + +my $tmp_opssec = &get_nfsops(); + +if ($tmp_opssec >= $critical) { + $state = "CRITICAL"; +} +elsif ($tmp_opssec >= $opsthresh) { + $state = "WARNING"; +} +else { + $state = "OK"; +} + +$status_string .= "Ops\/Sec = $tmp_opssec "; + +print "$state $status_string\n"; +exit($STATUSCODE{$state}); diff --git a/contrib/check_nmap.py b/contrib/check_nmap.py new file mode 100644 index 00000000..4f53406d --- /dev/null +++ b/contrib/check_nmap.py @@ -0,0 +1,440 @@ +#!/usr/bin/python +# Change the above line if python is somewhere else + +# +# check_nmap +# +# Program: nmap plugin for Nagios +# License: GPL +# Copyright (c) 2000 Jacob Lundqvist (jaclu@galdrion.com) +# +_version_ = '1.20' +# +# +# Description: +# +# Does a nmap scan, compares open ports to those given on command-line +# Reports warning for closed that should be open and error for +# open that should be closed. +# If optional ports are given, no warning is given if they are closed +# and they are included in the list of valid ports. +# +# Requirements: +# python +# nmap +# +# History +# ------- +# 1.20 2000-07-15 jaclu Updated params to correctly comply to plugin-standard +# moved support classes to utils.py +# 1.16 2000-07-14 jaclu made options and return codes more compatible with +# the plugin developer-guidelines +# 1.15 2000-07-14 jaclu added random string to temp-file name +# 1.14 2000-07-14 jaclu added check for error from subproc +# 1.10 2000-07-14 jaclu converted main part to class +# 1.08 2000-07-13 jaclu better param parsing +# 1.07 2000-07-13 jaclu changed nmap param to -P0 +# 1.06 2000-07-13 jaclu make sure tmp file is deleted on errors +# 1.05 2000-07-12 jaclu in debug mode, show exit code +# 1.03 2000-07-12 jaclu error handling on nmap output +# 1.01 2000-07-12 jaclu added license +# 1.00 2000-07-12 jaclu implemented timeout handling +# 0.20 2000-07-10 jaclu Initial release + + +import sys, os, string, whrandom + +import tempfile +from getopt import getopt + +# +# import generic Nagios-plugin stuff +# +import utils + +# Where temp files should be placed +tempfile.tempdir='/usr/local/nagios/var' + +# Base name for tempfile +tempfile.template='check_nmap_tmp.' + +# location and possibly params for nmap +nmap_cmd='/usr/bin/nmap -P0' + + + + + + +# +# the class that does all the real work in this plugin... +# +# +class CheckNmap: + + # Retcodes, so we are compatible with nagios + #ERROR= -1 + UNKNOWN= -1 + OK= 0 + WARNING= 1 + CRITICAL= 2 + + + def __init__(self,cmd_line=[]): + """Constructor. + arguments: + cmd_line: normaly sys.argv[1:] if called as standalone program + """ + self.tmp_file='' + self.host='' # host to check + self.timeout=10 + self.debug=0 # 1= show debug info + self.ports=[] # list of mandatory ports + self.opt_ports=[] # list of optional ports + self.ranges='' # port ranges for nmap + self.exit_code=0 # numerical exit-code + self.exit_msg='' # message to caller + + self.ParseCmdLine(cmd_line) + + def Run(self): + """Actually run the process. + This method should be called exactly once. + """ + + # + # Only call check_host if cmd line was accepted earlier + # + if self.exit_code==0: + self.CheckHost() + + self.CleanUp() + return self.exit_code,self.exit_msg + + def Version(self): + return 'check_nmap %s' % _version_ + + #----------------------------------------- + # + # class internal stuff below... + # + #----------------------------------------- + + # + # Param checks + # + def param2int_list(self,s): + lst=string.split(string.replace(s,',',' ')) + try: + for i in range(len(lst)): + lst[i]=int(lst[i]) + except: + lst=[] + return lst + + def ParseCmdLine(self,cmd_line): + try: + opt_list=getopt(cmd_line,'vH:ho:p:r:t:V',['debug','host=','help', + 'optional=','port=','range=','timeout','version']) + for opt in opt_list[0]: + if opt[0]=='-v' or opt[0]=='--debug': + self.debug=1 + elif opt[0]=='-H' or opt[0]=='--host': + self.host=opt[1] + elif opt[0]=='-h' or opt[0]=='--help': + doc_help() + self.exit_code=1 # request termination + break + elif opt[0]=='-o' or opt[0]=='--optional': + self.opt_ports=self.param2int_list(opt[1]) + elif opt[0]=='-p' or opt[0]=='--port': + self.ports=self.param2int_list(opt[1]) + elif opt[0]=='-r' or opt[0]=='--range': + r=string.replace(opt[1],':','-') + self.ranges=r + elif opt[0]=='-t' or opt[0]=='--timeout': + self.timeout=opt[1] + elif opt[0]=='-V' or opt[0]=='--version': + print self.Version() + self.exit_code=1 # request termination + break + else: + self.host='' + break + + except: + # unknown param + self.host='' + + if self.debug: + print 'Params:' + print '-------' + print 'host = %s' % self.host + print 'timeout = %s' % self.timeout + print 'ports = %s' % self.ports + print 'optional ports = %s' % self.opt_ports + print 'ranges = %s' % self.ranges + print + + # + # a option that wishes us to terminate now has been given... + # + # This way, you can test params in debug mode and see what this + # program recognised by suplying a version param at the end of + # the cmd-line + # + if self.exit_code<>0: + sys.exit(self.UNKNOWN) + + if self.host=='': + doc_syntax() + self.exit_code=self.UNKNOWN + self.exit_msg='UNKNOWN: bad params, try running without any params for syntax' + + + def CheckHost(self): + 'Check one host using nmap.' + # + # Create a tmp file for storing nmap output + # + # The tempfile module from python 1.5.2 is stupid + # two processes runing at aprox the same time gets + # the same tempfile... + # For this reason I use a random suffix for the tmp-file + # Still not 100% safe, but reduces the risk significally + # I also inserted checks at various places, so that + # _if_ two processes in deed get the same tmp-file + # the only result is a normal error message to nagios + # + r=whrandom.whrandom() + self.tmp_file=tempfile.mktemp('.%s')%r.randint(0,100000) + if self.debug: + print 'Tmpfile is: %s'%self.tmp_file + # + # If a range is given, only run nmap on this range + # + if self.ranges<>'': + global nmap_cmd # needed, to avoid error on next line + # since we assigns to nmap_cmd :) + nmap_cmd='%s -p %s' %(nmap_cmd,self.ranges) + # + # Prepare a task + # + t=utils.Task('%s %s' %(nmap_cmd,self.host)) + # + # Configure a time-out handler + # + th=utils.TimeoutHandler(t.Kill, time_to_live=self.timeout, + debug=self.debug) + # + # Fork of nmap cmd + # + t.Run(detach=0, stdout=self.tmp_file,stderr='/dev/null') + # + # Wait for completition, error or timeout + # + nmap_exit_code=t.Wait(idlefunc=th.Check, interval=1) + # + # Check for timeout + # + if th.WasTimeOut(): + self.exit_code=self.CRITICAL + self.exit_msg='CRITICAL - Plugin timed out after %s seconds' % self.timeout + return + # + # Check for exit status of subprocess + # Must do this after check for timeout, since the subprocess + # also returns error if aborted. + # + if nmap_exit_code <> 0: + self.exit_code=self.UNKNOWN + self.exit_msg='nmap program failed with code %s' % nmap_exit_code + return + # + # Read output + # + try: + f = open(self.tmp_file, 'r') + output=f.readlines() + f.close() + except: + self.exit_code=self.UNKNOWN + self.exit_msg='Unable to get output from nmap' + return + + # + # Store open ports in list + # scans for lines where first word contains '/' + # and stores part before '/' + # + self.active_ports=[] + try: + for l in output: + if len(l)<2: + continue + s=string.split(l)[0] + if string.find(s,'/')<1: + continue + p=string.split(s,'/')[0] + self.active_ports.append(int(p)) + except: + # failure due to strange output... + pass + + if self.debug: + print 'Ports found by nmap: ',self.active_ports + # + # Filter out optional ports, we don't check status for them... + # + try: + for p in self.opt_ports: + self.active_ports.remove(p) + + if self.debug and len(self.opt_ports)>0: + print 'optional ports removed:',self.active_ports + except: + # under extreame loads the remove(p) above failed for me + # a few times, this exception hanlder handles + # this bug-alike situation... + pass + + opened=self.CheckOpen() + closed=self.CheckClosed() + + if opened <>'': + self.exit_code=self.CRITICAL + self.exit_msg='PORTS CRITICAL - Open:%s Closed:%s'%(opened,closed) + elif closed <>'': + self.exit_code=self.WARNING + self.exit_msg='PORTS WARNING - Closed:%s'%closed + else: + self.exit_code=self.OK + self.exit_msg='PORTS ok - Only defined ports open' + + + # + # Compares requested ports on with actually open ports + # returns all open that should be closed + # + def CheckOpen(self): + opened='' + for p in self.active_ports: + if p not in self.ports: + opened='%s %s' %(opened,p) + return opened + + # + # Compares requested ports with actually open ports + # returns all ports that are should be open + # + def CheckClosed(self): + closed='' + for p in self.ports: + if p not in self.active_ports: + closed='%s %s' % (closed,p) + return closed + + + def CleanUp(self): + # + # If temp file exists, get rid of it + # + if self.tmp_file<>'' and os.path.isfile(self.tmp_file): + try: + os.remove(self.tmp_file) + except: + # temp-file colition, some other process already + # removed the same file... + pass + + # + # Show numerical exits as string in debug mode + # + if self.debug: + print 'Exitcode:',self.exit_code, + if self.exit_code==self.UNKNOWN: + print 'UNKNOWN' + elif self.exit_code==self.OK: + print 'OK' + elif self.exit_code==self.WARNING: + print 'WARNING' + elif self.exit_code==self.CRITICAL: + print 'CRITICAL' + else: + print 'undefined' + # + # Check if invalid exit code + # + if self.exit_code<-1 or self.exit_code>2: + self.exit_msg=self.exit_msg+' - undefined exit code (%s)' % self.exit_code + self.exit_code=self.UNKNOWN + + + + + +# +# Help texts +# +def doc_head(): + print """ +check_nmap plugin for Nagios +Copyright (c) 2000 Jacob Lundqvist (jaclu@galdrion.com) +License: GPL +Version: %s""" % _version_ + + +def doc_syntax(): + print """ +Usage: check_ports [-v|--debug] [-H|--host host] [-V|--version] [-h|--help] + [-o|--optional port1,port2,port3 ...] [-r|--range range] + [-p|--port port1,port2,port3 ...] [-t|--timeout timeout]""" + + +def doc_help(): + 'Help is displayed if run without params.' + doc_head() + doc_syntax() + print """ +Options: + -h = help (this screen ;-) + -v = debug mode, show some extra output + -H host = host to check (name or IP#) + -o ports = optional ports that can be open (one or more), + no warning is given if optional port is closed + -p ports = ports that should be open (one or more) + -r range = port range to feed to nmap. Example: :1024,2049,3000:7000 + -t timeout = timeout in seconds, default 10 + -V = Version info + +This plugin attempts to verify open ports on the specified host. + +If all specified ports are open, OK is returned. +If any of them are closed, WARNING is returned (except for optional ports) +If other ports are open, CRITICAL is returned + +If possible, supply an IP address for the host address, +as this will bypass the DNS lookup. +""" + + +# +# Main +# +if __name__ == '__main__': + + if len (sys.argv) < 2: + # + # No params given, show syntax and exit + # + doc_syntax() + sys.exit(-1) + + nmap=CheckNmap(sys.argv[1:]) + exit_code,exit_msg=nmap.Run() + + # + # Give Nagios a msg and a code + # + print exit_msg + sys.exit(exit_code) diff --git a/contrib/check_nwstat.pl b/contrib/check_nwstat.pl new file mode 100644 index 00000000..2194640e --- /dev/null +++ b/contrib/check_nwstat.pl @@ -0,0 +1,188 @@ +#!/usr/bin/perl +# +# check_nwstat.pl: Nagios plugin that uses Jim Drews' nwstat.pl for +# MRTG instead of emulating it. For use particularly with Cliff +# Woolley's mrtgext.pl Unix companion to Drews' MRTGEXT.NLM, where +# mrtgext.pl can contain custom commands that check_nwstat won't recognize, +# though this also does its best to perfectly emulate the C version +# of check_nwstat. +# + + +###################################################################### +# Configuration +###################################################################### + +$nwstatcmd = "/apps/mrtg/helpers/nwstat.pl"; + +use Getopt::Long; + +$::host = shift || &usage(%ERROR); +$::opt_v = undef; +$::opt_wv = undef; +$::opt_cv = undef; +$::opt_to = 10; +$::opt_url = undef; + +GetOptions (qw(v=s wv=i cv=i to=i url=s)) || &usage(%ERROR); + +my $cmd1 = ""; +my $cmd2 = "ZERO"; +my $backward = 0; +my $desc = ""; +my $okstr = "OK"; +my $probstr = "Problem"; +my $result = ""; +my @CMD; +my %ERROR = ("UNKNOWN" => -1, + "OK" => 0, + "WARNING" => 1, + "CRITICAL" => 2); +my $status = $ERROR{"OK"}; + + +###################################################################### +# Main program +###################################################################### + +$SIG{'ALRM'} = sub { + print "Connection timed out\n"; + exit $ERROR{"CRITICAL"}; +}; + +# translate table for compatability with +# check_nwstat (C version) +SWITCH: for ($::opt_v) { + /^LOAD(1|5|15)$/ + && do { $desc = "Load <status> - Up <cmd2>, ". + "$1-min load average = <cmd0>%"; + $cmd1 = "UTIL$1"; last; }; + /^CONNS$/ && do { $desc = "Conns <status>: ". + "<cmd0> current connections"; + $cmd1 = "CONNECT"; last; }; + /^CDBUFF$/ && do { $desc = "Dirty cache buffers = <cmd0>"; + $cmd1 = "S3"; last; }; + /^LTCH$/ && do { $desc = "Long term cache hits = <cmd0>%"; + $cmd1 = "S1"; + $backward = 1; last; }; + /^CBUFF$/ && do { $desc = "Total cache buffers = <cmd0>"; + $cmd1 = "S2"; + $backward = 1; last; }; + /^LRUM$/ && do { $desc = "LRU sitting time = <cmd0> minutes"; + $cmd1 = "S5"; + $backward = 1; last; }; + /^VPF(.*)$/ && do { $desc = "<status><int(cmd0/1024)> MB ". + "(<result>%) free on volume $1"; + $okstr = ""; $probstr = "Only "; + $cmd1 = "VKF$1"; + $cmd2 = "VKS$1"; + $backward = 1; last; }; + /^VKF/ && do { $desc = "<status><cmd0> KB free on volume $1"; + $okstr = ""; $probstr = "Only "; + $cmd1 = "$::opt_v"; + $backward = 1; last; }; + /^$/ && die "Nothing to check!"; + $desc = "<status>: <cmd0>"; + $cmd1 = "$::opt_v"; + } + + +# begin timeout period, run the check +alarm($::opt_to); +open ( CMD, "$nwstatcmd $host $cmd1 $cmd2|" ) || die "Couldn't execute nwstat"; +@CMD = <CMD>; +close ( CMD ); +alarm(0); + +for (@CMD) { chomp; } + +# for any variables that manipulate the results instead of +# just using <cmd0> directly, do that manipulation here into <result> +SWITCH: for ($::opt_v) { + /^VPF/ && do { $result=int(("$CMD[0]"/"$CMD[1]")*100); last; }; + $result = "$CMD[0]"; + } + +if ("$result" == -1) { + $status = $ERROR{"UNKNOWN"}; + $desc = "Server returned \"variable unknown\""; +} elsif ("$result" == -2) { + $status = $ERROR{"CRITICAL"}; + $desc = "Connection failed"; +} + +if (defined($::opt_cv) && $status == $ERROR{"OK"}) { + if ($backward) { + ("$result" <= "$::opt_cv") && ( $status = $ERROR{"CRITICAL"} ); + } else { + ("$result" >= "$::opt_cv") && ( $status = $ERROR{"CRITICAL"} ); + } +} +if (defined($::opt_wv) && $status == $ERROR{"OK"}) { + if ($backward) { + ("$result" <= "$::opt_wv") && ( $status = $ERROR{"WARNING"} ); + } else { + ("$result" >= "$::opt_wv") && ( $status = $ERROR{"WARNING"} ); + } +} + +$desc =~ s/<status>/($status == $ERROR{"OK"})?"$okstr":"$probstr"/eg; +$desc =~ s/<([^>]*)cmd([0-3])([^>]*)>/eval("$1\"$CMD[$2]\"$3")/eg; +$desc =~ s/<result>/"$result"/eg; + +if (defined($::opt_url)) { + print "<A HREF=\"$::opt_url\">$desc</A>\n"; +} else { + print "$desc\n"; +} +exit $status; + + +###################################################################### +# Subroutines +###################################################################### + +sub usage { + + %ERROR = shift; + + print <<EOF +check_nwstat.pl plugin for Nagios +by Cliff Woolley, (c) 2000 + +Usage: ./check_nwstat.pl <host_address> [-v variable] [-wv warn_value] [-cv crit_value] [-to to_sec] [-url url_value] + +Options: + [variable] = Variable to check. Valid variables include: + LOAD1 = 1 minute average CPU load + LOAD5 = 5 minute average CPU load + LOAD15 = 15 minute average CPU load + CONNS = number of currently licensed connections + VPF<vol> = percent free space on volume <vol> + VKF<vol> = KB of free space on volume <vol> + LTCH = percent long term cache hits + CBUFF = current number of cache buffers + CDBUFF = current number of dirty cache buffers + LRUM = LRU sitting time in minutes + [warn_value] = Threshold for value necessary to result in a warning status + [crit_value] = Threshold for value necessary to result in a critical status + [to_sec] = Number of secs before connection times out - default is 10 sec + [url_value] = URL to use in output as a hyperlink. Useful to link to a page + with more details or history for this variable (ie an MRTG page) + +This plugin attempts to contact the MRTGEXT NLM running on a Novell server +to gather the requested system information. + +Notes: + - This plugin requres that the MRTGEXT.NLM file distributed with + James Drews' MRTG extension for NetWare (available from + http://www.engr.wisc.edu/~drews/mrtg/) be loaded on the Novell + servers you wish to check. + - Critical thresholds should be lower than warning thresholds when + the following variables are checked: VPF, VKF, LTCH, CBUFF, and LRUM. +EOF +; + + exit $ERROR{"UNKNOWN"}; +} + diff --git a/contrib/check_ora_table_space.pl b/contrib/check_ora_table_space.pl new file mode 100644 index 00000000..24497b24 --- /dev/null +++ b/contrib/check_ora_table_space.pl @@ -0,0 +1,82 @@ +#!/usr/bin/perl +# +# Program check_ora_table_space +# Written by: Erwan Arzur (erwan@netvalue.com) +# License: GPL +# +# Last Modified: $Date$ +# Revisiin: $Revision$ +# +# "check_ora_table_space.pl" plugin to check the state of Oracle +# table spaces. Scarce documentation. +# +# you need DBD-Oracle-1.03.tar.gz and DBI-1.13.tar.gz from CPAN.org as +# well as some Oracle client stuff to use it. +# +# The SQL request comes from www.dbasupport.com +# + +use DBI; +$ENV{"ORACLE_HOME"}="/intranet/apps/oracle"; + +my $host = shift || &usage ("no host specified"); +my $sid = shift || &usage ("no sid specified"); +my $port = shift || &usage ("no port specified"); +my $dbuser = shift || &usage ("no user specified"); +my $dbpass = shift || &usage ("no password specified"); +my $tablespace = shift || &usage ("no table space specified"); + +my $alertpct = int(shift) || &usage ("no warning state percentage specified"); +my $critpct = int(shift) || &usage ("no critical state percentage specified"); + +my $dbh = DBI->connect( "dbi:Oracle:host=$host;port=$port;sid=$sid", $dbuser, $dbpass, { PrintError => 0, AutoCommit => 1, RaiseError => 0 } ) + || &error ("cannot connect to $dbname: $DBI::errstr\n"); + +#$sth = $dbh->prepare(q{SELECT tablespace_name, SUM(BYTES)/1024/1024 FreeSpace FROM dba_free_space group by tablespace_name}) +my $exit_code = -1; +$sth = $dbh->prepare(<<EOF +select a.TABLESPACE_NAME, a.total,nvl(b.used,0) USED, +nvl((b.used/a.total)*100,0) PCT_USED +from (select TABLESPACE_NAME, sum(bytes)/(1024*1024) total +from sys.dba_data_files group by TABLESPACE_NAME) a, +(select TABLESPACE_NAME,bytes/(1024*1024) used from sys.SM\$TS_USED) b +where a.TABLESPACE_NAME='$tablespace' and + a.TABLESPACE_NAME=b.TABLESPACE_NAME(+) +EOF +) + || &error("Cannot prepare request : $DBI::errstr\n"); +$sth->execute + || &error("Cannot execute request : $DBI::errstr\n"); + +while (($tbname, $total, $used, $pct_used) = $sth->fetchrow) +{ + $pct_used=int($pct_used); + print STDOUT "size: " . $total . " MB Used:" . int($used) . " MB (" . int($pct_used) . "%)\n"; + #print "table space $answer\n"; + if ($pct_used > $alertpct) { + if ($pct_used > $critpct) { + $exit_code = 2 + } else { + $exit_code = 1; + } + } else { + $exit_code = 0; + } +} + +$rc = $dbh->disconnect + || &error ("Cannot disconnect from database : $dbh->errstr\n"); + +exit ($exit_code); + +sub usage { + print "@_\n" if @_; + print "usage : check_ora_table_space.pl <host> <sid> <port> <user> <passwd> <tablespace> <pctwarn> <pctcrit>\n"; + exit (-1); +} + +sub error { + print "@_\n" if @_; + exit (2); +} + diff --git a/contrib/check_pop3.pl b/contrib/check_pop3.pl new file mode 100644 index 00000000..c0c2712c --- /dev/null +++ b/contrib/check_pop3.pl @@ -0,0 +1,144 @@ +#!/usr/bin/perl +# ------------------------------------------------------------------------------ +# File Name: check_pop3.pl +# Author: Richard Mayhew - South Africa +# Date: 2000/01/21 +# Version: 1.0 +# Description: This script will check to see if an POP3 is running +# and whether authentication can take place. +# Email: netsaint@splash.co.za +# ------------------------------------------------------------------------------ +# Copyright 1999 (c) Richard Mayhew +# Credits go to Ethan Galstad for coding Nagios +# If any changes are made to this script, please mail me a copy of the +# changes :) +# License GPL +# ------------------------------------------------------------------------------ +# Date Author Reason +# ---- ------ ------ +# 1999/09/20 RM Creation +# 1999/09/20 TP Changed script to use strict, more secure by +# specifying $ENV variables. The bind command is +# still insecure through. Did most of my work +# with perl -wT and 'use strict' +# 2000/01/20 RM Corrected POP3 Exit State. +# 2000/01/21 RM Fix Exit Codes Again!! +# ------------------------------------------------------------------------------ + +# -----------------------------------------------------------------[ Require ]-- +require 5.004; + +# --------------------------------------------------------------------[ Uses ]-- +use Socket; +use strict; + +# --------------------------------------------------------------[ Enviroment ]-- +$ENV{PATH} = "/bin"; +$ENV{BASH_ENV} = ""; +$|=1; +# ------------------------------------------------------------------[ Global ]-- +my $TIMEOUT = 60; + +# -------------------------------------------------------------------[ usage ]-- +sub usage +{ + print "Minimum arguments not supplied!\n"; + print "\n"; + print "Perl Check POP3 plugin for Nagios\n"; + print "Copyright (c) 2000 Richard Mayhew\n"; + print "\n"; + print "Usage: check_pop3.pl <host> <username> <password> [port]\n"; + print "\n"; + print "<port> = Port that the pop3 daemon is running on <host>. Defaults to 110.\n"; + exit -1; + +} + +# --------------------------------------------------------------[ bindRemote ]-- +sub bindRemote +{ + my ($in_remotehost, $in_remoteport, $in_hostname) = @_; + my $proto; + my $sockaddr; + my $this; + my $thisaddr; + my $that; + my ($name, $aliases,$type,$len,$thataddr) = gethostbyname($in_remotehost); + + if (!socket(ClientSocket,AF_INET, SOCK_STREAM, $proto)) { die $!; } + $sockaddr = 'S n a4 x8'; + $this = pack($sockaddr, AF_INET, 0, $thisaddr); + $that = pack($sockaddr, AF_INET, $in_remoteport, $thataddr); + if (!bind(ClientSocket, $this)) { print "Connection Refused"; exit 2; } + if (!connect(ClientSocket, $that)) { print "Connection Refused"; exit 2; } + select(ClientSocket); $| = 1; select(STDOUT); + return \*ClientSocket; +} + +# ====================================================================[ MAIN ]== +MAIN: +{ + my $hostname; + my $remotehost = shift || &usage; + my $username = shift || &usage; + my $password = shift || &usage; + my $remoteport = shift || 110; + + # Just in case of problems, let's not hang Nagios + $SIG{'ALRM'} = sub { + print "Something is Taking a Long Time, Increase Your TIMEOUT (Currently Set At $TIMEOUT Seconds)\n"; + exit -1; + }; + + alarm($TIMEOUT); + + chop($hostname = `hostname`); + my ($name, $alias, $proto) = getprotobyname('tcp'); + my $ClientSocket = &bindRemote($remotehost,$remoteport,$hostname); + + +print ClientSocket "user $username\n"; + +#Debug Server +#print "user $username\n"; + +#Sleep or 3 secs, incase server is slow. +sleep 3; + +print ClientSocket "pass $password\n"; + +#Debug Server +#print "pass $password\n"; + +while (<ClientSocket>) { + +print ClientSocket "pass $password\n"; + +#Debug Server +#print $_; + +err($_) if (m/\-ERR\s+(.*)\s+.*/); +message($_) if (m/\+OK Mailbox open,\s+(.*\d)\s+messages.*/); +} +} + +sub message +{ + my $answer = "UNKNOWN"; + $answer = "Pop3 OK - Total Messages On Server :- $1"; + alarm(0); + print ClientSocket "quit\n"; + print "$answer"; + exit 0; +} + +sub err +{ + my $answer = "UNKNOWN"; + $answer = "Pop3 Error :- $1"; + alarm(0); + print ClientSocket "quit\n"; + print "$answer"; + exit 2; +} + diff --git a/contrib/check_qmailq.pl b/contrib/check_qmailq.pl new file mode 100755 index 00000000..4c3f68ff --- /dev/null +++ b/contrib/check_qmailq.pl @@ -0,0 +1,121 @@ +#!/usr/bin/perl +# +# check_qmailq.pl - nagios plugin +# This plugin allows you to check the number of Mails in a qmail- +# queue. PLUGIN NEEDS CONFIGURATION ! (see below) +# +# Copyright 2000 Benjamin Schmid +# +# 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. +# +# +# Emergency E-Mail :) blueshift@gmx.net +# + +### CONFIGURATION SECTION #################### + +my $statcommand = "/var/qmail/bin/qmail-qstat"; +my $queuewarn = 5; # Warning, if more than x mail in Queue +my $queuecrit = 10; # Critical if "--" +my $prewarn = 1; # Warning, if more than x unhandled mails + # (not in Queue +my $precrit = 5; # Critical, if "--" + +### CONFIURATION SECTION END ################ + +use strict; +use Carp; + +#use Getopt::Long; +#&Getopt::Long::config('auto_abbrev'); + + + +my $TIMEOUT = 15; + +my %ERRORS = ('UNKNOWN' , '-1', + 'OK' , '0', + 'WARNING', '1', + 'CRITICAL', '2'); + +my $state = "UNKNOWN"; +my $answer = ""; + +#sub usage { +# printf "\nMissing arguments!\n"; +# printf "\n"; +# printf "Printer Server Queue Nagios Plugin\n"; +# printf "monitors jobs in lpr queues\n"; +# printf "usage: \n"; +# printf "check_lpq.pl \n"; +# printf "Copyright (C) 2000 Benjamin Schmid\n"; +# printf "check_lpq.pl comes with ABSOLUTELY NO WARRANTY\n"; +# printf "This programm is licensed under the terms of the "; +# printf "GNU General Public License\n(check source code for details)\n"; +# printf "\n\n"; +# exit $ERRORS{"UNKNOWN"}; +#} + +# Just in case of problems, let's not hang Nagios +$SIG{'ALRM'} = sub { + print ("ERROR: check_lpq.pl Time-Out $TIMEOUT s \n"); + exit $ERRORS{"UNKNOWN"}; +}; +alarm($TIMEOUT); + + +#$status = GetOptions("community=s",\$community, +# "port=i",\$port); +#if ($status == 0) +#{ +# &usage; +#} + +# $hostname = shift || &usage; + +if (! open STAT, "$statcommand|") { + print ("$state: $statcommand returns no result!"); + exit $ERRORS{$state}; +} +my @lines = <STAT>; +close STAT; + +# Mails in Queues +if ($lines[0]=~/^messages in queue: (\d+)/) { + my $anzq = $1; + $answer = $answer . "$anzq"; + $state='WARNING' if ($anzq >= $queuewarn); + $state='CRITICAL' if ($anzq >= $queuecrit); +} else { + $state='CRITICAL'; + $answer="Keine gueltigte Antwort (Zeile #1) von $statcommand\n"; +} + +# Unverarbeite Mails +if ($lines[1]=~/^messages in queue but not yet preprocessed: (\d+)/) { + my $anzp = $1; + $answer = $answer . " E-Mail(s) nicht ausgeliefert, $anzp unverarbeitet."; + $state='WARNING' if ($anzp >= $prewarn && $state eq 'UNKNOWN'); + $state='CRITICAL' if ($anzp >= $precrit); +} else { + $state='CRITICAL'; + $answer=$answer . "Keine gueltigte Antwort (Zeile #2) von $statcommand\n"; +} + +$state = 'OK' if ($state eq 'UNKNOWN'); + +print ("$state: $answer\n"); +exit $ERRORS{$state}; + diff --git a/contrib/check_rrd_data.pl b/contrib/check_rrd_data.pl new file mode 100644 index 00000000..0ff8750b --- /dev/null +++ b/contrib/check_rrd_data.pl @@ -0,0 +1,129 @@ +#!/usr/bin/perl -wT + +# check_rrd_data plugin for nagios +# +# usage: +# check_rrd machine_id perlexp_warn perlexp_crit perlexp_default [ds] +# +# Checks data from a RRD file. machine_id is normally an IP address, that has +# to be mapped to a RRD file, by means of the config file (by default +# /var/spool/nagios/rrd-files, a file with pairs of (machine_id,rrd_file), +# separated by whitespace). It can be a RRD file, too. +# +# The Perl expressions are expressions to be evaluated in the following cases: +# +# - perlexp_crit. The first one, to check if there is a critical situation. If +# it returns other than "", it will be a critical message. +# - perlexp_warn. The second one to be evaluated. If returns other than "", a +# warning will be issued to Nagios. +# - perlexp_default. If both of the above return "", it will be evaluated, and +# wathever returns this expression will be returned by the script. NOTE that +# this is different from the other two cases, to allow the user issue a +# warning or critical failure even if the other two don't return it. +# +# Use these hosts.cfg entries as examples +# +# command[check_ping]=$USER1$/check_rrd_data.pl $HOSTADDRESS$ \ +# 'return "CHECK_CRICKET_PING: Warning\n" if ($value > 10);' 'return \ +# "CHECK_CRICKET_PING: Critical\n" if ($value > 100);' 'printf \ +# "PING OK - RTA = %.2fms\n", $value; return 0;' 1 +# service[machine]=PING;0;24x7;3;5;1;router-admins;240;24x7;1;1;1;;check_ping +# +# initial version: 28 Nov 2000 by Esteban Manchado Velázquez +# current status: 0.1 +# +# Copyright Notice: GPL +# + +# Doesn't work! Why? +# BEGIN { + # my $runtimedir = substr($0,0,rindex($0,'/')); + # require "$runtimedir/utils.pm"; +# } + +require '/usr/libexec/nagios/plugins/utils.pm'; +use RRD::File; +# use strict; # RRD:File and utils.pm don't like this + +my $configfilepath = "/var/spool/nagios/rrd-files"; # Change if needed +my %hostfile; # For storing config +my $rrdfile; # RRD file to open + +$ENV{'PATH'} = "/bin:/usr/bin"; +$ENV{'ENV'} = ""; + +if (scalar @ARGV != 4 && scalar @ARGV != 5) { + print STDERR join "' '", @ARGV, "\n"; + my $foo = 'check_rrd_data'; + print STDERR $foo, " <file.rrd> <perl_exp_warn> <perl_exp_crit> <perl_exp_default> [<ds>]\n\n"; + print STDERR "<perl_exp_*> is an expression that gets evaluated with \$_ at the current\n"; + print STDERR "value of the data source. If it returns something other than \"\", there\n"; + print STDERR "will be a warning or a critical failure. Else, the expression\n"; + print STDERR "<perl_exp_default> will be evaluated\n"; + exit; +} + +# Check configuration file +open F, $configfilepath or do { + print "Can't open config file $configfilepath\n"; + return $ERRORS{'UNKNOWN'}; +}; +while (<F>) { + next unless /(.+)\s+(.+)/; + $hostfile{$1} = $2; +} +close F; + +# Default +my $ds = defined $ARGV[4]?$ARGV[4]:0; + # print "\$ds = " . $ds . ":"; + # print "\$ARGV[4] = " . $ARGV[4] . ":"; +$ds =~ s/\$//g; # Sometimes Nagios gives 1$ as the last parameter + +# Guess which RRD file have to be opened +$rrdfile = $ARGV[0] if (-r $ARGV[0]); # First the parameter +$rrdfile = $hostfile{$ARGV[0]} unless $rrdfile; # Second, the config file + # print "$ARGV[0]:"; + +if (! $rrdfile) { + print "Can't open data file for $ARGV[0]\n"; # Aaaargh! + return $ERRORS{'UNKNOWN'}; # Unknown +} + + # print "Opening file $rrdfile:"; +my $rrd = new RRD::File ( -file => $rrdfile ); +$rrd->open(); +if (! $rrd->loadHeader()) { + print "Couldn't read header from $rrdfile\n"; + exit $ERRORS{'UNKNOWN'}; # Unknown +} +my $value = $rrd->getDSCurrentValue($ds); +$rrd->close(); + +# Perl expressions to evaluate +my ($perl_exp_warn, $perl_exp_crit, $perl_exp_default) = + ($ARGV[1], $ARGV[2], $ARGV[3]); +my $result; # Result of the expressions (will be printed) +my @data; # Special data reserved for the expressions, to pass data + +# First check for critical errors +$perl_exp_crit =~ /(.*)/; +$perl_exp_crit = $1; +$result = eval $perl_exp_crit; +if ($result) { + print $result; + exit 2; # Critical +} + +# Check for warnings +$perl_exp_warn =~ /(.*)/; +$perl_exp_warn = $1; +$result = eval $perl_exp_warn; +if ($result) { + print $result; + exit 1; # Warning +} + +$perl_exp_default =~ /(.*)/; +$perl_exp_default = $1; +eval $perl_exp_default; # Normally returns 0 (OK) diff --git a/contrib/check_sap.sh b/contrib/check_sap.sh new file mode 100755 index 00000000..eadf977e --- /dev/null +++ b/contrib/check_sap.sh @@ -0,0 +1,70 @@ +#!/bin/sh +################################################################################ +# +# CHECK_SAP plugin for Nagios +# +# Written by Karel Salavec (karel.salavec@ct.cz) +# Last Modified: 20Apr2000 +# +# Command line: CHECK_SAP <typ_of_check> <param1> <param2> [<param3>] +# +# Description: +# This plugin will attempt to open an SAP connection with the message +# server or application server. +# It need the sapinfo program installed on your server (see Notes). +# +# Notes: +# - This plugin requires that the saprfc-devel-45A-1.i386.rpm (or higher) +# package be installed on your machine. Sapinfo program +# is a part of this package. +# - You can find this package at SAP ftp server in +# /general/misc/unsupported/linux +# +# +# Parameters: +# $1 - type of checking - valid values: "ms" = message server +# "as" = application server +# $2 - SAP server identification - can be IP address, DNS name or SAP +# connect string (for example: /H/saprouter/S/sapdp01/H/sapserv3) +# $3 - for $1="ms" - SAP system name (for example: DEV, TST, ... ) +# for $1="as" - SAP system number - note: central instance have sysnr=00 +# $4 - valid only for $1="ms" - logon group name - default: PUBLIC +# +# Example of command definitions for nagios: +# +# command[check_sap_ms]=/usr/local/nagios/libexec/check_sap ms $HOSTADDRESS$ $ARG1$ $ARG2$ +# command[check_sap_as]=/usr/local/nagios/libexec/check_sap as $HOSTADDRESS$ $ARG1$ +# command[check_sap_ex]=/usr/local/nagios/libexec/check_sap as $ARG1$ $ARG2$ +# (for ARG1 see SAP OOS1 transaction) +# +############################################################################## + +if [ $# -lt 3 ]; then +echo "Need min. 3 parameters" +exit 2 +fi + +case "$1" + in + ms) + if [ $4 ] + then + params="r3name=$3 mshost=$2 group=$4" + else + params="r3name=$3 mshost=$2" + fi + ;; + as) + params="ashost=$2 sysnr=$3" + ;; + *) + echo "The first parametr must be ms (message server) or as (application server)!" + exit 2 + ;; +esac + +if /usr/sap/rfcsdk/bin/sapinfo $params | grep -i ERROR ; then +exit 2 +else +exit 0 +fi diff --git a/contrib/check_sockets.pl b/contrib/check_sockets.pl new file mode 100644 index 00000000..b8ae24a2 --- /dev/null +++ b/contrib/check_sockets.pl @@ -0,0 +1,145 @@ +#! /usr/bin/perl +# ------------------------------------------------------------------------------ +# File Name: check_sockets.pl +# Author: Richard Mayhew - South Africa +# Date: 2000/07/11 +# Version: 1.0 +# Description: This script will check to see how may open sockets +# a server has and waron respectivly +# Email: netsaint@splash.co.za +# ------------------------------------------------------------------------------ +# Copyright 1999 (c) Richard Mayhew +# Credits go to Ethan Galstad for coding Nagios +# If any changes are made to this script, please mail me a copy of the +# changes :) +# Some code taken from Charlie Cook (check_disk.pl) +# License GPL +# +# ------------------------------------------------------------------------------ +# Date Author Reason +# ---- ------ ------ +# 1999/09/20 RM Creation +# 1999/09/20 TP Changed script to use strict, more secure by +# specifying $ENV variables. The bind command is +# still insecure through. Did most of my work +# with perl -wT and 'use strict' +# +# ------------------------------------------------------------------------------ + +# -----------------------------------------------------------------[ Require ]-- +require 5.004; +# --------------------------------------------------------------------[ Uses ]-- +use Socket; +use strict; +# --------------------------------------------------------------[ Enviroment ]-- +$ENV{'PATH'}='/bin:/sbin:/usr/bin:/usr/sbin'; +$ENV{BASH_ENV} = ""; +# ------------------------------------------------------------------[ Global ]-- +my $TIMEOUT = 20; +my %ERRORS = ( + 'UNKNOWN', '-1', + 'OK', '0', + 'WARNING', '1', + 'CRITICAL', '2'); +# --------------------------------------------------------------[ connection ]-- +sub connection +{ + my ($in_total,$in_warn,$in_crit,$in_high) = @_; + my $state; + my $answer; + + $in_total =~ s/\ //g; + if ($in_total >= 0) { + + if ($in_total > $in_crit) { + $state = "CRITICAL"; + $answer = "Critical Number Of Sockets Connected : $in_total (Limit = $in_crit)\n"; + + } elsif ($in_total > $in_warn) { + $state = "WARNING"; + $answer = "Warning Number Of Sockets Connected : $in_total (Limit = $in_warn)\n"; + + } else { + if ($in_high ne "") { + $answer = "Sockets OK - Current Sockets: $in_total : $in_high\n"; + } + if ($in_high eq "") { + $answer = "Sockets OK - Current Sockets: $in_total\n"; + } + $state = "OK"; + } + + } else { + $state = "UNKNOWN"; + $answer = "Something is Really WRONG! Sockets Is A Negative Figure!\n"; + } + + print $answer; + exit $ERRORS{$state}; +} + +# -------------------------------------------------------------------[ usage ]-- +sub usage +{ + print "Minimum arguments not supplied!\n"; + print "\n"; + print "Perl Check Sockets plugin for Nagios\n"; + print "Copyright (c) 2000 Richard Mayhew\n"; + print "\n"; + print "Usage: check_sockets.pl <type> <warn> <crit>\n"; + print "\n"; + print "<type> = TOTAL, TCP, UDP, RAW.\n"; + print "<warn> = Number of sockets connected at which a warning message will be generated.[Default = 256]\n"; + print "<crit> = Number of sockets connected at which a critical message will be generated.[Default = 512]\n"; + exit $ERRORS{"UNKNOWN"}; + +} + +# ====================================================================[ MAIN ]== +MAIN: +{ + my $type = shift || &usage; + my $warn = shift || 256; + my $crit = shift || 512; + my $data; + my @data; + my $line; + my $data1; + my $data2; + my $data3; + my $junk; + my $total1; + my $total2; + $type = uc $type; + if ($type eq "TOTAL") { + $type = "sockets"; + } + + # Just in case of problems, let's not hang Nagios + $SIG{'ALRM'} = sub { + print "Somthing is Taking a Long Time, Increase Your TIMEOUT (Currently Set At $TIMEOUT Seconds)\n"; + exit $ERRORS{"UNKNOWN"}; + }; + + $data = `/bin/cat /proc/net/sockstat`; + @data = split("\n",$data); + alarm($TIMEOUT); + my $output = ""; + my $high; + + + foreach $line (@data) { + if ($line =~ /$type/) { + ($data1,$data2,$data3) = split(" ",$line,3); + + if ($data3 =~ /highest/){ + ($total1,$junk,$total2) = split(" ",$data3,3); + $output = $total1; + $high = $total2; + } + else {$output = $data3;} + alarm(0); + connection($output,$warn,$crit,$high); + } + } +} diff --git a/contrib/check_timeout.c b/contrib/check_timeout.c new file mode 100644 index 00000000..858bdfe9 --- /dev/null +++ b/contrib/check_timeout.c @@ -0,0 +1,55 @@ +/***************************************************************************** + * + * CHECK_TIMEOUT.C + * + * Program: Plugin timeout tester for Nagios + * License: GPL + * Copyright (c) 1999 Ethan Galstad (nagios@nagios.org) + * + * Last Modified: 01-10-2000 + * + * Command line: CHECK_TIMEOUT <something..> + * + * Description: + * This 'plugin' - if you want to call it that - doesn't do anything. It + * just stays in a loop forever and never exits, and is therefore useful for + * testing service and host check timeouts in Nagios. You must supply at + * least one argument on the command line in order to activate the loop. + * + ****************************************************************************/ + +#include <stdio.h> +#include <unistd.h> + + +int main(int argc, char **argv){ + + if(argc==1){ + printf("Incorrect arguments supplied\n"); + printf("\n"); + printf("Plugin timeout tester for Nagios\n"); + printf("Copyright (c) 1999 Ethan Galstad (nagios@nagios.org)\n"); + printf("Last Modified: 01-10-2000\n"); + printf("License: GPL\n"); + printf("\n"); + printf("Usage: %s <something>\n",argv[0]); + printf("\n"); + printf("Options:\n"); + printf(" <something> = Anything at all...\n"); + printf("\n"); + printf("Notes:\n"); + printf("This 'plugin' doesn't do anything. It is designed to never exit and therefore\n"); + printf("provides an easy way of testing service and host check timeouts in Nagios.\n"); + printf("\n"); + return 0; + } + + /* let's never leave here, okay? */ + while(1) + sleep(1); + + return 0; + } + + + diff --git a/contrib/check_uptime.c b/contrib/check_uptime.c new file mode 100644 index 00000000..46a1b826 --- /dev/null +++ b/contrib/check_uptime.c @@ -0,0 +1,99 @@ +/****************************************************************************** + * + * CHECK_UPTIME.C + * + * Program: Uptime plugin for Nagios + * License: GPL + * Copyright (c) 2000 Teresa Ramanan (teresa@redowl.org) + * + * Based on CHECK_LOAD.C + * Copyright (c) 1999 Felipe Gustavo de Almeida <galmeida@linux.ime.usp.br> + * + * Last Modified: $Date$ + * + * Command line: CHECK_UPTIME <host_address> + * + * Description: + * + * This plugin parses the output from "uptime", tokenizing it with ',' as the + * delimiter. Returning only the number of days and/or the hours and minutes + * a machine has been up and running. + * + *****************************************************************************/ + +#include "common/config.h" +#include "common/common.h" +#include "common/utils.h" +#include "common/popen.h" + +int main(int argc, char **argv) +{ + + int result; + char input_buffer[MAX_INPUT_BUFFER]; + int ct; + int i; + char *tok1 = NULL; + char *daytok = NULL; + char *hrmintok = NULL; + char *runstr = NULL; + char tempp; + char ch; + char delim[] = ","; + + if(argc != 2){ + printf("Incorrect number of arguments supplied\n"); + printf("\n"); + print_revision(argv[0],"$Revision$"); + printf("Copyright (c) 2000 Teresa Ramanan (tlr@redowl.org)\n"); + printf("\n"); + printf("Usage: %s <host_address>\n",argv[0]); + printf("\n"); + return STATE_UNKNOWN; + } + + child_process = spopen(PATH_TO_UPTIME); + if(child_process==NULL){ + printf("Error opening %s\n",PATH_TO_UPTIME); + return STATE_UNKNOWN; + } + child_stderr=fdopen(child_stderr_array[fileno(child_process)],"r"); + if(child_stderr==NULL){ + printf("Could not open stderr for %s\n",PATH_TO_UPTIME); + } + fgets(input_buffer,MAX_INPUT_BUFFER-1,child_process); + i = 0; + ct = 0; + + /* Let's mark the end of this string for parsing purposes */ + input_buffer[strlen(input_buffer)-1]='\0'; + + tempp = input_buffer[0]; + while(ch != '\0'){ + ch = (&tempp)[i]; + if (ch == ',') { ct++; } + i++; + } + runstr = input_buffer; + tok1 = strsep(&runstr, delim); + if (ct > 4) { + hrmintok = strsep(&runstr, delim); + hrmintok++; + daytok = strstr(tok1,"up"); + } + else { + hrmintok = strstr(tok1, "up"); + } + + result = spclose(child_process); + if(result){ + printf("Error code %d returned in %s\n",result,PATH_TO_UPTIME); + return STATE_UNKNOWN; + } + if (hrmintok == NULL) { + printf("Problem - unexpected data returned\n"); + return STATE_UNKNOWN; + } + printf("%s%s%s\n",(daytok == NULL)?"":daytok,(daytok == NULL)?"":",",hrmintok); + return STATE_OK; +} diff --git a/contrib/checkciscotemp.pl b/contrib/checkciscotemp.pl new file mode 100644 index 00000000..a702a89e --- /dev/null +++ b/contrib/checkciscotemp.pl @@ -0,0 +1,163 @@ +#!/usr/bin/perl -wT +# check_ciscotemp.pl +# +# Copyright (C) 2000 Leland E. Vandervort <leland@mmania.com> +# +# 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 (or with Nagios); if not, write to the +# Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA +#################################### +# Nagios pluging to check inlet and outlet temperatures on +# Cisco router platforms which support environmental monitoring +# (7200, 7500, GSR12000...) +#################################### +# default temperature thresholds are 30C for inlet, 40C outlet. +# if input or output is less than thresholds, returns OK +# if equal to (the temps don't change that rapidly) returns WARNING +# if greater than threshold, returns CRITICAL +# if undetermined, or cannot access environmental, returns UNKNOWN +# (in accordance with the plugin coding guidelines) +#################################### + +use Net::SNMP; +use Getopt::Long; +&Getopt::Long::config('auto_abbrev'); + +my $status; +my $response = ""; +my $timeout = 10; +my $community = "public"; +my $port = 161; +my $INTAKE_TEMP = "1.3.6.1.4.1.9.9.13.1.3.1.3.1"; +my $OUTLET_TEMP = "1.3.6.1.4.1.9.9.13.1.3.1.3.3"; +my $in_temp; +my $out_temp; +my $inlet_thresh = 30; +my $outlet_thresh = 40; + +my %STATUSCODE = ( 'UNKNOWN' => '-1', + 'OK' => '0', + 'WARNING' => '1', + 'CRITICAL' => '2'); + +my $state = "UNKNOWN"; + + +$SIG{'ALRM'} = sub { + print "ERROR: No snmp response from $hostname (sigALRM)\n"; + exit($STATUSCODE{"UNKNOWN"}); +}; + +Getopt::Long::Configure('bundling'); +$status = GetOptions + ("community=s", \$community, + "C=s", \$community, + "H=s", \$hostname, + "hostname=s", \$hostname, + "port=i", \$port, + "timeout=i", \$timeout, + "c=s", \$critical_vals, + "w=s", \$warning_vals, + "ithresh=i", \$inlet_thresh, + "othresh=i", \$outlet_thresh); + +if($status == 0) { + &show_help; +} + +unless (defined($hostname)) { + $hostname = shift || &show_help; +} + +if (defined($critical_vals)) { + die "Cannot Parse Critical Thresholds\n" + unless (split(/:/,$critical_vals)>=2); + ($inlet_thresh,$outlet_thresh) = @_ +} +die unless(defined($inlet_thresh) && defined($outlet_thresh)); + +if (defined($warning_vals)) { + die "Cannot Parse Critical Thresholds\n" + unless (split(/:/,$warning_vals)>=2); + ($inlet_warn,$outlet_warn) = @_; +}else{ + $inlet_warn=$inlet_thresh; + $outlet_warn=$outlet_thresh; +} + +alarm($timeout); + +$in_temp = &SNMPGET($INTAKE_TEMP); +$out_temp = &SNMPGET($OUTLET_TEMP); + +if (($in_temp < $inlet_thresh) && ($out_temp < $outlet_thresh)) { + $state = "OK"; +} +elsif (($in_temp == $inlet_thresh) || ($out_temp == $outlet_thresh)) { + if(($in_temp > $inlet_thresh) || ($out_temp > $outlet_thresh)) { + $state = "CRITICAL"; + } + else { + $state = "WARNING"; + } +} +elsif (($in_temp > $inlet_thresh) || ($out_temp > $outlet_thresh)) { + $state = "CRITICAL"; +} +else { + $state = "WARNING"; +} + +print "$state Inlet Temp: $in_temp Outlet Temp: $out_temp\n"; +exit($STATUSCODE{$state}); + +sub show_help { + printf("\nPerl envmon temperature plugin for Nagios\n"); + printf("Usage:\n"); + printf(" + check_ciscotemp [options] <hostname> + Options: + -C snmp-community + -p snmp-port + -i input temperature threshold + -o output temperature threshold + +"); + printf("Copyright (C)2000 Leland E. Vandervort\n"); + printf("check_ciscotemp comes with absolutely NO WARRANTY either implied or explicit\n"); + printf("This program is licensed under the terms of the\n"); + printf("GNU General Public License\n(check source code for details)\n\n\n"); + exit($STATUSCODE{"UNKNOWN"}); +} + +sub SNMPGET { + $OID = shift; + ($session,$error) = Net::SNMP->session( + Hostname => $hostname, + Community => $community, + Port => $port + ); + if(!defined($session)) { + printf("$state %s\n", $error); + exit($STATUSCODE{$state}); + } + if(!defined($response = $session->get_request($OID))) { + printf("$state %s\n", $session->error()); + $session->close(); + exit($STATUSCODE{$state}); + } + $session->close(); + return($response->{$OID}); +} + diff --git a/contrib/maser-oracle.pl b/contrib/maser-oracle.pl new file mode 100644 index 00000000..aa2741f1 --- /dev/null +++ b/contrib/maser-oracle.pl @@ -0,0 +1,13 @@ +#!/usr/bin/perl + +# Oracle plugin submitted by Christopher Maser (maser@onvista.de) +# 12/31/1999 + +my $host=$ARGV[0]; +my @test=`tnsping $host`; +my $arg=$test[6]; +chomp $arg; +if ($arg =~ /^OK (.*)/) +{print "$arg"; exit 0} +else {exit 2;} + diff --git a/contrib/mrtgext.pl b/contrib/mrtgext.pl new file mode 100644 index 00000000..b9e9f6b9 --- /dev/null +++ b/contrib/mrtgext.pl @@ -0,0 +1,291 @@ +#!/usr/bin/perl -w +# +# mrtgext.pl v0.3 +# (c)2000 Cliff Woolley, Washington and Lee University +# jwoolley@wlu.edu +# +# A UNIX counterpart to Jim Drews' MRTG Extension for netware servers +# Mimics output of mrtgext.nlm using output of various standard UNIX +# programs (df, uptime, and uname) +# +# Dependencies: I make some assumptions about the output format of +# your df and uptime commands. If you have nonstandard outputs for +# any of these, either pick a different command that gives more +# standard output or modify the script below. Example: use /usr/bin/bdf +# on HP-UX instead of /usr/bin/df, because bdf follows the output format +# I expect while df does not. This was written on Linux and tested on +# HP-UX 10.20 (with changes to the subroutines at the bottom of the +# program to reflect HP's command parameters); similar tweaking could +# well be required to port this to other platforms. If you get it +# working on your platform, please send me any changes you had to +# make so I can try to incorporate them. +# +# +# Following is what I expect the programs' outputs to look like: +# +# ======= df ======== +# Filesystem 1k-blocks Used Available Use% Mounted on +# /dev/sda1 1014696 352708 609612 37% / +# /dev/sda2 2262544 586712 1559048 27% /apps +# /dev/sda3 4062912 566544 3286604 15% /share +# /dev/sr0 651758 651758 0 100% /cdrom +# =================== +# +# ===== uptime ====== +# 3:17pm up 15 days, 4:40, 5 users, load average: 0.12, 0.26, 0.33 +# =================== +# + +############################################################### +# Configuration section +############################################################### + +$dfcmd = "/bin/df 2>/dev/null"; +$uptimecmd = "/usr/bin/uptime"; +%customcmds = ( "PROCS" => "numprocesses", + "ZOMBIES" => "numzombies", + "MEMFREE" => "memfree", + "SWAPUSED" => "swapused", + "TCPCONNS" => "tcpconns", + "CLIENTS" => "ipclients" ); + # These are functions that you can + # define and customize for your system. + # You probably need to change the provided + # subroutines to work on your system (if + # not Linux). + +$rootfsnickname = "root"; # this is necessary as a kludge to + # better match the netware behavior. + # if you already have a _filesystem_ + # mounted as /root, then you'll need + # to change this to something else +$DEBUG = 0; +$recvtimeout = 30; + + +############################################################### +# Program section +############################################################### + +require 5.004; + +use Sys::Hostname; + + +$DEBUG = $ARGV[0] unless ($DEBUG); +$SIG{'ALRM'} = sub { exit 1; }; + +# some things never change +$hostname = hostname; + + +if ( $DEBUG ) { + $| = 1; + print scalar localtime,": mrtgext.pl started\n"; +} + +# timeout period +alarm($recvtimeout); +my $items = <STDIN>; +alarm(0); + +$items =~ s/[\r\n]//g; +( $DEBUG ) && print scalar localtime,": request: \"$items\"\n"; +my @items = split (/\s+/,"$items"); +( $DEBUG ) && print scalar localtime,": ",scalar @items," item(s) to process\n"; + +my $uptime = `$uptimecmd`; +my @df = grep {/^\//} `$dfcmd`; + +my $processed = 1; + +foreach $_ (@items) { + ( $DEBUG ) && print scalar localtime,": processing item #$processed: \"$_\"\n"; + $_ = uc; #convert $_ to upper case + if ( /^UTIL1$/ ) { + $uptime =~ /load average: ([^,]+),/; + print $1 * 100,"\n"; + } + elsif ( /^UTIL5$/ ) { + $uptime =~ /load average: [^,]+, ([^,]+)/; + print $1 * 100,"\n"; + } + elsif ( /^UTIL15$/ ) { + $uptime =~ /load average: [^,]+, [^,]+, ([^,]+)/; + print $1 * 100,"\n"; + } + elsif ( /^CONNECT$/ ) { + $uptime =~ /(\d+) users?,/; + print "$1\n"; + } + elsif ( /^NAME$/ ) { + print "$hostname\n"; + } + elsif ( /^UPTIME$/ ) { + $uptime =~ /up (.*),\s+\d+\s+users?,/; + print "$1\n"; + } + elsif ( /^VOLUMES$/ ) { + foreach $dfline (@df) { + my $volname = (split(/\s+/, "$dfline"))[5]; + $volname =~ s/^\/$/$rootfsnickname/; + $volname =~ s/^\///; + $volname =~ s/\//_/g; + print "$volname\n"; + } + } + elsif ( /^VF(\w*)$/ ) { + my $volname = ("$1" eq uc("$rootfsnickname")) ? "/" : "$1"; + foreach $dfline (@df) { + my @dfline = split(/\s+/, "$dfline"); + if ($dfline[5] =~ /^\/?$volname$/i ) { + print (($dfline[1]-$dfline[2]) * 1024,"\n"); + goto done; + } + } + ( $DEBUG ) && print scalar localtime,": ERROR: volume not found.\n"; + print "-1\n"; + } + elsif ( /^VU(\w*)$/ ) { + my $volname = ("$1" eq uc("$rootfsnickname")) ? "/" : "$1"; + foreach $dfline (@df) { + my @dfline = split(/\s+/, "$dfline"); + if ($dfline[5] =~ /^\/?$volname$/i ) { + print ($dfline[2] * 1024,"\n"); + goto done; + } + } + ( $DEBUG ) && print scalar localtime,": ERROR: volume not found.\n"; + print "-1\n"; + } + elsif ( /^VS(\w*)$/ ) { + my $volname = ("$1" eq uc("$rootfsnickname")) ? "/" : "$1"; + foreach $dfline (@df) { + my @dfline = split(/\s+/, "$dfline"); + if ($dfline[5] =~ /^\/?$volname$/i ) { + print ($dfline[1] * 1024,"\n"); + goto done; + } + } + ( $DEBUG ) && print scalar localtime,": ERROR: volume not found.\n"; + print "-1\n"; + } + elsif ( /^VKF(\w*)$/ ) { + my $volname = ("$1" eq uc("$rootfsnickname")) ? "/" : "$1"; + foreach $dfline (@df) { + my @dfline = split(/\s+/, "$dfline"); + if ($dfline[5] =~ /^\/?$volname$/i ) { + print (($dfline[1]-$dfline[2]),"\n"); + goto done; + } + } + ( $DEBUG ) && print scalar localtime,": ERROR: volume not found.\n"; + print "-1\n"; + } + elsif ( /^VKU(\w*)$/ ) { + my $volname = ("$1" eq uc("$rootfsnickname")) ? "/" : "$1"; + foreach $dfline (@df) { + my @dfline = split(/\s+/, "$dfline"); + if ($dfline[5] =~ /^\/?$volname$/i ) { + print ($dfline[2],"\n"); + goto done; + } + } + ( $DEBUG ) && print scalar localtime,": ERROR: volume not found.\n"; + print "-1\n"; + } + elsif ( /^VKS(\w*)$/ ) { + my $volname = ("$1" eq uc("$rootfsnickname")) ? "/" : "$1"; + foreach $dfline (@df) { + my @dfline = split(/\s+/, "$dfline"); + if ($dfline[5] =~ /^\/?$volname$/i ) { + print ($dfline[1],"\n"); + goto done; + } + } + ( $DEBUG ) && print scalar localtime,": ERROR: volume not found.\n"; + print "-1\n"; + } + elsif ( /^ZERO$/ ) { + print "0\n"; + } + elsif (exists( $customcmds{"$_"} )) { + my $cmdsub = "$customcmds{$_}"; + print &$cmdsub."\n"; + } + else { + print "-1\n"; + } + done: $processed++; +} +( $DEBUG ) && print scalar localtime,": done.\n"; + + +############################################################### +# CUSTOMIZED PROCEDURES +############################################################### + +sub numprocesses { + + my $num = `/bin/ps -eaf | /usr/bin/tail -n +2 | /usr/bin/wc -l`; + chomp ($num); + $num =~ s/\s+//g; + + $num; +} + +sub numzombies { + + my $num = `/bin/ps -afx | /usr/bin/awk '{print \$3}' | /usr/bin/grep Z | /usr/bin/tail -n +2 | /usr/bin/wc -l`; + chomp ($num); + $num =~ s/\s+//g; + + $num; +} + +sub tcpconns { + + my $num = `/bin/netstat -nt | /usr/bin/tail -n +3 | /usr/bin/wc -l`; + chomp ($num); + $num =~ s/\s+//g; + + $num; +} + +sub ipclients { + + my $num = `/bin/netstat -nt | /usr/bin/tail -n +3 | /usr/bin/awk '{print \$5}' | /bin/cut -d : -f 1 | /usr/bin/sort -nu | /usr/bin/wc -l`; + chomp ($num); + $num =~ s/\s+//g; + + $num; +} + +sub memfree { + + open( FP, "/proc/meminfo" ); + my @meminfo = <FP>; + close(FP); + + # total: used: free: shared: buffers: cached: + # Mem: 994615296 592801792 401813504 91193344 423313408 93118464 + # Swap: 204791808 0 204791808 + my ($total,$free,$buffers,$cache) = (split(/ +/,$meminfo[1]))[1,3,5,6]; + + int(($free+$buffers+$cache)/$total*100); +} + +sub swapused { + + open( FP, "/proc/meminfo" ); + my @meminfo = <FP>; + close(FP); + + # total: used: free: shared: buffers: cached: + # Mem: 994615296 592424960 402190336 89821184 423313408 93077504 + # Swap: 204791808 0 204791808 + + my ($total,$used) = (split(/ +/,$meminfo[2]))[1,2]; + + int($used/$total*100); +} diff --git a/contrib/readme.txt b/contrib/readme.txt new file mode 100644 index 00000000..d9ae0250 --- /dev/null +++ b/contrib/readme.txt @@ -0,0 +1,147 @@ +Contrib Plugins README +---------------------- + +This directory contains plugins which have been contributed by various people, but that +have not yet been incorporated into the core plugins distribution. + +If you have questions regarding the use of these plugins, try contacting the author(s) +or post a message to the nagios-users mailing list (nagios-users@onelist.com) +requesting assistance. + + +Plugin Overview +--------------- + +berger-ping.tar.gz - Perl script version of the check_ping plugin and a corresponding + CGI (mtr.cgi) that uses mtr to traceroute a path to a host. + (Gary Berger) + +bowen-langley_plugins.tar.gz + - Several C plugins including check_inode, check_boot, etc. + (Adam Bown & Thomas Langley) + + +check_bgpstate.tar.gz - Perl script intended for monitoring BGP sessions on Cisco routers. + Only useful if you are using BGP4 as a routing protocol. For + critical alert the AS (autonomous system) number has to be in the + uplinks hash (see the source code). Requires SNMP read community. + (Christoph Kron) + +check_breeze.tar.gz - Perl script to test signal strength on Breezecom wireless + equipment (Jeffrey Blank) + +check_dns_random.tar.gz - Perl script to see if dns resolves hosts randomly from a list + using the check_dns plugin (Richard Mayhew) + +check_flexlm.tar.gz - Perl script to check a flexlm licensing manager using lmtest + (Ernst-Dieter Martin) + +check_hltherm.tar.gz - C program to check the temperature on a Hot Little Therm temperature + probe. The HLT device, along with temperature probes, can be obtained + from Spiderplant at http://www.spiderplant.com + (Ethan Galstad) + +check_ifoperstatus.tar.gz + - Perl script that checks the operational interface status (up/down) for + one interface on cisco/ascend routers. Especially useful for monitoring + leased lines. Requires SNMP read community and SNMP interface key. + (Christoph Kron) + +check_ifstatus.tar.gz - Perl script that checks operational interface status for every interface + on cisco routers. Requires SNMP read community. + (Christoph Kron) + +check_ipxping.tar.gz - C program that it similiar to the check_ping plugin, except that it + send IPX ping packets to Novell servers or other IPX devices. This + requires the ipxping binary for Linux systems. It does NOT by work + without modification with the ipxping binary for SunOS/Solaris. + (Ethan Galstad) + +check_maxchannels.tar.gz + - Perl script that can only be used for monitoring Ascend/Lucent Max/TNT + access server. Checks ISDN channels and modem cards. Also shows ISDN and + modem usage. Requires SNMP read community. + (Christoph Kron) + +check_maxwanstate.tar.gz + - Perl script that can only be used for monitoring Ascend/Lucent Max/TNT + access server. Checks if every enabled E1/T1 interface is operational + (link active). Requires SNMP read community. + (Christoph Kron) + +check_memory.tgz - C program to check available system memory - RAM, swap, buffers, + and cache (Joshua Jackson) + +check_nfs.tar.gz - Perl script to test and NFS server using rpcinfo + (Ernst-Dieter Martin) + <NOW PART OF check_rpc IN CORE> + +check_ntp.tar.gz - Perl script to check an NTP time source (Bo Kernsey) + <MOVED TO CORE> + +check_ora.tar.gz - Shell script that will check an Oracle database and the TNS listener. + Unlike the check_oracle plugin, this plugin detects when a database is + down and does not create temp files (Jason Hedden) + <MOVED TO CORE> + +check_pop3.tar.gz - Perl script that checks to see if POP3 is running and whether or not + authentication can take place (Richard Mayhew) + +check_radius.tar.gz - C program to check RADIUS authentication. This is a hacked version of + the Cistron Radiusd program radtest that acts as a plugin for Nagios. + The vast majority of the code was written by someone at Livingston + Enterprises and Cistron. NOTE: Due to the copyright restrictions in + this code, it cannot be distributed under the GPL license, and thus + will not appear in the core plugin distribution! + (Adam Jacob) + +check_real.tar.gz - C program to check the status of a REAL media server + (Pedro Leite) + <MOVED TO CORE> + +check_rpc.pl.gz - Perl script to check rpc services. Will check to see if the a specified + program is running on the specified server (Chris Kolquist) + +check_sap.tar.gz - Shell script to check an SAP message or application server. Requires + that you install the saprfc-devel-45A-1.i386.rpm (or higher) package + on your system. The package can be obtained from the SAP FTP site in + the /general/misc/unsupported/linux directory. (Kavel Salavec) + +check_uptime.tar.gz - C program to check system uptime. Must be compiled with the release + 1.2.8 or later of the plugins. (Teresa Ramanan) + +check_wave.tar.gz - Perl script to test signal strength on Speedlan wireless + equipment (Jeffrey Blank) + +hopcroft-plugins.tar.gz - Various example plugin scripts contributed by Stanley Hopcroft. + Includes a plugin to check Internet connectivity by checking various + popular search engines, a plugin to check the availability of login + to a TN/3270 mainframe database using Expect to search for "usual" + screens, and another plugin to test the availability of a database + search via the web. + (Stanley Hopcroft) + +maser-oracle.tar.gz - This is a modification to the check_oracle plugin script that returns + the response time in milliseconds. Requires the Oracle tnsping utility. + (Christoph Maser) + +radius.tar.gz - Code modifications necessary to make the radexample app + supplied with the radiusclient code work as a RADIUS plugin + for Nagios (Nick Shore) + +vincent-check_radius.tar.gz + - C program to check RADIUS authentication. Requires the radiusclient + library available from ftp://ftp.cityline.net/pub/radiusclient/ + (Robert August Vincent II) + <MOVED TO CORE> + +weipert-mysql.tar.gz - C program to check a connection to a MySQL database server, with an + optional username and password. Requires mysql.h and libmysqlclient + to compile (Time Weipert) + +wright-mysql.tar.gz - Perl script to check MySQL database servers. Requires that mysqladmin(1) + be installed on the system (included in the MySQL distribution). This + plugin can accept warning and critical thresholds for the number of threads + in use by the server (Mitch Wright) + + diff --git a/contrib/restrict.pl b/contrib/restrict.pl new file mode 100755 index 00000000..75ea5698 --- /dev/null +++ b/contrib/restrict.pl @@ -0,0 +1,26 @@ +#!/usr/bin/perl + +eval 'exec /usr/bin/perl -S $0 ${1+"$@"}' + if 0; + +# Set this to your local Nagios plugin path +my $pluginpath = "/usr/libexec/nagios/plugins/"; + +# Put all the legal commands (i.e. the commands that are +# not Nagios checks but are allowed to be executed anyway) +# in the following associative array. +my %legal_cmds = ("nc" => "/usr/sbin/nc"); + +# This will not work on OpenSSH +# It does work on ssh-1.2.27-1i +@arg = split ' ',$ENV{'SSH_ORIGINAL_COMMAND'}; + +$arg[0] =~ s/.*\///; # strip leading path +$arg[0] =~ tr/-_.a-zA-Z0-9/X/c; # change atypical chars to X + +if (!defined ($cmd = $legal_cmds{$arg[0]})) +{ + $cmd = $pluginpath . $arg[0]; +} + +exec { $cmd } @arg or die "Can't exec $cmd: $!"; diff --git a/contrib/tarballs/berger-ping.tar.gz b/contrib/tarballs/berger-ping.tar.gz Binary files differnew file mode 100644 index 00000000..cc58750d --- /dev/null +++ b/contrib/tarballs/berger-ping.tar.gz diff --git a/contrib/tarballs/bowen-langley_plugins.tar.gz b/contrib/tarballs/bowen-langley_plugins.tar.gz Binary files differnew file mode 100644 index 00000000..6195109f --- /dev/null +++ b/contrib/tarballs/bowen-langley_plugins.tar.gz diff --git a/contrib/tarballs/check_bgp-1.0.tar.gz b/contrib/tarballs/check_bgp-1.0.tar.gz Binary files differnew file mode 100644 index 00000000..9d45c195 --- /dev/null +++ b/contrib/tarballs/check_bgp-1.0.tar.gz diff --git a/contrib/tarballs/check_breeze.tar.gz b/contrib/tarballs/check_breeze.tar.gz Binary files differnew file mode 100644 index 00000000..fb5186ef --- /dev/null +++ b/contrib/tarballs/check_breeze.tar.gz diff --git a/contrib/tarballs/check_flexlm.tar.gz b/contrib/tarballs/check_flexlm.tar.gz Binary files differnew file mode 100644 index 00000000..4ab71441 --- /dev/null +++ b/contrib/tarballs/check_flexlm.tar.gz diff --git a/contrib/tarballs/check_hltherm.tar.gz b/contrib/tarballs/check_hltherm.tar.gz Binary files differnew file mode 100644 index 00000000..7c45cc87 --- /dev/null +++ b/contrib/tarballs/check_hltherm.tar.gz diff --git a/contrib/tarballs/check_hprsc.tar.gz b/contrib/tarballs/check_hprsc.tar.gz Binary files differnew file mode 100644 index 00000000..8998ff83 --- /dev/null +++ b/contrib/tarballs/check_hprsc.tar.gz diff --git a/contrib/tarballs/check_radius.tar.gz b/contrib/tarballs/check_radius.tar.gz Binary files differnew file mode 100644 index 00000000..70bb08a2 --- /dev/null +++ b/contrib/tarballs/check_radius.tar.gz diff --git a/contrib/tarballs/check_wave.tar.gz b/contrib/tarballs/check_wave.tar.gz Binary files differnew file mode 100644 index 00000000..755be5a9 --- /dev/null +++ b/contrib/tarballs/check_wave.tar.gz diff --git a/contrib/tarballs/hopcroft-plugins.tar.gz b/contrib/tarballs/hopcroft-plugins.tar.gz Binary files differnew file mode 100644 index 00000000..0406a743 --- /dev/null +++ b/contrib/tarballs/hopcroft-plugins.tar.gz diff --git a/contrib/tarballs/radius.tar.gz b/contrib/tarballs/radius.tar.gz Binary files differnew file mode 100644 index 00000000..022dc3be --- /dev/null +++ b/contrib/tarballs/radius.tar.gz diff --git a/contrib/urlize.pl b/contrib/urlize.pl new file mode 100644 index 00000000..8bb591f2 --- /dev/null +++ b/contrib/urlize.pl @@ -0,0 +1,16 @@ +#!/usr/bin/perl +# +# urlize.pl +# jcw, 5/12/00 +# +# A wrapper around Nagios plugins that provides a URL link in the output +# + +($#ARGV < 1) && die "Incorrect arguments"; +my $url = shift; + +chomp ($result = `@ARGV`); +print "<A HREF=\"$url\">$result</A>\n"; + +# exit with same exit value as the child produced +exit ($? >> 8); diff --git a/contrib/utils.py b/contrib/utils.py new file mode 100644 index 00000000..73d795c9 --- /dev/null +++ b/contrib/utils.py @@ -0,0 +1,310 @@ +# +# +# Util classes for Nagios plugins +# +# + + + +#========================================================================== +# +# Version: = '$Id$' +# +# (C) Rob W.W. Hooft, Nonius BV, 1998 +# +# Contact r.hooft@euromail.net for questions/suggestions. +# See: <http://starship.python.net/crew/hooft/> +# Distribute freely. +# +# jaclu@galdrion.com 2000-07-14 +# Some changes in error handling of Run() to avoid error garbage +# when used from Nagios plugins +# I also removed the following functions: AbortableWait() and _buttonkill() +# since they are only usable with Tkinter + +import sys,os,signal,time,string + +class error(Exception): + pass + +class _ready(Exception): + pass + +def which(filename): + """Find the file 'filename' in the execution path. If no executable + file is found, return None""" + for dir in string.split(os.environ['PATH'],os.pathsep): + fn=os.path.join(dir,filename) + if os.path.exists(fn): + if os.stat(fn)[0]&0111: + return fn + else: + return None + +class Task: + """Manage asynchronous subprocess tasks. + This differs from the 'subproc' package! + - 'subproc' connects to the subprocess via pipes + - 'task' lets the subprocess run autonomously. + After starting the task, we can just: + - ask whether it is finished yet + - wait until it is finished + - perform an 'idle' task (e.g. Tkinter's mainloop) while waiting for + subprocess termination + - kill the subprocess with a specific signal + - ask for the exit code. + Summarizing: + - 'subproc' is a sophisticated os.popen() + - 'task' is a sophisticated os.system() + Another difference of task with 'subproc': + - If the Task() object is deleted, before the subprocess status + was retrieved, the child process will stay. + It will never be waited for (i.e., the process will turn into + a zombie. Not a good idea in general). + + Public data: + None. + + Public methods: + __init__, __str__, Run, Wait, Kill, Done, Status. + """ + def __init__(self,command): + """Constructor. + arguments: + command: the command to run, in the form of a string, + or a tuple or list of words. + """ + if type(command)==type(''): + self.cmd=command + self.words=string.split(command) + elif type(command)==type([]) or type(command)==type(()): + # Surround each word by ' '. Limitation: words cannot contain ' chars + self.cmd="'"+string.join(command,"' '")+"'" + self.words=tuple(command) + else: + raise error("command must be tuple, list, or string") + self.pid=None + self.status=None + + def Run(self,usesh=0,detach=0,stdout=None,stdin=None,stderr=None): + """Actually run the process. + This method should be called exactly once. + optional arguments: + usesh=0: if 1, run 'sh -c command', if 0, split the + command into words, and run it by ourselves. + If usesh=1, the 'Kill' method might not do what + you want (it will kill the 'sh' process, not the + command). + detach=0: if 1, run 'sh -c 'command&' (regardless of + 'usesh'). Since the 'sh' process will immediately + terminate, the task created will be inherited by + 'init', so you can safely forget it. Remember that if + detach=1, Kill(), Done() and Status() will manipulate + the 'sh' process; there is no way to find out about the + detached process. + stdout=None: filename to use as stdout for the child process. + If None, the stdout of the parent will be used. + stdin= None: filename to use as stdin for the child process. + If None, the stdin of the parent will be used. + stderr=None: filename to use as stderr for the child process. + If None, the stderr of the parent will be used. + return value: + None + """ + if self.pid!=None: + raise error("Second run on task forbidden") + self.pid=os.fork() + if not self.pid: + for fn in range(3,256): # Close all non-standard files in a safe way + try: + os.close(fn) + except os.error: + pass + # + # jaclu@galdrion.com 2000-07-14 + # + # I changed this bit somewhat, since Nagios plugins + # should send only limited errors to the caller + # The original setup here corupted output when there was an error. + # Instead the caller should check result of Wait() and anything + # not zero should be reported as a failure. + # + try: + if stdout: # Replace stdout by file + os.close(1) + i=os.open(stdout,os.O_CREAT|os.O_WRONLY|os.O_TRUNC,0666) + if i!=1: + sys.stderr.write("stdout not opened on 1!\n") + if stdin: # Replace stdin by file + os.close(0) + i=os.open(stdin,os.O_RDONLY) + if i!=0: + sys.stderr.write("stdin not opened on 0!\n") + if stderr: # Replace stderr by file + os.close(2) + i=os.open(stderr,os.O_CREAT|os.O_WRONLY|os.O_TRUNC,0666) + if i!=2: + sys.stdout.write("stderr not opened on 2!\n") + #try: + if detach: + os.execv('/bin/sh',('sh','-c',self.cmd+'&')) + elif usesh: + os.execv('/bin/sh',('sh','-c',self.cmd)) + else: + os.execvp(self.words[0],self.words) + except: + #print self.words + #sys.stderr.write("Subprocess '%s' execution failed!\n"%self.cmd) + sys.exit(1) + else: + # Mother process + if detach: + # Should complete "immediately" + self.Wait() + + def Wait(self,idlefunc=None,interval=0.1): + """Wait for the subprocess to terminate. + If the process has already terminated, this function will return + immediately without raising an error. + optional arguments: + idlefunc=None: a callable object (function, class, bound method) + that will be called every 0.1 second (or see + the 'interval' variable) while waiting for + the subprocess to terminate. This can be the + Tkinter 'update' procedure, such that the GUI + doesn't die during the run. If this is set to + 'None', the process will really wait. idlefunc + should ideally not take a very long time to + complete... + interval=0.1: The interval (in seconds) with which the 'idlefunc' + (if any) will be called. + return value: + the exit status of the subprocess (0 if successful). + """ + if self.status!=None: + # Already finished + return self.status + if callable(idlefunc): + while 1: + try: + pid,status=os.waitpid(self.pid,os.WNOHANG) + if pid==self.pid: + self.status=status + return status + else: + idlefunc() + time.sleep(interval) + except KeyboardInterrupt: + # Send the interrupt to the inferior process. + self.Kill(signal=signal.SIGINT) + elif idlefunc: + raise error("Non-callable idle function") + else: + while 1: + try: + pid,status=os.waitpid(self.pid,0) + self.status=status + return status + except KeyboardInterrupt: + # Send the interrupt to the inferior process. + self.Kill(signal=signal.SIGINT) + + def Kill(self,signal=signal.SIGTERM): + """Send a signal to the running subprocess. + optional arguments: + signal=SIGTERM: number of the signal to send. + (see os.kill) + return value: + see os.kill() + """ + if self.status==None: + # Only if it is not already finished + return os.kill(self.pid,signal) + + def Done(self): + """Ask whether the process has already finished. + return value: + 1: yes, the process has finished. + 0: no, the process has not finished yet. + """ + if self.status!=None: + return 1 + else: + pid,status=os.waitpid(self.pid,os.WNOHANG) + if pid==self.pid: + #print "OK:",pid,status + self.status=status + return 1 + else: + #print "NOK:",pid,status + return 0 + + def Status(self): + """Ask for the status of the task. + return value: + None: process has not finished yet (maybe not even started). + any integer: process exit status. + """ + self.Done() + return self.status + + def __str__(self): + if self.pid!=None: + if self.status!=None: + s2="done, exit status=%d"%self.status + else: + s2="running" + else: + s2="prepared" + return "<%s: '%s', %s>"%(self.__class__.__name__,self.cmd,s2) + + +#========================================================================== +# +# +# Class: TimeoutHandler +# License: GPL +# Copyright (c) 2000 Jacob Lundqvist (jaclu@galdrion.com) +# +# Version: 1.0 2000-07-14 +# +# Description: +# On init, suply a call-back kill_func that should be called on timeout +# +# Make sure that what ever you are doing is calling Check periodically +# +# To check if timeout was triggered call WasTimeOut returns (true/false) +# + +import time,sys + +class TimeoutHandler: + def __init__(self,kill_func,time_to_live=10,debug=0): + 'Generic time-out handler.' + self.kill_func=kill_func + self.start_time=time.time() + self.stop_time=+self.start_time+int(time_to_live) + self.debug=debug + self.aborted=0 + + def Check(self): + 'Call this periodically to check for time-out.' + if self.debug: + sys.stdout.write('.') + sys.stdout.flush() + if time.time()>=self.stop_time: + self.TimeOut() + + def TimeOut(self): + 'Trigger the time-out callback.' + self.aborted=1 + if self.debug: + print 'Timeout, aborting' + self.kill_func() + + def WasTimeOut(self): + 'Indicates if timeout was triggered 1=yes, 0=no.' + if self.debug: + print '' + print 'call duration: %.2f seconds' % (time.time()-self.start_time) + return self.aborted |