2008-06-18 Sancho Lerena <slerena@gmail.com>
* pandora_dbstress.pl: Added suppor for "text" moduletypes. * pandora_recon: Now is multithreaded. Better management of already registered IP's. Better status update. Some fixes (xprobe2 crash). * Config.pm: Added support for recon_threads token. * Tools.pm: added pandora_trash_ascii(), autocreate set agent in learning mode automatically. git-svn-id: https://svn.code.sf.net/p/pandora/code/trunk@879 c3f86ba8-e40f-0410-aaad-9ba5e7f4b01f
This commit is contained in:
parent
b8428c482c
commit
c76414caeb
|
@ -1,3 +1,15 @@
|
|||
2008-06-18 Sancho Lerena <slerena@gmail.com>
|
||||
|
||||
* pandora_dbstress.pl: Added suppor for "text" moduletypes.
|
||||
|
||||
* pandora_recon: Now is multithreaded. Better management of already
|
||||
registered IP's. Better status update. Some fixes (xprobe2 crash).
|
||||
|
||||
* Config.pm: Added support for recon_threads token.
|
||||
|
||||
* Tools.pm: added pandora_trash_ascii(), autocreate
|
||||
set agent in learning mode automatically.
|
||||
|
||||
2008-06-17 Sancho Lerena <slerena@artica.es>
|
||||
|
||||
* config.pm: Added options for xprobe2, and autocreate.
|
||||
|
|
|
@ -2,8 +2,8 @@
|
|||
##########################################################################
|
||||
# Pandora FMS Recon Server
|
||||
##########################################################################
|
||||
# Copyright (c) 2007 Sancho Lerena, slerena@gmail.com
|
||||
# Copyright (c) 2007 Artica Soluciones Tecnologicas S.L
|
||||
# Copyright (c) 2007-2008 Sancho Lerena, slerena@gmail.com
|
||||
# Copyright (c) 2007-2008 Artica Soluciones Tecnologicas S.L
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
|
@ -37,6 +37,13 @@ use PandoraFMS::Config;
|
|||
use PandoraFMS::Tools;
|
||||
use PandoraFMS::DB;
|
||||
|
||||
# Queue management
|
||||
my @pending_task : shared;
|
||||
my %pending_task_hash : shared;
|
||||
my %current_task_hash : shared;
|
||||
my $queue_lock : shared;
|
||||
|
||||
|
||||
# FLUSH in each IO (only for debug, very slooow)
|
||||
# ENABLED in DEBUGMODE
|
||||
# DISABLE FOR PRODUCTION
|
||||
|
@ -67,8 +74,15 @@ if ( $pa_config{"daemon"} eq "1" ){
|
|||
&pandora_daemonize ( \%pa_config);
|
||||
}
|
||||
|
||||
# Runs main program (have a infinite loop inside)
|
||||
threads->new( \&pandora_recon_subsystem, \%pa_config);
|
||||
# Launch now all plugin threads
|
||||
# $ax is local thread id for this server
|
||||
|
||||
for (my $ax=0; $ax < $pa_config{'recon_threads'}; $ax++){
|
||||
threads->new( \&pandora_recon_consumer, \%pa_config, $ax);
|
||||
}
|
||||
|
||||
# Launch now the producer thread
|
||||
threads->new( \&pandora_recon_producer, \%pa_config);
|
||||
|
||||
sleep(1);
|
||||
|
||||
|
@ -96,45 +110,110 @@ while ( 1 ){
|
|||
#------------------------------------------------------------------------------------
|
||||
#------------------------------------------------------------------------------------
|
||||
|
||||
##########################################################################
|
||||
# SUB pandora_recon_subsystem
|
||||
# This module runs each X seconds (server threshold) checking for new
|
||||
# recon tasks pending to do
|
||||
##########################################################################
|
||||
|
||||
sub pandora_recon_subsystem {
|
||||
# Init vars
|
||||
sub pandora_recon_producer ($) {
|
||||
my $pa_config = $_[0];
|
||||
print " [*] Starting up Recon Producer Thread ...\n";
|
||||
|
||||
my $dbh = DBI->connect("DBI:mysql:$pa_config->{'dbname'}:$pa_config->{'dbhost'}:3306", $pa_config->{'dbuser'}, $pa_config->{'dbpass'}, { RaiseError => 1, AutoCommit => 1 });
|
||||
my $server_id = dame_server_id($pa_config, $pa_config->{'servername'}."_Recon", $dbh);
|
||||
my $query_sql; # for use in SQL
|
||||
my $exec_sql; # for use in SQL
|
||||
my @sql_data; # for use in SQL
|
||||
while ( 1 ) {
|
||||
logger ($pa_config, "Loop in Recon Module Subsystem", 10);
|
||||
$query_sql = "SELECT * FROM trecon_task WHERE id_network_server = $server_id AND status = -1";
|
||||
$exec_sql = $dbh->prepare($query_sql);
|
||||
$exec_sql->execute;
|
||||
while (@sql_data = $exec_sql->fetchrow_array()) {
|
||||
my $interval = $sql_data[11];
|
||||
my $my_timestamp = &UnixDate("today","%Y-%m-%d %H:%M:%S");
|
||||
my $my_utimestamp = &UnixDate($my_timestamp, "%s"); # convert from human to integer
|
||||
my $utimestamp = $sql_data[9];
|
||||
my $id_task = $sql_data[0];
|
||||
my $task_name = $sql_data[1];
|
||||
# Need to exec this task ?
|
||||
if (($utimestamp + $interval) < $my_utimestamp){
|
||||
logger($pa_config,"Recon Server: Executing task [$task_name]",8);
|
||||
# EXEC TASK and mark as "in progress" != -1
|
||||
pandora_update_reconstatus ($pa_config, $dbh, $id_task, 0);
|
||||
pandora_recon_exec_task ($pa_config, $id_task);
|
||||
my $server_id = $pa_config->{'server_id'};
|
||||
|
||||
# Initialize variables for posterior usage
|
||||
my $query_sql;
|
||||
my @sql_data1;
|
||||
my $data_id_task;
|
||||
my $exec_sql1;
|
||||
|
||||
while (1) {
|
||||
$query_sql = "SELECT * FROM trecon_task
|
||||
WHERE
|
||||
id_network_server = $server_id
|
||||
AND
|
||||
status = -1
|
||||
AND
|
||||
(utimestamp + interval_sweep) < UNIX_TIMESTAMP()
|
||||
";
|
||||
|
||||
$exec_sql1 = $dbh->prepare($query_sql);
|
||||
$exec_sql1 ->execute;
|
||||
while (@sql_data1 = $exec_sql1->fetchrow_array()) {
|
||||
$data_id_task = $sql_data1[0];
|
||||
|
||||
# Skip modules already queued
|
||||
if ((!defined($pending_task_hash{$data_id_task})) &&
|
||||
(!defined($current_task_hash{$data_id_task}))) {
|
||||
pandora_update_reconstatus ($pa_config, $dbh, $data_id_task, 0);
|
||||
# Locking scope, do not remove redundant { }
|
||||
{
|
||||
lock $queue_lock;
|
||||
push (@pending_task, $data_id_task);
|
||||
$pending_task_hash {$data_id_task}=1;
|
||||
}
|
||||
}
|
||||
}
|
||||
$exec_sql->finish();
|
||||
}
|
||||
$exec_sql1->finish();
|
||||
threads->yield;
|
||||
sleep($pa_config->{"server_threshold"});
|
||||
} # Main loop
|
||||
}
|
||||
|
||||
##########################################################################
|
||||
# SUB pandora_recon_consumer
|
||||
# This module runs each X seconds (server threshold) checking for recon task
|
||||
##########################################################################
|
||||
sub pandora_recon_consumer ($$) {
|
||||
my $pa_config = $_[0];
|
||||
my $thread_id = $_[1];
|
||||
|
||||
if ($pa_config->{"quiet"} == 0){
|
||||
print " [*] Starting up Recon Consumer Thread # $thread_id \n";
|
||||
}
|
||||
|
||||
my $data_id_task;
|
||||
# Create Database handler
|
||||
my $dbh = DBI->connect("DBI:mysql:$pa_config->{'dbname'}:$pa_config->{'dbhost'}:3306", $pa_config->{'dbuser'}, $pa_config->{'dbpass'}, { RaiseError => 1, AutoCommit => 1 });
|
||||
my $counter =0;
|
||||
|
||||
LOOP: while (1) {
|
||||
if ($counter > 10) {
|
||||
threads->yield;
|
||||
$counter = 0;
|
||||
}
|
||||
|
||||
# Take the first element on the shared queue
|
||||
# Insert this element on the current task hash
|
||||
{
|
||||
lock $queue_lock;
|
||||
if (scalar(@pending_task) == 0){
|
||||
$counter++;
|
||||
next LOOP;
|
||||
}
|
||||
|
||||
$data_id_task = shift(@pending_task);
|
||||
delete($pending_task_hash{$data_id_task});
|
||||
$current_task_hash{$data_id_task}=1;
|
||||
}
|
||||
|
||||
# Executing recon task with unmanaged error trapping
|
||||
eval {
|
||||
pandora_recon_exec_task ($pa_config, $data_id_task, $dbh);
|
||||
};
|
||||
if ($@){
|
||||
logger ($pa_config, "[ERROR] Recon Task for Task ID $data_id_task causes a system exception", 0);
|
||||
logger ($pa_config, "ERROR Code: $@", 1);
|
||||
}
|
||||
|
||||
# Remove from queue. If catch an error, probably data is
|
||||
# not been processed, but has been freed from task queue
|
||||
{
|
||||
lock $queue_lock;
|
||||
delete($current_task_hash{$data_id_task});
|
||||
}
|
||||
$counter = 0;
|
||||
threads->yield;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
##########################################################################
|
||||
# SUB pandora_detect_os (paconfig, host)
|
||||
# Detect OS using xprobe2 tool. Return tconfig_os id code.
|
||||
|
@ -146,9 +225,15 @@ sub pandora_detect_os {
|
|||
|
||||
my $xprobe2 = $pa_config->{"xprobe2"};
|
||||
if (! -e $xprobe2){
|
||||
return 10;
|
||||
return 10; # other
|
||||
}
|
||||
my $command = `$xprobe2 $host 2> /dev/null | grep "Running OS" | head -1`;
|
||||
my $command= "";
|
||||
eval {
|
||||
$command = `$xprobe2 $host 2> /dev/null | grep "Running OS" | head -1`;
|
||||
};
|
||||
if ($@){
|
||||
return 10;
|
||||
}
|
||||
return pandora_get_os ($command);
|
||||
}
|
||||
##########################################################################
|
||||
|
@ -158,14 +243,15 @@ sub pandora_detect_os {
|
|||
sub pandora_recon_exec_task {
|
||||
my $pa_config = $_[0];
|
||||
my $id_task = $_[1];
|
||||
my $dbh = $_[2];
|
||||
|
||||
my $target_ip; # Real ip to check
|
||||
my @ip2; # temp array for NetAddr::IP
|
||||
my $space; # temp var to store space of ip's for netaddr::ip
|
||||
my $query_sql; # for use in SQL
|
||||
my $exec_sql; # for use in SQL
|
||||
my @sql_data; # for use in SQL
|
||||
my $dbh = DBI->connect("DBI:mysql:$pa_config->{'dbname'}:$pa_config->{'dbhost'}:3306", $pa_config->{'dbuser'}, $pa_config->{'dbpass'}, { RaiseError => 1, AutoCommit => 1 });
|
||||
|
||||
|
||||
$query_sql = "SELECT * FROM trecon_task WHERE id_rt = $id_task";
|
||||
$exec_sql = $dbh->prepare($query_sql);
|
||||
$exec_sql ->execute;
|
||||
|
@ -209,20 +295,21 @@ sub pandora_recon_exec_task {
|
|||
$space++; $position++;
|
||||
|
||||
$add_host = 0;
|
||||
# Check ICMP for this IP
|
||||
if (($task_type == 1) && (scan_icmp ($target_ip, $pa_config->{'networktimeout'}) == 1)){
|
||||
$add_host = 1;
|
||||
}
|
||||
# Check TCP port for this IP
|
||||
elsif (($task_type == 2) && (scan_icmp ($target_ip, $pa_config->{'networktimeout'}) == 1)) {
|
||||
if (scan_tcp ($target_ip, $pa_config->{'networktimeout'}, $extended_value) == 1){
|
||||
# Is this IP listed for any agent ?
|
||||
if (pandora_check_ip ($pa_config, $dbh, $target_ip) == 0){
|
||||
|
||||
# Check ICMP for this IP
|
||||
if (($task_type == 1) && (scan_icmp ($target_ip, $pa_config->{'networktimeout'}) == 1)){
|
||||
$add_host = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if ($add_host == 1){
|
||||
# Is this IP listed for any agent ?
|
||||
if (pandora_check_ip ($pa_config, $dbh, $target_ip) == 0){
|
||||
# Check TCP port for this IP
|
||||
elsif (($task_type == 2) && (scan_icmp ($target_ip, $pa_config->{'networktimeout'}) == 1)) {
|
||||
if (scan_tcp ($target_ip, $pa_config->{'networktimeout'}, $extended_value) == 1){
|
||||
$add_host = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if ($add_host == 1){
|
||||
$host_found ++;
|
||||
my $target_ip_resolved = resolv_ip2name($target_ip);
|
||||
$list_ip = $list_ip." ".$target_ip;
|
||||
|
@ -248,7 +335,8 @@ sub pandora_recon_exec_task {
|
|||
}
|
||||
|
||||
my $progress = ceil($position / ($total_hosts / 100));
|
||||
pandora_update_reconstatus ($pa_config, $dbh, $id_task, $progress);
|
||||
pandora_update_reconstatus ($pa_config, $dbh, $id_task, $progress);
|
||||
pandora_task_set_utimestamp ($pa_config, $dbh, $id_task);
|
||||
} while ($space < $space->broadcast); # fin del buclie principal de iteracion de Ips
|
||||
|
||||
# Create incident
|
||||
|
@ -276,27 +364,27 @@ sub scan_icmp {
|
|||
my $l_timeout = $_[1];
|
||||
# temporal vars.
|
||||
my $result = 0;
|
||||
my $result2 = 0;
|
||||
my $p;
|
||||
|
||||
# Check for valid destination
|
||||
if (!defined($dest)) {
|
||||
return 0;
|
||||
}
|
||||
# Thread safe
|
||||
# Some hosts don't accept ICMP with too small payload. Use 16 Bytes
|
||||
$p = Net::Ping->new("icmp",$l_timeout,16);
|
||||
$p->source_verify(1);
|
||||
|
||||
$result = $p->ping($dest);
|
||||
$result2 = $p->ping($dest);
|
||||
{
|
||||
$p = Net::Ping->new("icmp",$l_timeout,16);
|
||||
$p->source_verify(1);
|
||||
$result = $p->ping($dest);
|
||||
}
|
||||
|
||||
# Check for valid result
|
||||
if ((!defined($result)) || (!defined($result2))) {
|
||||
if (!defined($result)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
# Lets see the result
|
||||
if (($result == 1) && ($result2 == 1)) {
|
||||
if ($result == 1) {
|
||||
$p->close();
|
||||
return 1;
|
||||
} else {
|
||||
|
@ -326,6 +414,9 @@ sub scan_tcp {
|
|||
}
|
||||
alarm 0;
|
||||
};
|
||||
if ($@){
|
||||
return 0;
|
||||
}
|
||||
return $opened;
|
||||
}
|
||||
|
||||
|
@ -530,14 +621,7 @@ sub pandora_getparent ($$){
|
|||
);
|
||||
|
||||
my $success = 0;
|
||||
eval {
|
||||
alarm $pa_config->{"networktimeout"};
|
||||
$success = $t->traceroute();
|
||||
alarm 0;
|
||||
};
|
||||
if ($@){
|
||||
return 0;
|
||||
}
|
||||
$success = $t->traceroute();
|
||||
if ($t->hops > 1){
|
||||
if ($success){
|
||||
my $parent_ip = $t->hop_query_host($t->hops-1,0);
|
||||
|
|
|
@ -176,3 +176,7 @@ autocreate_group 2
|
|||
# set to 0 to disable
|
||||
|
||||
autocreate 1
|
||||
|
||||
# recon_threads (3 by default)
|
||||
|
||||
recon_threads 3
|
|
@ -175,6 +175,7 @@ sub pandora_loadconfig {
|
|||
$pa_config->{"tcp_timeout"} = 20; # Introduced on 1.3.1
|
||||
$pa_config->{"snmp_proc_deadresponse"} = 0; # Introduced on 1.3.1 10 Feb08
|
||||
$pa_config->{"plugin_threads"} = 3; # Introduced on 2.0
|
||||
$pa_config->{"recon_threads"} = 3; # Introduced on 2.0
|
||||
$pa_config->{"prediction_threads"} = 3; # Introduced on 2.0
|
||||
$pa_config->{"plugin_timeout"} = 5; # Introduced on 2.0
|
||||
$pa_config->{"wmi_threads"} = 3; # Introduced on 2.0
|
||||
|
@ -194,6 +195,7 @@ sub pandora_loadconfig {
|
|||
$pa_config->{"xprobe2"} = "/usr/bin/xprobe2";
|
||||
$pa_config->{'autocreate_group'} = 2;
|
||||
$pa_config->{'autocreate'} = 1;
|
||||
$pa_config{'recon_threads'} = 3;
|
||||
|
||||
# Check for UID0
|
||||
if ($pa_config->{"quiet"} != 0){
|
||||
|
@ -397,6 +399,9 @@ sub pandora_loadconfig {
|
|||
elsif ($parametro =~ m/^autocreate_group\s([0-9*]*)/i) {
|
||||
$pa_config->{'autocreate_group'}= clean_blank($1);
|
||||
}
|
||||
elsif ($parametro =~ m/^recon_threads\s([0-9]*)/i) {
|
||||
$pa_config->{'recon_threads'}= clean_blank($1);
|
||||
}
|
||||
|
||||
} # end of loop for parameter #
|
||||
|
||||
|
|
|
@ -560,7 +560,8 @@ sub execute_alert (%$$$$$$$$$$$$$$$) {
|
|||
|
||||
|
||||
##########################################################################
|
||||
## SUB pandora_writestate (pa_config, nombre_agente,tipo_modulo,nombre_modulo,valor_datos, estado)
|
||||
## SUB pandora_writestate (pa_config, nombre_agente,tipo_modulo,
|
||||
# nombre_modulo,valor_datos, estado, dbh, needupdate)
|
||||
## Alter data, chaning status of modules in state table
|
||||
##########################################################################
|
||||
|
||||
|
@ -1001,9 +1002,9 @@ sub module_generic_data_string (%$$$$$) {
|
|||
my $m_data = $datos->{data}->[0];
|
||||
my $a_desc = $datos->{description}->[0];
|
||||
my $a_max = $datos->{max}->[0];
|
||||
my $a_min = $datos->{min}->[0];
|
||||
my $a_min = $datos->{min}->[0];
|
||||
if (ref($m_data) eq "HASH") {
|
||||
$m_data = XMLout($m_data, RootName=>undef);
|
||||
$m_data = XMLout($m_data, RootName=>undef);
|
||||
}
|
||||
if (ref($a_max) eq "HASH") {
|
||||
$a_max = "";
|
||||
|
@ -1018,19 +1019,20 @@ sub module_generic_data_string (%$$$$$) {
|
|||
|
||||
|
||||
##########################################################################
|
||||
## SUB pandora_writedata (pa_config, timestamp,nombre_agente,tipo_modulo,nombre_modulo,datos)
|
||||
## SUB pandora_writedata (pa_config, timestamp,nombre_agente,tipo_modulo,
|
||||
# nombre_modulo, datos, max, min, descripcion, dbh, update)
|
||||
## Insert data in main table: tagente_datos
|
||||
|
||||
##########################################################################
|
||||
|
||||
sub pandora_writedata (%$$$$$$$$$$){
|
||||
my $pa_config = $_[0];
|
||||
my $timestamp = $_[1];
|
||||
my $nombre_agente = $_[2];
|
||||
my $tipo_modulo = $_[3];
|
||||
my $nombre_modulo = $_[4];
|
||||
my $datos = $_[5];
|
||||
my $max = $_[6];
|
||||
my $timestamp = $_[1];
|
||||
my $nombre_agente = $_[2];
|
||||
my $tipo_modulo = $_[3];
|
||||
my $nombre_modulo = $_[4];
|
||||
my $datos = $_[5];
|
||||
my $max = $_[6];
|
||||
my $min = $_[7];
|
||||
my $descripcion = $_[8];
|
||||
my $dbh = $_[9];
|
||||
|
|
|
@ -41,8 +41,25 @@ our @EXPORT = qw(
|
|||
pandora_create_agent
|
||||
pandora_get_os
|
||||
pandora_event
|
||||
pandora_trash_ascii
|
||||
);
|
||||
|
||||
##########################################################################
|
||||
## SUB pandora_trash_ascii
|
||||
# Generate random ascii strings with variable lenght
|
||||
##########################################################################
|
||||
|
||||
sub pandora_trash_ascii {
|
||||
my $config_depth = $_[0];
|
||||
my $a;
|
||||
my $output;
|
||||
|
||||
for ($a=0;$a<$config_depth;$a++){
|
||||
$output = $output.chr(int(rand(25)+97));
|
||||
}
|
||||
return $output
|
||||
}
|
||||
|
||||
##########################################################################
|
||||
## SUB pandora_event
|
||||
## Write in internal audit system an entry.
|
||||
|
@ -157,7 +174,7 @@ sub pandora_create_agent {
|
|||
|
||||
my $server = $pa_config->{'servername'}.$pa_config->{"servermode"};
|
||||
logger($pa_config,"$server: Creating agent $name $target_ip ", 1);
|
||||
my $query_sql2 = "INSERT INTO tagente (nombre, direccion, comentarios, id_grupo, id_os, id_network_server, intervalo, id_parent) VALUES ('$name', '$target_ip', 'Created by $server', $id_group, $id_os, $id_server, 300, $id_parent)";
|
||||
my $query_sql2 = "INSERT INTO tagente (nombre, direccion, comentarios, id_grupo, id_os, id_network_server, intervalo, id_parent, modo) VALUES ('$name', '$target_ip', 'Created by $server', $id_group, $id_os, $id_server, 300, $id_parent, 1)";
|
||||
$dbh->do ($query_sql2);
|
||||
my $lastid = $dbh->{'mysql_insertid'};
|
||||
|
||||
|
|
|
@ -197,6 +197,23 @@ sub process_module(){
|
|||
}
|
||||
|
||||
}
|
||||
|
||||
# Generate pseudo-random data for boolean data
|
||||
if ( $target_name =~ /text/i ){
|
||||
for ($a=1;$a<$iterations;$a++){
|
||||
$valor = pandora_trash_ascii (rand(100)+50);
|
||||
$m_timestamp = DateCalc($m_timestamp,"+ $target_interval seconds",\$err);
|
||||
$mysql_date = &UnixDate($m_timestamp,"%Y-%m-%d %H:%M:%S");
|
||||
if ($a % 20 eq 0) {
|
||||
print "\r -> ".int($a / ($iterations / 100))."% generated for ($target_name) ";
|
||||
}
|
||||
pandora_lastagentcontact($pa_config, $mysql_date, $agent_name, "none","1.2", $target_interval, $dbh);
|
||||
#print LOG $mysql_date, $target_name, $valor, "\n";
|
||||
pandora_writedata($pa_config,$mysql_date,$agent_name,$target_type,$target_name,$valor,0,0,"",$dbh,\$bUpdateDatos);
|
||||
pandora_writestate ($pa_config,$agent_name,$target_type,$target_name,$valor,100,$dbh,$bUpdateDatos);
|
||||
}
|
||||
}
|
||||
|
||||
close (LOG);
|
||||
print "\n";
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue