2007-03-19 Sancho Lerena <slerena@artica.es>
* pandora_recon: Startup script for recon server. * pandora_recon.pl: Major code cleanup. First "complete" version, this sould be enought for a while. Works for me. * pandora_db.pm: Added generic functions to add incident . Added function give_network_component_profile_name(). Now updates correctly recon server status in pandora_updateserver function call. * pandora_network.pm: Replaced Net::Ping::External usage with Net::Ping library. This should fix many problems with some distros. Added pandora_ping_icmp() function to check ICMP boolean. git-svn-id: https://svn.code.sf.net/p/pandora/code/trunk@398 c3f86ba8-e40f-0410-aaad-9ba5e7f4b01f
This commit is contained in:
parent
46d686fece
commit
7691af0f11
|
@ -1,3 +1,20 @@
|
||||||
|
2007-03-19 Sancho Lerena <slerena@artica.es>
|
||||||
|
|
||||||
|
* pandora_recon: Startup script for recon server.
|
||||||
|
|
||||||
|
* pandora_recon.pl: Major code cleanup. First "complete" version,
|
||||||
|
this sould be enought for a while. Works for me.
|
||||||
|
|
||||||
|
* pandora_db.pm: Added generic functions to add incident . Added
|
||||||
|
function give_network_component_profile_name(). Now updates
|
||||||
|
correctly recon server status in pandora_updateserver function
|
||||||
|
call.
|
||||||
|
|
||||||
|
* pandora_network.pm: Replaced Net::Ping::External usage with
|
||||||
|
Net::Ping library. This should fix many problems with some
|
||||||
|
distros. Added pandora_ping_icmp() function to check ICMP boolean.
|
||||||
|
|
||||||
|
|
||||||
2007-03-12 Sancho Lerena <slerena@artica.es>
|
2007-03-12 Sancho Lerena <slerena@artica.es>
|
||||||
|
|
||||||
* util/pandora_dbstress.pl: Upgraded. Now admits one agent or all
|
* util/pandora_dbstress.pl: Upgraded. Now admits one agent or all
|
||||||
|
|
|
@ -1,14 +1,13 @@
|
||||||
package pandora_db;
|
package pandora_db;
|
||||||
##########################################################################
|
##########################################################################
|
||||||
# Pandora Database Package
|
# Pandora FMS Database Package
|
||||||
##########################################################################
|
##########################################################################
|
||||||
# Copyright (c) 2004-2007 Sancho Lerena, slerena@gmail.com
|
# Copyright (c) 2004-2007 Sancho Lerena, slerena@gmail.com
|
||||||
# Copyright (c) 2005-2007 Artica Soluciones Tecnologicas S.L
|
# Copyright (c) 2005-2007 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 General Public License
|
#modify it under the terms of the GNU General Public License
|
||||||
#as published by the Free Software Foundation; either version 2
|
#as published by the Free Software Foundation; version 2
|
||||||
#of the License, or (at your option) any later version.
|
|
||||||
#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
|
||||||
|
@ -63,6 +62,8 @@ our @EXPORT = qw( crea_agente_modulo
|
||||||
module_generic_data_inc
|
module_generic_data_inc
|
||||||
module_generic_data_string
|
module_generic_data_string
|
||||||
execute_alert
|
execute_alert
|
||||||
|
give_network_component_profile_name
|
||||||
|
pandora_create_incident
|
||||||
);
|
);
|
||||||
|
|
||||||
# Spanish translation note:
|
# Spanish translation note:
|
||||||
|
@ -871,7 +872,7 @@ fin_DB_insert_datos:
|
||||||
##########################################################################
|
##########################################################################
|
||||||
sub pandora_serverkeepaliver (%$) {
|
sub pandora_serverkeepaliver (%$) {
|
||||||
my $pa_config= $_[0];
|
my $pa_config= $_[0];
|
||||||
my $opmode = $_[1]; # 0 dataserver, 1 network server, 2 snmp console
|
my $opmode = $_[1]; # 0 dataserver, 1 network server, 2 snmp console, 3 recon server
|
||||||
my $dbh = $_[2];
|
my $dbh = $_[2];
|
||||||
my $pandorasuffix;
|
my $pandorasuffix;
|
||||||
my @data;
|
my @data;
|
||||||
|
@ -898,13 +899,12 @@ sub pandora_serverkeepaliver (%$) {
|
||||||
}
|
}
|
||||||
$s_idag->finish();
|
$s_idag->finish();
|
||||||
# Update my server
|
# Update my server
|
||||||
pandora_updateserver ($pa_config,$pa_config->{'servername'},1,$opmode, $dbh);
|
pandora_updateserver ($pa_config, $pa_config->{'servername'}, 1, $opmode, $dbh);
|
||||||
$pa_config->{"keepalive"}=$pa_config->{"keepalive_orig"};
|
$pa_config->{"keepalive"}=$pa_config->{"keepalive_orig"};
|
||||||
}
|
}
|
||||||
$pa_config->{"keepalive"}=$pa_config->{"keepalive"}-$pa_config->{"server_threshold"};
|
$pa_config->{"keepalive"}=$pa_config->{"keepalive"}-$pa_config->{"server_threshold"};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
##########################################################################
|
##########################################################################
|
||||||
## SUB pandora_updateserver (pa_config, status, dbh)
|
## SUB pandora_updateserver (pa_config, status, dbh)
|
||||||
## Update server status
|
## Update server status
|
||||||
|
@ -913,7 +913,7 @@ sub pandora_updateserver (%$$$) {
|
||||||
my $pa_config= $_[0];
|
my $pa_config= $_[0];
|
||||||
my $servername = $_[1];
|
my $servername = $_[1];
|
||||||
my $status = $_[2];
|
my $status = $_[2];
|
||||||
my $opmode = $_[3]; # 0 dataserver, 1 network server, 2 snmp console
|
my $opmode = $_[3]; # 0 dataserver, 1 network server, 2 snmp console, 3 recon
|
||||||
my $dbh = $_[4];
|
my $dbh = $_[4];
|
||||||
my $sql_update;
|
my $sql_update;
|
||||||
my $pandorasuffix;
|
my $pandorasuffix;
|
||||||
|
@ -921,8 +921,10 @@ sub pandora_updateserver (%$$$) {
|
||||||
$pandorasuffix = "_Data";
|
$pandorasuffix = "_Data";
|
||||||
} elsif ($opmode == 1){
|
} elsif ($opmode == 1){
|
||||||
$pandorasuffix = "_Net";
|
$pandorasuffix = "_Net";
|
||||||
} else {
|
} elsif ($opmode == 2){
|
||||||
$pandorasuffix = "_SNMP";
|
$pandorasuffix = "_SNMP";
|
||||||
|
} elsif ($opmode == 3){
|
||||||
|
$pandorasuffix = "_Recon";
|
||||||
}
|
}
|
||||||
my $id_server = dame_server_id($pa_config, $servername.$pandorasuffix, $dbh);
|
my $id_server = dame_server_id($pa_config, $servername.$pandorasuffix, $dbh);
|
||||||
if ($id_server == -1){
|
if ($id_server == -1){
|
||||||
|
@ -944,11 +946,13 @@ sub pandora_updateserver (%$$$) {
|
||||||
# Update server data
|
# Update server data
|
||||||
my $timestamp = &UnixDate("today","%Y-%m-%d %H:%M:%S");
|
my $timestamp = &UnixDate("today","%Y-%m-%d %H:%M:%S");
|
||||||
if ($opmode == 0){
|
if ($opmode == 0){
|
||||||
$sql_update = "update tserver set status = 1, laststart = '$timestamp', keepalive = '$timestamp', snmp_server = 0, network_server = 0, data_server = 1, master = $pa_config->{'pandora_master'}, checksum = $pa_config->{'pandora_check'} where id_server = $id_server";
|
$sql_update = "update tserver set status = 1, laststart = '$timestamp', keepalive = '$timestamp', recon_server = 0, snmp_server = 0, network_server = 0, data_server = 1, master = $pa_config->{'pandora_master'}, checksum = $pa_config->{'pandora_check'} where id_server = $id_server";
|
||||||
} elsif ($opmode == 1){
|
} elsif ($opmode == 1){
|
||||||
$sql_update = "update tserver set status = 1, laststart = '$timestamp', keepalive = '$timestamp', snmp_server = 0, network_server = 1, data_server = 0, master = $pa_config->{'pandora_master'}, checksum = 0 where id_server = $id_server";
|
$sql_update = "update tserver set status = 1, laststart = '$timestamp', keepalive = '$timestamp', recon_server = 0, snmp_server = 0, network_server = 1, data_server = 0, master = $pa_config->{'pandora_master'}, checksum = 0 where id_server = $id_server";
|
||||||
} else {
|
} elsif ($opmode == 2) {
|
||||||
$sql_update = "update tserver set status = 1, laststart = '$timestamp', keepalive = '$timestamp', snmp_server = 1, network_server = 0, data_server = 0, master = $pa_config->{'pandora_master'}, checksum = 0 where id_server = $id_server";
|
$sql_update = "update tserver set status = 1, laststart = '$timestamp', keepalive = '$timestamp', recon_server = 0, snmp_server = 1, network_server = 0, data_server = 0, master = $pa_config->{'pandora_master'}, checksum = 0 where id_server = $id_server";
|
||||||
|
} elsif ($opmode == 3) {
|
||||||
|
$sql_update = "update tserver set status = 1, laststart = '$timestamp', keepalive = '$timestamp', recon_server = 1, snmp_server = 0, network_server = 0, data_server = 0, master = $pa_config->{'pandora_master'}, checksum = 0 where id_server = $id_server";
|
||||||
}
|
}
|
||||||
$dbh->do($sql_update);
|
$dbh->do($sql_update);
|
||||||
}
|
}
|
||||||
|
@ -987,7 +991,7 @@ sub pandora_lastagentcontact (%$$$$$$) {
|
||||||
}
|
}
|
||||||
|
|
||||||
##########################################################################
|
##########################################################################
|
||||||
## SUB pandora_event (pa_config, evento, id_grupo, id_agente)
|
## SUB pandora_event (pa_config, evento, id_grupo, id_agente, dbh)
|
||||||
## Write in internal audit system an entry.
|
## Write in internal audit system an entry.
|
||||||
##########################################################################
|
##########################################################################
|
||||||
|
|
||||||
|
@ -1001,11 +1005,31 @@ sub pandora_event (%$$$$) {
|
||||||
my $timestamp = &UnixDate("today","%Y-%m-%d %H:%M:%S");
|
my $timestamp = &UnixDate("today","%Y-%m-%d %H:%M:%S");
|
||||||
$evento = $dbh->quote($evento);
|
$evento = $dbh->quote($evento);
|
||||||
$timestamp = $dbh->quote($timestamp);
|
$timestamp = $dbh->quote($timestamp);
|
||||||
my $query = "insert into tevento (id_agente, id_grupo, evento, timestamp, estado) VALUES ($id_agente,$id_grupo,$evento,$timestamp,0)";
|
my $query = "INSERT INTO tevento (id_agente, id_grupo, evento, timestamp, estado) VALUES ($id_agente,$id_grupo,$evento,$timestamp,0)";
|
||||||
logger ($pa_config,"EVENT Insertion: $query",5);
|
logger ($pa_config,"EVENT Insertion: $query", 5);
|
||||||
$dbh->do($query);
|
$dbh->do($query);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
##########################################################################
|
||||||
|
## SUB pandora_incident (pa_config, dbh, title, text, priority, status, origin, id_group
|
||||||
|
## Write in internal incident management system
|
||||||
|
##########################################################################
|
||||||
|
|
||||||
|
sub pandora_create_incident (%$$$$$$$) {
|
||||||
|
my $pa_config = $_[0];
|
||||||
|
my $dbh = $_[1];
|
||||||
|
my $title = $_[2];
|
||||||
|
my $text = $_[3];
|
||||||
|
my $priority = $_[4];
|
||||||
|
my $status = $_[5];
|
||||||
|
my $origin = $_[6];
|
||||||
|
my $id_group = $_[7];
|
||||||
|
my $my_timestamp = &UnixDate("today","%Y-%m-%d %H:%M:%S");
|
||||||
|
my $sql = "INSERT INTO tincidencia (inicio, actualizacion, titulo, descripcion, origen, estado, prioridad, id_grupo) VALUES ('$my_timestamp', '$my_timestamp', '$title', '$text', '$origin', $status, $priority, $id_group)";
|
||||||
|
$dbh->do($sql);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
##########################################################################
|
##########################################################################
|
||||||
## SUB pandora_audit (pa_config, escription, name, action, pandora_dbcfg_hash)
|
## SUB pandora_audit (pa_config, escription, name, action, pandora_dbcfg_hash)
|
||||||
## Write in internal audit system an entry.
|
## Write in internal audit system an entry.
|
||||||
|
@ -1348,6 +1372,28 @@ sub dame_id_tipo_modulo (%$$) {
|
||||||
$s_idag->finish();
|
$s_idag->finish();
|
||||||
return $tipo;
|
return $tipo;
|
||||||
}
|
}
|
||||||
|
##########################################################################
|
||||||
|
## SUB give_network_component_profile_name ($pa_config, $dbh, $task_ncprofile)
|
||||||
|
## Return network component profile name, given it's id
|
||||||
|
##########################################################################
|
||||||
|
sub give_network_component_profile_name (%$$) {
|
||||||
|
my $pa_config = $_[0];
|
||||||
|
my $dbh = $_[1];
|
||||||
|
my $id_np = $_[2];
|
||||||
|
|
||||||
|
my $tipo; my @data;
|
||||||
|
my $query_idag = "SELECT * FROM tnetwork_profile WHERE id_np = ".$id_np;
|
||||||
|
my $s_idag = $dbh->prepare($query_idag);
|
||||||
|
$s_idag ->execute;
|
||||||
|
if ($s_idag->rows == 0) {
|
||||||
|
logger($pa_config, "ERROR give_network_component_profile_name(): Cannot find network profile $id_nc",1);
|
||||||
|
logger($pa_config, "ERROR: SQL Query is $query_idag ",2);
|
||||||
|
$tipo = 0;
|
||||||
|
} else { @data = $s_idag->fetchrow_array(); }
|
||||||
|
$tipo= $data[1];
|
||||||
|
$s_idag->finish();
|
||||||
|
return $tipo;
|
||||||
|
}
|
||||||
|
|
||||||
##########################################################################
|
##########################################################################
|
||||||
## SUB dame_intervalo (id_agente)
|
## SUB dame_intervalo (id_agente)
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
#!/usr/bin/perl
|
#!/usr/bin/perl
|
||||||
##########################################################################
|
##########################################################################
|
||||||
# Pandora Network Server
|
# Pandora FMS Network Server
|
||||||
##########################################################################
|
##########################################################################
|
||||||
# Copyright (c) 2007 Sancho Lerena, slerena@gmail.com
|
# Copyright (c) 2006-2007 Sancho Lerena, slerena@gmail.com
|
||||||
#
|
#
|
||||||
# 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 General Public License
|
# modify it under the terms of the GNU General Public License
|
||||||
|
@ -22,7 +22,6 @@ use warnings;
|
||||||
|
|
||||||
use Date::Manip; # Needed to manipulate DateTime formats of input, output and compare
|
use Date::Manip; # Needed to manipulate DateTime formats of input, output and compare
|
||||||
use Time::Local; # DateTime basic manipulation
|
use Time::Local; # DateTime basic manipulation
|
||||||
use Net::Ping::External qw(ping); # For ICMP conectivity
|
|
||||||
use Net::Ping; # For ICMP latency
|
use Net::Ping; # For ICMP latency
|
||||||
use Time::HiRes; # For high precission timedate functions (Net::Ping)
|
use Time::HiRes; # For high precission timedate functions (Net::Ping)
|
||||||
use IO::Socket; # For TCP/UDP access
|
use IO::Socket; # For TCP/UDP access
|
||||||
|
@ -247,6 +246,25 @@ sub pandora_network_subsystem {
|
||||||
$dbh->disconnect();
|
$dbh->disconnect();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
##############################################################################
|
||||||
|
# pandora_ping_icmp (destination, timeout) - Do a ICMP scan, 1 if alive, 0 if not
|
||||||
|
##############################################################################
|
||||||
|
|
||||||
|
sub pandora_ping_icmp {
|
||||||
|
my $p;
|
||||||
|
my $dest = $_[0];
|
||||||
|
my $l_timeout = $_[1];
|
||||||
|
|
||||||
|
$p = Net::Ping->new("icmp",$l_timeout);
|
||||||
|
if ($p->ping($dest)) {
|
||||||
|
$p->close();
|
||||||
|
return 1;
|
||||||
|
} else {
|
||||||
|
$p->close();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
##########################################################################
|
##########################################################################
|
||||||
# SUB pandora_query_snmp (pa_config, oid, community, target, error, dbh)
|
# SUB pandora_query_snmp (pa_config, oid, community, target, error, dbh)
|
||||||
# Makes a call to SNMP modules to get a value,
|
# Makes a call to SNMP modules to get a value,
|
||||||
|
@ -335,15 +353,15 @@ sub exec_network_module {
|
||||||
# ICMP Modules
|
# ICMP Modules
|
||||||
# ------------
|
# ------------
|
||||||
if ($id_tipo_modulo == 6){ # ICMP (Connectivity only: Boolean)
|
if ($id_tipo_modulo == 6){ # ICMP (Connectivity only: Boolean)
|
||||||
$temp = ping(hostname => $ip_target, timeout => $pa_config->{'networktimeout'});
|
|
||||||
if ($temp eq "1" ){
|
$temp = pandora_ping_icmp ($ip_target, $pa_config->{'networktimeout'});
|
||||||
|
if ($temp == 1 ){
|
||||||
$module_result = 0; # Successful
|
$module_result = 0; # Successful
|
||||||
$module_data = 1;
|
$module_data = 1;
|
||||||
} else {
|
} else {
|
||||||
$module_result = 0; # Error, cannot connect
|
$module_result = 0; # Error, cannot connect
|
||||||
$module_data = 0;
|
$module_data = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
} elsif ($id_tipo_modulo == 7){ # ICMP (data for latency in ms)
|
} elsif ($id_tipo_modulo == 7){ # ICMP (data for latency in ms)
|
||||||
# This module only could be executed if executed as root
|
# This module only could be executed if executed as root
|
||||||
if ($> == 0){
|
if ($> == 0){
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
#!/usr/bin/perl
|
#!/usr/bin/perl
|
||||||
##########################################################################
|
##########################################################################
|
||||||
# Pandora Recon Server
|
# Pandora FMS Recon Server
|
||||||
##########################################################################
|
##########################################################################
|
||||||
# Copyright (c) 2007 Sancho Lerena, slerena@gmail.com
|
# Copyright (c) 2007 Sancho Lerena, slerena@gmail.com
|
||||||
# Copyright (c) 2007 Artica Soluciones Tecnologicas S.L
|
# Copyright (c) 2007 Artica Soluciones Tecnologicas S.L
|
||||||
|
@ -26,7 +26,8 @@ use Date::Manip; # Needed to manipulate DateTime formats
|
||||||
use Time::Local; # DateTime basic manipulation
|
use Time::Local; # DateTime basic manipulation
|
||||||
use Net::Ping; # ICMP
|
use Net::Ping; # ICMP
|
||||||
use NetAddr::IP; # To manage IP Addresses
|
use NetAddr::IP; # To manage IP Addresses
|
||||||
#use IO::Socket; # For TCP/UDP access
|
use POSIX; # to use ceil() function
|
||||||
|
use Socket; # to resolve address
|
||||||
use threads;
|
use threads;
|
||||||
|
|
||||||
# Pandora Modules
|
# Pandora Modules
|
||||||
|
@ -44,9 +45,18 @@ my %pa_config;
|
||||||
# Inicio del bucle principal de programa
|
# Inicio del bucle principal de programa
|
||||||
pandora_init(\%pa_config, "Pandora FMS Recon server");
|
pandora_init(\%pa_config, "Pandora FMS Recon server");
|
||||||
# Read config file for Global variables
|
# Read config file for Global variables
|
||||||
pandora_loadconfig (\%pa_config,3);
|
pandora_loadconfig (\%pa_config, 3);
|
||||||
# Audit server starting
|
# Audit server starting
|
||||||
pandora_audit (\%pa_config, "Pandora FMS Recon Daemon starting", "SYSTEM", "System");
|
pandora_audit (\%pa_config, "Pandora FMS Recon Daemon starting", "SYSTEM", "System");
|
||||||
|
sleep(1);
|
||||||
|
|
||||||
|
# Connect ONCE to Database, we cannot pass DBI handler to all subprocess because
|
||||||
|
# cannot share DBI between threads without use method CLONE.
|
||||||
|
my $pa_config = \%pa_config;
|
||||||
|
my $dbhost = $pa_config->{'dbhost'};
|
||||||
|
my $dbuser = $pa_config->{'dbuser'};
|
||||||
|
my $dbpass = $pa_config->{'dbpass'};
|
||||||
|
my $dbh = DBI->connect("DBI:mysql:pandora:$dbhost:3306", $dbuser, $dbpass, { RaiseError => 1, AutoCommit => 1 });
|
||||||
|
|
||||||
# Daemonize of configured
|
# Daemonize of configured
|
||||||
if ( $pa_config{"daemon"} eq "1" ) {
|
if ( $pa_config{"daemon"} eq "1" ) {
|
||||||
|
@ -56,15 +66,13 @@ if ( $pa_config{"daemon"} eq "1" ) {
|
||||||
|
|
||||||
# Runs main program (have a infinite loop inside)
|
# Runs main program (have a infinite loop inside)
|
||||||
|
|
||||||
threads->new( \&pandora_recon_subsystem, \%pa_config, 1);
|
threads->new( \&pandora_recon_subsystem, \%pa_config);
|
||||||
sleep(1);
|
sleep(1);
|
||||||
#threads->new( \&pandora_network_subsystem, \%pa_config, 2);
|
|
||||||
#sleep(1);
|
|
||||||
#threads->new( \&pandora_network_subsystem, \%pa_config, 3);
|
|
||||||
|
|
||||||
while ( 1 ){
|
while ( 1 ){
|
||||||
sleep(3600);
|
pandora_serverkeepaliver ($pa_config, 3, $dbh);
|
||||||
threads->yield;
|
threads->yield;
|
||||||
|
sleep($pa_config->{"server_threshold"});
|
||||||
}
|
}
|
||||||
|
|
||||||
#------------------------------------------------------------------------------------
|
#------------------------------------------------------------------------------------
|
||||||
|
@ -84,76 +92,128 @@ while ( 1 ){
|
||||||
sub pandora_recon_subsystem {
|
sub pandora_recon_subsystem {
|
||||||
# Init vars
|
# Init vars
|
||||||
my $pa_config = $_[0];
|
my $pa_config = $_[0];
|
||||||
my $nettype = $_[1]; # 1 for ICMP, 2 for TCP/UDO, 3 for SNMP
|
|
||||||
# Connect ONCE to Database, we pass DBI handler to all subprocess.
|
|
||||||
my $dbh = DBI->connect("DBI:mysql:pandora:$pa_config->{'dbhost'}:3306", $pa_config->{'dbuser'}, $pa_config->{'dbpass'}, { RaiseError => 1, AutoCommit => 1 });
|
my $dbh = DBI->connect("DBI:mysql:pandora:$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);
|
||||||
|
threads->new( \&pandora_exec_task, $pa_config, $id_task);
|
||||||
|
# pandora_exec_task ($pa_config, $id_task);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$exec_sql->finish();
|
||||||
|
sleep($pa_config->{"server_threshold"});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
##########################################################################
|
||||||
my $server_id = dame_server_id($pa_config, $pa_config->{'servername'}."_Net", $dbh);
|
# SUB pandora_exec_task (pa_config, id_task)
|
||||||
my $target_network; # Network range defined in database task
|
# Execute task
|
||||||
my $target_mode; # 1 for netmask/bit, 2 for range of IP separated by -
|
##########################################################################
|
||||||
|
sub pandora_exec_task {
|
||||||
|
my $pa_config = $_[0];
|
||||||
|
my $id_task = $_[1];
|
||||||
my $target_ip; # Real ip to check
|
my $target_ip; # Real ip to check
|
||||||
my @ip2; # temp array for NetAddr::IP
|
my @ip2; # temp array for NetAddr::IP
|
||||||
my $space; # temp var to store space of ip's for netaddr::ip
|
my $space; # temp var to store space of ip's for netaddr::ip
|
||||||
my $query_sql; # for use in SQL
|
my $query_sql; # for use in SQL
|
||||||
my $exec_sql; # for use in SQL
|
my $exec_sql; # for use in SQL
|
||||||
my @sql_data; # for use in SQL
|
my @sql_data; # for use in SQL
|
||||||
|
my $dbh = DBI->connect("DBI:mysql:pandora:$pa_config->{'dbhost'}:3306", $pa_config->{'dbuser'}, $pa_config->{'dbpass'}, { RaiseError => 1, AutoCommit => 1 });
|
||||||
|
|
||||||
while ( 1 ) {
|
$query_sql = "SELECT * FROM trecon_task WHERE id_rt = $id_task";
|
||||||
logger ($pa_config, "Loop in Recon Module Subsystem", 10);
|
|
||||||
$query_sql = "SELECT * FROM trecon_task WHERE id_network_server = $server_id ";
|
|
||||||
$exec_sql = $dbh->prepare($query_sql);
|
$exec_sql = $dbh->prepare($query_sql);
|
||||||
$exec_sql ->execute;
|
$exec_sql ->execute;
|
||||||
while (@sql_data = $exec_sql->fetchrow_array()) {
|
if ($exec_sql->rows == 0) {
|
||||||
my $my_timestamp = &UnixDate("today","%Y-%m-%d %H:%M:%S");
|
# something wrong..
|
||||||
my $my_utimestamp = &UnixDate($my_timestamp, "%s"); # convert from human to integer
|
return -1;
|
||||||
my $utimestamp = $sql_data[9];
|
}
|
||||||
|
@sql_data = $exec_sql->fetchrow_array();
|
||||||
my $status = $sql_data[10];
|
my $status = $sql_data[10];
|
||||||
my $interval = $sql_data[11];
|
my $interval = $sql_data[11];
|
||||||
$interval = $interval * 60; # Interval is stored in MINUTES !
|
my $network_server_assigned = $sql_data[12];
|
||||||
$target_network = $sql_data[4];
|
my $target_network = $sql_data[4];
|
||||||
my $id_task = $sql_data[0];
|
my $task_name = $sql_data[1];
|
||||||
my $position = 0;
|
my $position = 0;
|
||||||
# Need to exec this task ?
|
my $task_type = $sql_data[3];
|
||||||
if (($utimestamp + $interval) < $my_utimestamp){
|
my $task_ncprofile = $sql_data[6];
|
||||||
# EXEC TASK and mark as "in progress" != -1
|
my $task_group = $sql_data[8];
|
||||||
pandora_update_reconstatus ($pa_config, $dbh, $id_task, 0);
|
my $task_create_incident = $sql_data[7];
|
||||||
|
my $list_ip = "";
|
||||||
|
my $list_host = "";
|
||||||
|
my $host_found = 0;
|
||||||
|
|
||||||
|
|
||||||
if ( $target_network =~ /[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+\/[0-9]+\z/){
|
|
||||||
$target_mode=1; # Netmask w/bit
|
|
||||||
}
|
|
||||||
elsif ( $target_network =~ /[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+\-[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+\z/){
|
|
||||||
$target_mode=2; # Range of iPs
|
|
||||||
}
|
|
||||||
# Asign target dir to netaddr object "space"
|
# Asign target dir to netaddr object "space"
|
||||||
$space = new NetAddr::IP $target_network;
|
$space = new NetAddr::IP $target_network;
|
||||||
|
if (!defined($space)){
|
||||||
|
logger ($pa_config, "Bad network $target_network for task $task_name", 2);
|
||||||
|
pandora_update_reconstatus ($pa_config, $dbh, $id_task, -1);
|
||||||
|
pandora_task_set_utimestamp ($pa_config, $dbh, $id_task);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
my $total_hosts= $space->num +1 ;
|
my $total_hosts= $space->num +1 ;
|
||||||
# Begin scanning main loop
|
# Begin scanning main loop
|
||||||
do {
|
do {
|
||||||
@ip2 = split(/\//,$space);
|
@ip2 = split(/\//,$space);
|
||||||
$target_ip = $ip2[0];
|
$target_ip = $ip2[0];
|
||||||
$space++;
|
$space++; $position++;
|
||||||
$position++;
|
|
||||||
if (scan_icmp ($target_ip, $pa_config->{'networktimeout'}) == 1){
|
# Check ICMP for this IP
|
||||||
printf ("IP $target_ip VIVA !!! \n");
|
if (($task_type == 1) && (scan_icmp ($target_ip, $pa_config->{'networktimeout'}) == 1)){
|
||||||
|
# Is this IP listed for any agent ?
|
||||||
if (pandora_check_ip ($pa_config, $dbh, $target_ip) == 0){
|
if (pandora_check_ip ($pa_config, $dbh, $target_ip) == 0){
|
||||||
printf (" IP $target_ip NO MONITORIZADA !!! \n");
|
$host_found ++;
|
||||||
} else {
|
my $target_ip_resolved = resolv_ip2name($target_ip);
|
||||||
printf (" IP $target_ip monitorizada\n");
|
$list_ip = $list_ip." ".$target_ip;
|
||||||
|
$list_host = $list_host." ".resolv_ip2name($target_ip_resolved);
|
||||||
|
# If has a network profile, create agent and modules
|
||||||
|
if ($task_ncprofile > 0){
|
||||||
|
# Create address, agent and more...
|
||||||
|
my $target_ip_id = pandora_task_create_address ($pa_config, $dbh, $id_task, $target_ip);
|
||||||
|
my $agent_id = pandora_task_create_agent($pa_config, $dbh, $target_ip, $target_ip_id, $task_group, $network_server_assigned, $target_ip_resolved);
|
||||||
|
pandora_task_create_agentmodules($pa_config, $dbh, $agent_id, $task_ncprofile, $target_ip);
|
||||||
}
|
}
|
||||||
} else {
|
my $title = "[RECON] New host [$target_ip_resolved] detected on network [$target_network]";
|
||||||
printf ("IP $target_ip no contesta \n");
|
# Always create event about this detected IP
|
||||||
|
pandora_event ($pa_config, $title, $task_group, 0, $dbh);
|
||||||
}
|
}
|
||||||
#my $progress = ceil($position / ($total_hosts / 100));
|
}
|
||||||
#pandora_update_reconstatus ($pa_config, $dbh, $id_task, $progress);
|
my $progress = ceil($position / ($total_hosts / 100));
|
||||||
|
pandora_update_reconstatus ($pa_config, $dbh, $id_task, $progress);
|
||||||
} while ($space < $space->broadcast); # fin del buclie principal de iteracion de Ips
|
} while ($space < $space->broadcast); # fin del buclie principal de iteracion de Ips
|
||||||
|
|
||||||
|
# Create incident
|
||||||
|
if (($host_found > 0) && ($task_create_incident == 1)){
|
||||||
|
my $my_timestamp = &UnixDate("today","%Y-%m-%d %H:%M:%S");
|
||||||
|
my $text = "At $my_timestamp a new hosts ($host_found) has been detected by Pandora FMS Recon Server running on [".$pa_config->{'servername'}."_Recon]. This incident has been automatically created following instructions for this recon task [$task_name].\n\n";
|
||||||
|
if ($task_ncprofile > 0){
|
||||||
|
$text = $text."Aditionally, and following instruction for this task, agent(s) has been created, with modules assigned to network component profile [".give_network_component_profile_name ($pa_config, $dbh, $task_ncprofile)."]. Please check this agent as soon as possible to verify it.";
|
||||||
|
}
|
||||||
|
$text = $text . "\n\nThis is the list of IP addresses found: \n\n$list_host ";
|
||||||
|
pandora_create_incident ( $pa_config, $dbh, "[RECON] New hosts detected", $text, 0, 0, "Pandora FMS Recon Server", $task_group);
|
||||||
}
|
}
|
||||||
# Mark RECON TASK as done (-1)
|
# Mark RECON TASK as done (-1)
|
||||||
pandora_update_reconstatus ($pa_config, $dbh, $id_task, -1);
|
pandora_update_reconstatus ($pa_config, $dbh, $id_task, -1);
|
||||||
}
|
pandora_task_set_utimestamp ($pa_config, $dbh, $id_task);
|
||||||
$exec_sql->finish();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
##############################################################################
|
##############################################################################
|
||||||
|
@ -175,6 +235,26 @@ sub scan_icmp {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
##########################################################################
|
||||||
|
# SUB resolv_ip2name (ip_address)
|
||||||
|
# return name (if could resolve) or ip of ipaddress
|
||||||
|
##########################################################################
|
||||||
|
sub resolv_ip2name {
|
||||||
|
my $ip = $_[0];
|
||||||
|
my $addr=inet_aton($ip);
|
||||||
|
if ($addr) {
|
||||||
|
my $name=gethostbyaddr($addr, AF_INET);
|
||||||
|
if ($name) {
|
||||||
|
return $name;
|
||||||
|
} else {
|
||||||
|
return $ip;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return $ip;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
##########################################################################
|
##########################################################################
|
||||||
# SUB pandora_check_ip (pa_config, dbh, ip_address)
|
# SUB pandora_check_ip (pa_config, dbh, ip_address)
|
||||||
# Return 1 if this IP exists, 0 if not
|
# Return 1 if this IP exists, 0 if not
|
||||||
|
@ -197,8 +277,8 @@ sub pandora_check_ip {
|
||||||
}
|
}
|
||||||
|
|
||||||
##########################################################################
|
##########################################################################
|
||||||
# SUB pandora_update_reconstatus (pa_config, dbh, ip_address)
|
# SUB pandora_update_reconstatus (pa_config, dbh, id_task, status)
|
||||||
# Update recontask
|
# Update recontask status flag
|
||||||
##########################################################################
|
##########################################################################
|
||||||
sub pandora_update_reconstatus {
|
sub pandora_update_reconstatus {
|
||||||
my $pa_config = $_[0];
|
my $pa_config = $_[0];
|
||||||
|
@ -207,7 +287,117 @@ sub pandora_update_reconstatus {
|
||||||
my $status = $_[3];
|
my $status = $_[3];
|
||||||
|
|
||||||
my $query_sql2 = "UPDATE trecon_task SET status = $status WHERE id_rt = $id_task";
|
my $query_sql2 = "UPDATE trecon_task SET status = $status WHERE id_rt = $id_task";
|
||||||
my $exec_sql2 = $dbh->prepare($query_sql2);
|
$dbh->do($query_sql2);
|
||||||
$exec_sql2 -> execute;
|
|
||||||
$exec_sql2 -> finish();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
##########################################################################
|
||||||
|
# SUB pandora_task_set_utimestamp (pa_config, dbh, id_task)
|
||||||
|
# Update utimestamp to current timestamp
|
||||||
|
##########################################################################
|
||||||
|
sub pandora_task_set_utimestamp {
|
||||||
|
my $pa_config = $_[0];
|
||||||
|
my $dbh = $_[1];
|
||||||
|
my $id_task = $_[2];
|
||||||
|
my $my_timestamp = &UnixDate("today","%Y-%m-%d %H:%M:%S");
|
||||||
|
my $my_utimestamp = &UnixDate($my_timestamp, "%s"); # convert from human to integer
|
||||||
|
|
||||||
|
my $query_sql2 = "UPDATE trecon_task SET utimestamp = '$my_utimestamp' WHERE id_rt = $id_task";
|
||||||
|
$dbh->do($query_sql2);
|
||||||
|
}
|
||||||
|
|
||||||
|
##########################################################################
|
||||||
|
# SUB pandora_task_create_address (pa_config, dbh, id_task, address)
|
||||||
|
# Add address to table taddress, return ID of created record
|
||||||
|
##########################################################################
|
||||||
|
sub pandora_task_create_address {
|
||||||
|
my $pa_config = $_[0];
|
||||||
|
my $dbh = $_[1];
|
||||||
|
my $id_task = $_[2];
|
||||||
|
my $ip_address = $_[3];
|
||||||
|
my $query_sql2 = "INSERT INTO taddress (ip) VALUES ('$ip_address')";
|
||||||
|
$dbh->do ($query_sql2);
|
||||||
|
my $lastid = $dbh->{'mysql_insertid'};
|
||||||
|
return $lastid;
|
||||||
|
}
|
||||||
|
|
||||||
|
##########################################################################
|
||||||
|
# SUB pandora_task_create_agent (pa_config, dbh, target_ip, target_ip_id,
|
||||||
|
# id_group, network_server_assigned, name)
|
||||||
|
# Create agent, and associate address to agent in taddress_agent table.
|
||||||
|
# it returns created id_agent.
|
||||||
|
##########################################################################
|
||||||
|
sub pandora_task_create_agent {
|
||||||
|
my $pa_config = $_[0];
|
||||||
|
my $dbh = $_[1];
|
||||||
|
my $target_ip = $_[2];
|
||||||
|
my $target_ip_id = $_[3];
|
||||||
|
my $id_group = $_[4];
|
||||||
|
my $id_server= $_[5];
|
||||||
|
my $name = $_[6];
|
||||||
|
|
||||||
|
logger($pa_config,"Recon Server: Creating agent for ip $target_ip ",2);
|
||||||
|
my $query_sql2 = "INSERT INTO tagente (nombre, direccion, comentarios, id_grupo, id_os, agent_type, id_server, intervalo) VALUES ('$name', '$target_ip', 'Autogenerated by Pandora FMS Recon Server', $id_group, 11, 1, $id_server, 300)";
|
||||||
|
$dbh->do ($query_sql2);
|
||||||
|
my $lastid = $dbh->{'mysql_insertid'};
|
||||||
|
my $query_sql3 = "INSERT INTO taddress_agent (id_a, id_agent) values ($target_ip_id, $lastid)";
|
||||||
|
$dbh->do($query_sql3);
|
||||||
|
return $lastid;
|
||||||
|
}
|
||||||
|
|
||||||
|
##########################################################################
|
||||||
|
# SUB pandora_task_create_agentmodules (pa_config, dbh, agent_id, ncprofile, ipaddress)
|
||||||
|
# Create modules from a network component profile and associated to given agent
|
||||||
|
##########################################################################
|
||||||
|
sub pandora_task_create_agentmodules {
|
||||||
|
my $pa_config = $_[0];
|
||||||
|
my $dbh = $_[1];
|
||||||
|
my $agent_id = $_[2];
|
||||||
|
my $ncprofile_id = $_[3];
|
||||||
|
my $ip_adress = $_[4];
|
||||||
|
my @sql_data;
|
||||||
|
|
||||||
|
# Search each network component that belongs to ncprofile_id
|
||||||
|
my $query_sql = "SELECT * FROM tnetwork_profile_component where id_np = $ncprofile_id ";
|
||||||
|
my $exec_sql = $dbh->prepare($query_sql);
|
||||||
|
$exec_sql ->execute;
|
||||||
|
while (@sql_data = $exec_sql->fetchrow_array()) {
|
||||||
|
my $id_nc = $sql_data[1];
|
||||||
|
my $query_sql2 = "SELECT * FROM tnetwork_component where id_nc = $id_nc ";
|
||||||
|
my $exec_sql2 = $dbh->prepare($query_sql2);
|
||||||
|
$exec_sql2 ->execute;
|
||||||
|
if ($exec_sql2->rows != 0) {
|
||||||
|
my @sql_data2 = $exec_sql2->fetchrow_array();
|
||||||
|
my $name = "";
|
||||||
|
$name = $sql_data2[1];
|
||||||
|
my $description = "Autocreated by Pandora FMS Recon Server";
|
||||||
|
$description = $sql_data2[2];
|
||||||
|
my $type = "1";
|
||||||
|
$type = $sql_data2[4];
|
||||||
|
my $max = 0;
|
||||||
|
$max = $sql_data2[5];
|
||||||
|
my $min = 0;
|
||||||
|
$min = $sql_data2[6];
|
||||||
|
my $interval = 300;
|
||||||
|
$interval = $sql_data2[7];
|
||||||
|
my $tcp_port = "";
|
||||||
|
$tcp_port = $sql_data2[8];
|
||||||
|
my $tcp_send = "";
|
||||||
|
$tcp_send = $sql_data2[9];
|
||||||
|
my $tcp_rcv = "";
|
||||||
|
$tcp_rcv = $sql_data2[10];
|
||||||
|
my $snmp_community = "public";
|
||||||
|
$snmp_community = $sql_data2[11];
|
||||||
|
my $snmp_oid = "";
|
||||||
|
$snmp_oid = $sql_data2[12];
|
||||||
|
my $id_module_group = 0;
|
||||||
|
$id_module_group = $sql_data2[13];
|
||||||
|
|
||||||
|
my $query_sql3 = "INSERT INTO tagente_modulo (id_agente, id_tipo_modulo, descripcion, nombre, max, min, module_interval, tcp_port, tcp_send, tcp_rcv, snmp_community, snmp_oid, ip_target, id_module_group, flag ) VALUES ( $agent_id, $type, '$description', '$name', $max, $min, $interval, $tcp_port, '$tcp_send', '$tcp_rcv', '$snmp_community', '$snmp_oid', '$ip_adress', $id_module_group, 1)";
|
||||||
|
$dbh->do($query_sql3);
|
||||||
|
logger($pa_config,"Recon Server: Creating module $name for agent $ip_adress",3);
|
||||||
|
}
|
||||||
|
$exec_sql2->finish();
|
||||||
|
}
|
||||||
|
$exec_sql->finish();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -61,7 +61,7 @@ dataserver 1
|
||||||
reconserver 1
|
reconserver 1
|
||||||
|
|
||||||
# Network timeout (in seconds) for timeout in network connections for Network agents
|
# Network timeout (in seconds) for timeout in network connections for Network agents
|
||||||
network_timeout 2
|
network_timeout 5
|
||||||
|
|
||||||
# Server keepalive (in seconds)
|
# Server keepalive (in seconds)
|
||||||
server_keepalive 45
|
server_keepalive 45
|
||||||
|
|
|
@ -0,0 +1,66 @@
|
||||||
|
#!/bin/sh
|
||||||
|
# Pandora FMS Recon Server, startup script
|
||||||
|
# Sancho Lerena, <slerena@gmail.com>
|
||||||
|
# Linux Version (generic)
|
||||||
|
# v1.3 (Mar/2007)
|
||||||
|
|
||||||
|
# Configurable path and filenames
|
||||||
|
PANDORA_HOME="/opt/pandora_server"
|
||||||
|
PANDORA_PID="$PANDORA_HOME/var/pandora_recon.pid"
|
||||||
|
|
||||||
|
# Main script
|
||||||
|
|
||||||
|
if [ ! -f $PANDORA_HOME/bin/pandora_recon.pl ]
|
||||||
|
then
|
||||||
|
echo "Pandora FMS Recon Server not found, please check setup and read manual"
|
||||||
|
exit
|
||||||
|
fi
|
||||||
|
|
||||||
|
case "$1" in
|
||||||
|
start)
|
||||||
|
OLD_PATH="`pwd`"
|
||||||
|
if [ -f $PANDORA_PID ]
|
||||||
|
then
|
||||||
|
PID_2=`cat $PANDORA_PID`
|
||||||
|
if [ ! -z "`ps -F -p $PID_2 | grep -v grep | grep 'pandora_recon.pl'`" ]
|
||||||
|
then
|
||||||
|
echo "Pandora FMS Recon Server is currently running on this machine. Aborting now..."
|
||||||
|
exit
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
cd $PANDORA_HOME/bin
|
||||||
|
./pandora_recon.pl $PANDORA_HOME -D
|
||||||
|
MYPID=`ps aux | grep 'pandora_recon.pl' | grep -v grep | tail -1 | awk '{print $2}'`
|
||||||
|
if [ ! -z "$MYPID" ]
|
||||||
|
then
|
||||||
|
echo $MYPID > $PANDORA_PID
|
||||||
|
echo "Pandora FMS Recon Server is now running with PID $MYPID"
|
||||||
|
else
|
||||||
|
echo "Cannot start Pandora FMS Recon Server. Aborted"
|
||||||
|
fi
|
||||||
|
cd "$OLD_PATH"
|
||||||
|
;;
|
||||||
|
stop)
|
||||||
|
if [ -f $PANDORA_PID ]
|
||||||
|
then
|
||||||
|
echo "Stopping Pandora FMS Recon Server"
|
||||||
|
PID_2=`cat $PANDORA_PID`
|
||||||
|
if [ ! -z "`ps -F -p $PID_2 | grep -v grep | grep 'pandora_recon.pl'`" ]
|
||||||
|
then
|
||||||
|
kill `cat $PANDORA_PID` 2> /dev/null > /dev/null
|
||||||
|
fi
|
||||||
|
rm -f $PANDORA_PID
|
||||||
|
else
|
||||||
|
echo "Pandora FMS Recon Server is not running, cannot stop it."
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
force-reload|restart)
|
||||||
|
$0 stop
|
||||||
|
$0 start
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "Usage: pandora_recon {start|stop|restart}"
|
||||||
|
exit 1
|
||||||
|
esac
|
||||||
|
|
|
@ -19,8 +19,8 @@
|
||||||
################################################################################
|
################################################################################
|
||||||
|
|
||||||
my $target_interval = 300;
|
my $target_interval = 300;
|
||||||
my $target_days = 7;
|
my $target_days = 30 ;
|
||||||
my $target_agent = -1; # if -1, uses ALL agents
|
my $target_agent = 640; # if -1, uses ALL agents
|
||||||
|
|
||||||
################################################################################
|
################################################################################
|
||||||
################################################################################
|
################################################################################
|
||||||
|
|
Loading…
Reference in New Issue