Add support for temporal_max_size and temporal_max_files.

temporal_max_size sets a limit for the size (in MB) of the agent's XML buffer.
temporal_max_files sets a limit for the number of files in the agent's XML buffer.
This commit is contained in:
Ramon Novoa 2022-09-14 17:12:08 +02:00
parent 06be85e044
commit 5f6d7b2a8f
5 changed files with 131 additions and 15 deletions

View File

@ -165,9 +165,15 @@ remote_config 0
# should consider changing the temporal directory, since /tmp is world writable.
xml_buffer 1
# Minimum available bytes in the temporal directory to enable the XML buffer
# Minimum available megabytes in the temporal directory to enable the XML buffer
temporal_min_size 1024
# Maximum size (in megabytes) allowed for the XML buffer.
temporal_max_size 1024
# Maximum number of files allowed for the XML buffer.
temporal_max_files 1024
# Agent mode: Learn (default), No-learn, Autodisable
# agent_mode autodisable

View File

@ -1145,7 +1145,9 @@ my %DefaultConf = (
'secondary_server_opts' => '',
'secondary_temporal' => '/var/spool/pandora',
'autotime' => 0,
'temporal_min_size' => 1,
'temporal_min_size' => 1024,
'temporal_max_files' => 1024,
'temporal_max_size' => 1024,
'timezone_offset' => 0,
'pandora_exec' => 'pandora_agent_exec',
'agent_threads' => 1,
@ -2110,13 +2112,13 @@ sub send_xml_file ($) {
swap_servers();
# Secondary buffer.
if ($rc_sec != 0 && $Conf{'xml_buffer'} == 1 && temporal_freedisk () > $Conf{'temporal_min_size'}) {
if ($rc_sec != 0 && write_to_buffer($Conf{'secondary_temporal'}) == 1) {
copy($file, $Conf{'secondary_temporal'}) || die("Error copying file $file to " . $Conf{'secondary_temporal'} . ": $!");
}
}
# Primary buffer.
if ($rc == 0 || $Conf{'xml_buffer'} == 0 || temporal_freedisk () <= $Conf{'temporal_min_size'}) {
if ($rc == 0 || write_to_buffer($Conf{'temporal'}) == 0) {
if ($Conf{'debug'} eq '1') {
rename($file, $file . "sent");
} else {
@ -3761,20 +3763,45 @@ sub kill_signal_handler (){
}
################################################################################
# Get the free disk space in the temporal directory (in bytes).
# Get the free disk space in the temporal directory (in megabytes).
################################################################################
sub temporal_freedisk () {
sub temporal_freedisk {
my ($temporal) = @_;
# Call df
return 0 unless defined (DF_CMDS->{$OS});
my $cmd = DF_CMDS->{$OS} . ' ' . $Conf{'temporal'} . ' | awk \'NR > 1 {print $4}\'';
my $cmd = DF_CMDS->{$OS} . ' ' . $temporal . ' | awk \'NR > 1 {print $4}\'';
my $temporal_freedisk = `$cmd`;
# Check for errors
return 0 unless ($? eq 0);
# Convert to bytes
return 1024 * int ($temporal_freedisk);
# Convert from KB to MB.
return $temporal_freedisk / 1024;
}
################################################################################
# Return the number of data files in the temporal directory and their total
# size (in megabytes).
################################################################################
sub temporal_stats {
my ($temporal) = @_;
my $file_count = 0;
my $file_size = 0;
opendir(my $dir, $temporal) or die($!);
while (my $f = readdir($dir)) {
if ($f =~ m/.data$/ || $f =~ m/.datasent$/) {
$file_count += 1;
$file_size += (stat $temporal . '/' . $f)[7];
}
}
closedir($dir);
# Convert from B to MB.
$file_size /= 1048576;
return ($file_count, $file_size);
}
################################################################################
@ -3960,6 +3987,27 @@ sub get_ehkey {
return '';
}
################################################################################
# Return 1 if XML files should be written to the buffer. 0 otherwise.
################################################################################
sub write_to_buffer {
my ($temporal) = @_;
# The XML buffer is disabled.
return 0 if ($Conf{'xml_buffer'} == 0);
# Check available disk space.
return 0 if ($Conf{'temporal_min_size'} != 0 && temporal_freedisk($temporal) < $Conf{'temporal_min_size'});
# Check buffer file count and size limits.
my ($file_count, $file_size) = temporal_stats($temporal);
return 0 if ($Conf{'temporal_max_files'} != 0 && $file_count > $Conf{'temporal_max_files'});
return 0 if ($Conf{'temporal_max_size'} != 0 && $file_size > $Conf{'temporal_max_size'});
# It's OK to write to the buffer.
return 1;
}
################################################################################
# Main.
################################################################################

View File

@ -55,9 +55,15 @@ address auto
# or setting a fixed IP address, like for example:
#address 192.168.36.73
# This limits operation if temporal dir has not enough free disk.
# This limits operation if temporal dir has not enough free disk (in megabytes).
#temporal_min_size 1024
# Maximum size (in megabytes) allowed for the XML buffer.
temporal_max_size 1024
# Maximum number of files allowed for the XML buffer.
temporal_max_files 1024
# Delay start execution X second before start to monitoring nothing
#startup_delay 30

View File

@ -1705,12 +1705,10 @@ Pandora_Windows_Service::sendXml (Pandora_Module_List *modules, string extra /*
string ehorus_conf, eh_key;
static HANDLE mutex = 0;
ULARGE_INTEGER free_bytes;
double min_free_bytes = 0;
Pandora_Agent_Conf *conf = NULL;
FILE *conf_fh = NULL;
conf = this->getConf ();
min_free_bytes = 1024 * atoi (conf->getValue ("temporal_min_size").c_str ());
xml_buffer = atoi (conf->getValue ("xml_buffer").c_str ());
if (mutex == 0) {
@ -1814,14 +1812,14 @@ Pandora_Windows_Service::sendXml (Pandora_Module_List *modules, string extra /*
rc_sec = this->copyToSecondary (tmp_filename, false);
/* Secondary buffer. */
if (rc_sec != 0 && xml_buffer == 1 && (GetDiskFreeSpaceEx (conf->getValue ("secondary_temporal").c_str (), &free_bytes, NULL, NULL) != 0 && free_bytes.QuadPart >= min_free_bytes)) {
if (rc_sec != 0 && this->writeToBuffer(conf->getValue ("secondary_temporal").c_str ())) {
secondary_filepath = conf->getValue ("secondary_temporal") + "\\" + tmp_filename;
CopyFile (tmp_filepath.c_str(), secondary_filepath.c_str(), false);
}
}
/* Primary buffer. Delete the file if successfully copied, buffer disabled or not enough space available. */
if (rc == 0 || xml_buffer == 0 || (GetDiskFreeSpaceEx (tmp_filepath.c_str (), &free_bytes, NULL, NULL) != 0 && free_bytes.QuadPart < min_free_bytes)) {
if (rc == 0 || !writeToBuffer(conf->getValue ("temporal").c_str ())) {
/* Rename the file if debug mode is enabled*/
if (getPandoraDebug ()) {
string tmp_filepath_sent = tmp_filepath;
@ -2218,3 +2216,60 @@ Pandora_Windows_Service::generateAgentName () {
sha256(data.str().c_str(), digest);
return std::string(digest);
}
bool
Pandora_Windows_Service::writeToBuffer (string temporal) {
int xml_buffer;
long int temporal_max_files;
double temporal_min_size, temporal_max_size;
string dir, file_name;
ULARGE_INTEGER free_bytes;
Pandora_Agent_Conf *conf = NULL;
conf = this->getConf ();
dir = temporal;
if (dir[dir.length () - 1] != '\\') {
dir += "\\";
}
file_name = dir + "*.data";
// Is the XML buffer disabled?
xml_buffer = atoi (conf->getValue ("xml_buffer").c_str ());
if (xml_buffer == 0) {
return false;
}
// Check available disk space.
temporal_min_size = atoi (conf->getValue ("temporal_min_size").c_str ());
if (GetDiskFreeSpaceEx (dir.c_str (), &free_bytes, NULL, NULL) && (free_bytes.QuadPart / 1048576) < temporal_min_size) { // Convert free_bytes.QuadPart from B to MB.
pandoraLog ("[writeToBuffer] Disk full.");
return false;
}
// Check buffer file count and size limits.
temporal_max_size = atoi (conf->getValue ("temporal_max_size").c_str ());
temporal_max_files = atol (conf->getValue ("temporal_max_files").c_str ());
if (temporal_max_size != 0 || temporal_max_files != 0) {
long int file_count = 0;
ULONGLONG file_size = 0;
HANDLE hFind;
WIN32_FIND_DATA FindFileData;
if ((hFind = FindFirstFile(file_name.c_str(), &FindFileData)) != INVALID_HANDLE_VALUE) {
do {
file_count += 1;
file_size += (FindFileData.nFileSizeHigh * (MAXDWORD + 1)) + FindFileData.nFileSizeLow;
} while (FindNextFile(hFind, &FindFileData));
FindClose(hFind);
}
file_size /= 1048576; // Convert from B to MB.
if ((temporal_max_size != 0 && file_size > temporal_max_size) ||
(temporal_max_files != 0 && file_count > temporal_max_files)) {
pandoraLog ("[writeToBuffer] Too many files or buffer full.");
return false;
}
}
return true;
}

View File

@ -124,6 +124,7 @@ namespace Pandora {
long getInterval ();
long getIntensiveInterval ();
string generateAgentName ();
bool writeToBuffer (string temporal);
};
}