#!/usr/bin/perl

=pod

=head1 NAME

check_alcatel_ports.pl


=head1 SYNOPSIS

 check_alcatel_ports.pl community-string agent


=head1 DESCRIPTION

Uses Net::SNMP to query an Alcatel 7450 VPLS switch to find status of the
network ports. Alarms critical if the ports are UP/DOWN.

=head1 NOTES

=head1 TODO

=head1 REFERENCES

TIMETRA-PORT-MIB.mib

=cut

# Modules
use strict;
use warnings;
use Net::SNMP;
use Getopt::Long;
Getopt::Long::Configure("bundling");
use lib qw( /usr/local/nagios/libexec );
use utils qw($TIMEOUT %ERRORS &print_revision &support);

# Globals
use vars qw|$PROGNAME $DEBUG $VERSION|;
$DEBUG = 0;
$VERSION = '01.00';
$PROGNAME = "$0";

my $agent;
my $comm_string;
my $ok;
my $state = $ERRORS{'OK'};
my ($opt_V, $opt_h);

# Just in case of problems, let's not hang Nagios
$SIG{'ALRM'} = sub {
     print ("ERROR: Unable to get status from $agent (alarm timeout)\n");
     exit $ERRORS{"UNKNOWN"};
};
alarm($TIMEOUT);

#Option checking
$ok = GetOptions(
                "V"   => \$opt_V,   "version"    => \$opt_V,
                "h"   => \$opt_h,   "help"       => \$opt_h,
                "H=s" => \$agent,  "hostname=s" => \$agent,
                "C=s" => \$comm_string, "community=s" => \$comm_string,
                );

unless ( $ok ) {
    exit $ERRORS{'OK'};
}

if ($opt_V) {
    exit $ERRORS{'OK'};
}

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

if (!$comm_string) {
    print STDERR "No community string specified!\n";
    exit $ERRORS{'UNKNOWN'};
}

unless ( utils::is_hostname($agent) ) {
    print "Invalid hostname\n";
    exit $ERRORS{"UNKNOWN"};
}

# Alcatel OIDs
my $port_name_oid = '1.3.6.1.4.1.6527.3.1.2.2.4.2.1.6';
my $port_desc_oid = '1.3.6.1.4.1.6527.3.1.2.2.4.2.1.5';
my $port_mode_oid = '1.3.6.1.4.1.6527.3.1.2.2.4.2.1.11';
my $port_admin_oid = '1.3.6.1.4.1.6527.3.1.2.2.4.2.1.37';
my $port_oper_oid = '1.3.6.1.4.1.6527.3.1.2.2.4.2.1.38';
my $port_state_oid = '1.3.6.1.4.1.6527.3.1.2.2.4.2.1.39';

my %ports;
my $answer = '';
my $error = 0;

# Initiate SNMP session
my $session = Net::SNMP->session(
              -hostname => $agent,
              -version => 'snmpv2c',
              -community => $comm_string,
              -port => 161,
              -timeout => 2,
              -retries => 1,
              -maxmsgsize => 20000,
);

# Port Name
my $table = $session->get_table( -baseoid => $port_name_oid );
if ($session->error) {
    print $session->error . "\n";
    exit(1);
}

foreach my $entry (sort keys %{$table}) {
	my $index = (split /\./, $entry)[16];
	$ports{$index} = [ $table->{$entry} ];
}

# Port Mode
$table = $session->get_table( -baseoid => $port_mode_oid );
if ($session->error) {
    print $session->error . "\n";
    exit(1);
}

foreach my $entry (sort keys %{$table}) {
	my $index = (split /\./, $entry)[16];
	$ports{$index}->[1] = $table->{$entry};
}


# Port Admin Status
$table = $session->get_table( -baseoid => $port_admin_oid );
if ($session->error) {
    print $session->error . "\n";
    exit(1);
}

foreach my $entry (sort keys %{$table}) {
	my $index = (split /\./, $entry)[16];
	$ports{$index}->[2] = $table->{$entry};
}

# Port Oper Status
$table = $session->get_table( -baseoid => $port_oper_oid );
if ($session->error) {
    print $session->error . "\n";
    exit(1);
}

foreach my $entry (sort keys %{$table}) {
	my $index = (split /\./, $entry)[16];
	$ports{$index}->[3] = $table->{$entry};
}

# Port Desc
$table = $session->get_table( -baseoid => $port_desc_oid );
if ($session->error) {
    print $session->error;
    exit(1);
}

foreach my $entry (sort keys %{$table}) {
	my $index = (split /\./, $entry)[16];
	$ports{$index}->[4] = $table->{$entry};
}

# Port State
$table = $session->get_table( -baseoid => $port_state_oid );
if ($session->error) {
    print $session->error;
    exit(1);
}

foreach my $entry (sort keys %{$table}) {
	my $index = (split /\./, $entry)[16];
	$ports{$index}->[5] = $table->{$entry};
}


foreach my $port (sort keys %ports) {

    my $name = $ports{$port}->[0];
    my $desc = $ports{$port}->[4];
    my $mode = $ports{$port}->[1];
    my $admin = $ports{$port}->[2];
    my $oper = $ports{$port}->[3];
	my $port_state = $ports{$port}->[5];


# Skip if not network port
    if ($mode != 2) {
	next;
    }

# Skip if admin down
    elsif ($admin == 3) {
	next;
    }

# Skip if state is 'ghost' (port provisioned by not physically present)
    elsif ($port_state == 2){
	next;
	}

# Skip if name is A/4 or B/4
    elsif ($name == "A/4" || $name == "B/4"){
        next;
        }

# Alarm if oper down
    elsif ($oper != 2) {
	$error = 1;
	$state = $ERRORS{'CRITICAL'};
	$answer .= "[$name $desc OperStatus down] ";
	next;
    }

}

if (!$error) {
    $answer .= "All ports OK.";
    print $answer;
}

else {
    print "$answer";
}

exit $state;

