#!/usr/bin/perl
#
##################################################################
#                        introduction                            #
##################################################################
#
# This script serves as an example for processing events.  You may use this as a starting point
# and make enhancements or extensions to suit your own networking environment.  To have events
# fed to an alternative script in the same directory, just override "EventScript" in the global
# preferences file.

##################################################################
#                        configuration                           #
##################################################################

# script debug parameters
$debug = 1;

# directories
$productHome = $ENV{'INMON_HOME'};
$stateDir = "$productHome/server/state";

# mail output parameters
$output_mail = 1;
$mail_to = "inmon";
$mail_subject = "[event] network monitoring event";

# trap output parameters
$output_trap = 1;
$trap_destination = "localhost";

#syslog output parameters
$output_syslog = 1;
$syslog_priority = "local3.info";
$syslog_tag = "inmon";

# text separators
$macLocations_separator = ':';
$addressMap_separator = ',';
$event_separator = ':';

##################################################################
#                         addressLocation                        #
##################################################################

$locationLookupLoaded = 0;

sub addressLocation {
    my ($address) = @_;
    if($locationLookupLoaded == 0) {
	# load the lookup table for ip->mac->location
	if(open(MACLOC, "$stateDir/macLocations.txt")) {
	    while(<MACLOC>) {
		chomp();
		my($mac, $agent, $port) = split($macLocations_separator);
		$MACToLocation{$mac} = "$mac,$agent,$port";
	    }
	    close(MACLOC);
	}
	if(open(ADDRMAP, "$stateDir/addressMap.txt")) {
	    while(<ADDRMAP>) {
		chomp();
		my($addrType, $addr, $mac) = split($addressMap_separator);
		$AddrToLocation{$addr} = $MACToLocation{$mac};
	    }
	    close(ADDRMAP);
	}
	$locationLookupLoaded = 1;
    }
    return $AddrToLocation{$address};
}


##################################################################
#                      event processing                          #
##################################################################

# read events from stdin, one per line
while(<STDIN>) {
    chomp();
    
    if($output_syslog) {
	my $logger_cmd = "logger -d -p $syslog_priority -t '$syslog_tag' -- $_";
	if($debug) { print("invoking logger command: $logger_cmd\n"); }
	system($logger_cmd);
	if($?) { print STDERR "exit $? from logger command: $logger_cmd ($!)"; }
    }

    # parse comma-separated parameters
    my ($timestamp,
	$server,
	$severity,
	$eventType,
	$eventName,
	$eventValue,
	$address,
	$interface,
	$eventUrl,
	$comment) = split($event_separator);

    my $host = "";
    my $hostMAC = "";
    my $agentIP = "";

    if(($eventType eq "security") && ($eventName eq "rule")) {
	# the host that has violated the rule was given to us in the address field
	$host = $address;
	# see if we can find his location too, and load that into the agent and interface fields
	$loc = &addressLocation($host);
	($hostMAC, $agentIP, $interface) = split(",", $loc);
    }
    else {
	# not a security rule, so the address field (if set) is the agentIP
	$agentIP = $address;
    }
    
    my $msg = "
  timestamp: $timestamp
     server: $server
   severity: $severity
  eventType: $eventType
  eventName: $eventName
 eventValue: $eventValue
      agent: $agentIP
  interface: $interface
        url: $url
    comment: $comment
       host: $host
    hostMAC: $hostMAC
";
    
    if($debug) { print("$msg\n"); }
    
    if($output_mail) {
	# invoke the local "mail" command-line program, which is assumed to be present and configured appropriately
	# could use Mail::Sendmail here instead, see http://cpan.uwinnipeg.ca/dist/Mail-Sendmail
	my $mail_cmd = "mail -s '$mail_subject' '$mail_to'";
	if($debug) { print("invoking mail command: $mail_cmd\n"); }
	if(open(MAIL, "| $mail_cmd")) {
	    print MAIL $msg;
	    close(MAIL);
	}
	if($?) { "exit $? from mail command: $mail_cmd ($!)"; }
    }

    if($output_trap) {
	# check that net-snmp-utils is installed, and snmptrap is in the PATH?
	$trap_version = "2c";
	$trap_community = "public";

	$inmontrap_oid = "enterprises.4300.3"; # enterprises.inmon.inmonTrap
	$trap_oid = "$inmontrap_oid.2.1";      # inmonTrap.inmonTraps.inmonEventTrap

	# the individual objects
	$trap_objects_oid = "$inmontrap_oid.1";
	# leave out the server field (assumed to be implicit)
	$trap_oid_severity = "$trap_objects_oid.1";
	$trap_oid_eventType = "$trap_objects_oid.2";
	$trap_oid_eventName = "$trap_objects_oid.3";
	$trap_oid_eventValue = "$trap_objects_oid.4";
	$trap_oid_agentIP = "$trap_objects_oid.5";
	$trap_oid_interface = "$trap_objects_oid.6";
	$trap_oid_url = "$trap_objects_oid.7";
	$trap_oid_comment = "$trap_objects_oid.8";
	$trap_oid_host =  "$trap_objects_oid.9";
	$trap_oid_hostMAC =  "$trap_objects_oid.10";

	my $uptime = "''"; # empty string - snmptrap program will use default

	$snmptrap_cmd = "snmptrap -v $trap_version -c $trap_community $trap_destination $uptime $trap_oid";
	$snmptrap_cmd .= " $trap_oid_severity s '$severity'";
	$snmptrap_cmd .= " $trap_oid_eventType s '$eventType'";
	$snmptrap_cmd .= " $trap_oid_eventName s '$eventName'";
	$snmptrap_cmd .= " $trap_oid_eventValue  s '$eventValue'";
	$snmptrap_cmd .= " $trap_oid_agentIP s '$agentIP'";
	$snmptrap_cmd .= " $trap_oid_interface s '$interface'";
	$snmptrap_cmd .= " $trap_oid_url s '$eventUrl'";
	$snmptrap_cmd .= " $trap_oid_comment s '$comment'"; 
	$snmptrap_cmd .= " $trap_oid_host s '$host'"; 
	$snmptrap_cmd .= " $trap_oid_hostMAC s '$hostMAC'"; 

	if($debug) { print("invoking snmptrap command: $snmptrap_cmd\n"); }
	system($snmptrap_cmd);
	if($?) { "exit $? from snmptrap command: $snmptrap_cmd ($!)"; }
    }
}
