#! /usr/bin/perl -w

# Ce script génère une alarme warning quand des sessions
# BGP sont administrativement UP mais dans un état autre
# que ESTABLISHED.
# On peut renseigner dans ce script les peers pour lesquels on ne 
# veut pas générer d'alarme jusqu'à une certaine date.

# 213.228.3.162
# "nous effectuons d'importantes opérations de maintenance sur notre réseau"
# depuis octobre, ça doit être des modifs très importantes :)
# relancés le 26/12/2007
 
# 62.35.254.13 (metaboli) down depuis les soucis sur PANAP, contacté le 2007/12/26

my %no_check_until = (
	"213.228.3.162" => ParseDate('2008/01/25'),
	"62.35.254.13"  => ParseDate('2008/01/25'),

);

my $today_date = ParseDate("today");

use strict;
use Net::SNMP qw/:debug DEBUG_ALL/;
use Getopt::Std;
use Date::Manip;
use vars qw/$opt_h $opt_c $opt_u $opt_x/;
# use Data::Dumper;

my $debug = 0;
sub usage {
   print <<EOF;
print "UNKNOWN: usage\n";


Usage:
$0 -h host -c community
 -h host : hôte cible
 -c community : communauté SNMP (v1/v2c)
 -u user : user SNMP SNMPv3
 -x password : user password SNMP SNMPv3

EOF
   exit(3);
}

getopt("h:c:u:x:");
my $host = $opt_h || usage();
my $community = $opt_c;
my $snmp_user = $opt_u;
my $snmp_password = $opt_x;

my $snmp_version;
if ($snmp_user && $snmp_password) {
	$snmp_version = 3
} else {
	$snmp_version = 1;
	if (! $community) { 
		usage();
	}
}
	
my %bgp_admin_status;
my %bgp_state;

my %bgp_admin_status_code = (
    1 => "stop",
    2 => "start",
);

my %bgp_state_code = (
    1 => "idle",
    2 => "connect",
    3 => "active",
    4 => "opensent",
    5 => "openconfirm",
    6 => "established",
);
    
# BGP4-MIB
# bgpPeerAdminStatus
my $bgp_admin_status_oid = ".1.3.6.1.2.1.15.3.1.3";
# bgpPeerState
my $bgp_state_oid = ".1.3.6.1.2.1.15.3.1.2";

my ($session, $error);

if ($snmp_version == 3) {
	($session, $error) =
  	 Net::SNMP->session(-hostname => $host, -version => "3", -username => $snmp_user,
									-authpassword => $snmp_password, -authprotocol => "sha");
} else {
	($session, $error) =
   	Net::SNMP->session(-hostname => $host, -version => "1", -community => $community);
}

if (not defined($session)) {
   print "Impossible d'ouvrir une session SNMP avec $host: $error !\n";
   exit(3); # UNKNOWN
}

# On récupère le status administratif
my $admin_result = $session->get_table(-baseoid => $bgp_admin_status_oid);

if (not defined($admin_result)) {
    my $error = $session->error();
    print "Impossible de récupérer la table ifDescr : $error\n";
    exit(3); # UNKNOWN
}

for my $index ( keys(%{$admin_result}) ) {

    my $bgp_admin_status = $admin_result->{$index};
    
    if ( $index =~ /^$bgp_admin_status_oid\.(\d+\.\d+\.\d+\.\d+)$/ ) {
        my $peer = $1;
        print "index = $peer, status = $bgp_admin_status\n" if $debug;
        $bgp_admin_status{$peer} = $bgp_admin_status;
    }
    else {
        print "UNKNOWN: format d'OID inattendu : $index\n"
    }
    
}

# On récupère le status opérationnel

my $oper_result = $session->get_table(-baseoid => $bgp_state_oid);

if (not defined($oper_result)) {
    my $error = $session->error();
    print "Impossible de récupérer la table ifDescr : $error\n";
    exit(3); # UNKNOWN
}

for my $index ( keys(%{$oper_result}) ) {

    my $bgp_state = $oper_result->{$index};
    
    if ( $index =~ /^$bgp_state_oid\.(\d+\.\d+\.\d+\.\d+)$/ ) {
        my $peer = $1;
        print "index = $peer, state = $bgp_state\n" if $debug;
        $bgp_state{$peer} = $bgp_state;
    }
    else {
        print "UNKNOWN: format d'OID inattendu : $index\n"
    }
}

my $alarm;

for my $peer ( keys(%bgp_admin_status) ) {

    my $status = $bgp_admin_status_code{$bgp_admin_status{$peer}};
    my $state = $bgp_state_code{$bgp_state{$peer}};
    print "peer $peer status $status state $state\n" if $debug;

    next unless $status eq "start";

    
    if ( $state ne "established" ) {

        if (  $no_check_until{$peer} && Date_Cmp( $today_date, $no_check_until{$peer} ) < 0 ) {

            print "peer $peer status $status state $state : check disabled\n" if $debug;

        }

        else {
            $alarm .= "WARNING: $peer state is $state\n";
        }
    }
}



if ($alarm) {
    print $alarm;
    exit(1); # WARNING
}

else {
    print "OK: ", scalar keys(%bgp_admin_status), " peers.\n";
}

