#! /usr/bin/perl -w
use strict;
use Net::SNMP;
use Getopt::Std;
use vars qw/$opt_h $opt_c $opt_e/;
# use Data::Dumper;

# Options
my ($host , $community, $exec_handle);

sub usage()
{
	print <<EOF;

Usage:
$0 -h host -c community -e exec-name
 -h host : hôte cible
 -c community : communauté SNMP utilisée
 -e exec-name : nom net-snmp du script défini dans snmpd.conf,
    (mysql1_connect_test dans l'example plus bas)

$0 permet d'utiliser un script défini sur un hôte distant pour générer
une alarme Nagios.
Le script distant doit utiliser les conventions Nagios.

Pour fonctionner, une clause "exec" doit être définie sur l'hôte distant
dans la configuration snmpd.conf.
Par exemple :\n
exec mysql1_connect_test mysql.py -h mysql1 -u user -p pass -d db -t 1

EOF
	exit(3);
}

getopt("h:c:e");
$host = $opt_h || usage();
$community = $opt_c || usage();
$exec_handle = $opt_e || usage();


# La table extTable (pour exécution des scripts) ressemble à ceci :
# .iso.org.dod.internet.private.enterprises.ucdavis.extTable.extEntry.extIndex.1
#   .1.3.6.1.4.1.2021.8.1.1.1 = INTEGER: 1
# .iso.org.dod.internet.private.enterprises.ucdavis.extTable.extEntry.extNames.1
#   .1.3.6.1.4.1.2021.8.1.2.1 = STRING: mysql1_connect_test
# .iso.org.dod.internet.private.enterprises.ucdavis.extTable.extEntry.extCommand.1
#   .1.3.6.1.4.1.2021.8.1.3.1 = STRING: mysql.py -h mysql1 -u user -p pass -d db -t 1
# .iso.org.dod.internet.private.enterprises.ucdavis.extTable.extEntry.extResult.1
#   .1.3.6.1.4.1.2021.8.1.100.1 = INTEGER: 2
# .iso.org.dod.internet.private.enterprises.ucdavis.extTable.extEntry.extOutput.1
#   .1.3.6.1.4.1.2021.8.1.101.1 = STRING: "Can't connect to MySQL server on 'mysql1.co'"

my $extTable_oid = ".1.3.6.1.4.1.2021.8";

# Les OID suivant sont indexés par extIndex :
my $extIndex_oid = ".1.3.6.1.4.1.2021.8.1.1";
my $extNames_oid = ".1.3.6.1.4.1.2021.8.1.2";
my $extCommand_oid = ".1.3.6.1.4.1.2021.8.1.3";
my $extResult_oid = ".1.3.6.1.4.1.2021.8.1.100";
my $extOutput_oid = ".1.3.6.1.4.1.2021.8.1.101";

my ($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 essaie de récupérer l'index correspondant au nom du script
my $exec_handle_index;

my $result = $session->get_table(-baseoid => $extNames_oid);

# print Dumper($result);

if (not defined($result)) {
    my $error = $session->error();
	print "Impossible de récupérer la table extNames pour le script $exec_handle sur $host : $error!\n";
	exit(3); # UNKNOWN
}

foreach my $index ( keys(%{$result}) ) {
    next unless $result->{$index} eq $exec_handle;
    $exec_handle_index = $index;
}

if (! $exec_handle_index) {
    print "Pas de script SNMP $exec_handle défini sur $host !\n";
    exit(3); # UNKNOWN
}
		
# Seul l'index est intéressant, pas tout l'OID.
($exec_handle_index) = reverse split /\./, $exec_handle_index;

# On essaie de récupèrer la première ligne de sortie du script :
$result = $session->get_request(-varbindlist => ["$extOutput_oid.$exec_handle_index"]);

if (not defined($result)) {
    my $error = $session->error();
    print "Impossible de récupérer la sortie du script $exec_handle sur $host : $error !\n";
    exit(3); # UNKNOWN
}

my $output = $result->{"$extOutput_oid.$exec_handle_index"};

# On essaie de récupèrer le code de status du script :
$result = $session->get_request(-varbindlist => ["$extResult_oid.$exec_handle_index"]);

if (not defined($result)) {
    my $error = $session->error();
    print "Impossible de récupérer le code de status du script $exec_handle sur $host : $error !\n";
    exit(3); # UNKNOWN
}

my $status = $result->{"$extResult_oid.$exec_handle_index"};

if ($status == 0 or $status == 1 or $status == 2 or $status == 3) {
    print "$output\n";
    exit($status);
} else {
    print "Code de status erroné ($status) du script $exec_handle sur $host !\n";
    exit(3); # UNKNOWN
}
