Fixed permissions over snmp IDX file

This commit is contained in:
fbsanchez 2016-10-31 12:36:54 +01:00
parent e559937697
commit 0df53387a1

View File

@ -1,477 +1,478 @@
package PandoraFMS::SNMPServer; package PandoraFMS::SNMPServer;
########################################################################## ##########################################################################
# Pandora FMS SNMP Console. # Pandora FMS SNMP Console.
# Pandora FMS. the Flexible Monitoring System. http://www.pandorafms.org # Pandora FMS. the Flexible Monitoring System. http://www.pandorafms.org
########################################################################## ##########################################################################
# Copyright (c) 2005-2009 Artica Soluciones Tecnologicas S.L # Copyright (c) 2005-2009 Artica Soluciones Tecnologicas S.L
# #
# This program is free software; you can redistribute it and/or # This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public License # modify it under the terms of the GNU Lesser General Public License
# as published by the Free Software Foundation; version 2 # as published by the Free Software Foundation; version 2
# This program is distributed in the hope that it will be useful, # This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
########################################################################## ##########################################################################
use strict; use strict;
use warnings; use warnings;
use threads; use threads;
use threads::shared; use threads::shared;
use Thread::Semaphore; use Thread::Semaphore;
use Time::Local; use Time::Local;
use Time::HiRes qw(usleep); use Time::HiRes qw(usleep);
use XML::Simple; use XML::Simple;
# Default lib dir for RPM and DEB packages # Default lib dir for RPM and DEB packages
use lib '/usr/lib/perl5'; use lib '/usr/lib/perl5';
use PandoraFMS::Tools; use PandoraFMS::Tools;
use PandoraFMS::DB; use PandoraFMS::DB;
use PandoraFMS::Core; use PandoraFMS::Core;
use PandoraFMS::ProducerConsumerServer; use PandoraFMS::ProducerConsumerServer;
# Inherits from PandoraFMS::ProducerConsumerServer # Inherits from PandoraFMS::ProducerConsumerServer
our @ISA = qw(PandoraFMS::ProducerConsumerServer); our @ISA = qw(PandoraFMS::ProducerConsumerServer);
# Global variables # Global variables
my @TaskQueue :shared; my @TaskQueue :shared;
my %PendingTasks :shared; my %PendingTasks :shared;
my $Sem :shared; my $Sem :shared;
my $TaskSem :shared; my $TaskSem :shared;
# Trap statistics by agent # Trap statistics by agent
my %AGENTS = (); my %AGENTS = ();
# Index file management # Index file management
my ($IDX_FILE, $LAST_LINE, $LAST_SIZE) = (); my ($IDX_FILE, $LAST_LINE, $LAST_SIZE) = ();
######################################################################################## ########################################################################################
# SNMP Server class constructor. # SNMP Server class constructor.
######################################################################################## ########################################################################################
sub new ($$$) { sub new ($$$) {
my ($class, $config, $dbh) = @_; my ($class, $config, $dbh) = @_;
return undef unless $config->{'snmpconsole'} == 1; return undef unless $config->{'snmpconsole'} == 1;
# Start snmptrapd # Start snmptrapd
if (start_snmptrapd ($config) != 0) { if (start_snmptrapd ($config) != 0) {
return undef; return undef;
} }
# Wait for the SNMP log file to be available # Wait for the SNMP log file to be available
my $log_file = $config->{'snmp_logfile'}; my $log_file = $config->{'snmp_logfile'};
sleep ($config->{'server_threshold'}) if (! -e $log_file); sleep ($config->{'server_threshold'}) if (! -e $log_file);
if (!open (SNMPLOGFILE, $log_file)) { if (!open (SNMPLOGFILE, $log_file)) {
logger ($config, ' [E] Could not open the SNMP log file ' . $config->{'snmp_logfile'} . ".", 1); logger ($config, ' [E] Could not open the SNMP log file ' . $config->{'snmp_logfile'} . ".", 1);
print_message ($config, ' [E] Could not open the SNMP log file ' . $config->{'snmp_logfile'} . ".", 1); print_message ($config, ' [E] Could not open the SNMP log file ' . $config->{'snmp_logfile'} . ".", 1);
return 1; return 1;
} }
# Process index file, if available # Process index file, if available
($IDX_FILE, $LAST_LINE, $LAST_SIZE) = ($log_file . '.index', 0, 0); ($IDX_FILE, $LAST_LINE, $LAST_SIZE) = ($log_file . '.index', 0, 0);
if (-e $IDX_FILE) { if (-e $IDX_FILE) {
open (INDEXFILE, $IDX_FILE) or return; open (INDEXFILE, $IDX_FILE) or return;
my $idx_data = <INDEXFILE>; my $idx_data = <INDEXFILE>;
close INDEXFILE; close INDEXFILE;
($LAST_LINE, $LAST_SIZE) = split(/\s+/, $idx_data); ($LAST_LINE, $LAST_SIZE) = split(/\s+/, $idx_data);
} }
my $log_size = (stat ($log_file))[7]; my $log_size = (stat ($log_file))[7];
# New SNMP log file found # New SNMP log file found
if ($log_size < $LAST_SIZE) { if ($log_size < $LAST_SIZE) {
unlink ($IDX_FILE); unlink ($IDX_FILE);
($LAST_LINE, $LAST_SIZE) = (0, 0); ($LAST_LINE, $LAST_SIZE) = (0, 0);
} }
# Skip already processed lines # Skip already processed lines
read_snmplogfile() for (1..$LAST_LINE); read_snmplogfile() for (1..$LAST_LINE);
# Initialize semaphores and queues # Initialize semaphores and queues
@TaskQueue = (); @TaskQueue = ();
%PendingTasks = (); %PendingTasks = ();
$Sem = Thread::Semaphore->new; $Sem = Thread::Semaphore->new;
$TaskSem = Thread::Semaphore->new (0); $TaskSem = Thread::Semaphore->new (0);
# Call the constructor of the parent class # Call the constructor of the parent class
my $self = $class->SUPER::new($config, SNMPCONSOLE, \&PandoraFMS::SNMPServer::data_producer, \&PandoraFMS::SNMPServer::data_consumer, $dbh); my $self = $class->SUPER::new($config, SNMPCONSOLE, \&PandoraFMS::SNMPServer::data_producer, \&PandoraFMS::SNMPServer::data_consumer, $dbh);
# Save the path of snmptrapd # Save the path of snmptrapd
$self->{'snmp_trapd'} = $config->{'snmp_trapd'}; $self->{'snmp_trapd'} = $config->{'snmp_trapd'};
bless $self, $class; bless $self, $class;
return $self; return $self;
} }
############################################################################### ###############################################################################
# Run. # Run.
############################################################################### ###############################################################################
sub run ($) { sub run ($) {
my $self = shift; my $self = shift;
my $pa_config = $self->getConfig (); my $pa_config = $self->getConfig ();
print_message ($pa_config, " [*] Starting Pandora FMS SNMP Console.", 2); print_message ($pa_config, " [*] Starting Pandora FMS SNMP Console.", 2);
# Set the initial date for storm protection. # Set the initial date for storm protection.
$pa_config->{"__storm_ref__"} = time(); $pa_config->{"__storm_ref__"} = time();
$self->setNumThreads ($pa_config->{'snmpconsole_threads'}); $self->setNumThreads ($pa_config->{'snmpconsole_threads'});
$self->SUPER::run (\@TaskQueue, \%PendingTasks, $Sem, $TaskSem); $self->SUPER::run (\@TaskQueue, \%PendingTasks, $Sem, $TaskSem);
} }
############################################################################### ###############################################################################
# Data producer. # Data producer.
############################################################################### ###############################################################################
sub data_producer ($) { sub data_producer ($) {
my $self = shift; my $self = shift;
my ($pa_config, $dbh) = ($self->getConfig (), $self->getDBH ()); my ($pa_config, $dbh) = ($self->getConfig (), $self->getDBH ());
my @tasks; my @tasks;
# Reset storm protection counters # Reset storm protection counters
my $curr_time = time (); my $curr_time = time ();
if ($pa_config->{"__storm_ref__"} + $pa_config->{"snmp_storm_timeout"} < $curr_time) { if ($pa_config->{"__storm_ref__"} + $pa_config->{"snmp_storm_timeout"} < $curr_time) {
$pa_config->{"__storm_ref__"} = $curr_time; $pa_config->{"__storm_ref__"} = $curr_time;
%AGENTS = (); %AGENTS = ();
} }
while (my $line_with_pos = read_snmplogfile()) { while (my $line_with_pos = read_snmplogfile()) {
my $line; my $line;
$LAST_LINE++; $LAST_LINE++;
($LAST_SIZE, $line) = @$line_with_pos; ($LAST_SIZE, $line) = @$line_with_pos;
chomp ($line); chomp ($line);
# Update index file # Update index file
open INDEXFILE, '>' . $IDX_FILE; open INDEXFILE, '>' . $IDX_FILE;
print INDEXFILE $LAST_LINE . ' ' . $LAST_SIZE; print INDEXFILE $LAST_LINE . ' ' . $LAST_SIZE;
close INDEXFILE; close INDEXFILE;
set_file_permissions($pa_config, $IDX_FILE, "0666");
# Skip lines other than SNMP Trap logs
next unless ($line =~ m/^SNMPv[12]\[\*\*\]/); # Skip lines other than SNMP Trap logs
next unless ($line =~ m/^SNMPv[12]\[\*\*\]/);
# Storm protection.
my ($ver, $date, $time, $source, $null) = split(/\[\*\*\]/, $line, 5); # Storm protection.
next unless defined ($source); my ($ver, $date, $time, $source, $null) = split(/\[\*\*\]/, $line, 5);
if (! defined ($AGENTS{$source})) { next unless defined ($source);
$AGENTS{$source}{'count'} = 1; if (! defined ($AGENTS{$source})) {
$AGENTS{$source}{'event'} = 0; $AGENTS{$source}{'count'} = 1;
} else { $AGENTS{$source}{'event'} = 0;
$AGENTS{$source}{'count'} += 1; } else {
} $AGENTS{$source}{'count'} += 1;
if ($pa_config->{'snmp_storm_protection'} > 0 && $AGENTS{$source}{'count'} > $pa_config->{'snmp_storm_protection'}) { }
if ($AGENTS{$source}{'event'} == 0) { if ($pa_config->{'snmp_storm_protection'} > 0 && $AGENTS{$source}{'count'} > $pa_config->{'snmp_storm_protection'}) {
pandora_event ($pa_config, "Too many traps coming from $source. Silenced for " . int ($pa_config->{"snmp_storm_timeout"} / 60) . " minutes.", 0, 0, 4, 0, 0, 'system', 0, $dbh); if ($AGENTS{$source}{'event'} == 0) {
} pandora_event ($pa_config, "Too many traps coming from $source. Silenced for " . int ($pa_config->{"snmp_storm_timeout"} / 60) . " minutes.", 0, 0, 4, 0, 0, 'system', 0, $dbh);
$AGENTS{$source}{'event'} = 1; }
next; $AGENTS{$source}{'event'} = 1;
} next;
}
push (@tasks, $line);
} push (@tasks, $line);
}
return @tasks;
} return @tasks;
}
###############################################################################
# Data consumer. ###############################################################################
############################################################################### # Data consumer.
sub data_consumer ($$) { ###############################################################################
my ($self, $task) = @_; sub data_consumer ($$) {
my ($self, $task) = @_;
pandora_snmptrapd ($self->getConfig (), $task, $self->getServerID (), $self->getDBH ());
} pandora_snmptrapd ($self->getConfig (), $task, $self->getServerID (), $self->getDBH ());
}
##########################################################################
# Process SNMP log file. ##########################################################################
########################################################################## # Process SNMP log file.
sub pandora_snmptrapd { ##########################################################################
my ($pa_config, $line, $server_id, $dbh) = @_; sub pandora_snmptrapd {
my ($pa_config, $line, $server_id, $dbh) = @_;
(my $trap_ver, $line) = split(/\[\*\*\]/, $line, 2);
(my $trap_ver, $line) = split(/\[\*\*\]/, $line, 2);
# Process SNMP filter
next if (matches_filter ($dbh, $pa_config, $line) == 1); # Process SNMP filter
next if (matches_filter ($dbh, $pa_config, $line) == 1);
logger($pa_config, "Reading trap '$line'", 10);
my ($date, $time, $source, $oid, $type, $type_desc, $value, $data) = ('', '', '', '', '', '', '', ''); logger($pa_config, "Reading trap '$line'", 10);
my ($date, $time, $source, $oid, $type, $type_desc, $value, $data) = ('', '', '', '', '', '', '', '');
if ($trap_ver eq "SNMPv1") {
($date, $time, $source, $oid, $type, $type_desc, $value, $data) = split(/\[\*\*\]/, $line, 8); if ($trap_ver eq "SNMPv1") {
($date, $time, $source, $oid, $type, $type_desc, $value, $data) = split(/\[\*\*\]/, $line, 8);
$value = limpia_cadena ($value);
$value = limpia_cadena ($value);
# Try to save as much information as possible if the trap could not be parsed
$oid = $type_desc if ($oid eq '' || $oid eq '.'); # Try to save as much information as possible if the trap could not be parsed
$oid = $type_desc if ($oid eq '' || $oid eq '.');
} elsif ($trap_ver eq "SNMPv2") {
($date, $time, $source, $data) = split(/\[\*\*\]/, $line, 4); } elsif ($trap_ver eq "SNMPv2") {
my @data = split(/\t/, $data); ($date, $time, $source, $data) = split(/\[\*\*\]/, $line, 4);
my @data = split(/\t/, $data);
shift @data; # Drop unused 1st data.
$oid = shift @data; shift @data; # Drop unused 1st data.
$oid = shift @data;
if (!defined($oid)) {
logger($pa_config, "[W] snmpTrapOID not found (Illegal SNMPv2 trap?)", 1); if (!defined($oid)) {
return; logger($pa_config, "[W] snmpTrapOID not found (Illegal SNMPv2 trap?)", 1);
} return;
$oid =~ s/.* = OID: //; }
if ($oid =~ m/^\.1\.3\.6\.1\.6\.3\.1\.1\.5\.([1-5])$/) { $oid =~ s/.* = OID: //;
$type = $1 - 1; if ($oid =~ m/^\.1\.3\.6\.1\.6\.3\.1\.1\.5\.([1-5])$/) {
} else { $type = $1 - 1;
$type = 6; } else {
} $type = 6;
$data = join("\t", @data); }
} $data = join("\t", @data);
}
if ($trap_ver eq "SNMPv2" || $pa_config->{'snmp_pdu_address'} eq '1' ) {
# extract IP address from %b part: if ($trap_ver eq "SNMPv2" || $pa_config->{'snmp_pdu_address'} eq '1' ) {
# * destination part (->[dest_ip]:dest_port) appears in Net-SNMP > 5.3 # extract IP address from %b part:
# * protocol name (TCP: or UDP:) and bracketted IP addr w/ port number appear in # * destination part (->[dest_ip]:dest_port) appears in Net-SNMP > 5.3
# Net-SNMP > 5.1 (Net-SNMP 5.1 has IP addr only). # * protocol name (TCP: or UDP:) and bracketted IP addr w/ port number appear in
# * port number is signed (often negative) in Net-SNMP 5.2 # Net-SNMP > 5.1 (Net-SNMP 5.1 has IP addr only).
$source =~ s/(?:(?:TCP|UDP):\s*)?\[?([^] ]+)\]?(?::-?\d+)?(?:\s*->.*)?$/$1/; # * port number is signed (often negative) in Net-SNMP 5.2
} $source =~ s/(?:(?:TCP|UDP):\s*)?\[?([^] ]+)\]?(?::-?\d+)?(?:\s*->.*)?$/$1/;
}
my $timestamp = $date . ' ' . $time;
my ($custom_oid, $custom_type, $custom_value) = ('', '', ''); my $timestamp = $date . ' ' . $time;
my ($custom_oid, $custom_type, $custom_value) = ('', '', '');
# custom_type, custom_value is not used since 4.0 version, all custom data goes on custom_oid
$custom_oid = $data; # custom_type, custom_value is not used since 4.0 version, all custom data goes on custom_oid
$custom_oid = $data;
#Trap forwarding
if ($pa_config->{'snmp_forward_trap'}==1) { #Trap forwarding
my $trap_data_string = ""; if ($pa_config->{'snmp_forward_trap'}==1) {
my $trap_data_string = "";
#We loop through all the custom data of the received trap, creating the $trap_data_string string to forward the trap properly
while ($data =~ /([\.\d]+)\s=\s([^:]+):\s([\S ]+)/g) { #We loop through all the custom data of the received trap, creating the $trap_data_string string to forward the trap properly
my ($trap_data, $trap_type, $trap_value) = ($1, $2, $3); while ($data =~ /([\.\d]+)\s=\s([^:]+):\s([\S ]+)/g) {
if ($trap_type eq "INTEGER") { my ($trap_data, $trap_type, $trap_value) = ($1, $2, $3);
#FIX for translated traps from IF-MIB.txt MIB if ($trap_type eq "INTEGER") {
$trap_value =~ s/\D//g; #FIX for translated traps from IF-MIB.txt MIB
$trap_data_string = $trap_data_string . "$trap_data i $trap_value "; $trap_value =~ s/\D//g;
} $trap_data_string = $trap_data_string . "$trap_data i $trap_value ";
elsif ($trap_type eq "UNSIGNED"){ }
$trap_data_string = $trap_data_string . "$trap_data u $trap_value "; elsif ($trap_type eq "UNSIGNED"){
} $trap_data_string = $trap_data_string . "$trap_data u $trap_value ";
elsif ($trap_type eq "COUNTER32"){ }
$trap_data_string = $trap_data_string . "$trap_data c $trap_value "; elsif ($trap_type eq "COUNTER32"){
} $trap_data_string = $trap_data_string . "$trap_data c $trap_value ";
elsif ($trap_type eq "STRING"){ }
$trap_data_string = $trap_data_string . "$trap_data s $trap_value "; elsif ($trap_type eq "STRING"){
} $trap_data_string = $trap_data_string . "$trap_data s $trap_value ";
elsif ($trap_type eq "HEX STRING"){ }
$trap_data_string = $trap_data_string . "$trap_data x $trap_value "; elsif ($trap_type eq "HEX STRING"){
} $trap_data_string = $trap_data_string . "$trap_data x $trap_value ";
elsif ($trap_type eq "DECIMAL STRING"){ }
$trap_data_string = $trap_data_string . "$trap_data d $trap_value "; elsif ($trap_type eq "DECIMAL STRING"){
} $trap_data_string = $trap_data_string . "$trap_data d $trap_value ";
elsif ($trap_type eq "NULLOBJ"){ }
$trap_data_string = $trap_data_string . "$trap_data n $trap_value "; elsif ($trap_type eq "NULLOBJ"){
} $trap_data_string = $trap_data_string . "$trap_data n $trap_value ";
elsif ($trap_type eq "OBJID"){ }
$trap_data_string = $trap_data_string . "$trap_data o $trap_value "; elsif ($trap_type eq "OBJID"){
} $trap_data_string = $trap_data_string . "$trap_data o $trap_value ";
elsif ($trap_type eq "TIMETICKS"){ }
$trap_data_string = $trap_data_string . "$trap_data t $trap_value "; elsif ($trap_type eq "TIMETICKS"){
} $trap_data_string = $trap_data_string . "$trap_data t $trap_value ";
elsif ($trap_type eq "IPADDRESS"){ }
$trap_data_string = $trap_data_string . "$trap_data a $trap_value "; elsif ($trap_type eq "IPADDRESS"){
} $trap_data_string = $trap_data_string . "$trap_data a $trap_value ";
elsif ($trap_type eq "BITS"){ }
$trap_data_string = $trap_data_string . "$trap_data b $trap_value "; elsif ($trap_type eq "BITS"){
} $trap_data_string = $trap_data_string . "$trap_data b $trap_value ";
} }
}
#We distinguish between the three different kinds of SNMP forwarding
if ($pa_config->{'snmp_forward_version'} eq '3') { #We distinguish between the three different kinds of SNMP forwarding
system("snmptrap -v $pa_config->{'snmp_forward_version'} -n \"\" -a $pa_config->{'snmp_forward_authProtocol'} -A $pa_config->{'snmp_forward_authPassword'} -x $pa_config->{'snmp_forward_privProtocol'} -X $pa_config->{'snmp_forward_privPassword'} -l $pa_config->{'snmp_forward_secLevel'} -u $pa_config->{'snmp_forward_secName'} -e $pa_config->{'snmp_forward_engineid'} $pa_config->{'snmp_forward_ip'} '' $oid $trap_data_string"); if ($pa_config->{'snmp_forward_version'} eq '3') {
} system("snmptrap -v $pa_config->{'snmp_forward_version'} -n \"\" -a $pa_config->{'snmp_forward_authProtocol'} -A $pa_config->{'snmp_forward_authPassword'} -x $pa_config->{'snmp_forward_privProtocol'} -X $pa_config->{'snmp_forward_privPassword'} -l $pa_config->{'snmp_forward_secLevel'} -u $pa_config->{'snmp_forward_secName'} -e $pa_config->{'snmp_forward_engineid'} $pa_config->{'snmp_forward_ip'} '' $oid $trap_data_string");
elsif ($pa_config->{'snmp_forward_version'} eq '2' || $pa_config->{'snmp_forward_version'} eq '2c') { }
system("snmptrap -v 2c -n \"\" -c $pa_config->{'snmp_forward_community'} $pa_config->{'snmp_forward_ip'} '' $oid $trap_data_string"); elsif ($pa_config->{'snmp_forward_version'} eq '2' || $pa_config->{'snmp_forward_version'} eq '2c') {
} system("snmptrap -v 2c -n \"\" -c $pa_config->{'snmp_forward_community'} $pa_config->{'snmp_forward_ip'} '' $oid $trap_data_string");
elsif ($pa_config->{'snmp_forward_version'} eq '1') { }
#Because of tne SNMP v1 protocol, we must perform additional steps for creating the trap elsif ($pa_config->{'snmp_forward_version'} eq '1') {
my $value_sending = ""; #Because of tne SNMP v1 protocol, we must perform additional steps for creating the trap
my $type_sending = ""; my $value_sending = "";
my $type_sending = "";
if ($value eq ''){
$value_sending = "\"\""; if ($value eq ''){
} $value_sending = "\"\"";
else { }
$value_sending = $value; else {
$value_sending =~ s/[\$#@~!&*()\[\];.,:?^ `\\\/]+//g; $value_sending = $value;
} $value_sending =~ s/[\$#@~!&*()\[\];.,:?^ `\\\/]+//g;
if ($type eq ''){ }
$type_sending = "\"\""; if ($type eq ''){
} $type_sending = "\"\"";
else{ }
$type_sending = $type; else{
} $type_sending = $type;
}
system("snmptrap -v 1 -c $pa_config->{'snmp_forward_community'} $pa_config->{'snmp_forward_ip'} $oid \"\" $type_sending $value_sending \"\" $trap_data_string");
} system("snmptrap -v 1 -c $pa_config->{'snmp_forward_community'} $pa_config->{'snmp_forward_ip'} $oid \"\" $type_sending $value_sending \"\" $trap_data_string");
} }
}
# Insert the trap into the DB
if (! defined(enterprise_hook ('snmp_insert_trap', [$pa_config, $source, $oid, $type, $value, $custom_oid, $custom_value, $custom_type, $timestamp, $server_id, $dbh]))) { # Insert the trap into the DB
my $trap_id = db_insert ($dbh, 'id_trap', 'INSERT INTO ttrap (timestamp, source, oid, type, value, oid_custom, value_custom, type_custom) VALUES (?, ?, ?, ?, ?, ?, ?, ?)', if (! defined(enterprise_hook ('snmp_insert_trap', [$pa_config, $source, $oid, $type, $value, $custom_oid, $custom_value, $custom_type, $timestamp, $server_id, $dbh]))) {
$timestamp, $source, $oid, $type, $value, $custom_oid, $custom_value, $custom_type); my $trap_id = db_insert ($dbh, 'id_trap', 'INSERT INTO ttrap (timestamp, source, oid, type, value, oid_custom, value_custom, type_custom) VALUES (?, ?, ?, ?, ?, ?, ?, ?)',
logger ($pa_config, "Received SNMP Trap from $source", 4); $timestamp, $source, $oid, $type, $value, $custom_oid, $custom_value, $custom_type);
logger ($pa_config, "Received SNMP Trap from $source", 4);
# Evaluate alerts for this trap
pandora_evaluate_snmp_alerts ($pa_config, $trap_id, $source, $oid, $type, $oid, $value, $custom_oid, $dbh); # Evaluate alerts for this trap
} pandora_evaluate_snmp_alerts ($pa_config, $trap_id, $source, $oid, $type, $oid, $value, $custom_oid, $dbh);
}
# Delay the consumption of the next task.
sleep($pa_config->{'snmp_delay'}) if ($pa_config->{'snmp_delay'} > 0); # Delay the consumption of the next task.
} sleep($pa_config->{'snmp_delay'}) if ($pa_config->{'snmp_delay'} > 0);
}
########################################################################################
# Returns 1 if the given string matches any SNMP filter, 0 otherwise. ########################################################################################
######################################################################################## # Returns 1 if the given string matches any SNMP filter, 0 otherwise.
sub matches_filter ($$$) { ########################################################################################
my ($dbh, $pa_config, $string) = @_; sub matches_filter ($$$) {
my ($dbh, $pa_config, $string) = @_;
# Get filters
my @filters = get_db_rows ($dbh, 'SELECT filter FROM tsnmp_filter'); # Get filters
foreach my $filter (@filters) { my @filters = get_db_rows ($dbh, 'SELECT filter FROM tsnmp_filter');
my $regexp = safe_output($filter->{'filter'}) ; foreach my $filter (@filters) {
my $eval_result; my $regexp = safe_output($filter->{'filter'}) ;
my $eval_result;
# eval protects against server down (by invalid regular expressions)
$eval_result = eval { # eval protects against server down (by invalid regular expressions)
$string =~ m/$regexp/i ; $eval_result = eval {
}; $string =~ m/$regexp/i ;
};
if ($eval_result) {
logger($pa_config, "Trap '$string' matches filter '$regexp'. Discarding...", 10); if ($eval_result) {
return 1; logger($pa_config, "Trap '$string' matches filter '$regexp'. Discarding...", 10);
} return 1;
}
}
}
return 0;
} return 0;
}
########################################################################################
# Start snmptrapd, attempting to kill it if it is already running. Returns 0 if ########################################################################################
# successful, 1 otherwise. # Start snmptrapd, attempting to kill it if it is already running. Returns 0 if
######################################################################################## # successful, 1 otherwise.
sub start_snmptrapd ($) { ########################################################################################
my ($config) = @_; sub start_snmptrapd ($) {
my ($config) = @_;
my $pid_file = '/var/run/pandora_snmptrapd.pid';
my $snmptrapd_running = 0; my $pid_file = '/var/run/pandora_snmptrapd.pid';
my $snmptrapd_running = 0;
# Manual start of snmptrapd
if ($config->{'snmp_trapd'} eq 'manual') { # Manual start of snmptrapd
logger ($config, "No SNMP trap daemon configured. Start snmptrapd manually.", 1); if ($config->{'snmp_trapd'} eq 'manual') {
print_message ($config, " [*] No SNMP trap daemon configured. Start snmptrapd manually.", 1); logger ($config, "No SNMP trap daemon configured. Start snmptrapd manually.", 1);
print_message ($config, " [*] No SNMP trap daemon configured. Start snmptrapd manually.", 1);
if (! -f $config->{'snmp_logfile'}) {
logger ($config, "SNMP log file " . $config->{'snmp_logfile'} . " not found.", 1); if (! -f $config->{'snmp_logfile'}) {
print_message ($config, " [E] SNMP log file " . $config->{'snmp_logfile'} . " not found.", 1); logger ($config, "SNMP log file " . $config->{'snmp_logfile'} . " not found.", 1);
return 1; print_message ($config, " [E] SNMP log file " . $config->{'snmp_logfile'} . " not found.", 1);
} return 1;
}
return 0;
} return 0;
}
if ( -e $pid_file && open (PIDFILE, $pid_file)) {
my $pid = <PIDFILE> + 0; if ( -e $pid_file && open (PIDFILE, $pid_file)) {
close PIDFILE; my $pid = <PIDFILE> + 0;
close PIDFILE;
# Check if snmptrapd is running
if ($snmptrapd_running = kill (0, $pid)) { # Check if snmptrapd is running
logger ($config, "snmptrapd (pid $pid) is already running, attempting to kill it...", 1); if ($snmptrapd_running = kill (0, $pid)) {
print_message ($config, "snmptrapd (pid $pid) is already running, attempting to kill it...", 1); logger ($config, "snmptrapd (pid $pid) is already running, attempting to kill it...", 1);
kill (9, $pid); print_message ($config, "snmptrapd (pid $pid) is already running, attempting to kill it...", 1);
} kill (9, $pid);
} }
}
# Ignore auth failure traps
my $snmp_ignore_authfailure = ($config->{'snmp_ignore_authfailure'} eq '1' ? ' -a' : ''); # Ignore auth failure traps
my $snmp_ignore_authfailure = ($config->{'snmp_ignore_authfailure'} eq '1' ? ' -a' : '');
# Select agent-addr field of the PDU or PDU source address for V1 traps
my $address_format = ($config->{'snmp_pdu_address'} eq '0' ? '%a' : '%b'); # Select agent-addr field of the PDU or PDU source address for V1 traps
my $address_format = ($config->{'snmp_pdu_address'} eq '0' ? '%a' : '%b');
my $snmptrapd_args = ' -t -On -n' . $snmp_ignore_authfailure . ' -Lf ' . $config->{'snmp_logfile'} . ' -p ' . $pid_file;
$snmptrapd_args .= ' --format1=SNMPv1[**]%4y-%02.2m-%l[**]%02.2h:%02.2j:%02.2k[**]' . $address_format . '[**]%N[**]%w[**]%W[**]%q[**]%v\\\n'; my $snmptrapd_args = ' -t -On -n' . $snmp_ignore_authfailure . ' -Lf ' . $config->{'snmp_logfile'} . ' -p ' . $pid_file;
$snmptrapd_args .= ' --format2=SNMPv2[**]%4y-%02.2m-%l[**]%02.2h:%02.2j:%02.2k[**]%b[**]%v\\\n'; $snmptrapd_args .= ' --format1=SNMPv1[**]%4y-%02.2m-%l[**]%02.2h:%02.2j:%02.2k[**]' . $address_format . '[**]%N[**]%w[**]%W[**]%q[**]%v\\\n';
$snmptrapd_args .= ' --format2=SNMPv2[**]%4y-%02.2m-%l[**]%02.2h:%02.2j:%02.2k[**]%b[**]%v\\\n';
if (system ($config->{'snmp_trapd'} . $snmptrapd_args . " >$DEVNULL 2>&1") != 0) {
logger ($config, " [E] Could not start snmptrapd.", 1); if (system ($config->{'snmp_trapd'} . $snmptrapd_args . " >$DEVNULL 2>&1") != 0) {
print_message ($config, " [E] Could not start snmptrapd.", 1); logger ($config, " [E] Could not start snmptrapd.", 1);
return 1; print_message ($config, " [E] Could not start snmptrapd.", 1);
} return 1;
}
return 0;
} return 0;
}
###############################################################################
# Read SNMP Log file with buffering (to handle multi-line Traps). ###############################################################################
# Return reference of array (file-pos, line-data) if successful, undef othersise. # Read SNMP Log file with buffering (to handle multi-line Traps).
############################################################################### # Return reference of array (file-pos, line-data) if successful, undef othersise.
my $read_ahead_line; # buffer to save fetched ahead line ###############################################################################
my $read_ahead_pos; my $read_ahead_line; # buffer to save fetched ahead line
my $read_ahead_pos;
sub read_snmplogfile()
{ sub read_snmplogfile()
my $line; {
my $pos; my $line;
my $pos;
if(defined($read_ahead_line)) {
# Restore saved line if(defined($read_ahead_line)) {
$line = $read_ahead_line; # Restore saved line
$pos = $read_ahead_pos; $line = $read_ahead_line;
} $pos = $read_ahead_pos;
else { }
# No saved line else {
$line = <SNMPLOGFILE>; # No saved line
$pos = tell(SNMPLOGFILE); $line = <SNMPLOGFILE>;
} $pos = tell(SNMPLOGFILE);
}
return undef if (! defined($line));
return undef if (! defined($line));
# More lines ?
while($read_ahead_line = <SNMPLOGFILE>) { # More lines ?
while($read_ahead_line = <SNMPLOGFILE>) {
# Get current file position
$read_ahead_pos = tell(SNMPLOGFILE); # Get current file position
$read_ahead_pos = tell(SNMPLOGFILE);
# Get out of the loop if you find another Trap
last if($read_ahead_line =~ /^SNMP/ ); # Get out of the loop if you find another Trap
last if($read_ahead_line =~ /^SNMP/ );
# $read_ahead_line looks continued line...
# $read_ahead_line looks continued line...
# Append to the line and correct the position
chomp($line); # Append to the line and correct the position
$line .= "$read_ahead_line"; chomp($line);
$pos = $read_ahead_pos; $line .= "$read_ahead_line";
} $pos = $read_ahead_pos;
}
# return fetched line with file position to be saved.
return [$pos, $line]; # return fetched line with file position to be saved.
} return [$pos, $line];
}
###############################################################################
# Clean-up when the server is destroyed. ###############################################################################
############################################################################### # Clean-up when the server is destroyed.
sub DESTROY { ###############################################################################
my $self = shift; sub DESTROY {
my $self = shift;
if ($self->{'snmp_trapd'} ne 'manual') {
system ("kill -9 `cat /var/run/pandora_snmptrapd.pid 2>$DEVNULL`"); if ($self->{'snmp_trapd'} ne 'manual') {
unlink ('/var/run/pandora_snmptrapd.pid'); system ("kill -9 `cat /var/run/pandora_snmptrapd.pid 2>$DEVNULL`");
} unlink ('/var/run/pandora_snmptrapd.pid');
} }
}
1;
__END__ 1;
__END__