#!/usr/bin/perl -w
##
## Host Alive effect
##
##  1.3 - correção da funcao udp
##
use Nagios::Plugin;
use strict;
use File::Basename;
use Net::Ping;
use Data::Dumper;
use IO::Socket;
use IO::Select;

$ENV{"USER"} = "opuser";

#evil globals but Perl loves them
use vars qw($sess $np $status $msg);

#Other vars
my ($VERSION,$PROGNAME);
my ($onlyTest,$warn,$crit);

#INIT
$VERSION = "1.3";
$PROGNAME = basename($0);
$status = 0;
$msg = undef;
$onlyTest = 0;

$np = Nagios::Plugin->new(
  usage => "Usage: %s -H <host> [-i|--icmp] [-p <tcp ports>] [ -u <udp ports> ] [ -T <timeout checks> ] ",
  version => $VERSION,
  blurb => "This plugin return host alive",
  extra => "Note: ",
  shortname => " ",
);

# Define and document the valid command line options
# usage, help, version, timeout and verbose are defined by default.
$np->add_arg(
  spec => 'host|H=s',
  help =>
  qq{
 -H, --host=ADDRESS
   Host name or IP Address},
  required => 1
);

$np->add_arg(
  spec => 'icmp|i',
  help =>
  qq{-i, --icmp(boolean)
   Check ping status},
  required => 0,
);

$np->add_arg(
  spec => 'timeoutcheck|T=i',
  help =>
  qq{-T, --timeoutcheck=2
   Timeout checks},
  required => 0,
  default => 2
);

$np->add_arg(
  spec => 'udp|u=s',
  help =>
  qq{-u, --udp=161,754
   Check ports UDP},
  required => 0,
);


$np->add_arg(
  spec => 'ports|p=s',
  help =>
  qq{-p, --ports=22,80
   Check ports TCP},
  required => 0,
);

$np->getopts;
my $host = $np->opts->host;
my $ports = $np->opts->ports;
my $ports_udp = $np->opts->udp;
my $timeoutcheck = $np->opts->timeoutcheck;

my $checks = 0;
my $checksOk = 0;
my @msgs = ();


if($np->opts->icmp){
  my $ping = getPing($host, $timeoutcheck);
  #print Dumper $ping;
  #print "ping\n";
  $checks++;
  if($ping > 0 ){
    $checksOk++;
    push @msgs, 'Ping:OK';

  }else{
     push @msgs, 'Ping:Fail';
  }
}

if($ports){# check TCP
  my @ports = split /,/, $ports;
#  print Dumper \@ports;

  foreach (@ports) {
#    print Dumper $_;
    my $tcp = getTcp($host,$_, $timeoutcheck);
#    print Dumper $tcp;
#    print "tcp\n";
    $checks++;
    if($tcp > 0 ){
      $checksOk++;
      push @msgs, 'tcp_'.$_.':OK';

    }else{
       push @msgs, 'tcp_'.$_.':Fail';
    }
  }
}

if($ports_udp){# check UDP
  my @ports = split /,/, $ports_udp;
#  print Dumper \@ports;

  foreach (@ports) {
#    print Dumper $_;
    my $udp = getUdp($host,$_, $timeoutcheck);
 #   print Dumper $udp;
 #   print "udp\n";
    $checks++;
    if($udp > 0 ){
      $checksOk++;
      push @msgs, 'udp_'.$_.':OK';

    }else{
       push @msgs, 'udp_'.$_.':Fail';
    }
  }
}


#print "@msgs\n";
#print "checks: $checks\n";
#print "checksOk: $checksOk\n";

if($checksOk > 0){
  print "Host Up - Success checks:".$checksOk."/".$checks." - @msgs | 'checks_ok'=".$checksOk.";;;; \n";
  exit(0);
}else{
  print "Host Down - Success checks:".$checksOk."/".$checks." - @msgs | 'checks_ok'=".$checksOk.";;;; \n";
  exit(2);
}

sub getPing{
  my $host = shift;
  my $timeoutping = shift;

  my $output = `/usr/local/opmon/libexec/check_icmp -H $host -w 3000.0,80% -c 5000.0,100% -n 20 -b 52 `;
  my $exit_code = $?>>8;

  #print Dumper $output;
  #print Dumper $exit_code;

  my $connect = 0;
  if($exit_code == 0 ){
    $connect = 1;
  }
return $connect;
}

sub getTcp {
  my $host = shift;
  my $ports = shift;
  my $timeoutcheck = shift;
    # auto-flush on socket
  $| = 1;

  # create a connecting socket
  my $socket = new IO::Socket::INET (
    PeerHost => $host,
    PeerPort => $ports,
    Proto => 'tcp' ,
    Timeout   => $timeoutcheck ,
  );

  #print Dumper $socket;
  my $connect = 0;
  if($socket){
    $connect = 1;
    $socket->close();
  }
return $connect;
}

sub getUdp {
  my $address = shift;
  my $port = shift;
  my $connect = 0;

  my $command = 'nmap -p '.$port.' '.$address.' -sU | grep '.$port.' | grep open';
  #print Dumper $command;
  my $retCommand = `$command`;
  chomp($retCommand);
  #print Dumper $retCommand;

  if( $retCommand =~ m/open/){
    $connect = 1;
  }
  
  return $connect;
}
