#!/usr/bin/perl
#    Big Sister network monitor
#    Copyright (C) 1998  Thomas Aeby
#
#    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.
#

#=============================================================================
#
$BigSister::common::Usage  = "[-D level] [-l logfile] [-f cfgfile]";
#
#=============================================================================
use lib "."; use lib "uxmon"; use lib "platforms"; 		#inslib
@BigSister::common::options = ( "l:s", "f:s" );
use BigSister::common;
proginit();

use strict;
use BER;
use SNMP_util;
use SNMP_Session;
use Socket;
use RotatingLog;

$SIG{"ALRM"} = $SIG{"PIPE"} = $SIG{"INT"} = "IGNORE";

my $dl = $BigSister::common::dl;
my $cfgfile = $BigSister::common::opt_f;
my %OIDS;
my $traplog = new RotatingLog( "$BigSister::common::fs{'var'}/snmp_traplog", undef, 2 );


unless( $cfgfile ) {
    $cfgfile = $BigSister::common::fs{'adm'}."/bstrapd.cfg";
}
else {
    unless( $cfgfile =~ /^\// ) {
	$cfgfile = $BigSister::common::root."/".$cfgfile;
    }
}
unless( -f $cfgfile ) {
    print STDERR "$BigSister::common::prog: config file $cfgfile not found\n";
}
    

unshift( @INC, "$BigSister::common::fs{'bin'}" );

use Platforms;

$BigSister::common::on_unix = Platforms::isunix();

&background unless( $BigSister::common::dl );

&load_mib( undef, $BigSister::common::fs{'etc'}."/mibs.txt" );

my $trap_session = SNMPv1_Session->open_trap_session ( );

while( 1 ) {
    my ($binding, $oid, $value);
    my ($trap, $sender_addr, $sender_port) = $trap_session->receive_trap ();
    next unless( $trap );
    my ($community, $enterprise, $agent,
	$generic, $specific, $sysuptime, $bindings)
      = $trap_session->decode_trap_request ($trap);
    next unless( $community );
    my $msg;
    my $succ = 0;
    eval {
	$msg = "trap from ".inet_ntoa($sender_addr)."\n";
	($msg .= "community=$community ") if( $community );
	($msg .= "enterprise=".poid($enterprise)." ") if( $enterprise );
	($msg .= "agent=".inet_ntoa($agent)." ") if( $agent );
	($msg .= "generic=$generic ") if( $generic );
	($msg .= "specific=$specific ") if( $specific );
	($msg .= "sysuptime=$sysuptime ") if( $sysuptime );
	$msg .= "\n";
	my $i=1;
	while ($bindings ne '') {
	    ($binding,$bindings) = decode_sequence ($bindings);
	    ($oid, $value) = decode_by_template ($binding, "%O%@");
	    $oid = poid($oid);
	    eval {
		my $val = BER::pretty_print($value);
		$val =~ s/\n/\n-/gs;
		$msg .= "argument $i $oid => ".$val."\n";
	    };
	    $i++;
	}
	$traplog->log( $msg );
	$succ = 1;
    };
    unless( $succ ) {
	$traplog->log( "received invalid (undecodable) trap\n" );
	BigSister::common::log( "notice", "received invalid (undecodeable) SNMP trap" );
    }
}


sub load_mib {
    my( $self, $file ) = @_;

    open( IN, "<$file" );
    while( <IN> ) {
	chomp;
	next if( /^#/ );
	if( /^([^\s\t]+)[\s\t]+([^\s\t]+)$/ ) {
	    $OIDS{$2} = $1;
	}
    }
    close IN;
}


sub poid {
    my( $oid ) = @_;

    return() unless( $oid );
    $oid = BER::pretty_oid($oid);
    if( defined $OIDS{$oid} ) {
	$oid = $OIDS{$oid};
    }
    return( $oid );
}


