#!/usr/bin/perl -wT
#
# check_bgpstate.pl - nagios plugin 
#
# Copyright (C) 2000 Christoph Kron
#
# 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: ck@zet.net
#
# 11.01.2000 Version 1.0



require 5.004;
use strict;
use lib utils.pm ;
use Plugin;
use Plugin::Parameter qw($helpparameterlist $versionparameterlist $hostnameparameter
			 $communityparameter $portparameter $timeoutparameter
			 $verboseparameter);

use Net::SNMP;

use vars qw($opt_h $opt_H $opt_t $opt_C $opt_p $xml $PROGNAME);
use utils qw(%ERRORS &usage);

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

sub adduplink ($);

$portparameter->default(161);

my $uplinkparameter = new Plugin::Parameter(-name => "uplink", -flags => [ 'u', 'uplink' ],
					    -optional => "yes", -valueoptional => 0, -type => "ASNUMBER",
					    -description => "AS number for a critical uplink",
					    -binding => \&adduplink);
my @commandparameterlist = ( $hostnameparameter,
			     $communityparameter,
			     $portparameter,
			     $timeoutparameter,
			     $uplinkparameter,
			     $verboseparameter );

my $plugin = new Plugin(-revision => '$Revision: 1.0 $',
			-copyright => "2000 Christoph Kron, 2004 Howard Wilkinson <howard\@cohtech.com>",
			-shortcomment => "Checks the bgpstate of a 'router'.",
			-parameterlists => [ \@commandparameterlist, $helpparameterlist, $versionparameterlist ] );

# whois program for RIPE database queries
my $whois = '/usr/bin/whois';

# Extra work needed to support different links
# critical bgp sessions
my %uplinks = ( 1273 => 'Uplink ECRC',
                1755 => 'Uplink EBONE',
                3300 => 'Uplink AUCS' );

my %bgpPeerState = ('1' => "idle",
		    '2' => "connect",
		    '3' => "active",
		    '4' => "opensent",
		    '5' => "openconfirm",
		    '6' => "established" );

my $state = "UNKNOWN";
my $answer = "";
my $community = "public";
my $port = 161;

my $snmpbgpPeerState = '1.3.6.1.2.1.15.3.1.2';
my $snmpbgpPeerLocalAddr = '1.3.6.1.2.1.15.3.1.5';
my $snmpbgpPeerRemoteAddr = '1.3.6.1.2.1.15.3.1.7';
my $snmpbgpPeerRemoteAs = '1.3.6.1.2.1.15.3.1.9';
my @snmpoids = ( $snmpbgpPeerState, $snmpbgpPeerLocalAddr, $snmpbgpPeerRemoteAddr, $snmpbgpPeerRemoteAs);

$plugin->init();

my ($session, $error) = Net::SNMP->session(-hostname  => $opt_H,
					   -community => $opt_C,
					   -timeout   => $opt_t,
					   -port      => $opt_p,
					   -version   => "snmpv1",
					   -translate => undef);
if (!defined($session)) {
  $state='UNKNOWN';
  print ("$PROGNAME $state: $error\n");
  exit $ERRORS{$state};
}

my %bgpStatus = ();

foreach my $snmpoid (@snmpoids) {
  my $response = $session->get_table(-baseoid => $snmpoid);
  $answer=$session->error;
  if (!defined $response) {
    $state = 'CRITICAL';
    print ("$PROGNAME $state: $answer\n");
    exit $ERRORS{$state};
  }

  foreach my $snmpkey (keys %{$response}) {
    $snmpkey =~ m/.*\.(\d+\.\d+\.\d+\.\d+$)/;
    my $peer =  $1;
    $bgpStatus{$peer}{$snmpoid} = $response->{$snmpkey};
  }
}

$session->close;

my $bgpestablished = 0;
my $bgpcritical = 0;
my $bgpdown = 0;
my $bgpidle = 0;
my $bgpmessage = "";

foreach my $peer (keys %bgpStatus) {
  if ($bgpStatus{$peer}{$snmpbgpPeerState} == 6 ) {
    $bgpestablished++;
  } elsif ($bgpStatus{$peer}{$snmpbgpPeerState} == 1 ) {
    $bgpidle++;
  } else {
    $bgpdown++ ;
    if (exists($uplinks{$bgpStatus{$peer}{$snmpbgpPeerRemoteAs}}) ) {
      $bgpcritical++;
    }
    my $asname = "";
    foreach (`$whois -h whois.ripe.net -- -T aut-num AS$bgpStatus{$peer}{$snmpbgpPeerRemoteAs}`) {
      if (m/^as-name:/) {
	$asname = $_;
	$asname =~ s/^as-name://;
	chomp $asname;
	next;
      }
      if ( m/^descr:/ ) {
	my $descr = $_;
	$descr =~ s/^descr://;
	chomp $descr;
	$asname .= $descr;
	next;
      }
    }
    $asname =~ s/^\s*//;
    $asname =~ s/\s*$//;
    $bgpmessage .= sprintf("Peering not established with %s",
			   (($asname)?$asname:"AS".$bgpStatus{$peer}{$snmpbgpPeerRemoteAs}));
  }
}

if ($bgpdown > 0) {
  if ($bgpcritical > 0) {
    $state = 'CRITICAL';
  } else {
    $state = 'WARNING';
  }
  $answer = sprintf("host '%s', sessions up: %d, down: %d, shutdown: %d. ",
		    $opt_H,
		    $bgpestablished,
		    $bgpdown, $bgpidle);
  $answer = $answer . $bgpmessage . "\n";
} else {
  $state = 'OK';
  $answer = sprintf("host '%s', sessions up: %d, down: %d, shutdown: %d\n",
		    $opt_H,
		    $bgpestablished,
		    $bgpdown,$bgpidle);
}

print ("$PROGNAME $state: $answer");

exit $ERRORS{$state};

sub adduplink ($) {
  my ($arg, $uplink) = @_;
  $uplinks{$uplink} = $uplink;
}
