]> git.tokkee.org Git - nagiosplug.git/commitdiff

Code

New /contrib plugin
authorStanley Hopcroft <stanleyhopcroft@users.sourceforge.net>
Thu, 27 Jan 2005 04:46:08 +0000 (04:46 +0000)
committerStanley Hopcroft <stanleyhopcroft@users.sourceforge.net>
Thu, 27 Jan 2005 04:46:08 +0000 (04:46 +0000)
git-svn-id: https://nagiosplug.svn.sourceforge.net/svnroot/nagiosplug/nagiosplug/trunk@1112 f882894a-f735-0410-b71e-b25c423dba1c

contrib/check_arping.pl [new file with mode: 0644]
contrib/check_cpqarray.c [new file with mode: 0644]
contrib/check_frontpage [new file with mode: 0644]
contrib/check_logins.c [new file with mode: 0644]
contrib/check_oracle_tbs [new file with mode: 0644]
contrib/check_pcpmetric.py [new file with mode: 0644]
contrib/check_pfstate [new file with mode: 0644]

diff --git a/contrib/check_arping.pl b/contrib/check_arping.pl
new file mode 100644 (file)
index 0000000..b78ec68
--- /dev/null
@@ -0,0 +1,120 @@
+#! /usr/bin/perl -w
+#
+# check_arping.pl - Nagios plugin to check host status via ARP ping
+#
+# usage:
+#     check_arping -H hostname -I interface -T timeout
+#
+#
+# Copyright (C) 2003  Kenny Root
+#
+# 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: kenny@the-b.org, nagiosplug-help@lists.sf.net
+
+use POSIX;
+use strict;
+use lib "/usr/lib/nagios/plugins" ;
+use utils qw($TIMEOUT %ERRORS &print_revision &support);
+
+use Net::Arping;
+use Getopt::Long;
+
+my $PROGNAME = "check_arping";
+
+my($status, $state, $answer);
+my($opt_V, $opt_h, $opt_t, $opt_I, $opt_H);
+
+
+#Option checking
+$status = GetOptions(
+       "V|version"     => \$opt_V,
+       "help"  => \$opt_h, 
+       "I|interface=s" => \$opt_I,
+       "H|host=s"      => \$opt_H,
+       "t|timeout=i"   => \$opt_t);
+               
+if ($status == 0)
+{
+       print_help() ;
+       exit $ERRORS{'OK'};
+}
+
+
+if ($opt_V) {
+       print_revision($PROGNAME,'$Revision$ ');
+       exit $ERRORS{'OK'};
+}
+
+if ($opt_h) {
+       print_help();
+       exit $ERRORS{'OK'};
+}
+
+if ($opt_t) {
+       if ($opt_t ne int($opt_t)) {
+               print "Timeout not in seconds!\n";
+               print_help();
+               exit $ERRORS{'OK'};
+       }
+       $opt_t = int($opt_t);
+} else {
+       $opt_t = 3;
+}
+
+if (! utils::is_hostname($opt_H)){
+       usage();
+       exit $ERRORS{"UNKNOWN"};
+}
+
+my $ping = Net::Arping->new();
+
+my $reply = $ping->arping(Host => $opt_H, Interface => $opt_I, Timeout => $opt_t);
+
+if ($reply eq "0") {
+       $state = "CRITICAL";
+       print "$state: no reply from $opt_H on interface $opt_I in $opt_t seconds.\n";
+       exit $ERRORS{$state};
+} else {
+       $state = "OK";
+       $answer = "replied with MAC address $reply";
+}
+
+print "ARPING $state - $answer\n";
+exit $ERRORS{$state};
+
+
+sub usage {
+       print "\nMissing arguments!\n";
+       print "\n";
+       print "check_arping -I <interface> -H <host IP> [-t <timeout>]\n";
+       print "\n\n";
+       support();
+       exit $ERRORS{"UNKNOWN"};
+}
+
+sub print_help {
+       print "check_arping pings hosts that normally wouldn't allow\n";
+       print "ICMP packets but are still on the local network.\n";
+       print "\nUsage:\n";
+       print "   -H (--host)       IP to query - (required)\n";
+       print "   -I (--interface)  Interface to use.\n";
+       print "   -t (--timeout)    Timeout in seconds.\n";
+       print "   -V (--version)    Plugin version\n";
+       print "   -h (--help)       usage help \n\n";
+       print_revision($PROGNAME, '$Revision$');
+       
+}
diff --git a/contrib/check_cpqarray.c b/contrib/check_cpqarray.c
new file mode 100644 (file)
index 0000000..badffeb
--- /dev/null
@@ -0,0 +1,430 @@
+/*
+   check_cpqarray, an extension for Netsaint / Nagios to check the
+   status of a Compaq SmartArray controller from the commandline.
+   Copyright (C) 2003  Guenther Mair
+
+   based on the work and using main parts of
+
+   CpqArray Deamon, a program to monitor and remotely configure a 
+   SmartArray controller.
+   Copyright (C) 1999  Hugo Trippaers
+
+   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
+ */
+
+#include <unistd.h>
+#include <sys/ioctl.h>
+#include <sys/utsname.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <string.h>
+#include <errno.h>
+
+#include "/usr/src/linux/drivers/block/ida_ioctl.h"
+#include "/usr/src/linux/drivers/block/ida_cmd.h"
+#include "/usr/src/linux/drivers/block/cpqarray.h"
+
+
+const char *controllers[] =
+{
+  "/dev/ida/c0d0",
+  "/dev/ida/c1d0",
+  "/dev/ida/c2d0",
+  "/dev/ida/c3d0",
+  "/dev/ida/c4d0",
+  "/dev/ida/c5d0",
+  "/dev/ida/c6d0",
+  "/dev/ida/c7d0"
+};
+
+const char *statusstr[] = {
+        "Logical drive /dev/ida/c%dd%d: OK\n",
+        "Logical drive /dev/ida/c%dd%d: FAILED\n",
+        "Logical drive /dev/ida/c%dd%d: not configured.\n",
+        "Logical drive /dev/ida/c%dd%d: using interim recovery mode, %3.2f%% done.\n",
+        "Logical drive /dev/ida/c%dd%d: ready for recovery operation.\n",
+        "Logical drive /dev/ida/c%dd%d: is currently recovering, %3.2f%% done.\n",
+        "Wrong physical drive was replaced.\n",
+        "A physical drive is not properly connected.\n",
+        "Hardware is overheating.\n",
+        "Hardware has overheated.\n",
+        "Logical drive /dev/ida/c%dd%d: currently expanding, %3.2f%% done.\n",
+        "Logical drive /dev/ida/c%dd%d: not yet available.\n",
+        "Logical drive /dev/ida/c%dd%d: queued for expansion.\n",
+};
+
+extern char *optarg;
+extern int optind, opterr, optopt;
+
+int ctrls_found_num;
+int exit_code = 0;
+struct controller ctrls_found[8];
+
+#define DEBUG(x)  fprintf(stderr, x)
+
+struct opts 
+{
+  char debug;
+};
+
+struct slog_disk
+{
+  int status;
+  float pvalue;
+};
+
+struct controller 
+{
+  char ctrl_devicename[20];
+  int num_logd_found;
+  struct slog_disk log_disk[16];
+};
+
+
+
+int status_check (struct opts opts) 
+{
+  int devicefd;
+  int ctrl_cntr;
+  int logd_cntr;
+  ida_ioctl_t io, io2;
+  int status, nr_blks, blks_tr;
+  float pvalue;
+  int counter;
+    
+  for ( ctrl_cntr=0;
+        ctrl_cntr <  ctrls_found_num;
+        ctrl_cntr++) {
+    
+    devicefd = open (controllers[ctrl_cntr], O_RDONLY);
+    
+    for ( logd_cntr=0;
+          logd_cntr < ctrls_found[ctrl_cntr].num_logd_found;
+          logd_cntr++) {
+      
+        memset (&io, 0, sizeof (io));
+
+        io.cmd = SENSE_LOG_DRV_STAT;
+        io.unit = logd_cntr  | UNITVALID;
+        
+        if (ioctl (devicefd, IDAPASSTHRU, &io) < 0)
+          {
+            perror ("SENSE_LOG_DRV_STAT ioctl");
+            return 0;
+          }
+
+        status=io.c.sense_log_drv_stat.status;
+        
+        if ((status == 3) || (status == 5) || (status == 7)) {
+          /* is a progress indicator required?
+           */
+          memset (&io2, 0, sizeof (io));
+          
+          io2.cmd = ID_LOG_DRV;
+          io2.unit = logd_cntr  | UNITVALID;
+          
+          if (ioctl (devicefd, IDAPASSTHRU, &io2) < 0)
+            {
+              perror ("ID_LOG_DRV ioctl");
+              /* return 0;   no return this isn't fatal for now */
+            }
+          else 
+            {
+              nr_blks = io2.c.id_log_drv.nr_blks;
+              blks_tr = io.c.sense_log_drv_stat.blks_to_recover;
+                  
+              pvalue = ((float)(nr_blks - blks_tr)/(float)nr_blks) * 100;
+            }
+        }
+        else {
+          pvalue = 0.0;
+        }
+
+        if (opts.debug) {
+         fprintf(stdout, "DEBUG: Status of controller %d unit %d is %d\n", 
+                 ctrl_cntr, logd_cntr, status);
+          fprintf(stdout, "DEBUG: ");
+         fprintf(stdout, statusstr[status], 
+                 ctrl_cntr, logd_cntr, pvalue);
+         fprintf(stdout, "\n");
+       }
+       
+       printf(statusstr[status], ctrl_cntr, logd_cntr, pvalue);
+
+       switch(status)
+         {
+         case 1:
+         case 2:
+         case 6:
+         case 7:
+         case 9:
+           /* CRITICAL */
+           exit_code = 2;
+           break;
+         case 3:
+         case 4:
+         case 5:
+         case 8:
+         case 10:
+         case 11:
+         case 12:
+           /* WARNING (only if not yet at CRITICAL LEVEL) */
+           if (exit_code < 2) exit_code = 1;
+           break;
+         case 0:
+         default:
+           /* do nothing */
+           break;
+         }
+
+       ctrls_found[ctrl_cntr].log_disk[logd_cntr].pvalue = pvalue;
+       ctrls_found[ctrl_cntr].log_disk[logd_cntr].status = status;
+    }
+    close (devicefd);
+  }
+
+  return 1;
+}
+
+int discover_controllers (struct opts opts)
+{
+  int cntr;
+  int foundone = 0;
+
+  for (cntr = 0; cntr < 8; cntr++)
+    {
+      /* does this device exist ? */
+      if ((access (controllers[cntr], R_OK | F_OK)) == 0)
+       {
+         /* it does :) */
+         if (interrogate_controller (opts, cntr))
+           {
+             foundone = 1;
+             if (opts.debug) 
+               fprintf (stderr, "DEBUG: %s is a existing controller\n",
+                        controllers[cntr]);
+           }
+       }
+      else if (opts.debug)
+       {
+         fprintf (stderr, "DEBUG: Device %s could not be opened\n", controllers[cntr]);
+         perror ("DEBUG: reason");
+       }
+    }
+   return foundone;
+}
+
+void boardid2str (unsigned long board_id, char *name)
+{
+  switch (board_id)
+    {
+    case 0x0040110E:           /* IDA */
+      strcpy (name, "Compaq IDA");
+      break;
+    case 0x0140110E:           /* IDA-2 */
+      strcpy (name, "Compaq IDA-2");
+      break;
+    case 0x1040110E:           /* IAES */
+      strcpy (name, "Compaq IAES");
+      break;
+    case 0x2040110E:           /* SMART */
+      strcpy (name, "Compaq SMART");
+      break;
+    case 0x3040110E:           /* SMART-2/E */
+      strcpy (name, "Compaq SMART-2/E");
+      break;
+    case 0x40300E11:           /* SMART-2/P or SMART-2DH */
+      strcpy (name, "Compaq SMART-2/P (2DH)");
+      break;
+    case 0x40310E11:           /* SMART-2SL */
+      strcpy (name, "Compaq SMART-2SL");
+      break;
+    case 0x40320E11:           /* SMART-3200 */
+      strcpy (name, "Compaq SMART-3200");
+      break;
+    case 0x40330E11:           /* SMART-3100ES */
+      strcpy (name, "Compaq SMART-3100ES");
+      break;
+    case 0x40340E11:           /* SMART-221 */
+      strcpy (name, "Compaq SMART-221");
+      break;
+    case 0x40400E11:           /* Integrated Array */
+      strcpy (name, "Compaq Integrated Array");
+      break;
+    case 0x40500E11:           /* Smart Array 4200 */
+      strcpy (name, "Compaq Smart Array 4200");
+      break;
+    case 0x40510E11:           /* Smart Array 4250ES */
+      strcpy (name, "Compaq Smart Array 4250ES");
+      break;
+    case 0x40580E11:           /* Smart Array 431 */
+      strcpy (name, "Compaq Smart Array 431");
+      break;
+    default:
+      /*
+       * Well, its a SMART-2 or better, don't know which
+       * kind.
+       */
+      strcpy (name, "Unknown Controller Type");
+    }
+}
+
+int interrogate_controller (struct opts opts, int contrnum)
+{
+  int devicefd;
+  ida_ioctl_t io;
+  char buffer[30];
+  int foundone = 0;
+  int cntr;
+  devicefd = open (controllers[contrnum], O_RDONLY);
+  /* no checks, did that before */
+
+  /* clear io */
+  memset (&io, 0, sizeof (io));
+
+  io.cmd = ID_CTLR;
+
+  if (ioctl (devicefd, IDAPASSTHRU, &io) < 0)
+    {
+      if (opts.debug) perror ("DEBUG: ioctl");
+      return 0;
+    }
+
+  boardid2str (io.c.id_ctlr.board_id, buffer);
+
+  strncpy (ctrls_found[ctrls_found_num].ctrl_devicename, 
+          buffer, 20);
+
+  ctrls_found[ctrls_found_num].num_logd_found = 0;
+
+  for (cntr = 0; cntr < io.c.id_ctlr.nr_drvs; cntr++)
+    {
+      if (interrogate_logical (opts, devicefd, cntr))
+       {
+         /* logical drive found, this could be used later one */
+         foundone = 1;
+       }
+    }
+
+  switch (ctrls_found[ctrls_found_num].num_logd_found)
+    {
+    case 0:
+      printf("Found a %s with no logical drives.\n", buffer);
+      break;
+    case 1:
+      printf("Found a %s with one Logical drive.\n", buffer,
+       ctrls_found[ctrls_found_num].num_logd_found);
+      break;
+    default:
+      printf("Found a %s with %d Logical drives.\n", buffer,
+       ctrls_found[ctrls_found_num].num_logd_found);
+      break;
+    }
+
+  ctrls_found_num++;
+
+  close (devicefd);
+  return 1;
+}
+
+int interrogate_logical (struct opts opts, int devicefd, int unit_nr)
+{
+  ida_ioctl_t io;
+  ida_ioctl_t io2;
+  int nr_blks, blks_tr;
+
+  if (opts.debug) printf ("DEBUG: interrogating unit %d\n", unit_nr);
+
+  memset (&io, 0, sizeof (io));
+
+  io.cmd = ID_LOG_DRV;
+  io.unit = unit_nr | UNITVALID;
+
+  if (ioctl (devicefd, IDAPASSTHRU, &io) < 0)
+    {
+      perror ("FATAL: ID_LOG_DRV ioctl");
+      return 0;
+    }
+
+  memset (&io2, 0, sizeof (io2));
+
+  io2.cmd = SENSE_LOG_DRV_STAT;
+  io2.unit = unit_nr | UNITVALID;
+
+  if (ioctl (devicefd, IDAPASSTHRU, &io2) < 0)
+    {
+      perror ("FATAL: SENSE_LOG_DRV_STAT ioctl");
+      return 0;
+    }
+  
+  ctrls_found[ctrls_found_num].num_logd_found++;
+  /*  ctrls_found[ctrls_found_num].log_disk[unit_nr].status =
+   * io2.c.sense_log_drv_stat.status;
+
+   * nr_blks = io2.c.id_log_drv.nr_blks;
+   * blks_tr = io.c.sense_log_drv_stat.blks_to_recover;
+   * ctrls_found[ctrls_found_num].log_disk[unit_nr].pvalue =
+   *  ((float)(nr_blks - blks_tr)/(float)nr_blks) * 100;
+   */
+  ctrls_found[ctrls_found_num].log_disk[unit_nr].status = 0;
+  ctrls_found[ctrls_found_num].log_disk[unit_nr].pvalue = 0;
+
+  return 1;
+}
+
+
+void print_usage() 
+{
+  printf("cpqarrayd [options]\n");
+  printf("   -h         prints this text\n");
+  printf("   -d         enables debugging\n");
+}
+
+
+int main(int argc, char *argv[]) 
+{
+  char option;
+  struct opts opts; /* commandline options */
+  
+  memset(&opts, 0, sizeof(struct opts));
+  
+  /* check options */
+  while ((option = getopt (argc, argv, "dh:")) != EOF)
+    {
+      switch (option)
+        {
+       case 'd':
+         opts.debug = 1;
+         break;
+       case '?':
+       case 'h':
+       default:
+         print_usage();
+         exit(0);
+         break;
+       }
+    }
+  
+  /* Check for existance of array controllers */
+  if (!discover_controllers(opts)) {
+    printf("No array controller found!\n\n");
+    exit(1);
+  }
+
+  status_check(opts);
+
+  return exit_code;
+}
diff --git a/contrib/check_frontpage b/contrib/check_frontpage
new file mode 100644 (file)
index 0000000..ee958d3
--- /dev/null
@@ -0,0 +1,151 @@
+#! /usr/bin/perl -w
+#
+# $Id$
+#
+# Check that FrontPage extensions appear to be working on a specified host.
+# Currently only checks that the hit counter is not returning an error.
+#
+# Probably not a good idea to use this on a host that someone's counting
+# the hits on, so create a separate vhost for frontpage extensions testing,
+# or just install the extensions on the default/root host for your server, and
+# point it against that hostname, running it against all vhosts on a server is
+# probably rather wasteful.
+#
+# Kev Green, oRe Net (http://www.orenet.co.uk/).
+
+
+use strict;
+use lib "/usr/lib/nagios/plugins";
+use utils qw($TIMEOUT %ERRORS &print_revision &support);
+use vars qw($PROGNAME);
+use Getopt::Long;
+use LWP;
+use vars qw($opt_V $opt_h $verbose $opt_w $opt_c $opt_H);
+my ($tt,$url,$response,$stime, $etime,$warning,$critical,$mimetype,$failtype,$temp,$message);
+my $rt = 0;
+
+$PROGNAME = "check_frontpage";
+sub print_help ();
+sub print_usage ();
+
+$ENV{'PATH'}='';
+$ENV{'BASH_ENV'}='';
+$ENV{'ENV'}='';
+
+Getopt::Long::Configure('bundling');
+GetOptions
+       ("V"   => \$opt_V, "version"    => \$opt_V,
+        "h"   => \$opt_h, "help"       => \$opt_h,
+        "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);
+
+if ($opt_V) {
+       print_revision($PROGNAME,'$Revision$'); #'
+       exit $ERRORS{'OK'};
+}
+
+if ($opt_h) {
+       print_help();
+       exit $ERRORS{'OK'};
+}
+
+$opt_H = shift unless ($opt_H);
+print_usage() unless $opt_H;
+my $host = $1 if ($opt_H =~ m/^([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+|[a-zA-Z][-a-zA-Z0-9]+(\.[a-zA-Z0-9][-a-zA-Z0-9]+)*)$/);
+print_usage() unless $host;
+
+($opt_c) || ($opt_c = shift) || ($opt_c = 120);
+if ($opt_c =~ /([0-9]+)/) {
+   $critical = $1;
+} else {
+   $critical = 10;
+}
+
+($opt_w) || ($opt_w = shift) || ($opt_w = 60);
+if ($opt_w =~ /([0-9]+)/) {
+   $warning = $1;
+} else {
+   $warning = 5;
+}
+
+# Guts go here, once we're through argument parsing and have warning and
+# critical thresholds.
+my $browser = LWP::UserAgent->new;
+
+my @urls = ( 
+ # This is the "Hit Counter", which continues to work if frontpage extensions
+ # are 'uninstall'ed from the site, but not when they are 'fulluninstall'ed.
+ {
+   url => "_vti_bin/fpcount.exe?Page=_borders/right.htm|Image=4",
+   mimetype => "image/gif",
+   message => "None, or broken frontpage extensions on server, or virtual site 'fulluninstall'ed?",
+   failtype => "CRITICAL"
+ },
+ # This is the "FrontPage Configuration Information" file, which is removed
+ # when you 'uninstall' the extensions from a site.
+ { 
+   url => "_vti_inf.html",
+   mimetype => "text/html",
+   message => "Someone 'uninstall'ed extensions on virtual site?",
+   failtype => "WARNING" 
+ }
+);
+
+print "FRONTPAGE: ";
+
+foreach $temp (@urls) {
+   $url = $temp->{'url'};
+   $mimetype = $temp->{'mimetype'};
+   $failtype = $temp->{'failtype'};
+   $message = $temp->{'message'};
+   $stime = time();
+   $response=$browser->get("http://".$host."/".$url);
+   $etime = time();
+   $tt = $etime - $stime;
+
+# If we got a server error, or unknown output type, report back as critical.
+   if ($response->status_line !~ "^200") {
+      print $message." (".$response->status_line.")\r\n";
+      exit $ERRORS{$failtype};
+   } elsif ($response->content_type !~ $mimetype) {
+      print $message." (Wrong Content-type: ".$response->content_type.")\r\n";
+      exit $ERRORS{$failtype};
+   } else {
+      # Because we're dealing with multiple URL's
+      $rt += $tt;
+   }
+
+# Decide if the response time was critical or not.
+#
+   if ($rt > $critical) {
+      print "Response time ".$rt." over critical threshold ".$critical."\r\n";
+      exit($ERRORS{'CRITICAL'});
+   } elsif ($rt > $warning) {
+      print "Response time ".$rt." over warning threshold ".$warning."\r\n";
+      exit($ERRORS{'WARNING'});
+   }
+}
+printf(" %s - %s second response time, ",$response->status_line, $rt);
+
+# If all the required URL's give the right responses quick enough, then we 
+# should be okay.
+exit($ERRORS{'OK'});
+
+sub print_usage () {
+   print "Usage: $PROGNAME -H <host> [-w <warn>] [-c <crit>]\n";
+   exit;
+}
+
+sub print_help () {
+   print_revision($PROGNAME,'$Revision$');
+   print "Copyright (c) 2003 Kev Green\n";
+   print "\n";
+   print "FrontPage remains a copyright/trademark of Microsoft Corporation.\n";
+   print_usage();
+   print "\n";
+   print "<warn> = Unknown.\n";
+   print "<crit> = Server error from FrontPage extensions.\n\n";
+   support();
+}
diff --git a/contrib/check_logins.c b/contrib/check_logins.c
new file mode 100644 (file)
index 0000000..fa3ed17
--- /dev/null
@@ -0,0 +1,351 @@
+/*=================================
+ *  check_logins - Nagios plugin
+ *  Copyright (C) 2003  Dag RobĆøle
+ *
+ *  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
+ *
+ *  Authors email: drobole@broadpark.no
+ */
+//=================================
+#include <sys/types.h>
+#include <signal.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+
+#include "config.h"
+#include "common.h"
+#include "utils.h"
+#include "popen.h"
+//=================================
+#define REVISION               "$Revision$"
+#define COPYRIGHT              "2003"
+#define AUTHOR                 "Dag Robole"
+#define EMAIL                  "drobole@broadpark.no"
+#define SUMMARY                        "Check for multiple user logins"
+
+#define check(func, errmsg)    { if((func) == -1) die(STATE_UNKNOWN, errmsg); }
+#define checkz(func, errmsg)   { if(!(func)) die(STATE_UNKNOWN, errmsg); }
+//=================================
+typedef struct USERNODE_TYP {
+       char *name;
+       char *host;
+       struct USERNODE_TYP* next;
+} USERNODE;
+//=================================
+char *progname = NULL;
+USERNODE *userlist = NULL, *adminlist = NULL;
+int warning_limit = 0, critical_limit = 0;
+
+void print_usage();
+void print_help();
+void process_arguments(int argc, char* *argv);
+void parse_wholine(const char *line, char *name, char *host);
+void node_create(USERNODE* *node, const char *name, const char *host);
+void node_free(USERNODE* *node);
+USERNODE* list_insert_sort_uniq(USERNODE* *list, USERNODE* *node);
+void list_free(USERNODE* *list);
+void cleanup();
+//=================================
+int main(int argc, char* *argv)
+{
+       FILE *who;
+       USERNODE *newnode, *nptra, *nptrb;
+       char buffer[BUFSIZ], username[BUFSIZ], hostname[BUFSIZ], *cptra, *cptrb;
+       char max_login_name[BUFSIZ], currname[BUFSIZ];
+       int max_login_count = 0, counter = 0, skip;
+       void (*old_sig_alrm)();
+
+       progname = argv[0];
+       if(atexit(cleanup))
+               die(STATE_UNKNOWN, "atexit failed\n");
+       
+       if((old_sig_alrm = signal((int)SIGALRM, timeout_alarm_handler)) == SIG_ERR)
+               die(STATE_UNKNOWN, "signal failed\n");
+       alarm(timeout_interval);
+
+       process_arguments(argc, argv);
+       
+       checkz(who = spopen(PATH_TO_WHO), "spopen failed\n");
+       
+       while(fgets(buffer, sizeof(buffer), who) != NULL) {     
+               parse_wholine(buffer, username, hostname);
+               skip = 0;
+               nptra = adminlist;
+               
+               while(nptra != NULL) {
+                       if(!strcmp(nptra->name, username)) {
+                               skip = 1;
+                               break;
+                       }
+                       nptra = nptra->next;
+               }               
+               if(!skip) {
+                       node_create(&newnode, username, hostname);
+                       if(!list_insert_sort_uniq(&userlist, &newnode))
+                               node_free(&newnode);
+               }
+       }
+       
+       check(spclose(who), "spclose failed\n");
+
+       if(userlist != NULL) {
+               nptra = userlist;
+               strcpy(currname, nptra->name);
+               strcpy(max_login_name, nptra->name);
+               max_login_count = 1;
+               while(nptra != NULL) {
+                       if(!strcmp(currname, nptra->name))
+                               ++counter;
+                       else {
+                               if(counter > max_login_count) {
+                                       max_login_count = counter;
+                                       strcpy(max_login_name, currname);
+                               }
+                               strcpy(currname, nptra->name);
+                               counter = 1;
+                       }
+                       nptra = nptra->next;
+               }
+               
+               if(counter > max_login_count) {
+                       max_login_count = counter;
+                       strcpy(max_login_name, currname);
+               }
+       }
+
+       if(signal((int)SIGALRM, old_sig_alrm) == SIG_ERR)
+               die(STATE_UNKNOWN, "signal failed\n");
+               
+       if(max_login_count) {
+               if(critical_limit && max_login_count >= critical_limit) {
+                       printf("CRITICAL - User %s has logged in from %d different hosts\n", max_login_name, max_login_count);
+                       return STATE_CRITICAL;
+               }
+               else if(warning_limit && max_login_count >= warning_limit) {
+                       printf("WARNING - User %s has logged in from %d different hosts\n", max_login_name, max_login_count);
+                       return STATE_WARNING;
+               }       
+       }
+
+       printf("OK - No users has exceeded the login limits\n");        
+       return STATE_OK;
+}
+//=================================
+void print_usage()
+{
+       fprintf(stderr, "Usage: %s [ -hV ] [ -w limit ] [ -c limit ] [ -u username1, ... ,usernameN ]\n", progname);
+}
+//=================================
+void print_help()
+{
+       print_revision(progname, REVISION);
+       printf("Copyright (c) %s %s <%s>\n\n%s\n\n", COPYRIGHT, AUTHOR, EMAIL, SUMMARY);
+       print_usage();
+       printf("\nDescription:\n"
+              "\tThis plugin supports the w (warning) and c (critical) options indicating the upper limits\n"
+              "\tof logins allowed before a warning is given.\n"
+              "\tThe output from %s is the username and number of login sessions for the user\n"
+              "\twho has the most login sessions (from different hosts) running at a given point in time.\n"
+              "\tThe u (users) option takes a comma separated list of usernames that will be ignored\n"
+              "\twhile scannig users.\n"
+              "\nOptions:\n"
+              "\t-h | --help\n\t\tShow this help message and exit\n"
+              "\t-V | --version\n\t\tShow version description\n"
+              "\t-w | --warning=INTEGER\n\t\tSet warning limit for logins (minimum value is 2)\n"
+              "\t-c | --critical=INTEGER\n\t\tSet critical limit for logins (minimum value is 2)\n"
+              "\t-u | --users=STRING\n\t\tSet usernames to be ignored\n"
+              "\nExamples:\n\t%s -w 3 -c 5\n"
+              "\t%s -w 3 -c 5 -u root,guest,jcarmack\n\n", progname, progname, progname);
+}
+//=================================
+void process_arguments(int argc, char* *argv)
+{      
+       USERNODE *newnode;
+       int optch;
+       char buffer[BUFSIZ], *cptra;
+       static struct option long_opts[] = {
+               {"help", no_argument, 0, 'h'},
+               {"version", no_argument, 0, 'V'},
+               {"warning", required_argument, 0, 'w'},
+               {"critical", required_argument, 0, 'c'},
+               {"users", required_argument, 0, 'u'},
+               {0, 0, 0, 0},
+       };
+       
+       while((optch = getopt_long(argc, argv, "hVw:c:u:", long_opts, NULL)) != -1) {
+               switch(optch) {
+                       case 'h':
+                               print_help();
+                               exit(STATE_OK);
+                               break;
+                       case 'V':
+                               print_revision(progname, REVISION);
+                               exit(STATE_OK);
+                               break;
+                       case 'w':
+                               if(!is_numeric(optarg)) {
+                                       print_usage();
+                                       die(STATE_UNKNOWN, "invalid options\n");
+                               }
+                               warning_limit = atoi(optarg) > 2 ? atoi(optarg) : 2;
+                               break;
+                       case 'c':
+                               if(!is_numeric(optarg)) {
+                                       print_usage();
+                                       die(STATE_UNKNOWN, "invalid options\n");
+                               }
+                               critical_limit = atoi(optarg) > 2 ? atoi(optarg) : 2;
+                               break;
+                       case 'u':
+                               strcpy(buffer, optarg);
+                               cptra = strtok(buffer, ",");
+                               while(cptra != NULL) {
+                                       node_create(&newnode, cptra, "(adminhost)");
+                                       list_insert_sort_uniq(&adminlist, &newnode);
+                                       cptra = strtok(NULL, ",");
+                               }
+                               break;
+                       default:
+                               print_usage();
+                               exit(STATE_UNKNOWN);
+                               break;
+               }
+       }
+
+       if(argc > optind) {
+               print_usage();
+               die(STATE_UNKNOWN, "invalid options\n");
+       }
+
+       if(!warning_limit && !critical_limit) {
+               print_usage();
+               die(STATE_UNKNOWN, "you must provide a limit for this plugin\n");
+       }
+       
+       if(critical_limit && warning_limit > critical_limit) {
+               print_usage();
+               die(STATE_UNKNOWN, "warning limit must be less or equal critical limit\n");
+       }
+}
+//=================================
+void parse_wholine(const char *line, char *name, char *host)
+{      
+       char buffer[BUFSIZ], *cptra, *cptrb, *display;
+       strcpy(buffer, line);
+
+       cptra = buffer;
+       checkz(cptrb = (char*)strchr(buffer, ' '), "strchr failed\n");
+       strncpy(name, cptra, cptrb-cptra);
+       name[cptrb-cptra] = '\0';
+
+       if((cptra = strchr(buffer, '(')) != NULL) // hostname found in source arg...
+       {
+               if(cptra[1] == ':') // local host
+                       strcpy(host, "(localhost)");
+               else // extern host
+               {
+                       checkz(cptrb = strchr(cptra, ')'), "strchr failed\n");
+                       cptrb++;
+                       strncpy(host, cptra, cptrb-cptra);
+                       host[cptrb-cptra] = '\0';
+               }
+       }
+       else // no hostname in source arg, look in line arg...
+       {
+               checkz(cptra = strtok(buffer, " \t\r\n"), "strtok failed\n"); 
+               checkz(cptra = strtok(NULL, " \t\r\n"), "strtok failed\n");
+               if(cptra[0] == ':') // local host
+                       strcpy(host, "(localhost)");
+               else // extern host
+                       sprintf(host, "(%s)", cptra);
+       }
+       
+       if((cptra = strchr(host, ':')) != NULL) // remove display if any...
+               strcpy(cptra, ")");
+}
+//================================= 
+void node_create(USERNODE* *node, const char *name, const char *host)
+{      
+       checkz(*node = (USERNODE*)malloc(sizeof(USERNODE)), "malloc failed\n");
+       checkz((*node)->name = (char*)malloc(strlen(name)+1), "malloc failed\n");
+       checkz((*node)->host = (char*)malloc(strlen(host)+1), "malloc failed\n");
+       (*node)->next = NULL;
+       strcpy((*node)->name, name);
+       strcpy((*node)->host, host);
+}
+//================================= 
+void node_free(USERNODE* *node)
+{      
+       free((*node)->name);
+       free((*node)->host);
+       free(*node);
+       *node = NULL;
+}
+//================================= 
+USERNODE* list_insert_sort_uniq(USERNODE* *list, USERNODE* *node)
+{
+       char n1[BUFSIZ], n2[BUFSIZ];
+       USERNODE *last_nptr = NULL, *nptr = *list;
+       
+       if(*list == NULL)
+               return(*list = *node);
+       else {
+               sprintf(n1, "%s %s", (*node)->name, (*node)->host);
+               while(nptr != NULL) {
+                       sprintf(n2, "%s %s", nptr->name, nptr->host);
+                       if(!strcmp(n1, n2))
+                               return NULL;
+                       else if(strcmp(n1, n2) < 0) {
+                               if(last_nptr) {
+                                       last_nptr->next = *node;
+                                       (*node)->next = nptr;
+                               }
+                               else {
+                                       (*node)->next = *list;
+                                       *list = *node;
+                               }
+                               break;
+                       }
+                       else {
+                               last_nptr = nptr;
+                               nptr = nptr->next;
+                       }
+               }
+               if(nptr == NULL)
+                       last_nptr->next = *node;
+       }
+       return *node;
+}
+//================================= 
+void list_free(USERNODE* *list)
+{      
+       USERNODE *doe, *nptr = *list;
+       while(nptr != NULL) {
+               doe = nptr;
+               nptr = nptr->next;
+               node_free(&doe);
+       }
+       *list = NULL;
+}
+//=================================
+void cleanup()
+{
+       list_free(&userlist);
+       list_free(&adminlist);
+}
+//=================================
diff --git a/contrib/check_oracle_tbs b/contrib/check_oracle_tbs
new file mode 100644 (file)
index 0000000..bcc4af8
--- /dev/null
@@ -0,0 +1,206 @@
+#!/usr/local/bin/perl -w
+
+# (c)2003 John Koyle, RFP Depot, LLC.
+# This is free software use it however you would like.
+# Thanks to the folks at http://www.think-forward.com for the SQL query
+
+
+use strict;
+use DBI;
+use Getopt::Long 2.16;
+use lib "/usr/local/nagios/libexec";
+use utils qw(%ERRORS);
+
+
+#*******************************************************************************
+# Set user configureable options here.
+#
+# Global Oracle info set here rather than command line to avoid output in ps -ef
+# Make sure this script is mode 700 and owner of the nrpe user
+#
+#*******************************************************************************
+my $orasid = "";
+my $orauser = "";
+my $orapwd = "";
+
+
+if (!$ENV{ORACLE_HOME}) {
+        $ENV{ORACLE_HOME} = '/a01/app/oracle/product/9.2.0.1';
+}
+
+#*****************You shouldn't need to modify anything below here *************
+my $state = $ERRORS{'UNKNOWN'};
+my $answer = undef;
+
+my ($MAJOR_VERSION, $MINOR_VERSION) = q$Revision$ =~ /(\d+)\.(\d+)/;
+my $VERSION = sprintf("%d.%02d", $MAJOR_VERSION - 1, $MINOR_VERSION);
+
+my $opt_debug;                  # -d|--debug
+my $opt_help;                   # -h|--help
+my $opt_version;                               # -V|--version
+my $opt_warn_space;            # -w|--warn-space
+my $opt_crit_space;            # -c|--crit-space
+
+my $help = <<MARK;      # help statement
+
+check_oracle_tbs v$VERSION
+
+Checks the tablespaces in an Oracle database for available free space.
+Usage: check_oracle_tbs [-w <warn>] [-c <crit>]
+
+  -d, --debug              Output debug to screen.
+  -h, --help               Displays this help and exits.
+  -w, --warn-space=...     Warning threshold % free (default 15)
+  -c, --crit-space=...     Critical threshold % free (default 10)
+  -V, --version            Output version information and exit.
+
+MARK
+
+## We want exact matches to the switches
+
+Getopt::Long::config('no_auto_abbrev', 'no_ignore_case');
+
+my $rc = GetOptions(
+                "debug|d"               => \$opt_debug,
+                "help|h"                => \$opt_help,
+                "w|warn-space=s"        => \$opt_warn_space,
+                "c|crit-space=s"        => \$opt_crit_space,
+                "V|version"             => \$opt_version,
+                   );
+
+
+#***********************************************************************
+# Process command-line switches
+#***********************************************************************
+
+if (! $rc || defined $opt_help)
+{
+    print STDERR $help;
+    exit (defined $opt_help ? 0 : 1);
+}
+
+if (defined $opt_version)
+{
+    print STDERR "check_oracle_tbs v$VERSION\n";
+    exit 0;
+}
+
+if (! defined $opt_warn_space)
+{
+    if(defined $opt_debug) {
+        print STDOUT "Warn space not defined, using 80%\n\n";
+    }
+    $opt_warn_space = 15;
+}
+
+if (! defined $opt_crit_space)
+{
+    if(defined $opt_debug) {
+        print STDOUT "Crit space not defined, using 90%\n\n";
+    }
+    $opt_crit_space = 10;
+}
+
+my $array_ref = executeSQL();
+
+foreach my $row (@$array_ref) {
+    my ( $tbs_name, $tot_mb, $free_mb, $free_pct, $used_pct, $fsfi) = @$row;
+    if ($opt_debug) { print STDOUT "Output: $tbs_name\t$tot_mb\t$free_mb\t$free_pct\t$used_pct\t$fsfi\n\n"; }
+    if ($used_pct > (100 - $opt_crit_space) && $tbs_name !~ /RBS/) {
+        $state = $ERRORS{'CRITICAL'};
+        $answer .= "$tbs_name = $used_pct\% ";
+        last;
+    }
+    if ($used_pct > (100 - $opt_warn_space) && $tbs_name !~ /RBS/) {
+        $state = $ERRORS{'WARNING'};
+        $answer .= "$tbs_name = $used_pct\% ";
+    }
+}
+
+if ($state != $ERRORS{'CRITICAL'} && $state != $ERRORS{'WARNING'}) {
+    $state = $ERRORS{'OK'};
+    $answer = "All Tablespaces OK";
+}
+
+if ($opt_debug && $state != $ERRORS{'OK'}) { print STDOUT "The following tablespaces are in question: $answer\n\n"; }
+
+foreach my $key (keys %ERRORS) {
+        if ($state==$ERRORS{$key}) {
+                print ("$key: $answer");
+                last;
+        }
+}
+exit $state;
+
+sub executeSQL
+{
+    my ($dbh, $sth, $results);
+
+    $dbh = openOracle();
+
+    eval {
+      $dbh->{RaiseError} = 1;
+      # This query is taken from this URL and used with permission: http://www.think-forward.com/sql/tspace.htm
+      $sth = $dbh->prepare(q{
+            select df.tablespace_name tspace, 
+                   df.bytes/(1024*1024) tot_ts_size,
+                   sum(fs.bytes)/(1024*1024) free_ts_size,
+                   round(sum(fs.bytes)*100/df.bytes) ts_pct,
+                   round((df.bytes-sum(fs.bytes))*100/df.bytes) ts_pct1,
+                   ROUND(100*SQRT(MAX(fs.bytes)/SUM(fs.bytes))*
+                   (1/SQRT(SQRT(COUNT(fs.bytes)))) ,2) FSFI
+              from dba_free_space fs, (select tablespace_name, sum(bytes) bytes
+                                         from dba_data_files
+                                     group by tablespace_name ) df          
+             where fs.tablespace_name = df.tablespace_name
+          group by df.tablespace_name, df.bytes
+         });
+
+      $sth->execute();
+      $results = $sth->fetchall_arrayref();
+      $sth->finish;
+      $dbh->{RaiseError} = 0;
+    };
+
+    if ($@) {
+      closeOracle($dbh);
+      if($opt_debug) { print STDOUT "DB Failed Query: $@\n"; }
+      CleanupAndExit($ERRORS{'UNKNOWN'});
+    }
+
+    closeOracle($dbh);
+
+    return $results;
+}
+
+#------ Open the connection to the database and return the handle
+sub openOracle
+{
+   my ($dbh);
+
+   $dbh = DBI->connect("$orasid", "$orauser", "$orapwd", "Oracle");
+
+   if (!$dbh) {
+      if ($opt_debug) { print "ERROR: Could not connect to Oracle!\n\n"; }
+      CleanupAndExit($ERRORS{'UNKNOWN'});
+   }
+   if ($opt_debug) { print "Connected to Oracle SID $orasid\n\n"; }
+   return $dbh;
+}
+
+#------- Close the database connection
+sub closeOracle()
+{
+   my ($dbh) = @_;
+
+   $dbh->disconnect;
+}
+
+#------ Exit with the current return code
+sub CleanupAndExit
+{
+        my ($rc) = @_;
+
+        exit($rc);
+}
+
diff --git a/contrib/check_pcpmetric.py b/contrib/check_pcpmetric.py
new file mode 100644 (file)
index 0000000..71d816d
--- /dev/null
@@ -0,0 +1,106 @@
+#! /usr/bin/env python
+#
+# Nagios client for checking Performance Co-Pilot metrics
+#
+#
+
+from sys import argv,exit
+import popen2, getopt, string, types
+
+DEBUG=0
+
+nagios_pcpclient_version = 0.01
+PMVAL='/usr/bin/pmval'
+COMMANDLINE=PMVAL + " -s 1"
+METRIC='undefined'
+CRITICAL=0
+WARNING=0
+
+def usage():
+       print "Usage:", argv[0], "[options]"
+       print "Options:"
+       print "\t[-H host]\tHostname to contact"
+       print "\t[-m metric]\tPCP metric to check"
+       print "\t[-i instance]\tPCP metric instance"
+       print "\t[-w warn]\tIssue warning alert if value is larger than this"
+       print "\t[-c critical]\tIssue critical alert value is larger than this"
+       print "\t[-V]\t\tProgram version"
+       print "\t[-h]\t\tThis helptext"
+       print ""
+       print "F.ex. to check 5 minute loadaverage, warn if the load is above 2,"
+       print "and give critical warning if it's above 10:"
+       print "\n\t%", argv[0], " -i 5 -m kernel.all.load -w 2 -c 10"
+       print ""
+       print "A list of all PCP metrics can be found with the command 'pminfo'."
+       print "A list of all instances within a metric can be found with 'pminfo -f metric'."
+       print "F.ex. to see all available instances of 'filesys.full' execute:"
+       print "\n\t% pminfo -f filesys.full"
+       print "\tfilesys.full"
+       print """\t\tinst [0 or "/dev/root"] value 45.35514044640914"""
+       print """\t\tinst [1 or "/dev/sda1"] value 46.74285959344712"""
+       print """\t\tinst [2 or "/dev/sdb1"] value 0.807766570678168"""
+       print ""
+       print "And the command to have nagios monitor the /dev/sda1 filesystem would be:"
+       print "\n\t", argv[0], " -i /dev/sda1 -m filesys.full -w 70 -c 90"
+
+
+opts, args = getopt.getopt(argv[1:],'hH:c:w:m:i:V')
+for opt in opts:
+       key,value = opt
+       if key == '-H':
+               COMMANDLINE = COMMANDLINE + " -h " + value
+       elif key == '-m':
+               METRIC=value
+       elif key == '-i':
+               COMMANDLINE = COMMANDLINE + " -i " + value
+       elif key == '-c':
+               CRITICAL = value
+       elif key == '-w':
+               WARNING = value
+       elif key == '-h':
+               usage()
+               exit(0)
+       elif key == '-V':
+               print "Nagios Performance CoPilot client v%.2f" % nagios_pcpclient_version
+               print "Written by Jan-Frode Myklebust <janfrode@parallab.uib.no>"
+               exit(0)
+
+if METRIC == 'undefined': 
+       usage()
+       exit(3)
+
+COMMANDLINE = COMMANDLINE + " " + METRIC
+if DEBUG: print COMMANDLINE
+p=popen2.Popen4(COMMANDLINE)
+exitcode=p.wait()
+
+# Get the last line of output from 'pmval':
+buffer = p.fromchild.readline()
+while (buffer != ''):
+       output=buffer
+       buffer = p.fromchild.readline()
+       
+returndata = string.split(output)[0]
+
+
+# Confirm that we have gotten a float, and not
+# some errormessage in the returndata. If not, 
+# print the error, and give the UNKNOWN exit code:
+
+try:
+       retval = string.atof(returndata)
+except ValueError, e:
+       print e
+       exit(3)
+
+if (retval < WARNING):
+       EXITCODE=0
+elif (retval > CRITICAL):
+       EXITCODE=2
+elif (retval > WARNING):
+       EXITCODE=1
+else:
+       EXITCODE=3
+
+print retval
+exit(EXITCODE)
diff --git a/contrib/check_pfstate b/contrib/check_pfstate
new file mode 100644 (file)
index 0000000..6fe0d9b
--- /dev/null
@@ -0,0 +1,75 @@
+#!/usr/bin/perl
+
+use strict;
+use Getopt::Long;
+use vars qw($opt_V $opt_h $opt_P $opt_H $opt_w $opt_c $PROGNAME);
+use lib "/usr/local/nagios/libexec"  ;
+use utils qw(%ERRORS &print_revision &support &usage);
+
+my $remote_user = "root";
+my $path_to_ssh = "/usr/bin/ssh";
+my $path_to_grep = "/usr/bin/grep";
+my $path_to_awk = "/usr/bin/awk";
+my $warn = 50000;
+my $crit = 60000;
+
+$PROGNAME = "check_pfstate";
+$ENV{'PATH'}='';
+$ENV{'BASH_ENV'}='';
+$ENV{'ENV'}='';
+
+Getopt::Long::Configure('bundling');
+GetOptions
+        ("V"   => \$opt_V, "version"    => \$opt_V,
+         "h"   => \$opt_h, "help"       => \$opt_h,
+         "H=s" => \$opt_H, "hostname=s" => \$opt_H,
+        "w=s" => \$opt_w, "warning=s"  => \$opt_w,
+        "c=s" => \$opt_c, "critical=s" => \$opt_c);
+
+if ($opt_V) {
+        print_revision($PROGNAME,'$Revision$');
+        exit $ERRORS{'OK'};
+}
+if ($opt_h) {
+       print_help();
+       exit $ERRORS{'OK'};
+}
+if ($opt_w) {
+       if ($opt_w =~ /(\d+)/) {
+               $warn = $1;
+       } else {
+               usage("Invalid values: $opt_w\n");
+               exit $ERRORS{'OK'};
+       }
+}
+if ($opt_c) {
+       if ($opt_c =~ /(\d+)/) {
+               $crit = $1;
+       } else {
+               usage("Invalid values: $opt_c\n");
+               exit $ERRORS{'OK'};
+       }
+}
+($opt_H) || usage("Host name/address not specified\n");
+my $host = $1 if ($opt_H =~ /([-.A-Za-z0-9]+)/);
+($host) || usage("Invalid host: $opt_H\n");
+
+my $result = `$path_to_ssh -l $remote_user $host '/sbin/pfctl -s info' | $path_to_grep entries`;
+chomp $result;
+$result =~ /(\d+)/;
+$result = $1;
+
+print "$result PF state entries\n";
+
+exit $ERRORS{'CRITICAL'} if ($result >= $crit);
+exit $ERRORS{'WARNING'} if ($result >= $warn);
+exit $ERRORS{'OK'};
+
+
+sub print_help {
+        print_revision($PROGNAME,'$Revision$');
+        print "Copyright (c) 2002 Jason Dixon\n\nThis plugin checks the number of state table entries on a PF-enabled OpenBSD system.\n\n";
+        print "Usage:\t-H, --hostname=<HOST> [-w, --warning=<WARNING>] [-c, --critical=<CRITICAL>]\n\n\tDefault warning is 50000 and critical is 60000.\n\n";
+        support();
+}
+