#!/usr/bin/perl

#
# a partial replacment for ping in a freebsd jail
#

require 5.002;
use Socket;
use Time::HiRes qw(gettimeofday tv_interval);
use Errno qw(ECONNREFUSED EINTR);


use Getopt::Long;

my ( $opt_host, $opt_warning, $opt_critical, $opt_packets, $opt_timeout );

unless ( GetOptions (
                     '-H|host=s'     => \$opt_host,
                     '-w|warning=s'  => \$opt_warning,
                     '-c|critical=s' => \$opt_critical,
                     '-p|packets=s'  => \$opt_packets,
                     '-t|timeout=s'  => \$opt_timeout,
                    )
       ) { die "Error parsing command line options" }

unless ( $opt_host )
{
  die "Error: no host specified: $opt_host\n"
}

my ( $opt_warning, undef ) = split( /,/, $opt_warning ) if $opt_warning;
my ( $opt_critical, undef ) = split( /,/, $opt_critical ) if $opt_critical;

my $elapsed = ping( $opt_host, 5, 1 );

if ( ! $elapsed )
{
  print "CRITICAL  No Response\n";
  exit 2;
}
elsif ( $opt_critical && $elapsed > $opt_critical )
{
  print "CRITICAL  Elapsed time $elapsed\n";
  exit 2;
}
elsif ( $opt_warning && $elapsed > $opt_warning )
{
  print "WARNING  Elapsed time: $elapsed\n";
  exit 1;
}
elsif ( $elapsed == -1 )
{
  print "CRITICAL ping_tcp error returned from host: $opt_host";
  exit 2;
}
else
{
  print "OK  Elapsed time: $elapsed\n";
  exit 0;
}




#
#_* Subroutines
#
#   taken from: http://www.cacti.net/downloads/scripts/ping-tcp.pl.txt
#

sub timeout
{
        return;
}

sub ping
{
        my($host, $timeout, $count) = @_;
        my $iaddr = inet_aton($host) or die "Unknown host: $host\n";
        my $proto = getprotobyname('tcp') or die "getprotobyname: $!\n";
        my $n = 0;
        my $port = 65535;
        my $paddr = undef;
        my $elapsed = 0;
        my $got = 0;

        while($n++ < $count || !$count)
        {
                $paddr = sockaddr_in($port, $iaddr) or
                        die "getprotobyname: $!\n";

                socket(SOCKET, PF_INET, SOCK_STREAM, $proto) or
                        die "socket: $!\n";

                local($SIG{'ALRM'}) = 'timeout';
                alarm($timeout);

                my $t0 = [gettimeofday];
                connect(SOCKET, $paddr);

                if ($! == &EINTR)
                {
                        $port--;
                }

                if ($! == &ECONNREFUSED)
                {
                        $got++;
                        $elapsed += tv_interval ($t0, [gettimeofday]);
                }

                close(SOCKET);
        }

        if ($got)
        {
                return (($elapsed * 1000) / $got);
        }
        else
        {
                return -1;
        }
}

