WIP multiple changes

This commit is contained in:
fbsanchez 2020-03-16 23:52:20 +01:00
parent ce11d89953
commit f3da919abc
20 changed files with 1934 additions and 524 deletions

View File

@ -1,5 +1,35 @@
START TRANSACTION;
ALTER TABLE trecon_task modify column `id_network_profile` text;
ALTER TABLE trecon_task MODIFY COLUMN `id_network_profile` TEXT;
ALTER TABLE `trecon_task` CHANGE COLUMN `create_incident` `direct_report` TINYINT(1) UNSIGNED DEFAULT 0;
UPDATE `trecon_task` SET `direct_report` = 1;
COMMIT;
CREATE TABLE `tdiscovery_tmp_agents` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`id_rt` int(10) unsigned NOT NULL,
`label` varchar(600) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL DEFAULT '',
`data` text,
`review_date` datetime DEFAULT NULL,
`created` int(1) unsigned NOT NULL DEFAULT '0',
PRIMARY KEY (`id`),
KEY `id_rt` (`id_rt`),
INDEX `label` (`label`),
CONSTRAINT `tdta_trt` FOREIGN KEY (`id_rt`) REFERENCES `trecon_task` (`id_rt`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `tdiscovery_tmp_connections` (
`id_rt` int(10) unsigned NOT NULL,
`id1` int(10) unsigned NOT NULL AUTO_INCREMENT,
`id2` int(10) unsigned NOT NULL,
`if1` text,
`if2` text,
PRIMARY KEY (`id1`,`id2`),
CONSTRAINT `tdtc_trt` FOREIGN KEY (`id_rt`)
REFERENCES `trecon_task` (`id_rt`) ON DELETE CASCADE ON UPDATE CASCADE,
CONSTRAINT `tdtc_tdta1` FOREIGN KEY (`id1`)
REFERENCES `tdiscovery_tmp_agents` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
CONSTRAINT `tdtc_tdta2` FOREIGN KEY (`id2`)
REFERENCES `tdiscovery_tmp_agents` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
COMMIT;

View File

@ -1657,22 +1657,42 @@ ALTER TABLE `trecon_task` ADD COLUMN `type` int(11) NOT NULL DEFAULT '0',
MODIFY COLUMN `auth_strings` text NULL,
MODIFY COLUMN `autoconfiguration_enabled` tinyint(1) unsigned NULL DEFAULT '0',
MODIFY COLUMN `summary` text NULL,
MODIFY COLUMN `id_network_profile` text;
MODIFY COLUMN `id_network_profile` text,
CHANGE COLUMN `create_incident` `direct_report` TINYINT(1) UNSIGNED DEFAULT 0;
-- Old recon always report.
UPDATE `trecon_task` SET `direct_report` = 1;
-- ----------------------------------------------------------------------
-- Table `tdiscovery_tmp`
-- ----------------------------------------------------------------------
CREATE TABLE IF NOT EXISTS `tdiscovery_tmp` (
`id` int(10) unsigned NOT NULL auto_increment,
`id_rt` int(10) unsigned NOT NULL,
`label` varchar(600) BINARY NOT NULL default '',
`data` text,
`review_date` datetime,
`created` int(1) unsigned NOT NULL default 0,
PRIMARY KEY (`id`),
FOREIGN KEY (`id_rt`) REFERENCES `trecon_task`(`id_rt`)
ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `tdiscovery_tmp_agents` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`id_rt` int(10) unsigned NOT NULL,
`label` varchar(600) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL DEFAULT '',
`data` text,
`review_date` datetime DEFAULT NULL,
`created` int(1) unsigned NOT NULL DEFAULT '0',
PRIMARY KEY (`id`),
KEY `id_rt` (`id_rt`),
INDEX `label` (`label`),
CONSTRAINT `tdta_trt` FOREIGN KEY (`id_rt`) REFERENCES `trecon_task` (`id_rt`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `tdiscovery_tmp_connections` (
`id_rt` int(10) unsigned NOT NULL,
`id1` int(10) unsigned NOT NULL AUTO_INCREMENT,
`id2` int(10) unsigned NOT NULL,
`if1` text,
`if2` text,
PRIMARY KEY (`id1`,`id2`),
CONSTRAINT `tdtc_trt` FOREIGN KEY (`id_rt`)
REFERENCES `trecon_task` (`id_rt`) ON DELETE CASCADE ON UPDATE CASCADE,
CONSTRAINT `tdtc_tdta1` FOREIGN KEY (`id1`)
REFERENCES `tdiscovery_tmp_agents` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
CONSTRAINT `tdtc_tdta2` FOREIGN KEY (`id2`)
REFERENCES `tdiscovery_tmp_agents` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- ---------------------------------------------------------------------
-- Table `twidget` AND Table `twidget_dashboard`

View File

@ -48,6 +48,9 @@ function get_wiz_class($str)
case 'ctask':
return 'ConsoleTasks';
case 'deploymentCenter':
return 'DeploymentCenter';
default:
// Main, show header.
ui_print_page_header(
@ -124,13 +127,28 @@ $classname_selected = get_wiz_class($wiz_in_use);
// Else: class not found pseudo exception.
if ($classname_selected !== null) {
$wiz = new $classname_selected($page);
$result = $wiz->run();
if (is_array($result) === true) {
// Redirect control and messages to DiscoveryTasklist.
$classname_selected = 'DiscoveryTaskList';
$wiz = new $classname_selected($page);
$result = $wiz->run($result['msg'], $result['result']);
$wiz = new $classname_selected((int) $page);
// AJAX controller.
if (is_ajax()) {
$method = get_parameter('method');
if (method_exists($wiz, $method) === true) {
$wiz->{$method}();
} else {
$wiz->error('Method not found. ['.$method.']');
}
// Stop any execution.
exit;
} else {
$result = $wiz->run();
if (is_array($result) === true) {
// Redirect control and messages to DiscoveryTasklist.
$classname_selected = 'DiscoveryTaskList';
$wiz = new $classname_selected($page);
$result = $wiz->run($result['msg'], $result['result']);
}
}
}

View File

@ -26,7 +26,9 @@
* ============================================================================
*/
require_once __DIR__.'/Wizard.main.php';
global $config;
require_once $config['homedir'].'/include/class/HTML.class.php';
require_once $config['homedir'].'/include/functions_users.php';
require_once $config['homedir'].'/include/functions_reports.php';
require_once $config['homedir'].'/include/functions_cron.php';
@ -34,11 +36,13 @@ enterprise_include_once('include/functions_tasklist.php');
enterprise_include_once('include/functions_cron.php');
ui_require_css_file('task_list');
ui_require_css_file('simTree');
ui_require_javascript_file('simTree');
/**
* Defined as wizard to guide user to explore running tasks.
*/
class DiscoveryTaskList extends Wizard
class DiscoveryTaskList extends HTML
{
@ -454,11 +458,20 @@ class DiscoveryTaskList extends Wizard
if ($task['disabled'] == 0 && $server_name !== '') {
if (check_acl($config['id_user'], 0, 'AW')) {
$data[0] = '<a href="'.ui_get_full_url(
$data[0] = '<span class="link" onclick="force_task(\'';
$data[0] .= ui_get_full_url(
'index.php?sec=gservers&sec2=godmode/servers/discovery&wiz=tasklist&server_id='.$id_server.'&force='.$task['id_rt']
).'">';
);
$data[0] .= '\'';
if ($task['type'] == DISCOVERY_HOSTDEVICES) {
$title = __('Are you sure?');
$message = 'This action will rescan the target networks.';
$data[0] .= ', {title: \''.$title.'\', message: \''.$message.'\'}';
}
$data[0] .= ');" >';
$data[0] .= html_print_image('images/target.png', true, ['title' => __('Force')]);
$data[0] .= '</a>';
$data[0] .= '</span>';
}
} else if ($task['disabled'] == 2) {
$data[0] = ui_print_help_tip(
@ -472,12 +485,12 @@ class DiscoveryTaskList extends Wizard
// Name task.
$data[1] = '';
if ($task['disabled'] != 2) {
$data[1] .= '<a href="#" onclick="progress_task_list('.$task['id_rt'].',\''.$task['name'].'\')">';
$data[1] .= '<span class="link" onclick="progress_task_list('.$task['id_rt'].',\''.$task['name'].'\')">';
}
$data[1] .= '<b>'.$task['name'].'</b>';
if ($task['disabled'] != 2) {
$data[1] .= '</a>';
$data[1] .= '</span>';
}
$data[2] = $server_name;
@ -496,10 +509,20 @@ class DiscoveryTaskList extends Wizard
$data[4] = '-';
}
if ($task['status'] <= 0) {
$data[5] = __('Done');
if ($task['direct_report'] == 1) {
if ($task['status'] <= 0) {
$data[5] = __('Done');
} else {
$data[5] = __('Pending');
}
} else {
$data[5] = __('Pending');
if ($task['status'] <= 0) {
$data[5] = '<span class="link review" onclick="show_review('.$task['id_rt'].',\''.$task['name'].'\')">';
$data[5] .= __('Review');
$data[5] .= '</span>';
} else {
$data[5] = __('Searching');
}
}
switch ($task['type']) {
@ -595,7 +618,28 @@ class DiscoveryTaskList extends Wizard
if ($task['status'] <= 0 || $task['status'] > 100) {
$data[7] = '-';
} else {
$data[7] = ui_progress($task['status'], '100%', 1.5);
$data[7] = ui_progress(
$task['status'],
'100%',
1.9,
// Color.
'#82b92e',
// Return.
true,
// Text.
'',
// Ajax.
[
'page' => 'godmode/servers/discovery',
'interval' => 10,
'simple' => 1,
'data' => [
'wiz' => 'tasklist',
'id' => $task['id_rt'],
'method' => 'task_progress',
],
]
);
}
if ($task['utimestamp'] > 0) {
@ -700,9 +744,15 @@ class DiscoveryTaskList extends Wizard
// Div neccesary for modal map task.
echo '<div id="map_task" style="display:none"></div>';
echo '<div id="task_review" style="display:none"></div>';
echo '<div id="msg" style="display:none"></div>';
echo '<input type="hidden" id="ajax-url" value="'.ui_get_full_url('ajax.php').'"/>';
echo '<input type="hidden" id="success-str" value="'.__('Success').'"/>';
echo '<input type="hidden" id="failed-str" value="'.__('Failed').'"/>';
unset($table);
ui_require_javascript_file('pandora_ui');
ui_require_javascript_file('pandora_taskList');
return $return;
@ -787,4 +837,333 @@ class DiscoveryTaskList extends Wizard
}
/**
* Returns percent of completion of target task.
*
* @return void
*/
public function task_progress()
{
if (!is_ajax()) {
return '';
}
$id_task = get_parameter('id', 0);
if ($id_task <= 0) {
echo json_encode(['error' => true]);
return;
}
$status = db_get_value('status', 'trecon_task', 'id_rt', $id_task);
if ($status < 0) {
$status = 100;
}
echo json_encode($status);
}
/**
* Generates charts for progress popup.
*
* @param array $task Task.
*
* @return string Charts in HTML.
*/
private function progress_task_graph($task)
{
$result .= '<div style="display: flex;">';
$result .= '<div style="width: 100%; text-align: center; margin-top: 40px;">';
$result .= '<span style="font-size: 1.9em; font-family: "lato-bolder", "Open Sans", sans-serif !important;">'._('Overall Progress').'</span>';
$result .= '<div style="margin-top: 25px;">';
$result .= progress_circular_bar(
$task['id_rt'],
($task['status'] < 0) ? 100 : $task['status'],
200,
200,
'#7eb641',
'%',
'',
'#3A3A3A',
0
);
$result .= '</div>';
if ($task['status'] > 0) {
switch ($task['stats']['step']) {
case STEP_SCANNING:
$str = __('Scanning network');
break;
case STEP_AFT:
$str = __('Finding AFT connectivity');
break;
case STEP_TRACEROUTE:
$str = __('Finding traceroute connectivity');
break;
case STEP_GATEWAY:
$str = __('Finding gateway connectivity');
break;
case STEP_STATISTICS:
$str = __('Searching for devices...');
break;
case STEP_APP_SCAN:
$str = __('Analyzing application...');
break;
case STEP_CUSTOM_QUERIES:
$str = __('Executing custom queries...');
break;
default:
$str = '';
break;
}
$result .= '</div>';
$result .= '<div style="width: 100%; text-align: center; margin-top: 40px;">';
$result .= '<span style="font-size: 1.9em; font-family: "lato-bolder", "Open Sans", sans-serif !important;">'.$str.' ';
if (!empty($str)) {
$result .= $task['stats']['c_network_name'];
}
$result .= '</span>';
$result .= '<div style="margin-top: 25px;">';
$result .= progress_circular_bar(
$task['id_rt'].'_detail',
$task['stats']['c_network_percent'],
200,
200,
'#7eb641',
'%',
'',
'#3A3A3A',
0
);
$result .= '</div></div>';
}
$result .= '</div></div>';
return $result;
}
/**
* Generates a summary table for given task.
*
* @param array $task Task.
*
* @return html code with summary.
*/
private function progress_task_summary($task)
{
global $config;
include_once $config['homedir'].'/include/graphs/functions_d3.php';
if (is_array($task) === false) {
return '';
}
$output = '';
if (is_array($task['stats'])) {
$i = 0;
$table = new StdClasS();
$table->class = 'databox data';
$table->width = '75%';
$table->styleTable = 'margin: 2em auto 0;border: 1px solid #ddd;background: white;';
$table->rowid = [];
$table->data = [];
// Content.
$table->data[$i][0] = '<b>'.__('Hosts discovered').'</b>';
$table->data[$i][1] = '<span id="discovered">';
$table->data[$i][1] .= $task['stats']['summary']['discovered'];
$table->data[$i++][1] .= '</span>';
$table->data[$i][0] = '<b>'.__('Alive').'</b>';
$table->data[$i][1] = '<span id="alive">';
$table->data[$i][1] .= $task['stats']['summary']['alive'];
$table->data[$i++][1] .= '</span>';
$table->data[$i][0] = '<b>'.__('Not alive').'</b>';
$table->data[$i][1] = '<span id="not_alive">';
$table->data[$i][1] .= $task['stats']['summary']['not_alive'];
$table->data[$i++][1] .= '</span>';
$table->data[$i][0] = '<b>'.__('Responding SNMP').'</b>';
$table->data[$i][1] = '<span id="SNMP">';
$table->data[$i][1] .= $task['stats']['summary']['SNMP'];
$table->data[$i++][1] .= '</span>';
$table->data[$i][0] = '<b>'.__('Responding WMI').'</b>';
$table->data[$i][1] = '<span id="WMI">';
$table->data[$i][1] .= $task['stats']['summary']['WMI'];
$table->data[$i++][1] .= '</span>';
$output = '<div style="margin-top: 40px; text-align: center;"><span style="font-size: 1.9em; font-family: "lato-bolder", "Open Sans", sans-serif !important;">'.__('Summary').'</span></div>';
$output .= html_print_table($table, true).'</div>';
}
return $output;
}
/**
* Content of modal 'task progress', ajax only.
*
* @return void
*/
public function progress_task_discovery()
{
if (!is_ajax()) {
return;
}
$id_task = get_parameter('id', 0);
if ($id_task <= 0) {
echo json_encode(['error' => true]);
return;
}
$task = db_get_row('trecon_task', 'id_rt', $id_task);
$task['stats'] = json_decode($task['summary'], true);
$global_progress = $task['status'];
$summary = $this->progress_task_summary($task);
$output = '';
// Header information.
if ((int) $task['status'] <= 0 && empty($summary)) {
$output .= ui_print_info_message(
__('This task has never executed'),
'',
true
);
} else if ($task['status'] == 1
|| ($task['utimestamp'] == 0 && $task['interval_sweep'])
) {
$output .= ui_print_info_message(
__('Task queued, please wait.'),
'',
true
).'</div>';
} else {
$output .= $this->progress_task_graph($task);
}
$output .= $summary;
echo json_encode(['html' => $output]);
}
/**
* Get a map of target task.
*
* @return void
*/
public function task_showmap()
{
global $config;
include_once $config['homedir'].'/include/class/NetworkMap.class.php';
$id_task = get_parameter('id', 0);
$map = new NetworkMap(
[
'id_task' => $id_task,
'pure' => 1,
'widget' => true,
]
);
$map->printMap();
}
/**
* Shows a modal to review results found by discovery task.
*
* @return void
*/
public function show_task_review()
{
$id_task = get_parameter('id', 0);
if ($id_task <= 0) {
ui_print_error_message(__('Invalid task'));
return;
}
$task = db_get_row('tdiscovery_tmp_agents', 'id_rt', $id_task);
if (is_array($task)) {
$data = json_decode(base64_decode($task['data']), true);
$simple_data = array_reduce(
$data,
function ($carry, $item) {
$id = $item['agent']['nombre'];
$carry[] = [
'id' => $id,
'name' => $item['agent']['nombre'],
];
$childs = array_reduce(
$item['modules'],
function ($c, $i) use ($id) {
$c[] = [
'name' => $i['name'],
'id' => $id.'-'.$i['name'],
'pid' => $id,
];
return $c;
},
[]
);
$carry = array_merge(
$carry,
$childs
);
return $carry;
},
[]
);
echo '<div id="tree"></div>';
echo parent::printTree('tree', $simple_data);
}
}
/**
* Processes a review over temporary results found by discovery task.
*
* @return void
*/
public function parse_task_review()
{
$id_task = get_parameter('id', 0);
if ($id_task <= 0) {
echo $this->error(__('Invalid task'));
return;
}
$out = obhd($_REQUEST);
echo json_encode(
['result' => $out]
);
}
}

View File

@ -233,6 +233,27 @@ class Wizard
}
/**
* Return formatted html for error handler.
*
* @param string $message Error mesage.
*
* @return string
*/
public function error($message)
{
if (is_ajax()) {
echo json_encode(
[
'error' => ui_print_error_message($message, '', true),
]
);
} else {
return ui_print_error_message($message, '', true);
}
}
/**
* To be overwritten.
*

View File

@ -24,154 +24,7 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* ============================================================================
*
*
* MOVED TO DiscoveryTaskList.class.
*/
require_once $config['homedir'].'/include/graphs/functions_d3.php';
$progress_task_discovery = (bool) get_parameter('progress_task_discovery', 0);
$showmap = (bool) get_parameter('showmap', 0);
if ($progress_task_discovery) {
$id_task = get_parameter('id', 0);
if ($id_task <= 0) {
echo json_encode(['error' => true]);
return;
}
$task = db_get_row('trecon_task', 'id_rt', $id_task);
$global_progress = $task['status'];
$summary = json_decode($task['summary'], true);
$result = '<div id = progress_task_'.$id_task.'>';
if ($task['utimestamp']) {
$result .= '<div style="display: flex;">';
$result .= '<div style="width: 100%; text-align: center; margin-top: 40px;">';
$result .= '<span style="font-size: 1.9em; font-family: "lato-bolder", "Open Sans", sans-serif !important;">'._('Overall Progress').'</span>';
$result .= '<div style="margin-top: 25px;">';
$result .= progress_circular_bar(
$id_task,
($global_progress < 0) ? 100 : $global_progress,
200,
200,
'#7eb641',
'%',
'',
'#3A3A3A',
0
);
$result .= '</div>';
if ($global_progress > 0) {
switch ($summary['step']) {
case STEP_SCANNING:
$str = __('Scanning network');
break;
case STEP_AFT:
$str = __('Finding AFT connectivity');
break;
case STEP_TRACEROUTE:
$str = __('Finding traceroute connectivity');
break;
case STEP_GATEWAY:
$str = __('Finding gateway connectivity');
break;
default:
$str = __('Searching for devices...');
break;
}
$result .= '</div>';
$result .= '<div style="width: 100%; text-align: center; margin-top: 40px;">';
$result .= '<span style="font-size: 1.9em; font-family: "lato-bolder", "Open Sans", sans-serif !important;">'.$str.' ';
$result .= $summary['c_network_name'];
$result .= '</span>';
$result .= '<div style="margin-top: 25px;">';
$result .= progress_circular_bar(
$id_task.'_detail',
$summary['c_network_percent'],
200,
200,
'#7eb641',
'%',
'',
'#3A3A3A',
0
);
$result .= '</div></div>';
}
$result .= '</div></div>';
$i = 0;
$table = new StdClasS();
$table->class = 'databox data';
$table->width = '75%';
$table->styleTable = 'margin: 2em auto 0;border: 1px solid #ddd;background: white;';
$table->rowid = [];
$table->data = [];
// Content.
$table->data[$i][0] = '<b>'.__('Hosts discovered').'</b>';
$table->data[$i][1] = '<span id="discovered">';
$table->data[$i][1] .= $summary['summary']['discovered'];
$table->data[$i++][1] .= '</span>';
$table->data[$i][0] = '<b>'.__('Alive').'</b>';
$table->data[$i][1] = '<span id="alive">';
$table->data[$i][1] .= $summary['summary']['alive'];
$table->data[$i++][1] .= '</span>';
$table->data[$i][0] = '<b>'.__('Not alive').'</b>';
$table->data[$i][1] = '<span id="not_alive">';
$table->data[$i][1] .= $summary['summary']['not_alive'];
$table->data[$i++][1] .= '</span>';
$table->data[$i][0] = '<b>'.__('Responding SNMP').'</b>';
$table->data[$i][1] = '<span id="SNMP">';
$table->data[$i][1] .= $summary['summary']['SNMP'];
$table->data[$i++][1] .= '</span>';
$table->data[$i][0] = '<b>'.__('Responding WMI').'</b>';
$table->data[$i][1] = '<span id="WMI">';
$table->data[$i][1] .= $summary['summary']['WMI'];
$table->data[$i++][1] .= '</span>';
$result .= '<div style="margin-top: 40px; text-align: center;"><span style="font-size: 1.9em; font-family: "lato-bolder", "Open Sans", sans-serif !important;">'.__('Summary').'</span></div>';
$result .= html_print_table($table, true).'</div>';
} else {
$global_progress = -1;
$result .= ui_print_error_message(
__('No data to show'),
'',
true
).'</div>';
}
$result_array['status'] = $global_progress;
$result_array['html'] = $result;
echo json_encode($result_array);
return;
}
if ($showmap) {
include_once $config['homedir'].'/include/class/NetworkMap.class.php';
$id_task = get_parameter('id', 0);
$map = new NetworkMap(
[
'id_task' => $id_task,
'pure' => 1,
'widget' => true,
]
);
$map->printMap();
}

View File

@ -1000,4 +1000,36 @@ class HTML
}
/**
* Returns a n-dimensional array (data) into a html tree structure.
*
* @param string $target Target DOM id.
* @param array $data N-dimensional array.
* @param string $callback Callback function.
*
* @return string
*/
public static function printTree($target, $data, $callback='')
{
ui_require_css_file('simTree');
ui_require_javascript_file('simTree');
$output = '
<script type="text/javascript">
$(document).ready(function() {
simTree({
el: $('.$target.'),
data: '.json_encode($data).',
onClick: function (item) {'.$callback.';},
check: true,
linkParent: true
});
});
</script>';
return $output;
}
}

View File

@ -527,6 +527,9 @@ define('STEP_SCANNING', 1);
define('STEP_AFT', 2);
define('STEP_TRACEROUTE', 3);
define('STEP_GATEWAY', 4);
define('STEP_STATISTICS', 1);
define('STEP_APP_SCAN', 2);
define('STEP_CUSTOM_QUERIES', 3);
// Networkmap node types.
define('NODE_AGENT', 0);

View File

@ -2839,6 +2839,7 @@ function ui_print_status_sets(
* [
* 'page' => 'operation/agentes/ver_agente', Target page.
* 'interval' => 100 / $agent["intervalo"], Ask every interval seconds.
* 'simple' => 0,
* 'data' => [ Data to be sent to target page.
* 'id_agente' => $id_agente,
* 'refresh_contact' => 1,
@ -2879,7 +2880,38 @@ function ui_progress(
$output .= '</span>';
if ($ajax !== false && is_array($ajax)) {
$output .= '<script type="text/javascript">
if ($ajax['simple']) {
$output .= '<script type="text/javascript">
$(document).ready(function() {
setInterval(() => {
$.post({
url: "'.ui_get_full_url('ajax.php', false, false, false).'",
data: {';
if (is_array($ajax['data'])) {
foreach ($ajax['data'] as $token => $value) {
$output .= '
'.$token.':"'.$value.'",';
}
}
$output .= '
page: "'.$ajax['page'].'"
},
success: function(data) {
try {
val = JSON.parse(data);
$(".progress_main").attr("data-label", val + " %");
$(".progress").width(val+"%");
} catch (e) {
console.error(e);
}
}
});
}, '.($ajax['interval'] > 0 ? $ajax['interval'] * 1000 : 30000 ).');
});
</script>';
} else {
$output .= '<script type="text/javascript">
$(document).ready(function() {
setInterval(() => {
last = $(".progress_main").attr("data-label").split(" ")[0]*1;
@ -2889,14 +2921,14 @@ function ui_progress(
$.post({
url: "'.ui_get_full_url('ajax.php', false, false, false).'",
data: {';
if (is_array($ajax['data'])) {
foreach ($ajax['data'] as $token => $value) {
$output .= '
'.$token.':"'.$value.'",';
if (is_array($ajax['data'])) {
foreach ($ajax['data'] as $token => $value) {
$output .= '
'.$token.':"'.$value.'",';
}
}
}
$output .= '
$output .= '
page: "'.$ajax['page'].'"
},
success: function(data) {
@ -2922,6 +2954,7 @@ function ui_progress(
}, 1000);
});
</script>';
}
}
if (!$return) {

View File

@ -22,7 +22,7 @@ function progress_task_list(id, title) {
autoOpen: false,
modal: false,
resizable: false,
draggable: false,
draggable: true,
closeOnEscape: true,
width: 800,
height: 600,
@ -35,19 +35,23 @@ function progress_task_list(id, title) {
// Function var.
var handleFetchTaskList = function(err, data) {
if (err) {
console.error(err);
}
if (data.error) {
// TODO: Show info about the problem.
$elem.html(data.error);
} else {
$elem.html(data.html);
}
$elem.html(data.html);
if (!$elem.dialog("isOpen")) $elem.dialog("open");
if (data.status != -1) {
timeoutRef = setTimeout(function() {
xhr = fetchTaskList(id, handleFetchTaskList);
}, 3000);
}
};
if (!$elem.dialog("isOpen"))
timeoutRef = setInterval(function() {
xhr = fetchTaskList(id, handleFetchTaskList);
}, 3000);
xhr = fetchTaskList(id, handleFetchTaskList);
}
@ -60,12 +64,13 @@ function progress_task_list(id, title) {
function fetchTaskList(id, callback) {
return jQuery.ajax({
data: {
page: "include/ajax/task_list.ajax",
progress_task_discovery: 1,
page: "godmode/servers/discovery",
wiz: "tasklist",
method: "progress_task_discovery",
id: id
},
type: "POST",
url: "ajax.php",
url: $("#ajax-url").val(),
dataType: "json",
success: function(data) {
callback(null, data);
@ -93,12 +98,13 @@ function show_map(id, name) {
jQuery.ajax({
data: {
page: "include/ajax/task_list.ajax",
showmap: 1,
page: "godmode/servers/discovery",
wiz: "tasklist",
method: "task_showmap",
id: id
},
type: "POST",
url: "ajax.php",
url: $("#ajax-url").val(),
dataType: "html",
success: function(data) {
$("#map_task")
@ -107,3 +113,105 @@ function show_map(id, name) {
}
});
}
function show_review(id, name) {
load_modal({
target: $("#task_review"),
form: "review",
url: $("#ajax-url").val(),
modal: {
title: "Review " + name,
ok: "OK",
cancel: "Cancel"
},
ajax_callback: function(data) {
var title = $("#success-str").val();
var text = "";
var failed = 0;
try {
data = JSON.parse(data);
text = data["result"];
} catch (err) {
title = $("#failed-str").val();
text = err.message;
failed = 1;
}
if (!failed && data["error"] != undefined) {
title = $("#failed-str").val();
text = data["error"];
failed = 1;
}
if (data["report"] != undefined) {
data["report"].forEach(function(item) {
text += "<br>" + item;
});
}
$("#msg").empty();
$("#msg").html(text);
$("#msg").dialog({
width: 450,
position: {
my: "center",
at: "center",
of: window,
collision: "fit"
},
title: title,
buttons: [
{
class:
"ui-widget ui-state-default ui-corner-all ui-button-text-only sub ok submit-next",
text: "OK",
click: function(e) {
if (!failed) {
$(".ui-dialog-content").dialog("close");
$(".info").hide();
cleanupDOM();
dt_keystore.draw(false);
} else {
$(this).dialog("close");
}
}
}
]
});
},
extradata: [
{
name: "id",
value: id
},
{
name: "wiz",
value: "tasklist"
}
],
onshow: {
page: "godmode/servers/discovery",
method: "show_task_review"
},
onsubmit: {
page: "godmode/servers/discovery",
method: "parse_task_review"
}
});
}
function force_task_run(url) {
window.location = url;
}
function force_task(url, ask) {
if (ask != undefined) {
confirmDialog({
title: ask.title,
message: ask.message,
onAccept: function() {
force_task_run(url);
}
});
} else {
force_task_run(url);
}
}

View File

@ -383,6 +383,7 @@ function confirmDialog(settings) {
"ui-widget ui-state-default ui-corner-all ui-button-text-only sub upd submit-cancel",
click: function() {
$(this).dialog("close");
$(this).remove();
if (typeof settings.onDeny == "function") settings.onDeny();
}
},
@ -392,6 +393,7 @@ function confirmDialog(settings) {
"ui-widget ui-state-default ui-corner-all ui-button-text-only sub ok submit-next",
click: function() {
$(this).dialog("close");
$(this).remove();
if (typeof settings.onAccept == "function") settings.onAccept();
}
}

View File

@ -0,0 +1,437 @@
!(function(e) {
var t = {};
function i(s) {
if (t[s]) return t[s].exports;
var n = (t[s] = { i: s, l: !1, exports: {} });
return e[s].call(n.exports, n, n.exports, i), (n.l = !0), n.exports;
}
(i.m = e),
(i.c = t),
(i.d = function(e, t, s) {
i.o(e, t) || Object.defineProperty(e, t, { enumerable: !0, get: s });
}),
(i.r = function(e) {
"undefined" != typeof Symbol &&
Symbol.toStringTag &&
Object.defineProperty(e, Symbol.toStringTag, { value: "Module" }),
Object.defineProperty(e, "__esModule", { value: !0 });
}),
(i.t = function(e, t) {
if ((1 & t && (e = i(e)), 8 & t)) return e;
if (4 & t && "object" == typeof e && e && e.__esModule) return e;
var s = Object.create(null);
if (
(i.r(s),
Object.defineProperty(s, "default", { enumerable: !0, value: e }),
2 & t && "string" != typeof e)
)
for (var n in e)
i.d(
s,
n,
function(t) {
return e[t];
}.bind(null, n)
);
return s;
}),
(i.n = function(e) {
var t =
e && e.__esModule
? function() {
return e.default;
}
: function() {
return e;
};
return i.d(t, "a", t), t;
}),
(i.o = function(e, t) {
return Object.prototype.hasOwnProperty.call(e, t);
}),
(i.p = ""),
i((i.s = 0));
})([
function(e, t, i) {
"use strict";
i.r(t);
i(1);
!(function(e, t) {
if (!e || !e.document) throw new Error("simTree need window");
!(function(e) {
var t,
i = e.document,
s = {
linkParent: !1,
response: {
name: "name",
id: "id",
pid: "pid",
checked: "checked",
open: "open",
disabled: "disabled"
}
},
n = function(e) {
throw new Error(e);
},
a = function(e, t) {
return e.replace(/\{\{(.+?)\}\}/g, function(e, i) {
return t[i] ? t[i] : "";
});
},
r = function e(t) {
if (
("undefined" == typeof $ && n("simTreeneed jquery"),
$.isPlainObject(t))
) {
if ((t.el || n("你没有传el"), !(this instanceof e)))
return new e(t);
(this.options = $.extend(!0, {}, s, t)), this.init();
}
},
d = [],
o = [];
(r.prototype = {
version: "0.0.2",
constructor: r,
on: function(e, t, i) {
var s, n;
return (
(this.handles[e] = this.handles[e] || []),
(s = this.handles[e].isTriggered),
(n = this.handles[e].args),
$.isFunction(t) &&
(!0 === i ? (this.handles[e] = [t]) : this.handles[e].push(t),
s && t.call(this, n)),
this
);
},
off: function(e) {
return (this.handles[e] = []), this;
},
trigger: function(e, t) {
var i, s;
for (
this.handles[e] = this.handles[e] || [],
i = 0,
s = this.handles[e].length,
this.handles[e].isTriggered = !0,
this.handles[e].args = t;
i < s;
i++
)
this.handles[e][i].call(this, t);
},
init: function() {
var e = this.options,
t = e.data;
(this.handles = {}),
(this.$el = $(e.el)),
(this.data = t),
this.event(),
this.render();
},
dataCallback: function() {
var e = arguments;
1 === e.length ? this.render(e[0]) : this.doRender(e[0], e[1]);
},
parse: function(e) {
var t = this.options,
i = t.response,
s = [],
n = {},
a = 0,
r = e.length,
d = i.id,
o = i.pid;
if (t.childNodeAsy) return e;
for (; a < r; a++) {
var h = e[a],
c = h[d];
if (h.children) return e;
c && (n[c] = h);
}
for (a = 0; a < r; a++) {
var h = e[a],
l = h[o],
u = n[l];
l && u ? (u.children || (u.children = [])).push(h) : s.push(h);
}
return s;
},
render: function(e) {
var e = e || this.data;
$.isFunction(e) && e({}, this.dataCallback.bind(this)),
$.isArray(e) && ((e = this.parse(e)), this.doRender(this.$el, e));
},
doRender: function(e, t, s) {
var n,
r,
h,
c,
l,
u = this,
f = this.options,
p = f.response,
m = t.length,
g = 0,
v = p.id,
k = p.name,
s = s || 1,
C =
'<i data-type="{{asy}}" class="sim-tree-spread {{spreadIcon}}"></i><a href="javascript:;"><i class="sim-tree-checkbox"></i>{{text}}</a>',
b = e === this.$el,
y = $(i.createElement("ul")),
w = f.childNodeAsy ? "asy" : "";
for (
f.check ||
(C = C.replace('<i class="sim-tree-checkbox"></i>', ""));
g < m;
g++
)
(n = t[g]),
(r = i.createElement("li")),
(c = !!n.children),
(l = n[p.disabled]),
(r.innerHTML = a(C, {
asy: w,
text: n[k],
spreadIcon: c ? "sim-icon-r" : "hidden"
})),
r.setAttribute("data-level", s),
r.setAttribute("data-id", n[v]),
l && r.setAttribute("class", "disabled"),
(h = $(r)).data("data", n),
y.append(h),
c && this.doRender(h, n.children, s + 1),
n[p.checked] && d.push(n[v]),
n[p.open] && o.push(n[v]);
m && e.append(y),
b
? (y.addClass("sim-tree"),
this.trigger("done", t),
$.each(o, function(e, t) {
u.expandNode(t);
}),
this.setSelected(d))
: f.childNodeAsy &&
(this.hideLoading(e.find(".sim-tree-spread")),
y.addClass("show"));
},
event: function() {
var e = this;
this.$el.off("click").on("click", function(t) {
var i = $(t.target);
return (
i.hasClass("sim-tree-spread") && e.spread.call(e, i),
i.hasClass("sim-tree-checkbox") && (i = i.parent()),
"a" === i[0].tagName.toLowerCase() && e.clickNode.call(e, i),
!1
);
}),
this.$el.on("selectstart", function() {
return !1;
}),
this.options.done && this.on("done", this.options.done),
this.options.onClick && this.on("click", this.options.onClick),
this.options.onChange && this.on("change", this.options.onChange),
this.options.onSearch && this.on("search", this.options.onSearch);
},
spread: function(e) {
e.hasClass("sim-icon-r")
? this.doSpread(e, !0)
: this.doSpread(e, !1);
},
showLoading: function(e) {
e.addClass("sim-loading");
},
hideLoading: function(e) {
e.removeClass("sim-loading");
},
doSpread: function(e, t) {
var i = e.parent(),
s = i.children("ul"),
n = i.data("data");
n.children &&
(t
? (e.removeClass("sim-icon-r").addClass("sim-icon-d"),
"asy" === e.data("type") &&
$.isFunction(this.data) &&
(this.showLoading(e),
this.data(i.data("data"), this.dataCallback.bind(this, i)),
e.data("type", "")),
s.addClass("show"))
: (e.removeClass("sim-icon-d").addClass("sim-icon-r"),
s.removeClass("show")));
},
clickNode: function(e) {
var i,
s,
n,
a = this,
r = e.parent(),
d = this.$el.find("li"),
o = d.length,
h = 0,
c = [],
l = !1;
if (!r.hasClass("disabled")) {
if (this.options.check)
for (
l = !0,
this.doCheck(e.find(".sim-tree-checkbox")),
this.options.linkParent &&
((s = r.children("ul")),
(n = s.find(".sim-tree-checkbox")),
$.each(n, function() {
a.doCheck($(this), r.data("checked"), !0);
}));
h < o;
h++
)
!0 === (i = d.eq(h).data()).checked && c.push(i.data);
else
t && t.css("font-weight", "normal"),
e.css("font-weight", "bold"),
(t = e),
(i = r.data("data")),
(c = [i]),
(l = !this.sels || !(this.sels[0] === i));
(this.sels = c),
this.trigger("click", c),
l && this.trigger("change", c);
}
},
doCheck: function(e, t, i) {
var s = e.closest("li"),
n = s.data();
void 0 === t && (t = !n.checked),
!0 === t
? e.removeClass("sim-tree-semi").addClass("checked")
: !1 === t
? e.removeClass("checked sim-tree-semi")
: "semi" === t &&
e.removeClass("checked").addClass("sim-tree-semi"),
s.data("checked", t),
!0 === this.options.linkParent && !i && this.setParentCheck(s);
},
setParentCheck: function(e) {
var t,
i = e.parent("ul"),
s = i.parent("li"),
n = i.children("li"),
a = s.find(">a .sim-tree-checkbox"),
r = [],
d = n.length;
s.length &&
(e.find(">a .sim-tree-checkbox").hasClass("sim-tree-semi")
? this.doCheck(a, "semi")
: ($.each(n, function() {
!0 === $(this).data("checked") && r.push($(this));
}),
(t = r.length),
d === t && this.doCheck(a, !0),
t || this.doCheck(a, !1),
t >= 1 && t < d && this.doCheck(a, "semi")));
},
search: function(e) {
if (this.$el) {
var t,
i,
s,
e = $.trim(e),
n = this.$el.find("li"),
a = 0,
r = n.length,
d = [],
o = new RegExp(e, "i");
for (
n
.hide()
.children(".sim-tree-spread")
.addClass("hidden");
a < r;
a++
)
(i = n.eq(a)),
(t = i.children("a").text()),
(s = i.data("data")),
e
? -1 !== t.search(o) &&
(1 !== parseInt(i.data("level")) &&
this.expandNode(s[this.options.response.pid]),
i
.parents("li")
.add(i)
.show(),
d.push(i))
: (i.show(),
s.children &&
i.children(".sim-tree-spread").removeClass("hidden"));
this.trigger("search", e);
}
},
expandNode: function(e) {
var t = e.addClass ? e : this.$el.find("[data-id=" + e + "]"),
i = t.data("data"),
s = i[this.options.response.pid],
n = t.children(".sim-tree-spread"),
a = parseInt(t.data("level"));
i.children &&
n.length &&
(n.removeClass("hidden"), this.doSpread(n, !0)),
1 !== a && this.expandNode(s);
},
setSelected: function(e) {
var t = this,
i = e,
s = [],
n = [];
("string" != typeof i && "number" != typeof i) || (i = [i]),
$.isArray(i) &&
(this.options.check || (i = [i[0]]),
$.each(i, function(e, i) {
var a = t.$el.find("[data-id=" + i + "]"),
r = a.children("a"),
d = r.children(".sim-tree-checkbox"),
o = a.data("data");
if (!a.length) return !0;
d.length ? t.doCheck(d, !0) : r.css("font-weight", "bold"),
1 !== parseInt(a.data("level")) &&
t.expandNode(o[t.options.response.pid]),
s.push(o),
n.push(a[0]);
}),
(t.sels = s),
t.trigger("click", s));
},
getSelected: function() {
return this.sels;
},
disableNode: function(e) {
var t = this,
i = e;
("string" != typeof i && "number" != typeof i) || (i = [i]),
$.isArray(i) &&
$.each(i, function(e, i) {
var s = t.$el.find("[data-id=" + i + "]");
s.addClass("disabled");
});
},
destroy: function() {
for (var e in (this.$el.html(""), this)) delete this[e];
},
refresh: function(e) {
this.$el.html(""), this.render(e);
}
}),
(e.simTree = r),
($.fn.simTree = function(e) {
return (e = $.extend(!0, { el: this }, e)), r(e);
});
})(e);
})("undefined" != typeof window ? window : void 0);
},
function(e, t, i) {}
]);

View File

@ -0,0 +1,124 @@
.sim-tree {
list-style: none;
font-size: 14px;
color: #333;
}
.sim-tree ul,
.sim-tree li {
margin: 0;
padding: 0;
}
.sim-tree li {
text-overflow: ellipsis;
overflow: hidden;
white-space: nowrap;
font-size: 0;
}
.sim-tree li ul {
display: none;
margin-left: 15px;
}
.sim-tree ul.show,
.sim-tree li.show {
display: block;
}
.sim-tree ul.none,
.sim-tree li.none {
display: none;
}
.sim-tree li.disabled > a {
color: #aaa;
cursor: not-allowed;
}
.sim-tree li.disabled > a .sim-tree-checkbox {
border-color: #eee;
}
.sim-tree a {
font-size: 14px;
color: #333;
text-decoration: none;
vertical-align: top;
line-height: 26px;
}
.sim-tree .sim-tree-spread {
width: 20px;
padding-left: 5px;
-webkit-box-sizing: border-box;
box-sizing: border-box;
}
.sim-tree .sim-tree-spread.hidden {
visibility: hidden;
}
.sim-tree .sim-tree-spread,
.sim-tree a {
display: inline-block;
height: 26px;
cursor: pointer;
}
.sim-tree .sim-loading {
background: url(data:image/gif;base64,R0lGODlhEAAQAMQQAObm5uLi4unp6dHR0cnJydfX1+jo6O/v7/Dw8NPT0/39/crKyvr6+uDg4MfHx////////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH/C05FVFNDQVBFMi4wAwEAAAAh+QQFAAAQACwAAAAAEAAQAAAFXeAjPkiTjGgaLI6Tvs9BtPAIMPH8KgK5DDhZSlFYlFrAGIrYMrUcyRGzdapZr6jE02FAyZ6JxrOrEAVnjgaCRS6IkjLjo9F2PaDBwLJAu+NfAix2LQsAMCVVYQgoIQAh+QQFAAAQACwJAAAABwAHAAAFFGDSIE/5OM7SmKhjsK55vjIt32UIACH5BAUAABAALAoAAwAGAAoAAAUaICQqgggpxYKcheM0qOskZm0/eA7luMibvRAAIfkEBQAAEAAsCQAJAAcABwAABRXgcxBOmTwi6TRouiAoIwbtI9d4/oQAIfkEBQAAEAAsAwAKAAoABgAABRsgJI7MKD6POJQnKjpD60IODKFzvQD3nDQISAgAIfkEBQAAEAAsAAAJAAcABwAABRPgI45kSSrFWTgj6rCisLwk0iQhACH5BAUAABAALAAAAwAHAAoAAAUcIPRAJPmco4mm61m+cJk4tGNATX0ryGK/jVspBAAh+QQFAAAQACwAAAAABwAHAAAFFOAjjmRpPgBDIsugio3juGIiz2oIADs=)
center center no-repeat;
}
.sim-tree .sim-loading.sim-icon-d:before,
.sim-tree .sim-loading.sim-icon-r:before {
display: none;
}
.sim-tree .sim-icon-d:before,
.sim-tree .sim-icon-r:before {
content: "";
display: inline-block;
width: 0;
height: 0;
border: 6px solid transparent;
vertical-align: top;
position: relative;
}
.sim-tree .sim-icon-r:before {
border-left-width: 8px;
border-left-color: #333;
top: 7px;
}
.sim-tree .sim-icon-d:before {
margin-left: -4px;
border-top-color: #333;
top: 10px;
}
.sim-tree .sim-tree-checkbox {
display: inline-block;
border: 1px solid #ccc;
height: 16px;
width: 16px;
border-radius: 3px;
-webkit-box-sizing: border-box;
box-sizing: border-box;
text-align: center;
line-height: 16px;
background: #fff;
color: #fff;
vertical-align: middle;
margin-right: 6px;
margin-top: -2px;
}
.sim-tree .sim-tree-checkbox.sim-tree-semi,
.sim-tree .sim-tree-checkbox.checked {
border-color: #2b85e4;
background-color: #2b85e4;
}
.sim-tree .sim-tree-checkbox.sim-tree-semi {
position: relative;
}
.sim-tree .sim-tree-checkbox.sim-tree-semi:after {
content: "";
display: block;
position: absolute;
width: 8px;
height: 2px;
background: #fff;
top: 6px;
left: 3px;
}
.sim-tree .sim-tree-checkbox.checked {
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAwAAAAMCAMAAABhq6zVAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAAPFBMVEUAAAD///////////////////////////////////////////////////////////////////////8AAADY904BAAAAE3RSTlMAOiE8877cHQkXr9cZQvUc20NAbrhSVAAAAAFiS0dEAIgFHUgAAAAJcEhZcwAACxIAAAsSAdLdfvwAAAA7SURBVAjXY2DADhiZEGxmFlYkNhs7KpuDE0mci5sHoYaXj5sHyOaHqOblE4CzGRgE+RBsBgYhfmxuAABcBQF5T7U3IwAAAABJRU5ErkJggg==);
background-repeat: no-repeat;
background-position: center center;
}

View File

@ -40,3 +40,15 @@ ul.progress_task_discovery li span {
font-size: 9pt;
margin-left: 20px;
}
.ui-dialog.ui-widget-content {
cursor: initial;
}
span.link {
cursor: pointer;
}
span.link.review {
font-weight: bold;
}

View File

@ -770,14 +770,14 @@ CREATE TABLE IF NOT EXISTS `trecon_task` (
`name` varchar(100) NOT NULL default '',
`description` varchar(250) NOT NULL default '',
`subnet` text NOT NULL,
`id_network_profile` int(10) unsigned NOT NULL default '0',
`create_incident` tinyint(3) unsigned NOT NULL default '0',
`id_group` int(10) unsigned NOT NULL default '1',
`utimestamp` bigint(20) unsigned NOT NULL default '0',
`status` tinyint(4) NOT NULL default '0',
`interval_sweep` int(10) unsigned NOT NULL default '0',
`id_recon_server` int(10) unsigned NOT NULL default '0',
`id_os` tinyint(4) NOT NULL default '0',
`id_network_profile` text,
`direct_report` tinyint(1) unsigned NOT NULL default 0,
`id_group` int(10) unsigned NOT NULL default 1,
`utimestamp` bigint(20) unsigned NOT NULL default 0,
`status` tinyint(4) NOT NULL default 0,
`interval_sweep` int(10) unsigned NOT NULL default 0,
`id_recon_server` int(10) unsigned NOT NULL default 0,
`id_os` tinyint(4) NOT NULL default 0,
`recon_ports` varchar(250) NOT NULL default '',
`snmp_community` varchar(64) NOT NULL default 'public',
`id_recon_script` int(10),
@ -785,31 +785,62 @@ CREATE TABLE IF NOT EXISTS `trecon_task` (
`field2` varchar(250) NOT NULL default '',
`field3` varchar(250) NOT NULL default '',
`field4` varchar(250) NOT NULL default '',
`os_detect` tinyint(1) unsigned default '0',
`resolve_names` tinyint(1) unsigned default '0',
`parent_detection` tinyint(1) unsigned default '0',
`parent_recursion` tinyint(1) unsigned default '0',
`disabled` tinyint(1) unsigned NOT NULL DEFAULT '0',
`os_detect` tinyint(1) unsigned default 0,
`resolve_names` tinyint(1) unsigned default 0,
`parent_detection` tinyint(1) unsigned default 0,
`parent_recursion` tinyint(1) unsigned default 0,
`disabled` tinyint(1) unsigned NOT NULL DEFAULT 0,
`macros` TEXT,
`alias_as_name` tinyint(2) NOT NULL default '0',
`snmp_enabled` tinyint(1) unsigned default '0',
`vlan_enabled` tinyint(1) unsigned default '0',
`snmp_version` varchar(5) NOT NULL default '1',
`alias_as_name` tinyint(2) NOT NULL default 0,
`snmp_enabled` tinyint(1) unsigned default 0,
`vlan_enabled` tinyint(1) unsigned default 0,
`snmp_version` varchar(5) NOT NULL default 1,
`snmp_auth_user` varchar(255) NOT NULL default '',
`snmp_auth_pass` varchar(255) NOT NULL default '',
`snmp_auth_method` varchar(25) NOT NULL default '',
`snmp_privacy_method` varchar(25) NOT NULL default '',
`snmp_privacy_pass` varchar(255) NOT NULL default '',
`snmp_security_level` varchar(25) NOT NULL default '',
`wmi_enabled` tinyint(1) unsigned DEFAULT '0',
`wmi_enabled` tinyint(1) unsigned DEFAULT 0,
`auth_strings` text,
`autoconfiguration_enabled` tinyint(1) unsigned default '0',
`autoconfiguration_enabled` tinyint(1) unsigned default 0,
`summary` text,
`type` int NOT NULL default 0,
PRIMARY KEY (`id_rt`),
KEY `recon_task_daemon` (`id_recon_server`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- ----------------------------------------------------------------------
-- Table `tdiscovery_tmp`
-- ----------------------------------------------------------------------
CREATE TABLE `tdiscovery_tmp_agents` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`id_rt` int(10) unsigned NOT NULL,
`label` varchar(600) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL DEFAULT '',
`data` text,
`review_date` datetime DEFAULT NULL,
`created` int(1) unsigned NOT NULL DEFAULT '0',
PRIMARY KEY (`id`),
KEY `id_rt` (`id_rt`),
INDEX `label` (`label`),
CONSTRAINT `tdta_trt` FOREIGN KEY (`id_rt`) REFERENCES `trecon_task` (`id_rt`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `tdiscovery_tmp_connections` (
`id_rt` int(10) unsigned NOT NULL,
`id1` int(10) unsigned NOT NULL AUTO_INCREMENT,
`id2` int(10) unsigned NOT NULL,
`if1` text,
`if2` text,
PRIMARY KEY (`id1`,`id2`),
CONSTRAINT `tdtc_trt` FOREIGN KEY (`id_rt`)
REFERENCES `trecon_task` (`id_rt`) ON DELETE CASCADE ON UPDATE CASCADE,
CONSTRAINT `tdtc_tdta1` FOREIGN KEY (`id1`)
REFERENCES `tdiscovery_tmp_agents` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
CONSTRAINT `tdtc_tdta2` FOREIGN KEY (`id2`)
REFERENCES `tdiscovery_tmp_agents` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- ----------------------------------------------------------------------
-- Table `tmodule_relationship`
-- ----------------------------------------------------------------------

View File

@ -20,6 +20,7 @@ package PandoraFMS::DB;
use strict;
use warnings;
use DBI;
use Carp qw/croak/;
use lib '/usr/lib/perl5';
use PandoraFMS::Tools;
@ -894,7 +895,7 @@ sub db_insert ($$$;@) {
$insert_id = $dbh->{'mysql_insertid'};
}
else {
die($exception);
croak (join(', ', @_));
}
}
@ -917,7 +918,7 @@ sub db_update ($$;@) {
$rows = $dbh->do($query, undef, @values);
}
else {
die($exception);
croak (join(', ', @_));
}
}
@ -1163,7 +1164,7 @@ sub db_do ($$;@) {
$dbh->do($query, undef, @values);
}
else {
die($exception);
croak (join(', ', @_));
}
}
}

View File

@ -1,8 +1,8 @@
package PandoraFMS::DiscoveryServer;
##########################################################################
################################################################################
# Pandora FMS Discovery Server.
# Pandora FMS. the Flexible Monitoring System. http://www.pandorafms.org
##########################################################################
################################################################################
# Copyright (c) 2005-2009 Artica Soluciones Tecnologicas S.L
#
# This program is free software; you can redistribute it and/or
@ -15,7 +15,7 @@ package PandoraFMS::DiscoveryServer;
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
##########################################################################
################################################################################
use strict;
use warnings;
@ -77,9 +77,9 @@ use constant {
DISCOVERY_APP_SAP => 10,
};
########################################################################################
################################################################################
# Discovery Server class constructor.
########################################################################################
################################################################################
sub new ($$$$$$) {
my ($class, $config, $dbh) = @_;
@ -113,9 +113,9 @@ sub new ($$$$$$) {
return $self;
}
###############################################################################
################################################################################
# Run.
###############################################################################
################################################################################
sub run ($) {
my $self = shift;
my $pa_config = $self->getConfig ();
@ -132,9 +132,9 @@ sub run ($) {
$self->SUPER::run (\@TaskQueue, \%PendingTasks, $Sem, $TaskSem);
}
###############################################################################
################################################################################
# Data producer.
###############################################################################
################################################################################
sub data_producer ($) {
my $self = shift;
my ($pa_config, $dbh) = ($self->getConfig (), $self->getDBH ());
@ -174,9 +174,9 @@ sub data_producer ($) {
return @tasks;
}
###############################################################################
################################################################################
# Data consumer.
###############################################################################
################################################################################
sub data_consumer ($$) {
my ($self, $task_id) = @_;
my ($pa_config, $dbh) = ($self->getConfig (), $self->getDBH ());
@ -300,18 +300,18 @@ sub data_consumer ($$) {
}
}
##########################################################################
################################################################################
# Update recon task status.
##########################################################################
################################################################################
sub update_recon_task ($$$) {
my ($dbh, $id_task, $status) = @_;
db_do ($dbh, 'UPDATE trecon_task SET utimestamp = ?, status = ? WHERE id_rt = ?', time (), $status, $id_task);
}
##########################################################################
################################################################################
# Executes recon scripts
##########################################################################
################################################################################
sub exec_recon_script ($$$) {
my ($pa_config, $dbh, $task) = @_;
@ -380,9 +380,9 @@ sub exec_recon_script ($$$) {
return 0;
}
##########################################################################
################################################################################
# Guess the OS using xprobe2 or nmap.
##########################################################################
################################################################################
sub PandoraFMS::Recon::Base::guess_os($$) {
my ($self, $device) = @_;
@ -422,9 +422,9 @@ sub PandoraFMS::Recon::Base::guess_os($$) {
return OS_OTHER;
}
##############################################################################
################################################################################
# Returns the number of open ports from the given list.
##############################################################################
################################################################################
sub PandoraFMS::Recon::Base::tcp_scan ($$) {
my ($self, $host) = @_;
@ -436,14 +436,23 @@ sub PandoraFMS::Recon::Base::tcp_scan ($$) {
return $open_ports;
}
##########################################################################
################################################################################
# Create network profile modules for the given agent.
##########################################################################
################################################################################
sub PandoraFMS::Recon::Base::create_network_profile_modules($$$) {
my ($self, $agent_id, $device) = @_;
return unless ($self->{'id_network_profile'} > 0);
#
# Plugin
# SNMP
# WMI
# ICMP
#
return if empty($self->{'id_network_profile'});
my @templates = split /,/, $self->{'id_network_profile'};
# Get network components associated to the network profile.
my @np_components = get_db_rows($self->{'dbh'}, 'SELECT * FROM tnetwork_profile_component WHERE id_np = ?', $self->{'id_network_profile'});
foreach my $np_component (@np_components) {
@ -455,6 +464,10 @@ sub PandoraFMS::Recon::Base::create_network_profile_modules($$$) {
next;
}
## XXX Puede tener varios penes.
#next if (defined($template->{'pen'})
# && get_enterprise_oid($device) != $template->{'pen'} );
# Use snmp_community from network task instead the component snmp_community
$component->{'snmp_community'} = safe_output($self->get_community($device));
$component->{'tcp_send'} = $self->{'snmp_version'};
@ -469,9 +482,84 @@ sub PandoraFMS::Recon::Base::create_network_profile_modules($$$) {
}
}
##########################################################################
################################################################################
# Create agents and modules reported by Recon::Base.
################################################################################
sub PandoraFMS::Recon::Base::report_scanned_agents($) {
my ($self) = @_;
if(defined($self->{'task_data'}{'direct_report'})
&& $self->{'task_data'}{'direct_report'} eq "2"
) {
# Load cache.
my @rows = get_db_rows(
$self->{'dbh'},
'SELECT * FROM tdiscovery_tmp_agents WHERE `id_rt`=?',
$self->{'task_data'}{'id_rt'}
);
foreach my $row (@rows) {
my $name = safe_output($row->{'label'});
my $data;
eval {
$data = decode_json(decode_base64($row->{'data'}));
};
# Store.
$self->{'agents_found'}{$name} = $data;
}
}
foreach my $label (keys %{$self->{'agents_found'}}) {
if (!is_enabled($self->{'direct_report'})) {
# Store temporally. Wait user approval.
my $encoded;
eval {
local $SIG{__DIE__};
$encoded = encode_base64(encode_json($self->{'agents_found'}));
};
my $id = get_db_value(
$self->{'dbh'},
'SELECT id FROM tdiscovery_tmp_agents WHERE id_rt = ? AND label = ?',
$self->{'task_data'}{'id_rt'},
safe_input($label)
);
if (defined($id)) {
# Already defined.
$self->{'agents_found'}{$label}{'id'} = $id;
db_do(
$self->{'dbh'},
'UPDATE tdiscovery_tmp_agents SET `data` = ? '
.'WHERE `id_rt` = ? AND `label` = ?',
$encoded,
$self->{'task_data'}{'id_rt'},
safe_input($label)
);
next;
}
# Insert.
$self->{'agents_found'}{$label}{'id'} = db_insert(
$self->{'dbh'},
'id',
'INSERT INTO tdiscovery_tmp_agents (`id_rt`,`label`,`data`,`created`) '
.'VALUES (?, ?, ?, now())',
$self->{'task_data'}{'id_rt'},
safe_input($label),
$encoded
);
} else {
# Create agents.
}
}
}
################################################################################
# Connect the given devices in the Pandora FMS database.
##########################################################################
################################################################################
sub PandoraFMS::Recon::Base::connect_agents($$$$$) {
my ($self, $dev_1, $if_1, $dev_2, $if_2) = @_;
@ -490,12 +578,12 @@ sub PandoraFMS::Recon::Base::connect_agents($$$$$) {
return unless defined($agent_2);
# Use ping modules by default.
$if_1 = 'ping' if ($if_1 eq '');
$if_2 = 'ping' if ($if_2 eq '');
$if_1 = 'Host Alive' if ($if_1 eq '');
$if_2 = 'Host Alive' if ($if_2 eq '');
# Check whether the modules exists.
my $module_name_1 = $if_1 eq 'ping' ? 'ping' : "${if_1}_ifOperStatus";
my $module_name_2 = $if_2 eq 'ping' ? 'ping' : "${if_2}_ifOperStatus";
my $module_name_1 = $if_1 eq 'Host Alive' ? 'Host Alive' : "${if_1}_ifOperStatus";
my $module_name_2 = $if_2 eq 'Host Alive' ? 'Host Alive' : "${if_2}_ifOperStatus";
my $module_id_1 = get_agent_module_id($self->{'dbh'}, $module_name_1, $agent_1->{'id_agente'});
if ($module_id_1 <= 0) {
$self->call('message', "ERROR: Module " . safe_output($module_name_1) . " does not exist for agent $dev_1.", 5);
@ -515,13 +603,13 @@ sub PandoraFMS::Recon::Base::connect_agents($$$$$) {
}
##########################################################################
################################################################################
# Create agents from db_scan. Uses DataServer methods.
# data = [
# 'agent_data' => {},
# 'module_data' => []
# ]
##########################################################################
################################################################################
sub PandoraFMS::Recon::Base::create_agents($$) {
my ($self, $data) = @_;
@ -618,10 +706,10 @@ sub PandoraFMS::Recon::Base::create_agents($$) {
}
##########################################################################
################################################################################
# Create an agent for the given device. Returns the ID of the new (or
# existing) agent, undef on error.
##########################################################################
################################################################################
sub PandoraFMS::Recon::Base::create_agent($$) {
my ($self, $device) = @_;
@ -930,9 +1018,9 @@ sub PandoraFMS::Recon::Base::create_agent($$) {
return $agent_id;
}
##########################################################################
################################################################################
# Delete already existing connections.
##########################################################################
################################################################################
sub PandoraFMS::Recon::Base::delete_connections($) {
my ($self) = @_;
@ -940,18 +1028,18 @@ sub PandoraFMS::Recon::Base::delete_connections($) {
db_do($self->{'dbh'}, 'DELETE FROM tmodule_relationship WHERE id_rt=?', $self->{'task_id'});
}
#######################################################################
################################################################################
# Print log messages.
#######################################################################
################################################################################
sub PandoraFMS::Recon::Base::message($$$) {
my ($self, $message, $verbosity) = @_;
logger($self->{'pa_config'}, "[Recon task " . $self->{'task_id'} . "] $message", $verbosity);
}
##########################################################################
################################################################################
# Connect the given hosts to its parent.
##########################################################################
################################################################################
sub PandoraFMS::Recon::Base::set_parent($$$) {
my ($self, $host, $parent) = @_;
@ -978,9 +1066,9 @@ sub PandoraFMS::Recon::Base::set_parent($$$) {
db_do($self->{'dbh'}, 'UPDATE tagente SET id_parent=? WHERE id_agente=?', $agent_parent->{'id_agente'}, $agent->{'id_agente'});
}
##########################################################################
################################################################################
# Create a WMI module for the given agent.
##########################################################################
################################################################################
sub PandoraFMS::Recon::Base::wmi_module {
my ($self, $agent_id, $target, $wmi_query, $wmi_auth, $column,
$module_name, $module_description, $module_type, $unit) = @_;
@ -1007,9 +1095,9 @@ sub PandoraFMS::Recon::Base::wmi_module {
pandora_create_module_from_hash($self->{'pa_config'}, \%module, $self->{'dbh'});
}
##########################################################################
################################################################################
# Update recon task status.
##########################################################################
################################################################################
sub PandoraFMS::Recon::Base::update_progress ($$) {
my ($self, $progress) = @_;

View File

@ -7,13 +7,14 @@ use strict;
use warnings;
# Default lib dir for RPM and DEB packages
use lib '/usr/lib/perl5';
use NetAddr::IP;
use POSIX qw/ceil/;
use Socket qw/inet_aton/;
use lib '/usr/lib/perl5';
use PandoraFMS::Tools;
use PandoraFMS::Recon::NmapParser;
use PandoraFMS::Recon::Util;
use Socket qw/inet_aton/;
# Constants.
use constant {
@ -67,6 +68,7 @@ our $SYSDESCR = ".1.3.6.1.2.1.1.1";
our $SYSSERVICES = ".1.3.6.1.2.1.1.7";
our $SYSUPTIME = ".1.3.6.1.2.1.1.3";
our $VTPVLANIFINDEX = ".1.3.6.1.4.1.9.9.46.1.3.1.1.18.1";
our $PEN_OID = ".1.3.6.1.2.1.1.2.0";
our @ISA = ("Exporter");
our %EXPORT_TAGS = ( 'all' => [qw( )] );
@ -389,6 +391,27 @@ sub are_connected($$$$$) {
return 0;
}
################################################################################
# Initialize tmp pool for device.
# Already discovered by scan_subnet.
################################################################################
sub icmp_discovery($$) {
my ($self, $addr) = @_;
$self->prepare_agent($addr);
$self->add_module($addr, 'icmp',
{
'ip_target' => $addr,
'name' => "Host Alive",
'description' => '',
'type' => 'generic_data',
'id_modulo' => 2,
}
);
}
################################################################################
# Discover as much information as possible from the given device using SNMP.
################################################################################
@ -425,13 +448,15 @@ sub snmp_discovery($$) {
# Check remote ARP caches.
$self->remote_arp($device);
# Get PEN.
$self->snmp_pen($device);
}
}
# Create an agent for the device and add it to the list of known hosts.
push(@{$self->{'hosts'}}, $device);
$self->add_agent($device);
$self->call('create_agent', $device);
}
################################################################################
@ -816,12 +841,14 @@ sub get_mac_from_ip($$) {
my $mac = undef;
eval {
$mac = `arping -c 1 -r $host 2>$DEVNULL`;
$mac = `arping -c 1 $host 2>$DEVNULL`;
$mac = undef unless ($? == 0);
};
return unless defined($mac);
($mac) = $mac =~ /\[(.*?)\]/ if defined($mac);
# Clean-up the MAC address.
chomp($mac);
$mac = parse_mac($mac);
@ -1104,11 +1131,11 @@ sub mark_connected($$;$$$) {
$child = $self->{'aliases'}->{$child} if defined($self->{'aliases'}->{$child});
# Use ping modules when interfaces are unknown.
$parent_if = "ping" if $parent_if eq '';
$child_if = "ping" if $child_if eq '';
$parent_if = "Host Alive" if $parent_if eq '';
$child_if = "Host Alive" if $child_if eq '';
# Do not connect devices using ping modules. A parent-child relationship is enough.
if ($parent_if ne "ping" || $child_if ne "ping") {
if ($parent_if ne "Host Alive" || $child_if ne "Host Alive") {
$self->{'connections'}->{"${parent}\t${parent_if}\t${child}\t${child_if}"} = 1;
$self->call('connect_agents', $parent, $parent_if, $child, $child_if);
}
@ -1264,72 +1291,65 @@ sub remote_arp($$) {
}
################################################################################
# Ping the given host. Returns 1 if the host is alive, 0 otherwise.
# Add agent to pool (will be registered at the end of the scan).
################################################################################
sub ping ($$$) {
my ($self, $host) = @_;
my ($timeout, $retries, $packets) = ($self->{'icmp_timeout'},$self->{'icmp_checks'},1,);
sub prepare_agent($$) {
my ($self, $addr) = @_;
$self->{'agents_found'} = {} if ref($self->{'agents_found'}) ne 'HASH';
# Windows
if (($^O eq "MSWin32") || ($^O eq "MSWin32-x64") || ($^O eq "cygwin")){
$timeout *= 1000; # Convert the timeout to milliseconds.
for (my $i = 0; $i < $retries; $i++) {
my $output = `ping -n $packets -w $timeout $host`;
return 1 if ($output =~ /TTL/);
}
# Already initialized.
return if ref($self->{'agents_found'}->{$addr}) eq 'HASH';
return 0;
$self->{'agents_found'}->{$addr} = {
'agent' => {
'nombre' => $addr,
'direccion' => $addr,
'alias' => $addr,
},
'pen' => $self->{'pen'}{$addr},
'modules' => [],
};
}
################################################################################
# Add agent to pool (will be registered at the end of the scan).
################################################################################
sub add_agent($$) {
my ($self, $addr) = @_;
$self->prepare_agent($addr);
}
################################################################################
# Add module to agent (tmp pool) (will be registered at the end of the scan).
################################################################################
sub add_module($$$$) {
my ($self, $agent, $type, $data) = @_;
$self->prepare_agent($agent);
push @{$self->{'agents_found'}->{$agent}->{'modules'}}, $data;
}
################################################################################
# Test target address (methods).
################################################################################
sub test_capabilities($$) {
my ($self, $addr) = @_;
$self->icmp_discovery($addr);
if (is_enabled($self->{'snmp_enabled'})) {
# SNMP discovery.
$self->snmp_discovery($addr);
}
# Solaris
if ($^O eq "solaris"){
my $ping_command = $host =~ /\d+:|:\d+/ ? "ping -A inet6" : "ping";
for (my $i = 0; $i < $retries; $i++) {
# Note: There is no timeout option.
`$ping_command -s -n $host 56 $packets >$DEVNULL 2>&1`;
return 1 if ($? == 0);
}
return 0;
# WMI discovery.
if (is_enabled($self->{'wmi_enabled'})) {
# Add wmi scan if enabled.
$self->wmi_scan($addr);
}
# FreeBSD
if ($^O eq "freebsd"){
my $ping_command = $host =~ /\d+:|:\d+/ ? "ping6" : "ping -t $timeout";
for (my $i = 0; $i < $retries; $i++) {
# Note: There is no timeout option for ping6.
`$ping_command -q -n -c $packets $host >$DEVNULL 2>&1`;
return 1 if ($? == 0);
}
return 0;
}
# NetBSD
if ($^O eq "netbsd"){
my $ping_command = $host =~ /\d+:|:\d+/ ? "ping6" : "ping -w $timeout";
for (my $i = 0; $i < $retries; $i++) {
# Note: There is no timeout option for ping6.
`$ping_command -q -n -c $packets $host >$DEVNULL 2>&1`;
if ($? == 0) {
return 1;
}
}
return 0;
}
# Assume Linux by default.
my $ping_command = $host =~ /\d+:|:\d+/ ? "ping6" : "ping";
for (my $i = 0; $i < $retries; $i++) {
`$ping_command -q -W $timeout -n -c $packets $host >$DEVNULL 2>&1`;
return 1 if ($? == 0);
}
return 0;
}
################################################################################
@ -1343,6 +1363,7 @@ sub scan_subnet($) {
foreach my $subnet (@subnets) {
$self->{'c_network_percent'} = 0;
$self->{'c_network_name'} = $subnet;
$self->call('update_progress', ceil($progress));
# Clean blanks.
$subnet =~ s/\s+//g;
@ -1357,81 +1378,82 @@ sub scan_subnet($) {
my $network = $net_addr->network();
my $broadcast = $net_addr->broadcast();
# fping scan.
if (-x $self->{'fping'} && $net_addr->num() > 1) {
$self->call('message', "Calling fping...", 5);
my @hosts = map { (split('/', $_))[0] } $net_addr->hostenum;
my $total_hosts = scalar(@hosts);
my %hosts_alive = ();
my @hosts = `"$self->{'fping'}" -ga "$subnet" 2>DEVNULL`;
next if (scalar(@hosts) == 0);
# By default 200, (20 * 10)
my $host_block_size = $self->{'block_size'};
$self->{'summary'}->{'discovered'} += scalar(@hosts);
# The first 50% of the recon task approx.
my $step = 40.0 / scalar(@subnets) / (($total_hosts / $host_block_size)+1);
my $subnet_step = 50.0 / (($total_hosts / $host_block_size)+1);
my $step = 50.0 / scalar(@subnets) / scalar(@hosts); # The first 50% of the recon task approx.
my $subnet_step = 100.0 / scalar(@hosts);
foreach my $line (@hosts) {
chomp($line);
for (my $block_index=0;
$block_index < $total_hosts;
$block_index += $host_block_size
) {
# Update the recon task
# Increase self summary.alive hosts.
$self->call('message', "Searching for hosts (".$block_index." / ".$total_hosts.")", 5);
my $to = $host_block_size + $block_index;
$to = $total_hosts if $to >= $total_hosts;
my @temp = split(/ /, $line);
if (scalar(@temp) != 1) {
my $c_block_size = $to - $block_index;
my @block = pandora_block_ping(
{
'fping' => $self->{'fping'},
# XXX CAMBIAR POR 0.5
'networktimeout' => 0.01 # use fping defaults
},
@hosts[$block_index .. $to - 1]
);
# Junk is shown for broadcast addresses.
# Increase summary.not_alive hosts.
$self->{'summary'}->{'not_alive'} += 1;
next;
}
my $host = $temp[0];
# check alive hosts in current block
%hosts_alive = (
%hosts_alive,
map {chomp; $_ => 1} @block
);
# Skip network and broadcast addresses.
next if ($host eq $network->addr() || $host eq $broadcast->addr());
$self->{'summary'}->{'not_alive'} += $c_block_size - (scalar @block);
$self->{'summary'}->{'alive'} += scalar @block;
# Increase self summary.alive hosts.
$self->{'summary'}->{'alive'} += 1;
$self->call('message', "Scanning host: $host", 5);
$self->call('update_progress', ceil($progress));
$progress += $step;
$self->{'c_network_percent'} += $subnet_step;
# Update progress.
$progress += $step;
$self->{'c_network_percent'} += $subnet_step;
$self->snmp_discovery($host);
# Add wmi scan if enabled.
$self->wmi_scan($host) if ($self->{'wmi_enabled'} == 1);
}
# Populate.
$self->call('update_progress', ceil($progress));
}
# ping scan.
else {
my @hosts = map { (split('/', $_))[0] } $net_addr->hostenum;
next if (scalar(@hosts) == 0);
# Update progress.
$self->call('message', "Searching for hosts (".$total_hosts." / ".$total_hosts.")", 5);
$progress = ceil($progress);
$self->{'c_network_percent'} = 50;
$self->{'summary'}->{'discovered'} += scalar(@hosts);
# Populate.
$self->call('update_progress', ceil($progress));
my $step = 50.0 / scalar(@subnets) / scalar(@hosts); # The first 50% of the recon task approx.
my $subnet_step = 100.0 / scalar(@hosts);
foreach my $host (@hosts) {
$total_hosts = scalar keys %hosts_alive;
$step = 40.0 / scalar(@subnets) / $total_hosts;
$subnet_step = 50.0 / $total_hosts;
foreach my $addr (keys %hosts_alive) {
# Increase self summary.alive hosts.
$self->call('message', "Scanning host: $addr", 5);
$self->call('message', "Scanning host: $host", 5);
$self->call('update_progress', ceil($progress));
$progress += $step;
# Update progress.
$progress += $step;
$self->{'c_network_percent'} += $subnet_step;
# Check if the host is up.
if ($self->ping($host) == 0) {
$self->{'summary'}->{'not_alive'} += 1;
next;
}
# Populate.
$self->call('update_progress', ceil($progress));
$self->{'summary'}->{'alive'} += 1;
$self->{'c_network_percent'} += $subnet_step;
$self->snmp_discovery($host);
# Add wmi scan if enabled.
$self->wmi_scan($host) if ($self->{'wmi_enabled'} == 1);
}
# Enable/ disable capabilities.
$self->test_capabilities($addr);
}
}
}
################################################################################
# Perform a Cloud scan
################################################################################
@ -1441,7 +1463,7 @@ sub cloud_scan($) {
my $type = '';
if ( $self->{'task_data'}->{'type'} == DISCOVERY_CLOUD_AWS_EC2
if ( $self->{'task_data'}->{'type'} == DISCOVERY_CLOUD_AWS_EC2
|| $self->{'task_data'}->{'type'} == DISCOVERY_CLOUD_AWS_RDS) {
$type = 'Aws';
} else {
@ -1783,12 +1805,19 @@ sub scan($) {
}
}
if(defined($self->{'task_data'}{'direct_report'})
&& $self->{'task_data'}{'direct_report'} eq "2"
) {
# Use Cached results.
return $self->call('report_scanned_agents');
}
# Find devices.
$self->call('message', "[1/4] Scanning the network...", 3);
$self->{'step'} = STEP_SCANNING;
$self->call('update_progress', $progress);
$self->scan_subnet();
$self->scan_subnet();
# Read the local ARP cache.
$self->local_arp();
@ -1802,7 +1831,7 @@ sub scan($) {
# Connectivity from address forwarding tables.
$self->call('message', "[2/4] Finding address forwarding table connectivity...", 3);
$self->{'step'} = STEP_AFT;
($progress, $step) = (50, 20.0 / scalar(@hosts)); # From 50% to 70%.
($progress, $step) = (80, 8.0 / scalar(@hosts)); # From 50% to 70%.
for (my $i = 0; defined($hosts[$i]); $i++) {
$self->call('update_progress', $progress);
$progress += $step;
@ -1812,7 +1841,7 @@ sub scan($) {
# Connect hosts that are still unconnected using traceroute.
$self->call('message', "[3/4] Finding traceroute connectivity.", 3);
$self->{'step'} = STEP_TRACEROUTE;
($progress, $step) = (70, 20.0 / scalar(@hosts)); # From 70% to 90%.
($progress, $step) = (88, 8.0 / scalar(@hosts)); # From 70% to 90%.
foreach my $host (@hosts) {
$self->call('update_progress', $progress);
$progress += $step;
@ -1823,7 +1852,7 @@ sub scan($) {
# Connect hosts that are still unconnected using known gateways.
$self->call('message', "[4/4] Finding host to gateway connectivity.", 3);
$self->{'step'} = STEP_GATEWAY;
($progress, $step) = (90, 10.0 / scalar(@hosts)); # From 70% to 90%.
($progress, $step) = (94, 6.0 / scalar(@hosts)); # From 70% to 90%.
$self->get_routes(); # Update the route cache.
foreach my $host (@hosts) {
$self->call('update_progress', $progress);
@ -1852,6 +1881,10 @@ sub scan($) {
$dev_info .= ')';
$self->call('message', $dev_info, 3);
}
# Send agent information to Database (Discovery) or XML (satellite.).
$self->call('report_scanned_agents', $self->{'agents_found'});
}
################################################################################
@ -1872,6 +1905,22 @@ sub set_device_type($$$) {
$self->{'visited_devices'}->{$device}->{'type'} = $type;
}
################################################################################
# Calculate
################################################################################
sub snmp_pen($$) {
my ($self, $addr) = @_;
$self->{'pen'} = {} if ref($self->{'pen'}) ne 'HASH';
$self->{'pen'}{$addr} = $self->snmp_get($addr, $PEN_OID);
if(defined($self->{'pen'}{$addr})) {
($self->{'pen'}{$addr}) = $self->{'pen'}{$addr} =~ /\.\d+\.\d+\.\d+\.\d+\.\d+\.\d+\.(\d+?)\./
}
}
################################################################################
# Performs an SNMP WALK and returns the response as an array.
################################################################################
@ -2015,7 +2064,7 @@ sub traceroute_connectivity($$) {
my $parent = $hops[$i]->ipaddr();
# Create an agent for the parent.
$self->call('create_agent', $parent);
$self->add_agent($parent);
$self->call('message', "Host $device is one hop away from host $parent.", 5);
$self->mark_connected($parent, '', $device, '');
@ -2064,27 +2113,61 @@ sub wmi_scan {
$self->call('message', "[".$target."] WMI available.", 10);
# Create the agent if it does not exist.
my $agent_id = $self->call('create_agent', $target);
next unless defined($agent_id);
# Register agent.
$self->add_agent($target);
# Add modules.
# CPU.
my @cpus = $self->wmi_get_value_array($target, $auth, 'SELECT DeviceId FROM Win32_Processor', 0);
foreach my $cpu (@cpus) {
$self->call('wmi_module',($agent_id,$target,"SELECT LoadPercentage FROM Win32_Processor WHERE DeviceId='$cpu'",$auth,1,"CPU Load $cpu","Load for $cpu (%)",'generic_data'));
$self->add_module($target, 'wmi',
{
'target' => $target,
'query' => "SELECT LoadPercentage FROM Win32_Processor WHERE DeviceId='$cpu'",
'auth' => $auth,
'column' => 1,
'name' => "CPU Load $cpu",
'description' => "Load for $cpu (%)",
'type' => 'generic_data',
'unit' => '%',
}
);
}
# Memory.
my $mem = $self->wmi_get_value($target, $auth, 'SELECT FreePhysicalMemory FROM Win32_OperatingSystem', 0);
if (defined($mem)) {
$self->call('wmi_module',($agent_id,$target,"SELECT FreePhysicalMemory, TotalVisibleMemorySize FROM Win32_OperatingSystem",$auth,0,'FreeMemory','Free memory','generic_data','KB'));
$self->add_module($target, 'wmi',
{
'target' => $target,
'query' => "SELECT FreePhysicalMemory, TotalVisibleMemorySize FROM Win32_OperatingSystem",
'auth' => $auth,
'column' => 0,
'name' => 'FreeMemory',
'description' => 'Free memory',
'type' => 'generic_data',
'unit' => 'KB',
}
);
}
# Disk.
my @units = $self->wmi_get_value_array($target, $auth, 'SELECT DeviceID FROM Win32_LogicalDisk', 0);
foreach my $unit (@units) {
$self->call('wmi_module',($agent_id,$target,"SELECT FreeSpace FROM Win32_LogicalDisk WHERE DeviceID='$unit'",$auth,1,"FreeDisk $unit",'Available disk space in kilobytes','generic_data','KB'));
$self->add_module($target, 'wmi',
{
'target' => $target,
'query' => "SELECT FreeSpace FROM Win32_LogicalDisk WHERE DeviceID='$unit'",
'auth' => $auth,
'column' => 1,
'name' => "FreeDisk $unit",
'description' => 'Available disk space in kilobytes',
'type' => 'generic_data',
'unit' => 'KB',
}
);
}
}
################################################################################

View File

@ -23,9 +23,9 @@ our @EXPORT = qw(
subnet_matches
);
########################################################################################
################################################################################
# Return an Enterprise Recon object.
########################################################################################
################################################################################
sub enterprise_new($$) {
my ($class, $arguments) = @_;
@ -53,18 +53,18 @@ sub enterprise_new($$) {
}
########################################################################################
################################################################################
# Return the numeric representation of the given IP address.
########################################################################################
################################################################################
sub ip_to_long($) {
my $ip_address = shift;
return unpack('N', inet_aton($ip_address));
}
########################################################################################
################################################################################
# Returns 1 if the two given MAC addresses are the same.
########################################################################################
################################################################################
sub mac_matches($$) {
my ($mac_1, $mac_2) = @_;
@ -75,9 +75,9 @@ sub mac_matches($$) {
return 0;
}
########################################################################################
################################################################################
# Convert a MAC address to decimal dotted notation.
########################################################################################
################################################################################
sub mac_to_dec($) {
my $mac = shift;
@ -91,9 +91,9 @@ sub mac_to_dec($) {
return $dec_mac;
}
########################################################################################
################################################################################
# Make sure all MAC addresses are in the same format (00 11 22 33 44 55 66).
########################################################################################
################################################################################
sub parse_mac($) {
my ($mac) = @_;
@ -114,9 +114,9 @@ sub parse_mac($) {
return $mac;
}
########################################################################################
################################################################################
# Returns 1 if the given IP address belongs to the given subnet.
########################################################################################
################################################################################
sub subnet_matches($$;$) {
my ($ipaddr, $subnet, $mask) = @_;
my ($netaddr, $netmask);

View File

@ -1,8 +1,8 @@
package PandoraFMS::Tools;
########################################################################
################################################################################
# Tools Package
# Pandora FMS. the Flexible Monitoring System. http://www.pandorafms.org
########################################################################
################################################################################
# Copyright (c) 2005-2011 Artica Soluciones Tecnologicas S.L
#
# This program is free software; you can redistribute it and/or
@ -15,7 +15,7 @@ package PandoraFMS::Tools;
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
##########################################################################
################################################################################
use warnings;
use Time::Local;
@ -109,8 +109,10 @@ our @EXPORT = qw(
float_equal
sqlWrap
is_numeric
is_enabled
is_metaconsole
is_offline
is_empty
to_number
clean_blank
credential_store_get_key
@ -128,6 +130,7 @@ our @EXPORT = qw(
pandora_ping
pandora_ping_latency
pandora_block_ping
ping
resolve_hostname
ticks_totime
safe_input
@ -361,9 +364,9 @@ my @ServerThreads;
# Keep threads running.
our $THRRUN :shared = 1;
##########################################################################
################################################################################
## Reads a file and returns entire content or undef if error.
##########################################################################
################################################################################
sub read_file {
my $path = shift;
@ -383,9 +386,9 @@ sub read_file {
}
###############################################################################
################################################################################
# Sets user:group owner for the given file
###############################################################################
################################################################################
sub set_file_permissions($$;$) {
my ($pa_config, $file, $grants) = @_;
if ($^O !~ /win/i ) { # Only for Linux environments
@ -410,10 +413,10 @@ sub set_file_permissions($$;$) {
}
########################################################################
################################################################################
## SUB pandora_trash_ascii
# Generate random ascii strings with variable lenght
########################################################################
################################################################################
sub pandora_trash_ascii {
my $config_depth = $_[0];
@ -426,9 +429,9 @@ sub pandora_trash_ascii {
return $output
}
########################################################################
################################################################################
## Convert the $value encode in html entity to clear char string.
########################################################################
################################################################################
sub safe_input($) {
my $value = shift;
@ -439,9 +442,9 @@ sub safe_input($) {
return $value;
}
########################################################################
################################################################################
## Convert the html entities to value encode to rebuild char string.
########################################################################
################################################################################
sub safe_output($) {
my $value = shift;
@ -452,10 +455,10 @@ sub safe_output($) {
return $value;
}
########################################################################
################################################################################
# Sub daemonize ()
# Put program in background (for daemon mode)
########################################################################
################################################################################
sub pandora_daemonize {
my $pa_config = $_[0];
@ -492,13 +495,13 @@ sub pandora_daemonize {
# Pandora other General functions |
# -------------------------------------------+
########################################################################
################################################################################
# SUB credential_store_get_key
# Retrieve all information related to target identifier.
# param1 - config hash
# param2 - dbh link
# param3 - string identifier
########################################################################
################################################################################
sub credential_store_get_key($$$) {
my ($pa_config, $dbh, $identifier) = @_;
@ -520,7 +523,7 @@ sub credential_store_get_key($$$) {
}
########################################################################
################################################################################
# SUB pandora_sendmail
# Send a mail, connecting directly to MTA
# param1 - config hash
@ -528,7 +531,7 @@ sub credential_store_get_key($$$) {
# param3 - Email subject
# param4 - Email Message body
# param4 - Email content type
########################################################################
################################################################################
sub pandora_sendmail {
@ -584,10 +587,10 @@ sub pandora_sendmail {
};
}
##########################################################################
################################################################################
# SUB is_numeric
# Return TRUE if given argument is numeric
##########################################################################
################################################################################
sub is_numeric {
my $val = $_[0];
@ -610,10 +613,56 @@ sub is_numeric {
}
}
##########################################################################
################################################################################
# SUB is_enabled
# Return TRUE if given argument is defined, number and greater than 1.
################################################################################
sub is_enabled {
my $value = shift;
if ((defined ($value)) && is_numeric($value) && ($value > 0)){
# return true
return 1;
}
#return false
return 0;
}
################################################################################
# SUB is_empty
# Return TRUE if given argument is an empty string/array/hash or undefined.
################################################################################
sub is_empty {
my $str = shift;
if (! (defined ($str)) ){
return 1;
}
if(looks_like_number($str)){
return 0;
}
if (ref ($str) eq "ARRAY") {
return (($#{$str}<0)?1:0);
}
if (ref ($str) eq "HASH") {
my @tmp = keys %{$str};
return (($#tmp<0)?1:0);
}
if ($str =~ /^\ *[\n\r]{0,2}\ *$/) {
return 1;
}
return 0;
}
################################################################################
# SUB md5check (param_1, param_2)
# Verify MD5 file .checksum
##########################################################################
################################################################################
# param_1 : Name of data file
# param_2 : Name of md5 file
@ -647,10 +696,10 @@ sub md5check {
}
}
########################################################################
################################################################################
# SUB logger (pa_config, message, level)
# Log to file
########################################################################
################################################################################
sub logger ($$;$) {
my ($pa_config, $message, $level) = @_;
@ -701,10 +750,10 @@ sub logger ($$;$) {
}
}
########################################################################
################################################################################
# SUB pandora_rotate_log (pa_config)
# Log to file
########################################################################
################################################################################
sub pandora_rotate_logfile ($) {
my ($pa_config) = @_;
@ -720,9 +769,9 @@ sub pandora_rotate_logfile ($) {
}
}
########################################################################
################################################################################
# limpia_cadena (string) - Purge a string for any forbidden characters (esc, etc)
########################################################################
################################################################################
sub limpia_cadena {
my $micadena;
$micadena = $_[0];
@ -736,9 +785,9 @@ sub limpia_cadena {
}
}
########################################################################
################################################################################
# clean_blank (string) - Remove leading and trailing blanks
########################################################################
################################################################################
sub clean_blank {
my $input = $_[0];
$input =~ s/^\s+//g;
@ -746,10 +795,10 @@ sub clean_blank {
return $input;
}
########################################################################################
################################################################################
# sub sqlWrap(texto)
# Elimina comillas y caracteres problematicos y los sustituye por equivalentes
########################################################################################
################################################################################
sub sqlWrap {
my $toBeWrapped = shift(@_);
@ -760,21 +809,21 @@ sub sqlWrap {
}
}
##########################################################################
################################################################################
# sub float_equal (num1, num2, decimals)
# This function make possible to compare two float numbers, using only x decimals
# in comparation.
# Taken from Perl Cookbook, O'Reilly. Thanks, guys.
##########################################################################
################################################################################
sub float_equal {
my ($A, $B, $dp) = @_;
return sprintf("%.${dp}g", $A) eq sprintf("%.${dp}g", $B);
}
##########################################################################
################################################################################
# Tries to load the PandoraEnterprise module. Must be called once before
# enterprise_hook ().
##########################################################################
################################################################################
sub enterprise_load ($) {
my $pa_config = shift;
@ -809,9 +858,9 @@ sub enterprise_load ($) {
return 1;
}
##########################################################################
################################################################################
# Tries to call a PandoraEnterprise function. Returns undef if unsuccessful.
##########################################################################
################################################################################
sub enterprise_hook ($$) {
my $func = shift;
my @args = @{shift ()};
@ -840,19 +889,19 @@ sub enterprise_hook ($$) {
return $output;
}
########################################################################
################################################################################
# Prints a message to STDOUT at the given log level.
########################################################################
################################################################################
sub print_message ($$$) {
my ($pa_config, $message, $log_level) = @_;
print STDOUT $message . "\n" if ($pa_config->{'verbosity'} >= $log_level);
}
##########################################################################
################################################################################
# Returns the value of an XML tag from a hash returned by XMLin (one level
# depth).
##########################################################################
################################################################################
sub get_tag_value ($$$;$) {
my ($hash_ref, $tag, $def_value, $all_array) = @_;
$all_array = 0 unless defined ($all_array);
@ -871,10 +920,10 @@ sub get_tag_value ($$$;$) {
return $def_value;
}
########################################################################
################################################################################
# Initialize some variables needed by the MD5 algorithm.
# See http://en.wikipedia.org/wiki/MD5#Pseudocode.
########################################################################
################################################################################
my (@R, @K);
sub md5_init () {
@ -890,10 +939,10 @@ sub md5_init () {
}
}
###############################################################################
################################################################################
# Return the MD5 checksum of the given string.
# Pseudocode from http://en.wikipedia.org/wiki/MD5#Pseudocode.
###############################################################################
################################################################################
sub md5 ($) {
my $str = shift;
@ -981,18 +1030,18 @@ sub md5 ($) {
return unpack ("H*", pack ("V", $h0)) . unpack ("H*", pack ("V", $h1)) . unpack ("H*", pack ("V", $h2)) . unpack ("H*", pack ("V", $h3));
}
###############################################################################
################################################################################
# MD5 leftrotate function. See http://en.wikipedia.org/wiki/MD5#Pseudocode.
###############################################################################
################################################################################
sub leftrotate ($$) {
my ($x, $c) = @_;
return (0xFFFFFFFF & ($x << $c)) | ($x >> (32 - $c));
}
##########################################################################
################################################################################
## Convert a date (yyy-mm-ddThh:ii:ss) to Timestamp.
##########################################################################
################################################################################
sub dateTimeToTimestamp {
$_[0] =~ /(\d{4})-(\d{2})-(\d{2})([ |T])(\d{2}):(\d{2}):(\d{2})/;
my($year, $mon, $day, $GMT, $hour, $min, $sec) = ($1, $2, $3, $4, $5, $6, $7);
@ -1002,10 +1051,10 @@ sub dateTimeToTimestamp {
#print "BST\t" . mktime($sec, $min, $hour, $day, $mon - 1, $year - 1900, 0, 0) . "\n";
}
##############################################################################
################################################################################
# Below some "internal" functions for automonitoring feature
# TODO: Implement the same for other systems like Solaris or BSD
##############################################################################
################################################################################
sub disk_free ($) {
my $target = $_[0];
@ -1082,10 +1131,10 @@ sub free_mem {
return $free_mem;
}
##########################################################################
################################################################################
## SUB ticks_totime
# Transform a snmp timeticks count in a date
##########################################################################
################################################################################
sub ticks_totime ($){
@ -1109,7 +1158,7 @@ sub ticks_totime ($){
return "$days days, $hours hours, $minutes minutes, $seconds seconds";
}
##############################################################################
################################################################################
=head2 C<< pandora_ping (I<$pa_config>, I<$host>) >>
Ping the given host.
@ -1118,7 +1167,7 @@ Returns:
0 otherwise.
=cut
##############################################################################
################################################################################
sub pandora_ping ($$$$) {
my ($pa_config, $host, $timeout, $retries) = @_;
@ -1236,13 +1285,13 @@ sub pandora_ping ($$$$) {
return $output;
}
########################################################################
################################################################################
=head2 C<< pandora_ping_latency (I<$pa_config>, I<$host>) >>
Ping the given host. Returns the average round-trip time. Returns undef if fails.
=cut
########################################################################
################################################################################
sub pandora_ping_latency ($$$$) {
my ($pa_config, $host, $timeout, $retries) = @_;
@ -1375,32 +1424,118 @@ sub pandora_ping_latency ($$$$) {
return $output;
}
########################################################################
################################################################################
=head2 C<< pandora_block_ping (I<$pa_config>, I<$hosts>) >>
Ping all given hosts. Returns an array with all hosts detected as alive.
=cut
########################################################################
################################################################################
sub pandora_block_ping($@) {
my ($pa_config, @hosts) = @_;
my ($cmd, $output);
# fping timeout in milliseconds
my $cmd = $pa_config->{'fping'} . " -a -q -t " . (1000 * $pa_config->{'networktimeout'}) . " " . (join (' ', @hosts));
my @output = `$cmd 2>$DEVNULL`;
if (-x $pa_config->{'fping'}) {
# fping timeout in milliseconds
$cmd = $pa_config->{'fping'} . " -a -q -t " . (1000 * $pa_config->{'networktimeout'}) . " " . (join (' ', @hosts));
@output = `$cmd 2>$DEVNULL`;
} else {
# Ping scan
foreach my $host (@hosts) {
if (ping($pa_config, $host) > 0) {
push @output, $host;
}
}
}
return @output;
}
########################################################################
################################################################################
=head2 C<< ping (I<$pa_config>, I<$hosts>) >>
Ping the given host. Returns 1 if the host is alive, 0 otherwise.
=cut
################################################################################
sub ping ($$) {
my ($pa_config, $host) = @_;
my ($timeout, $retries, $packets) = (
$pa_config->{'networktimeout'},
$pa_config->{'icmp_checks'},
1
);
# Windows
if (($^O eq "MSWin32") || ($^O eq "MSWin32-x64") || ($^O eq "cygwin")){
$timeout *= 1000; # Convert the timeout to milliseconds.
for (my $i = 0; $i < $retries; $i++) {
my $output = `ping -n $packets -w $timeout $host`;
return 1 if ($output =~ /TTL/);
}
return 0;
}
# Solaris
if ($^O eq "solaris"){
my $ping_command = $host =~ /\d+:|:\d+/ ? "ping -A inet6" : "ping";
for (my $i = 0; $i < $retries; $i++) {
# Note: There is no timeout option.
`$ping_command -s -n $host 56 $packets >$DEVNULL 2>&1`;
return 1 if ($? == 0);
}
return 0;
}
# FreeBSD
if ($^O eq "freebsd"){
my $ping_command = $host =~ /\d+:|:\d+/ ? "ping6" : "ping -t $timeout";
for (my $i = 0; $i < $retries; $i++) {
# Note: There is no timeout option for ping6.
`$ping_command -q -n -c $packets $host >$DEVNULL 2>&1`;
return 1 if ($? == 0);
}
return 0;
}
# NetBSD
if ($^O eq "netbsd"){
my $ping_command = $host =~ /\d+:|:\d+/ ? "ping6" : "ping -w $timeout";
for (my $i = 0; $i < $retries; $i++) {
# Note: There is no timeout option for ping6.
`$ping_command -q -n -c $packets $host >$DEVNULL 2>&1`;
if ($? == 0) {
return 1;
}
}
return 0;
}
# Assume Linux by default.
my $ping_command = $host =~ /\d+:|:\d+/ ? "ping6" : "ping";
for (my $i = 0; $i < $retries; $i++) {
`$ping_command -q -W $timeout -n -c $packets $host >$DEVNULL 2>&1`;
return 1 if ($? == 0);
}
return 0;
}
################################################################################
=head2 C<< month_have_days (I<$month>, I<$year>) >>
Pass a $month (as january 0 number and each month with numbers) and the year
as number (for example 1981). And return the days of this month.
=cut
########################################################################
################################################################################
sub month_have_days($$) {
my $month= shift(@_);
my $year= @_ ? shift(@_) : (1900 + (localtime())[5]);
@ -1428,9 +1563,9 @@ sub month_have_days($$) {
return $monthDays[$month];
}
###############################################################################
################################################################################
# Convert a text obj tag to an OID and update the module configuration.
###############################################################################
################################################################################
sub translate_obj ($$$) {
my ($pa_config, $dbh, $obj) = @_;
@ -1448,9 +1583,9 @@ sub translate_obj ($$$) {
return $oid;
}
###############################################################################
################################################################################
# Get the number of seconds left to the next execution of the given cron entry.
###############################################################################
################################################################################
sub cron_next_execution {
my ($cron, $interval) = @_;
@ -1482,18 +1617,18 @@ sub cron_next_execution {
return $nex_time - $cur_time;
}
###############################################################################
################################################################################
# Get the number of seconds left to the next execution of the given cron entry.
###############################################################################
################################################################################
sub cron_check_syntax ($) {
my ($cron) = @_;
return 0 if !defined ($cron);
return ($cron =~ m/^(\d|\*|-)+ (\d|\*|-)+ (\d|\*|-)+ (\d|\*|-)+ (\d|\*|-)+$/);
}
###############################################################################
################################################################################
# Check if a value is inside an interval.
###############################################################################
################################################################################
sub cron_check_interval {
my ($elem_cron, $elem_curr_time) = @_;
@ -1515,9 +1650,9 @@ sub cron_check_interval {
return 1;
}
###############################################################################
################################################################################
# Get the next execution date for the given cron entry in seconds since epoch.
###############################################################################
################################################################################
sub cron_next_execution_date {
my ($cron, $cur_time, $interval) = @_;
@ -1646,11 +1781,11 @@ sub cron_next_execution_date {
return $nex_time;
}
###############################################################################
################################################################################
# Returns if a date is in a cron. Recursive.
# Needs the cron like an array reference and
# current time in cron format to works properly
###############################################################################
################################################################################
sub cron_is_in_cron {
my ($elems_cron, $elems_curr_time) = @_;
@ -1687,11 +1822,11 @@ sub cron_get_next_time_element {
? $floor_data
: $elem_down;
}
###############################################################################
################################################################################
# Returns the interval of a cron element. If there is not a range,
# returns an array with the first element in the first place of array
# and the second place undefined.
###############################################################################
################################################################################
sub cron_get_interval {
my ($element) = @_;
@ -1702,10 +1837,10 @@ sub cron_get_interval {
return ($1, $2);
}
###############################################################################
################################################################################
# Returns the closest number to the target inside the given range (including
# the target itself).
###############################################################################
################################################################################
sub cron_get_closest_in_range ($$) {
my ($target, $range) = @_;
@ -1727,9 +1862,9 @@ sub cron_get_closest_in_range ($$) {
return $target;
}
###############################################################################
################################################################################
# Check if a date is valid to get timelocal
###############################################################################
################################################################################
sub cron_valid_date {
my ($min, $hour, $mday, $month, $year) = @_;
my $utime;
@ -1743,9 +1878,9 @@ sub cron_valid_date {
return $utime;
}
###############################################################################
################################################################################
# Attempt to resolve the given hostname.
###############################################################################
################################################################################
sub resolve_hostname ($) {
my ($hostname) = @_;
@ -1755,9 +1890,9 @@ sub resolve_hostname ($) {
return inet_ntoa($resolved_hostname);
}
###############################################################################
################################################################################
# Returns 1 if the given regular expression is valid, 0 otherwise.
###############################################################################
################################################################################
sub valid_regex ($) {
my $regex = shift;
@ -1773,9 +1908,9 @@ sub valid_regex ($) {
return 1;
}
###############################################################################
################################################################################
# Returns 1 if a valid metaconsole license is configured, 0 otherwise.
###############################################################################
################################################################################
sub is_metaconsole ($) {
my ($pa_config) = @_;
@ -1788,9 +1923,9 @@ sub is_metaconsole ($) {
return 0;
}
###############################################################################
################################################################################
# Returns 1 if a valid offline license is configured, 0 otherwise.
###############################################################################
################################################################################
sub is_offline ($) {
my ($pa_config) = @_;
@ -1802,9 +1937,9 @@ sub is_offline ($) {
return 0;
}
###############################################################################
################################################################################
# Check if a given variable contents a number
###############################################################################
################################################################################
sub to_number($) {
my $n = shift;
if ($n =~ /[\d+,]*\d+\.\d+/) {
@ -1956,10 +2091,10 @@ sub generate_agent_name_hash {
return sha256(join('|', ($agent_alias, $server_ip, time(), sprintf("%04d", rand(10000)))));
}
###############################################################################
################################################################################
# Return the SHA256 checksum of the given string as a hex string.
# Pseudocode from: http://en.wikipedia.org/wiki/SHA-2#Pseudocode
###############################################################################
################################################################################
my @K2 = (
0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1,
0x923f82a4, 0xab1c5ed5, 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
@ -2079,34 +2214,34 @@ sub sha256 {
unpack ("H*", pack ("N", $h7));
}
###############################################################################
################################################################################
# Rotate a 32-bit number a number of bits to the right.
###############################################################################
################################################################################
sub rightrotate {
my ($x, $c) = @_;
return (0xFFFFFFFF & ($x << (32 - $c))) | ($x >> $c);
}
###############################################################################
################################################################################
# Returns IP address(v4) in longint format
###############################################################################
sub ip_to_long {
################################################################################
sub ip_to_long($) {
my $ip_str = shift;
return unpack "N", inet_aton($ip_str);
}
###############################################################################
################################################################################
# Returns IP address(v4) in longint format
###############################################################################
################################################################################
sub long_to_ip {
my $ip_long = shift;
return inet_ntoa pack("N", ($ip_long));
}
###############################################################################
################################################################################
# Returns a list with enabled servers.
###############################################################################
################################################################################
sub get_enabled_servers {
my $conf = shift;