#!/usr/bin/perl -w
#
# check_infratec_rms.pl - Nagios(r) rms monitor plugin
# Version 1.0
# Copyright (C) 2006 Peter Hasler / office@it-hasler.at
#
# based on check_infratec_rms.pl from Gerd Mueller / Netways GmbH
#
# Send us bug reports, questions and comments about this plugin.
# Latest version of this software: http://www.nagiosexchange.org
#
# 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
 
use strict;
 
use Net::SNMP;
use Getopt::Long;
&Getopt::Long::config('bundling');
 
use Data::Dumper;

# default-values:
#
# temperature
#
my $t_warn1      = 20;
my $t_warn2      = 28;
my $t_crit1      = 17;
my $t_crit2      = 33;
#
# Alert-In
#
my $a_warn2      =900;
my $a_crit2      =60;
#
# Digital-In
#
my $d_warn2      =900;
my $d_crit2      =60;
#
# humidity
#
my $h_warn1      =15;
my $h_warn2      =70;
my $h_crit1      =10;
my $h_crit2      =90;
#
# mains
#
my $m_warn1      =215;
my $m_warn2      =250;
my $m_crit1      =210;
my $m_crit2      =255;
#
# ups-in
#
my $u_warn2      =900;
my $u_crit2      =60;
#
# digital output
#
my $o_warn2      =900;
my $o_crit2      =60; 
my $host_address;


my $opt_h;
my $snmpTimeOutput=0;
my $unit;
my $session;
my $error;
my $port=161;
my $snmp_version = 1;
my $opt_c="off";
my $invers = 0;
my $warning;
my $warn1 = 0;
my $warn2 = 250;
my $critical;
my $crit1 = 0;
my $crit2 = 255;
my $PortTyp;
my $verbose=0;
my @snmpoids;
my $exit_status = "OK";
my $TimeCount;
my $StateTxt="";;
my $response;

my %STATUS_CODE = ( 'OK'=> '0','WARNING'  => '1','CRITICAL' => '2',  'UNKNOWN'  => '3');


# SNMP OIDs for Traffic
my $snmpAlertIn     = '1.3.6.1.4.1.1909.10.2.2.1';
my $snmpDigitalIn   = '1.3.6.1.4.1.1909.10.2.1.1';
my $snmpTempIn      = '1.3.6.1.4.1.1909.10.4.1.1';
my $snmpHumidIn     = '1.3.6.1.4.1.1909.10.5.1.1';
my $snmpMainsIn     = '1.3.6.1.4.1.1909.10.6.1.1';
my $snmpUSVIn       = '1.3.6.1.4.1.1909.10.2.3.1';
my $snmpDigOut      = '1.3.6.1.4.1.1909.10.3.1.1';

my $snmpDescr       = '.2';
my $snmpState       = '.3';    
my $snmpTimeCount       = '.4';
 

#default values;
my $COMMUNITY    = "public";
 
my $status = GetOptions(
        "h"              => \$opt_h,
        "help"           => \$opt_h,
        "v=s"            => \$verbose,
        "verbose=s"      => \$verbose,
        "C=s"            => \$COMMUNITY,
        "community=s"    => \$COMMUNITY,
        "H=s"            => \$host_address,
        "hostname=s"     => \$host_address,
        "p=s"            => \$port,
        "port=s"         => \$port,
        "i=s"            => \$invers,
        "inverse=s"      => \$invers,
        "w=s"            => \$warning,
        "warning=s"      => \$warning,
        "c=s"            => \$critical,
        "critical=s"     => \$critical
);


if($port =~ /a([1-4])/i) {
        $snmpState  =$snmpAlertIn.$snmpState.".".$1;
        $snmpDescr  =$snmpAlertIn.$snmpDescr.".".$1;
        $snmpTimeCount =$snmpAlertIn.$snmpTimeCount.".".$1;
        $warn2      = $a_warn2;
        $crit2      = $a_crit2;
        $PortTyp    = 1;
} elsif($port =~ /d([1-8])/i) {
        $snmpState  =$snmpDigitalIn.$snmpState.".".$1;
        $snmpDescr  =$snmpDigitalIn.$snmpDescr.".".$1;
        $snmpTimeCount =$snmpDigitalIn.$snmpTimeCount.".".$1;
        $warn2      = $d_warn2;
        $crit2      = $d_crit2;
        $PortTyp    =1;
} elsif($port =~ /t([1-4])/i) {
        $snmpState  =$snmpTempIn.$snmpState.".".$1;
        $snmpDescr  =$snmpTempIn.$snmpDescr.".".$1;
        $unit       = "GradC";
        $warn1      = $t_warn1;
        $warn2      = $t_warn2;
        $crit1      = $t_crit1;
        $crit2      = $t_crit2;
        $PortTyp    =2;
} elsif($port =~ /h([1-4])/i) {
        $snmpState  =$snmpHumidIn.$snmpState.".".$1;
        $snmpDescr  =$snmpHumidIn.$snmpDescr.".".$1;
        $unit       = "% rF";
        $warn1      = $h_warn1;
        $warn2      = $h_warn2;
        $crit1      = $h_crit1;
        $crit2      = $h_crit2;
        $PortTyp    =2;
} elsif($port =~ /m([1-3])/i) {
        $snmpState  =$snmpMainsIn.$snmpState.".".$1;
        $snmpDescr  =$snmpMainsIn.$snmpDescr.".".$1;
        $unit       = "V";
        $warn1      = $m_warn1;
        $warn2      = $m_warn2;
        $crit1      = $m_crit1;
        $crit2      = $m_crit2;
        $PortTyp    =2;
} elsif($port =~ /u([1-2])/i) {
        $snmpState  =$snmpUSVIn.$snmpState.".".$1;
        $snmpDescr  =$snmpUSVIn.$snmpDescr.".".$1;
        $snmpTimeCount =$snmpUSVIn.$snmpTimeCount.".".$1;
        $warn2      = $u_warn2;
        $crit2      = $u_crit2;
        $PortTyp   =1;
} elsif($port =~ /o([1-4])/i) {
        $snmpState  =$snmpDigOut.$snmpState.".".$1;
        $snmpDescr  =$snmpDigOut.$snmpDescr.".".$1;
        $snmpTimeCount =$snmpDigOut.$snmpTimeCount.".".$1;
        $warn2      = $o_warn2;
        $crit2      = $o_crit2;
        $PortTyp    =1;
} else {
        print_usage();
        exit $STATUS_CODE{'CRITICAL'};
}


  if ( defined($warning) ) {
    if ($warning =~ /(\d+):(\d+)/ ) {
      $warn1 = $1;
      $warn2 = $2;
    }
    elsif ($warning =~ /(\d+):/ ) {
      $warn1 = $1;
    }
    elsif ($warning =~ /:(\d+)/ ) {
      $warn2 = $1;
    }
    elsif ($warning =~ /(\d+)/ ) {
      $warn2 = $1;
    }
    elsif ( !($warning eq "default" or $warning eq ":")  ) {
      $StateTxt = "CRITICAL: unknown parameter $warning for WARNING"; 
      $status = 0; 
    }

  }



  if ( defined($critical) ) {
    if ($critical =~ /(\d+):(\d+)/ ) {
      $crit1 = $1;
      $crit2 = $2;
    }
    elsif ($critical =~ /(\d+):/ ) {
      $crit1 = $1;
    }
    elsif ($critical =~ /:(\d+)/ ) {
      $crit2 = $1;
    }
    elsif ($critical =~ /(\d+)/ ) {
      $crit2 = $1;
    }
    elsif ( !($critical eq "default" or $critical eq ":")  ) {
      $StateTxt = "CRITICAL: unknown parameter $critical for CRITICAL";
      $status = 0;
    }


  }

 if ($verbose == 3){
   print "warn1:    $warn1\n";
   print "warn2:    $warn2\n";
   print "crit1:    $crit1\n";
   print "crit2:    $crit2\n";

 }


if ( $status == 0 ) {
        print "$StateTxt \n";
        print_usage();
        exit $STATUS_CODE{'CRITICAL'};
}

if((!$host_address)) 
{ 
 print_usage();
 exit $STATUS_CODE{'CRITICAL'};
}


( $session, $error ) = Net::SNMP->session(-hostname  => $host_address,-community => $COMMUNITY,-port=> 161,-version  => $snmp_version);

        if ( !defined($session) ) {
                print("WARNING: $error");
                exit $STATUS_CODE{'WARNING'};
        }


push( @snmpoids, $snmpDescr);
push( @snmpoids, $snmpState);

if ($PortTyp == "1") {
  push( @snmpoids, $snmpTimeCount);
}


$session->translate([-timeticks      => 0 ]);




if ( !defined( $response = $session->get_request(@snmpoids) ) ) {
        my $answer = $session->error;
        $session->close;

        print("WARNING: SNMP error: $answer\n");
        exit $STATUS_CODE{'WARNING'};
}

my $Descr = $response->{$snmpDescr};
my $State = $response->{$snmpState};


if ($PortTyp == 1) {
   $TimeCount = $response->{$snmpTimeCount}/100;

   if ($verbose == 3) {
      print "TimeCount: $TimeCount \n";
   }
   
}

$session->close;

if ($verbose == 3){
      print "Descr: $Descr \n";
      print "State: $State \n";
      print "inverse: $invers\n";
}


if ($PortTyp == 1) {
  $StateTxt = "ON";
  if ($State == "1"){
       $StateTxt = "OFF";
  }
 
  if ($invers =~ /ON/i) {
    if ($State == "1") {
     $State = "2";
     $StateTxt="INVERTED to ON";
     }
    elsif ($State == "2") {
     $State = "1";
     $StateTxt="INVERTED to OFF";
    }
  }
 

  
  
  my $Wochen   = int($TimeCount / 604800);
  my $Tage     = int(($TimeCount - $Wochen *604800)  / 86400);
  my $Stunden  = int(($TimeCount - $Wochen *604800 - $Tage * 86400) / 3600);
  my $Minuten  = int(($TimeCount - $Wochen *604800 - $Tage * 86400 - $Stunden * 3600) / 60);
  my $Sekunden = int($TimeCount - $Wochen *604800 - $Tage * 86400 - $Stunden * 3600 - $Minuten * 60 );


  my $TimeLong = $Sekunden ."sec";
  if ($Minuten > 0) {
    $TimeLong = $Minuten ."m " . $TimeLong  ;
  }
  if ($Stunden > 0) {
    $TimeLong = $Stunden ."h " . $TimeLong  ;
  }
  if ($Tage > 0) {
    $TimeLong = $Tage ."d " . $TimeLong  ;
  }
  if ($Wochen > 0) {
    $TimeLong = $Wochen ."w " . $TimeLong  ;
  }

  
  $StateTxt = $StateTxt ." since $TimeLong "  ;

  if ( $State ==  2 and  $TimeCount  < $warn2 ){
     $exit_status = "WARNING";
  }

  if ( $State ==  1 and  $TimeCount  > $crit2 ){
     $exit_status = "CRITICAL";

  }


}


if ($PortTyp == 2) {
 $StateTxt = "$State $unit Limit: -w $warn1".":"."$warn2 -c $crit1".":"."$crit2 $unit ";
 
 if ($State < $warn1 or $State > $warn2){
     $exit_status = "WARNING";

 }

 if ($State < $crit1 or $State > $crit2){
     $exit_status = "CRITICAL";
 }

 if ($invers =~ /ON/i) {
    if ($exit_status eq "CRITICAL") {
     $exit_status = "OK";
    }
    elsif ($exit_status eq "OK") {
     $exit_status = "CRITICAL";
    }
  $StateTxt = $StateTxt . "- INVERTED!! ";
 }

}


if ($verbose == 3){
      print "ExitStatus: $exit_status \n";
      print "StatusText : $StateTxt \n";
}



print "$exit_status: $Descr ($port): $StateTxt";


print "| State=$State\n";

exit($STATUS_CODE{$exit_status});


sub print_usage
{
 print "Usage: check_rms.pl -H host -p port [-C community] [-w warning] [-c critical] [-i inverse] \n";
 print "Options:\n";
 print " -H --host STRING or IPADDRESS\n";
 print "   Check interface on the indicated host.\n";
 print " -C --community STRING \n";
 print "   SNMP Community.\n";
 print " -p Port\n";
 print "   Port to be monitored \n";
 print "    e.g. d1 for digital 1 or a1 for alert 1 or t1 for temperature 1 \n";
 print "      or h1 for humidity 1  or m1 for mains 1 or u1 for usv 1 or o1 for output 1\n";
 print " -w --warning String\n";
 print "   the limit(s) of warning-state\n";
 print " -c --critical String\n";
 print "   the limit(s) of critical-state\n";
 print " -i --inverse [on|off]\n";
 print "   inverted state \n";
 print " -v --verbose String\n";
 print "   level of verbose-output (1-3)\n";
 print " -h --help\n";
 print "   help-info\n\n";
 print "DEFAULT-VALUES: \n ";
 print "temperature: warning: ";
 print  $t_warn1 . ":";
 print "$t_warn2 ";
 print "critical: " . $t_crit1 . ":";
 print "$t_crit2\n";

 print " humidity   : warning: ";
 print  $h_warn1 . ":";
 print "$h_warn2 ";
 print "critical: " . $h_crit1 . ":";
 print "$h_crit2\n";

 print " mains      : warning: ";
 print  $m_warn1 . ":";
 print "$m_warn2 ";
 print "critical: " . $m_crit1 . ":";
 print "$m_crit2\n";

 print " alert-in   : warning: ";
 print  "$a_warn2 ";
 print "critical: $a_crit2 \n";

 print " digital-in : warning: ";
 print  "$d_warn2 ";
 print "critical: $d_crit2 \n";

 print " UPS-in     : warning: ";
 print  "$u_warn2 ";
 print "critical: $u_crit2 \n";

 print " digital-out: warning: ";
 print  "$o_warn2 ";
 print "critical: $o_crit2 \n";

 exit($STATUS_CODE{"CRITICAL"});
}
