#!/usr/bin/perl

# check_cisco_command - telnet's to a Cisco router to run a command

# 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.
#
############################################################################

use strict;

use Getopt::Long;

use vars qw($opt_d $opt_u $opt_p $opt_P $opt_h $opt_H $opt_V $opt_v 
	$debug $username $password $hostname $state $error $PROGNAME 
	@command_output $session $command $opt_r $tmp_var_loss $tmp_var_latency 
	$opt_c $opt_w $info $answer $opt_m $metric $warning_rta $warning_pl
	$timeout $router $critical_rta $critical_pl $opt_t $vrf $stats);
use lib  "utils.pm";
use utils qw(%ERRORS &print_revision &support &usage );

use Net::Telnet::Cisco;

sub print_help ();
sub print_usage ();

$ENV{'PATH'}='';
$ENV{'BASH_ENV'}=''; 
$ENV{'ENV'}='';

# defaults 
my $debug = 0;
my $state = $ERRORS{'UNKNOWN'};
my $packets = 5;
my $command = "ping";
my $timeout = $packets * 4; # seconds
my $router = "";
my $username = "";
my $password  = "";
my $warning_rta = "";
my $critical_rta = "";
my $warning_pl = "";
my $critical_pl = "";

Getopt::Long::Configure('bundling');

GetOptions(
	"d"   => \$opt_d, "debug"		=> \$opt_d,
	"V"   => \$opt_V, "version"		=> \$opt_V,
	"u=s" => \$opt_u, "username=s"	=> \$opt_u, 
	"p=s" => \$opt_p, "password=s"  	=> \$opt_p,
	"r=s" => \$opt_r, "router=s"	=> \$opt_r,
	"v=s" => \$opt_v, "vrf=s"		=> \$opt_v,
	"P=i" => \$opt_P, "packets=i"	=> \$opt_P,
	"w=s" => \$opt_w, "warning=s"	=> \$opt_w,
	"c=s" => \$opt_c, "critical=s"	=> \$opt_c,
	"h"   => \$opt_h, "help"		=> \$opt_h,
	"t=i" => \$opt_t, "timeout=i"	=> \$opt_t,
	"H=s" => \$opt_H, "hostname=s"	=> \$opt_H);

$PROGNAME = "check_cisco_ping";

if ($opt_d) {
	$debug = 1;
}

if ($opt_V) {
	print_revision($PROGNAME,'$Revision: 1.1 $');
	exit $ERRORS{'OK'};
}

if ($opt_h) {print_help(); exit $ERRORS{'OK'};}

unless (defined $opt_H) {
	print("No target hostname specified\n");
	print_usage();
	exit $ERRORS{"UNKNOWN"};
}
$hostname = $opt_H;
if (! utils::is_hostname($hostname)){
	print("$hostname did not match pattern\n");
	print_usage();
	exit $ERRORS{"UNKNOWN"};
}

unless (defined $opt_u) {
	print("So who exactly do I login as ?\n");
	print_usage();
	exit $ERRORS{"UNKNOWN"};
}
$username = $opt_u;

unless (defined $opt_p) {
	print("So how exactly do I prove my identity ?\n");
	print_usage();
	exit $ERRORS{"UNKOWN"};
}
$password = $opt_p;

unless (defined $opt_r) {
	print("I need to know what router to login to\n");
	print_usage();
	exit $ERRORS{"UNKNOWN"};
}
if (! utils::is_hostname($opt_r)) {
	print("Invalid target hostname/IP address\n");
	pring_usage();
	exit $ERRORS{"UNKNOWN"};
}
$router = $opt_r;

if (defined $opt_P) {
	if ($opt_P > 0) {
		if ($opt_P > $packets) {
			$timeout = $opt_P * 4;
		}
		$packets = $opt_P;
	}
	else {
		print("Invalid packet count (try >= 1)\n");
		print_usage();
		exit $ERRORS{'UNKNOWN'};
	}
}

if (defined $opt_v) {
	$vrf = $opt_v;
}

if (defined $opt_t) {
	$timeout = $opt_t;
}

if (defined $opt_w) {
	if ($opt_w =~ /[0-9]+,[0-9]+\%/) {
		$opt_w =~ s/\%$//;
		($warning_rta, $warning_pl) = split(/,/, $opt_w);
	}
	else {
		print("Invalid threshold pair\n");
		print_usage();
		exit $ERRORS{'UNKNOWN'};
	}
}

if (defined $opt_c) {
	if ($opt_c =~ /[0-9]+,[0-9]+\%/) {
		$opt_c =~ s/\%$//;
		($critical_rta, $critical_pl) = split(/,/, $opt_c);
	} else {
		print("Invalid threshold pair\n");
		print_usage();
		exit $ERRORS{'UNKNOWN'};
	}
}

if ($debug == 1) {
	print "debug = $debug
username = '$username'
password = '$password'
router = '$router'
hostname = '$hostname'
vrf = '$vrf',
packets = '$packets',
warning rta = '$warning_rta',
critical rta = '$critical_rta',
warning pl = '$warning_pl',
critical pl = '$critical_pl'\n";
}


### main logic

#eag123-lv08-rt01.bne#ping ?
#  WORD       Ping destination address or hostname
#  appletalk  Appletalk echo
#  atm        ATM echo
#  clns       CLNS echo
#  decnet     DECnet echo
#  ip         IP echo
#  ipv6       IPv6 echo
#  ipx        Novell/IPX echo
#  srb        srb echo
#  tag        Tag encapsulated IP echo
#  vrf        Select VPN routing instance
#  <cr>
#
#eag123-lv08-rt01.bne#ping ip ns1.intrapower.com.au ?
#  data      specify data pattern
#  df-bit    enable do not fragment bit in IP header
#  repeat    specify repeat count
#  size      specify datagram size
#  source    specify source address or name
#  timeout   specify timeout interval
#  validate  validate reply data
#  <cr>
#

$session = Net::Telnet::Cisco->new(Host => "$router");
$session->login("$username", "$password");
$session->cmd('terminal length 0');
# TODO: Verify router has configuration with VRF tag

if (defined $vrf) {
	$command = "$command vrf $vrf ip $hostname repeat $packets";
} else {
	$command = "$command ip $hostname repeat $packets";
}

if ($debug == 1) {
	print "command = '$command'\n";
}

@command_output = $session->cmd(String => "$command", Timeout => $timeout);
$session->close;

$info = 'UNKNOWN ERROR';
$answer = 'UNKNOWN: $info';
$state = $ERRORS{'UNKNOWN'};
$stats = "PL=NULL,RTA=NULL";

foreach $info (@command_output) {
	chomp($info);

	if ($info =~ /Success\ rate/) {
		if ($debug == 1) {
			print "Information string found: '$info'\n";
		}

		$tmp_var_loss = $tmp_var_latency = $info;
		$tmp_var_loss =~ s/(^Success\ rate\ is\ |\ percent.*$)//g;

		if ($tmp_var_loss > 0) {
			$tmp_var_loss -= 100;
		} else {
			$tmp_var_loss = 100;
		}

		$state = 'OK';
		$stats = "Packet loss = $tmp_var_loss%";

        if ($debug == 1) {
        	print "Percentage loss: $tmp_var_loss%\n";
        }

        if ($critical_pl =~ /[0-9]+/ && $tmp_var_loss >= $critical_pl) {
            $state = 'CRITICAL';
        } elsif ($warning_pl =~ /[0-9]+/ && $tmp_var_loss >= $warning_pl) {
            $state = 'WARNING';
		} elsif ($tmp_var_loss != 100) {
			$tmp_var_latency =~ s/(^.*max\ \=\ [0-9]+\/|\/[0-9]+\ ms$)//g;

			if ($debug == 1) {
				print "Average Latency: $tmp_var_latency ms\n";
			}

			$stats = "$stats, RTA = $tmp_var_latency ms";

			if ($critical_rta =~ /[0-9]+/ && $tmp_var_latency >= $critical_rta) {
				$state = 'CRITICAL';
			} elsif ($warning_rta =~ /[0-9]+/ && $tmp_var_latency >= $warning_rta) {
				$state = 'WARNING';
			}
		}
	}

	$answer = "PING $state - $stats|$info";
}

print "$answer\n";
exit $ERRORS{$state};

#### subroutines

sub print_usage () {
	print "Usage: $PROGNAME -H <host> -u <username> -p <password> -r <router address>
                  -w <wrta,wpl>% -c <crta,cpl>% [--vrf <vrf>] [-P <packets>]
                  [-h <help>] [-V]\n";
}

sub print_help () {
	print_revision($PROGNAME,'$Revision: 1.0 $');
	print "Copyright (c) 2005 Colin Stubbs <cstubbs\@subverted.net>

This plugin runs commands on a Cisco device via telnet
";

print_usage();
	print "
-r, --router=HOST
   Name or IP address of Cisco device to run ping on
-H, --hostname=HOST
   Name or IP address to ping
-u --username=USERNAME
   Username to login with
-p --password=PASSWORD
   Password to login with
-v --vrf=VRF
   VRF routing target
-P --packets=$packets
   Number of ICMP ECHO packets to send (Default: 5)
-w --warning=THRESHOLD
   Warning threshold pair
-c --critical=THRESHOLD
   Critical threshold pair
-h --help
   This screen
-V --version
   Plugin version
THRESHOLD is <rta>,<pl>% where <rta> is the round trip average travel
time (ms) which triggers a WARNING or CRITICAL state, and <pl> is the
percentage of packet loss to trigger an alarm state.


";

	support();
}



