diff --git a/pandora_agents/unix/DEBIAN/control b/pandora_agents/unix/DEBIAN/control
index 620811d958..cbe5c93ed8 100644
--- a/pandora_agents/unix/DEBIAN/control
+++ b/pandora_agents/unix/DEBIAN/control
@@ -1,5 +1,5 @@
package: pandorafms-agent-unix
-Version: 7.0NG.744-200413
+Version: 7.0NG.744-200414
Architecture: all
Priority: optional
Section: admin
diff --git a/pandora_agents/unix/DEBIAN/make_deb_package.sh b/pandora_agents/unix/DEBIAN/make_deb_package.sh
index b9b3c894fd..68b1e4e171 100644
--- a/pandora_agents/unix/DEBIAN/make_deb_package.sh
+++ b/pandora_agents/unix/DEBIAN/make_deb_package.sh
@@ -14,7 +14,7 @@
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
-pandora_version="7.0NG.744-200413"
+pandora_version="7.0NG.744-200414"
echo "Test if you has the tools for to make the packages."
whereis dpkg-deb | cut -d":" -f2 | grep dpkg-deb > /dev/null
diff --git a/pandora_agents/unix/Linux/pandora_agent.conf b/pandora_agents/unix/Linux/pandora_agent.conf
index 52ca10f17b..34f9d8e02b 100644
--- a/pandora_agents/unix/Linux/pandora_agent.conf
+++ b/pandora_agents/unix/Linux/pandora_agent.conf
@@ -254,9 +254,6 @@ module_plugin pandora_mem_used
module_plugin pandora_netusage
-# Service autodiscovery plugin
-module_plugin autodiscover --default
-
# Plugin for inventory on the agent (Only Enterprise)
#module_plugin inventory 1 cpu ram video nic hd cdrom software init_services filesystem users route
diff --git a/pandora_agents/unix/pandora_agent b/pandora_agents/unix/pandora_agent
index 0929056b0e..0280895693 100755
--- a/pandora_agents/unix/pandora_agent
+++ b/pandora_agents/unix/pandora_agent
@@ -55,7 +55,7 @@ my $Sem = undef;
my $ThreadSem = undef;
use constant AGENT_VERSION => '7.0NG.744';
-use constant AGENT_BUILD => '200413';
+use constant AGENT_BUILD => '200414';
# Agent log default file size maximum and instances
use constant DEFAULT_MAX_LOG_SIZE => 600000;
diff --git a/pandora_agents/unix/pandora_agent.redhat.spec b/pandora_agents/unix/pandora_agent.redhat.spec
index f8dc6591df..6c7af89df6 100644
--- a/pandora_agents/unix/pandora_agent.redhat.spec
+++ b/pandora_agents/unix/pandora_agent.redhat.spec
@@ -3,7 +3,7 @@
#
%define name pandorafms_agent_unix
%define version 7.0NG.744
-%define release 200413
+%define release 200414
Summary: Pandora FMS Linux agent, PERL version
Name: %{name}
diff --git a/pandora_agents/unix/pandora_agent.spec b/pandora_agents/unix/pandora_agent.spec
index 9b5f041e13..b96019b8e0 100644
--- a/pandora_agents/unix/pandora_agent.spec
+++ b/pandora_agents/unix/pandora_agent.spec
@@ -3,7 +3,7 @@
#
%define name pandorafms_agent_unix
%define version 7.0NG.744
-%define release 200413
+%define release 200414
Summary: Pandora FMS Linux agent, PERL version
Name: %{name}
diff --git a/pandora_agents/unix/pandora_agent_installer b/pandora_agents/unix/pandora_agent_installer
index 43e57913e8..4e5072610c 100755
--- a/pandora_agents/unix/pandora_agent_installer
+++ b/pandora_agents/unix/pandora_agent_installer
@@ -10,7 +10,7 @@
# **********************************************************************
PI_VERSION="7.0NG.744"
-PI_BUILD="200413"
+PI_BUILD="200414"
OS_NAME=`uname -s`
FORCE=0
diff --git a/pandora_agents/unix/plugins/autodiscover b/pandora_agents/unix/plugins/autodiscover
deleted file mode 100644
index cbe4de677e..0000000000
Binary files a/pandora_agents/unix/plugins/autodiscover and /dev/null differ
diff --git a/pandora_agents/win32/bin/pandora_agent.conf b/pandora_agents/win32/bin/pandora_agent.conf
index 774797aa4b..ba1e0b6444 100644
--- a/pandora_agents/win32/bin/pandora_agent.conf
+++ b/pandora_agents/win32/bin/pandora_agent.conf
@@ -245,10 +245,6 @@ module_plugin cscript.exe //B "%ProgramFiles%\Pandora_Agent\util\network.vbs"
#module_crontab * 12-15 * * 1
#module_end
-# Service autodiscovery plugin
-module_plugin "%PROGRAMFILES%\Pandora_Agent\util\autodiscover.exe" --default
-
-
#########################################
# EXAMPLES #
#########################################
diff --git a/pandora_agents/win32/bin/util/autodiscover.exe b/pandora_agents/win32/bin/util/autodiscover.exe
deleted file mode 100644
index 41b7bf3629..0000000000
Binary files a/pandora_agents/win32/bin/util/autodiscover.exe and /dev/null differ
diff --git a/pandora_agents/win32/installer/pandora.mpi b/pandora_agents/win32/installer/pandora.mpi
index 61074a602b..d823426c8f 100644
--- a/pandora_agents/win32/installer/pandora.mpi
+++ b/pandora_agents/win32/installer/pandora.mpi
@@ -186,7 +186,7 @@ UpgradeApplicationID
{}
Version
-{200413}
+{200414}
ViewReadme
{Yes}
diff --git a/pandora_agents/win32/pandora.cc b/pandora_agents/win32/pandora.cc
index c497ebd0b4..1e3c7a48a1 100644
--- a/pandora_agents/win32/pandora.cc
+++ b/pandora_agents/win32/pandora.cc
@@ -30,7 +30,7 @@ using namespace Pandora;
using namespace Pandora_Strutils;
#define PATH_SIZE _MAX_PATH+1
-#define PANDORA_VERSION ("7.0NG.744(Build 200413)")
+#define PANDORA_VERSION ("7.0NG.744(Build 200414)")
string pandora_path;
string pandora_dir;
diff --git a/pandora_agents/win32/versioninfo.rc b/pandora_agents/win32/versioninfo.rc
index c557f2030a..ffb90a0619 100644
--- a/pandora_agents/win32/versioninfo.rc
+++ b/pandora_agents/win32/versioninfo.rc
@@ -11,7 +11,7 @@ BEGIN
VALUE "LegalCopyright", "Artica ST"
VALUE "OriginalFilename", "PandoraAgent.exe"
VALUE "ProductName", "Pandora FMS Windows Agent"
- VALUE "ProductVersion", "(7.0NG.744(Build 200413))"
+ VALUE "ProductVersion", "(7.0NG.744(Build 200414))"
VALUE "FileVersion", "1.0.0.0"
END
END
diff --git a/pandora_console/.htaccess b/pandora_console/.htaccess
index 593204bd27..a1e6f62d2d 100644
--- a/pandora_console/.htaccess
+++ b/pandora_console/.htaccess
@@ -1,2 +1,8 @@
# pandora disable listing
-Options -Indexes
\ No newline at end of file
+Options -Indexes
+
+
+Order Allow,Deny
+Deny from All
+
+
diff --git a/pandora_console/DEBIAN/control b/pandora_console/DEBIAN/control
index 18e85bb809..68255e4e05 100644
--- a/pandora_console/DEBIAN/control
+++ b/pandora_console/DEBIAN/control
@@ -1,5 +1,5 @@
package: pandorafms-console
-Version: 7.0NG.744-200413
+Version: 7.0NG.744-200414
Architecture: all
Priority: optional
Section: admin
diff --git a/pandora_console/DEBIAN/make_deb_package.sh b/pandora_console/DEBIAN/make_deb_package.sh
index 86a5a758d9..84a4c8d67b 100644
--- a/pandora_console/DEBIAN/make_deb_package.sh
+++ b/pandora_console/DEBIAN/make_deb_package.sh
@@ -14,7 +14,7 @@
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
-pandora_version="7.0NG.744-200413"
+pandora_version="7.0NG.744-200414"
package_pear=0
package_pandora=1
diff --git a/pandora_console/extras/mr/37.sql b/pandora_console/extras/mr/37.sql
index e3154fe0fb..60272f6a0c 100644
--- a/pandora_console/extras/mr/37.sql
+++ b/pandora_console/extras/mr/37.sql
@@ -2,6 +2,53 @@ START TRANSACTION;
ALTER TABLE tagente_modulo MODIFY COLUMN `custom_string_1` MEDIUMTEXT;
+ALTER TABLE `trecon_task` MODIFY COLUMN `id_network_profile` TEXT;
+ALTER TABLE `trecon_task` CHANGE COLUMN `create_incident` `review_mode` TINYINT(1) UNSIGNED DEFAULT 0;
+ALTER TABLE `trecon_task` ADD COLUMN `subnet_csv` TINYINT(1) UNSIGNED DEFAULT 1;
+
+UPDATE `trecon_task` SET `review_mode` = 1;
+ALTER TABLE trecon_task add column `auto_monitor` TINYINT(1) UNSIGNED DEFAULT 1 AFTER `auth_strings`;
+UPDATE `trecon_task` SET `auto_monitor` = 0;
+
+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` MEDIUMTEXT,
+ `review_date` datetime DEFAULT NULL,
+ `created` datetime DEFAULT NULL,
+ 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` int(10) unsigned NOT NULL AUTO_INCREMENT,
+ `id_rt` int(10) unsigned NOT NULL,
+ `dev_1` text,
+ `dev_2` text,
+ `if_1` text,
+ `if_2` text,
+ PRIMARY KEY (`id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+
+CREATE TABLE `tpen` (
+ `pen` int(10) unsigned NOT NULL,
+ `manufacturer` TEXT,
+ `description` TEXT,
+ PRIMARY KEY (`pen`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+
+CREATE TABLE IF NOT EXISTS `tnetwork_profile_pen` (
+ `pen` int(10) unsigned NOT NULL,
+ `id_np` int(10) unsigned NOT NULL,
+ CONSTRAINT `fk_network_profile_pen_pen` FOREIGN KEY (`pen`)
+ REFERENCES `tpen` (`pen`) ON DELETE CASCADE ON UPDATE CASCADE,
+ CONSTRAINT `fk_network_profile_pen_id_np` FOREIGN KEY (`id_np`)
+ REFERENCES `tnetwork_profile` (`id_np`) ON DELETE CASCADE ON UPDATE CASCADE
+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+
ALTER TABLE `twidget_dashboard` ADD COLUMN `position` TEXT NOT NULL default '';
ALTER TABLE `tagente_estado` ADD COLUMN `last_status_change` bigint(20) NOT NULL default '0';
@@ -12,4 +59,111 @@ ALTER TABLE `talert_templates` ADD COLUMN `disable_event` tinyint(1) DEFAULT 0;
ALTER TABLE `tevent_alert` ADD COLUMN `disable_event` tinyint(1) DEFAULT 0;
ALTER TABLE `talert_snmp` ADD COLUMN `disable_event` tinyint(1) DEFAULT 0;
+UPDATE twidget SET description='Show a visual console' WHERE class_name='MapsMadeByUser';
+UPDATE twidget SET description='Clock' WHERE class_name='ClockWidget';
+UPDATE twidget SET description='Group status' WHERE class_name='SystemGroupStatusWidget';
+
+INSERT IGNORE INTO `tpen` VALUES (9,'cisco','Cisco System'),(11,'hp','Hewlett Packard'),(2021,'general_snmp','U.C. Davis, ECE Dept. Tom'),(2636,'juniper','Juniper Networks'),(3375,'f5','F5 Labs'),(8072,'general_snmp','Net SNMP'),(12356,'fortinet','Fortinet');
+
+SET @template_name = 'Network Management';
+SET @template_description = 'Basic network monitoring template';
+
+INSERT INTO tnetwork_profile (id_np, name, description) SELECT * FROM (SELECT '' id_np, @template_name name, @template_description description) AS tmp WHERE NOT EXISTS (SELECT id_np FROM tnetwork_profile WHERE name = @template_name);
+INSERT INTO tnetwork_profile_component (id_nc, id_np) SELECT * FROM (SELECT c.id_nc id_nc, p.id_np id_np FROM tnetwork_profile p, tnetwork_component c, tnetwork_component_group g WHERE g.id_sg = c.id_group AND p.name = @template_name AND (g.name = 'Network Management')) AS tmp WHERE NOT EXISTS (SELECT pc.id_np FROM tnetwork_profile p, tnetwork_profile_component pc WHERE p.id_np = pc.id_np AND p.name = @template_name);
+
+SET @template_name = 'Cisco MIBS';
+SET @template_description = 'Cisco devices monitoring template (SNMP)';
+
+INSERT INTO tnetwork_profile (id_np, name, description) SELECT * FROM (SELECT '' id_np, @template_name name, @template_description description) AS tmp WHERE NOT EXISTS (SELECT id_np FROM tnetwork_profile WHERE name = @template_name);
+INSERT INTO tnetwork_profile_component (id_nc, id_np) SELECT * FROM (SELECT c.id_nc id_nc, p.id_np id_np FROM tnetwork_profile p, tnetwork_component c, tnetwork_component_group g WHERE g.id_sg = c.id_group AND p.name = @template_name AND (g.name = 'Cisco MIBS' OR g.name = 'Catalyst 2900')) AS tmp WHERE NOT EXISTS (SELECT pc.id_np FROM tnetwork_profile p, tnetwork_profile_component pc WHERE p.id_np = pc.id_np AND p.name = @template_name);
+INSERT INTO tnetwork_profile_pen (pen, id_np) SELECT * FROM (SELECT p.pen pen, np.id_np id_np FROM tnetwork_profile np, tpen p WHERE np.name = @template_name AND (p.pen = 9)) AS tmp WHERE NOT EXISTS (SELECT pp.id_np FROM tnetwork_profile p, tnetwork_profile_pen pp WHERE p.id_np = pp.id_np AND p.name = @template_name);
+
+SET @template_name = 'Linux System';
+SET @template_description = 'Linux system monitoring template (SNMP)';
+
+INSERT INTO tnetwork_profile (id_np, name, description) SELECT * FROM (SELECT '' id_np, @template_name name, @template_description description) AS tmp WHERE NOT EXISTS (SELECT id_np FROM tnetwork_profile WHERE name = @template_name);
+
+SET @module_group = 'Linux';
+
+INSERT INTO tnetwork_profile_component (id_nc, id_np) SELECT * FROM (SELECT c.id_nc id_nc, p.id_np id_np FROM tnetwork_profile p, tnetwork_component c, tnetwork_component_group g WHERE g.id_sg = c.id_group AND p.name = @template_name AND (g.name = 'Linux' OR g.name = 'UCD Mibs (Linux, UCD-SNMP)')) AS tmp WHERE NOT EXISTS (SELECT pc.id_np FROM tnetwork_profile p, tnetwork_profile_component pc WHERE p.id_np = pc.id_np AND p.name = @template_name);
+INSERT INTO tnetwork_profile_pen (pen, id_np) SELECT * FROM (SELECT p.pen pen, np.id_np id_np FROM tnetwork_profile np, tpen p WHERE np.name = @template_name AND (p.pen = 2021 OR p.pen = 2636)) AS tmp WHERE NOT EXISTS (SELECT pp.id_np FROM tnetwork_profile p, tnetwork_profile_pen pp WHERE p.id_np = pp.id_np AND p.name = @template_name);
+
+SET @template_name = 'Windows System';
+SET @template_description = 'Windows system monitoring template (WMI)';
+
+INSERT INTO tnetwork_profile (id_np, name, description) SELECT * FROM (SELECT '' id_np, @template_name name, @template_description description) AS tmp WHERE NOT EXISTS (SELECT id_np FROM tnetwork_profile WHERE name = @template_name);
+INSERT INTO tnetwork_profile_component (id_nc, id_np) SELECT * FROM (SELECT c.id_nc id_nc, p.id_np id_np FROM tnetwork_profile p, tnetwork_component c, tnetwork_component_group g WHERE g.id_sg = c.id_group AND p.name = @template_name AND (g.name = 'Microsoft Windows' OR g.name = 'Windows System')) AS tmp WHERE NOT EXISTS (SELECT pc.id_np FROM tnetwork_profile p, tnetwork_profile_component pc WHERE p.id_np = pc.id_np AND p.name = @template_name);
+
+SET @template_name = 'Windows Hardware';
+SET @template_description = 'Windows hardware monitoring templae (WMI)';
+
+INSERT INTO tnetwork_profile (id_np, name, description) SELECT * FROM (SELECT '' id_np, @template_name name, @template_description description) AS tmp WHERE NOT EXISTS (SELECT id_np FROM tnetwork_profile WHERE name = @template_name);
+INSERT INTO tnetwork_profile_component (id_nc, id_np) SELECT * FROM (SELECT c.id_nc id_nc, p.id_np id_np FROM tnetwork_profile p, tnetwork_component c, tnetwork_component_group g WHERE g.id_sg = c.id_group AND p.name = @template_name AND (g.name = 'Windows Hardware Layer')) AS tmp WHERE NOT EXISTS (SELECT pc.id_np FROM tnetwork_profile p, tnetwork_profile_component pc WHERE p.id_np = pc.id_np AND p.name = @template_name);
+
+SET @template_name = 'Windows Active Directory';
+SET @template_description = 'Active directory monitoring template (WMI)';
+
+INSERT INTO tnetwork_profile (id_np, name, description) SELECT * FROM (SELECT '' id_np, @template_name name, @template_description description) AS tmp WHERE NOT EXISTS (SELECT id_np FROM tnetwork_profile WHERE name = @template_name);
+INSERT INTO tnetwork_profile_component (id_nc, id_np) SELECT * FROM (SELECT c.id_nc id_nc, p.id_np id_np FROM tnetwork_profile p, tnetwork_component c, tnetwork_component_group g WHERE g.id_sg = c.id_group AND p.name = @template_name AND (g.name = 'Windows AD' OR g.name = 'AD Counters')) AS tmp WHERE NOT EXISTS (SELECT pc.id_np FROM tnetwork_profile p, tnetwork_profile_component pc WHERE p.id_np = pc.id_np AND p.name = @template_name);
+
+SET @template_name = 'Windows IIS';
+SET @template_description = 'IIS monitoring template (WMI)';
+
+INSERT INTO tnetwork_profile (id_np, name, description) SELECT * FROM (SELECT '' id_np, @template_name name, @template_description description) AS tmp WHERE NOT EXISTS (SELECT id_np FROM tnetwork_profile WHERE name = @template_name);
+INSERT INTO tnetwork_profile_component (id_nc, id_np) SELECT * FROM (SELECT c.id_nc id_nc, p.id_np id_np FROM tnetwork_profile p, tnetwork_component c, tnetwork_component_group g WHERE g.id_sg = c.id_group AND p.name = @template_name AND (g.name = 'Windows IIS' OR g.name = 'IIS services')) AS tmp WHERE NOT EXISTS (SELECT pc.id_np FROM tnetwork_profile p, tnetwork_profile_component pc WHERE p.id_np = pc.id_np AND p.name = @template_name);
+
+SET @template_name = 'Windows Exchange';
+SET @template_description = 'Exchange monitoring template (WMI)';
+
+INSERT INTO tnetwork_profile (id_np, name, description) SELECT * FROM (SELECT '' id_np, @template_name name, @template_description description) AS tmp WHERE NOT EXISTS (SELECT id_np FROM tnetwork_profile WHERE name = @template_name);
+INSERT INTO tnetwork_profile_component (id_nc, id_np) SELECT * FROM (SELECT c.id_nc id_nc, p.id_np id_np FROM tnetwork_profile p, tnetwork_component c, tnetwork_component_group g WHERE g.id_sg = c.id_group AND p.name = @template_name AND (g.name = 'Windows Exchange' OR g.name = 'Exchange Services' OR g.name = 'Exchange TCP Ports')) AS tmp WHERE NOT EXISTS (SELECT pc.id_np FROM tnetwork_profile p, tnetwork_profile_component pc WHERE p.id_np = pc.id_np AND p.name = @template_name);
+
+SET @template_name = 'Windows LDAP';
+SET @template_description = 'LDAP monitoring template (WMI)';
+
+INSERT INTO tnetwork_profile (id_np, name, description) SELECT * FROM (SELECT '' id_np, @template_name name, @template_description description) AS tmp WHERE NOT EXISTS (SELECT id_np FROM tnetwork_profile WHERE name = @template_name);
+INSERT INTO tnetwork_profile_component (id_nc, id_np) SELECT * FROM (SELECT c.id_nc id_nc, p.id_np id_np FROM tnetwork_profile p, tnetwork_component c, tnetwork_component_group g WHERE g.id_sg = c.id_group AND p.name = @template_name AND (g.name = 'Windows LDAP')) AS tmp WHERE NOT EXISTS (SELECT pc.id_np FROM tnetwork_profile p, tnetwork_profile_component pc WHERE p.id_np = pc.id_np AND p.name = @template_name);
+
+SET @template_name = 'Windows MDSTC';
+SET @template_description = 'MDSTC monitoring template (WMI)';
+
+INSERT INTO tnetwork_profile (id_np, name, description) SELECT * FROM (SELECT '' id_np, @template_name name, @template_description description) AS tmp WHERE NOT EXISTS (SELECT id_np FROM tnetwork_profile WHERE name = @template_name);
+INSERT INTO tnetwork_profile_component (id_nc, id_np) SELECT * FROM (SELECT c.id_nc id_nc, p.id_np id_np FROM tnetwork_profile p, tnetwork_component c, tnetwork_component_group g WHERE g.id_sg = c.id_group AND p.name = @template_name AND (g.name = 'Windows MSDTC')) AS tmp WHERE NOT EXISTS (SELECT pc.id_np FROM tnetwork_profile p, tnetwork_profile_component pc WHERE p.id_np = pc.id_np AND p.name = @template_name);
+
+SET @template_name = 'Windows Printers';
+SET @template_description = 'Windows printers monitoring template (WMI)';
+
+INSERT INTO tnetwork_profile (id_np, name, description) SELECT * FROM (SELECT '' id_np, @template_name name, @template_description description) AS tmp WHERE NOT EXISTS (SELECT id_np FROM tnetwork_profile WHERE name = @template_name);
+INSERT INTO tnetwork_profile_component (id_nc, id_np) SELECT * FROM (SELECT c.id_nc id_nc, p.id_np id_np FROM tnetwork_profile p, tnetwork_component c, tnetwork_component_group g WHERE g.id_sg = c.id_group AND p.name = @template_name AND (g.name = 'Windows Printers')) AS tmp WHERE NOT EXISTS (SELECT pc.id_np FROM tnetwork_profile p, tnetwork_profile_component pc WHERE p.id_np = pc.id_np AND p.name = @template_name);
+
+SET @template_name = 'Windows DNS';
+SET @template_description = 'Windows DNS monitoring template (WMI)';
+
+INSERT INTO tnetwork_profile (id_np, name, description) SELECT * FROM (SELECT '' id_np, @template_name name, @template_description description) AS tmp WHERE NOT EXISTS (SELECT id_np FROM tnetwork_profile WHERE name = @template_name);
+INSERT INTO tnetwork_profile_component (id_nc, id_np) SELECT * FROM (SELECT c.id_nc id_nc, p.id_np id_np FROM tnetwork_profile p, tnetwork_component c, tnetwork_component_group g WHERE g.id_sg = c.id_group AND p.name = @template_name AND (g.name = 'Windows DNS' OR g.name = 'DNS Counters')) AS tmp WHERE NOT EXISTS (SELECT pc.id_np FROM tnetwork_profile p, tnetwork_profile_component pc WHERE p.id_np = pc.id_np AND p.name = @template_name);
+
+SET @template_name = 'Windows MS SQL Server';
+SET @template_description = 'MS SQL Server monitoring template (WMI)';
+
+INSERT INTO tnetwork_profile (id_np, name, description) SELECT * FROM (SELECT '' id_np, @template_name name, @template_description description) AS tmp WHERE NOT EXISTS (SELECT id_np FROM tnetwork_profile WHERE name = @template_name);
+INSERT INTO tnetwork_profile_component (id_nc, id_np) SELECT * FROM (SELECT c.id_nc id_nc, p.id_np id_np FROM tnetwork_profile p, tnetwork_component c, tnetwork_component_group g WHERE g.id_sg = c.id_group AND p.name = @template_name AND (g.name = 'MS SQL Server')) AS tmp WHERE NOT EXISTS (SELECT pc.id_np FROM tnetwork_profile p, tnetwork_profile_component pc WHERE p.id_np = pc.id_np AND p.name = @template_name);
+
+SET @template_name = 'Oracle';
+SET @template_description = 'Oracle monitoring template';
+
+INSERT INTO tnetwork_profile (id_np, name, description) SELECT * FROM (SELECT '' id_np, @template_name name, @template_description description) AS tmp WHERE NOT EXISTS (SELECT id_np FROM tnetwork_profile WHERE name = @template_name);
+INSERT INTO tnetwork_profile_component (id_nc, id_np) SELECT * FROM (SELECT c.id_nc id_nc, p.id_np id_np FROM tnetwork_profile p, tnetwork_component c, tnetwork_component_group g WHERE g.id_sg = c.id_group AND p.name = @template_name AND (g.name = 'Oracle')) AS tmp WHERE NOT EXISTS (SELECT pc.id_np FROM tnetwork_profile p, tnetwork_profile_component pc WHERE p.id_np = pc.id_np AND p.name = @template_name);
+
+SET @template_name = 'MySQL';
+SET @template_description = 'MySQL monitoring template';
+
+INSERT INTO tnetwork_profile (id_np, name, description) SELECT * FROM (SELECT '' id_np, @template_name name, @template_description description) AS tmp WHERE NOT EXISTS (SELECT id_np FROM tnetwork_profile WHERE name = @template_name);
+INSERT INTO tnetwork_profile_component (id_nc, id_np) SELECT * FROM (SELECT c.id_nc id_nc, p.id_np id_np FROM tnetwork_profile p, tnetwork_component c, tnetwork_component_group g WHERE g.id_sg = c.id_group AND p.name = @template_name AND (g.name = 'MySQL')) AS tmp WHERE NOT EXISTS (SELECT pc.id_np FROM tnetwork_profile p, tnetwork_profile_component pc WHERE p.id_np = pc.id_np AND p.name = @template_name);
+
+SET @template_name = 'Windows Antivirus';
+SET @template_description = 'Windows antivirus monitoring template (WMI)';
+
+INSERT INTO tnetwork_profile (id_np, name, description) SELECT * FROM (SELECT '' id_np, @template_name name, @template_description description) AS tmp WHERE NOT EXISTS (SELECT id_np FROM tnetwork_profile WHERE name = @template_name);
+INSERT INTO tnetwork_profile_component (id_nc, id_np) SELECT * FROM (SELECT c.id_nc id_nc, p.id_np id_np FROM tnetwork_profile p, tnetwork_component c, tnetwork_component_group g WHERE g.id_sg = c.id_group AND p.name = @template_name AND (g.name = 'Norton' OR g.name = 'Panda' OR g.name = 'McAfee' OR g.name = 'Bitdefender' OR g.name = 'BullGuard' OR g.name = 'AVG' OR g.name = 'Kaspersky')) AS tmp WHERE NOT EXISTS (SELECT pc.id_np FROM tnetwork_profile p, tnetwork_profile_component pc WHERE p.id_np = pc.id_np AND p.name = @template_name);
+
COMMIT;
diff --git a/pandora_console/extras/pandoradb_migrate_6.0_to_7.0.mysql.sql b/pandora_console/extras/pandoradb_migrate_6.0_to_7.0.mysql.sql
index 2854b9e6c8..abfbdb4f96 100644
--- a/pandora_console/extras/pandoradb_migrate_6.0_to_7.0.mysql.sql
+++ b/pandora_console/extras/pandoradb_migrate_6.0_to_7.0.mysql.sql
@@ -1477,6 +1477,28 @@ ALTER TABLE tnetwork_component ADD COLUMN `dynamic_two_tailed` tinyint(1) unsign
ALTER TABLE `tnetwork_component` ADD COLUMN `ff_type` tinyint(1) unsigned default '0';
ALTER TABLE `tnetwork_component` MODIFY COLUMN `ff_type` tinyint(1) unsigned NULL DEFAULT '0';
+-- ----------------------------------------------------------------------
+-- Table `tpen`
+-- ----------------------------------------------------------------------
+CREATE TABLE IF NOT EXISTS `tpen` (
+ `pen` int(10) unsigned NOT NULL,
+ `manufacturer` TEXT,
+ `description` TEXT,
+ PRIMARY KEY (`pen`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+
+-- ----------------------------------------------------------------------
+-- Table `tnetwork_profile_pen`
+-- ----------------------------------------------------------------------
+CREATE TABLE IF NOT EXISTS `tnetwork_profile_pen` (
+ `pen` int(10) unsigned NOT NULL,
+ `id_np` int(10) unsigned NOT NULL,
+ CONSTRAINT `fk_network_profile_pen_pen` FOREIGN KEY (`pen`)
+ REFERENCES `tpen` (`pen`) ON DELETE CASCADE ON UPDATE CASCADE,
+ CONSTRAINT `fk_network_profile_pen_id_np` FOREIGN KEY (`id_np`)
+ REFERENCES `tnetwork_profile` (`id_np`) ON DELETE CASCADE ON UPDATE CASCADE
+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+
-- ---------------------------------------------------------------------
-- Table `tagente`
-- ---------------------------------------------------------------------
@@ -1662,7 +1684,39 @@ ALTER TABLE `trecon_task` ADD COLUMN `type` int(11) NOT NULL DEFAULT '0',
MODIFY COLUMN `wmi_enabled` tinyint(1) unsigned 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 `summary` text NULL,
+ MODIFY COLUMN `id_network_profile` text,
+ CHANGE COLUMN `create_incident` `review_mode` TINYINT(1) UNSIGNED DEFAULT 1,
+ ADD COLUMN `subnet_csv` TINYINT(1) UNSIGNED DEFAULT 0;
+
+-- Old recon always report.
+UPDATE `trecon_task` SET `review_mode` = 1;
+
+-- ----------------------------------------------------------------------
+-- 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` MEDIUMTEXT,
+ `review_date` datetime DEFAULT NULL,
+ `created` datetime DEFAULT NULL,
+ 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` int(10) unsigned NOT NULL AUTO_INCREMENT,
+ `id_rt` int(10) unsigned NOT NULL,
+ `dev_1` text,
+ `dev_2` text,
+ `if_1` text,
+ `if_2` text,
+ PRIMARY KEY (`id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- ---------------------------------------------------------------------
-- Table `twidget` AND Table `twidget_dashboard`
@@ -2129,6 +2183,8 @@ ALTER TABLE `trecon_task` ADD COLUMN `snmp_auth_method` varchar(25) NOT NULL def
ALTER TABLE `trecon_task` ADD COLUMN `snmp_privacy_method` varchar(25) NOT NULL default '';
ALTER TABLE `trecon_task` ADD COLUMN `snmp_privacy_pass` varchar(255) NOT NULL default '';
ALTER TABLE `trecon_task` ADD COLUMN `snmp_security_level` varchar(25) NOT NULL default '';
+ALTER TABLE trecon_task add column `auto_monitor` TINYINT(1) UNSIGNED DEFAULT 1 AFTER `auth_strings`;
+UPDATE `trecon_task` SET `auto_monitor` = 0;
-- ---------------------------------------------------------------------
-- Table `tagent_custom_fields_filter`
@@ -2537,3 +2593,132 @@ INSERT INTO `tnetwork_component` (`name`, `description`, `id_group`, `type`, `ma
INSERT INTO `tnetwork_component` (`name`, `description`, `id_group`, `type`, `max`, `min`, `module_interval`, `tcp_port`, `tcp_send`, `tcp_rcv`, `snmp_community`, `snmp_oid`, `id_module_group`, `id_modulo`, `id_plugin`, `plugin_user`, `plugin_pass`, `plugin_parameter`, `max_timeout`, `max_retries`, `history_data`, `min_warning`, `max_warning`, `max_critical`, `str_warning`, `min_ff_event`, `min_critical`, `custom_string_2`, `str_critical`, `custom_integer_1`, `custom_string_1`, `post_process`, `custom_string_3`, `wizard_level`, `custom_integer_2`, `critical_instructions`, `unit`, `unknown_instructions`, `macros`, `warning_inverse`, `warning_instructions`, `tags`, `critical_inverse`, `module_macros`, `id_category`, `min_ff_event_warning`, `disabled_types_event`, `ff_type`, `min_ff_event_normal`, `dynamic_interval`, `min_ff_event_critical`, `dynamic_min`, `each_ff`, `dynamic_two_tailed`, `dynamic_max`, `dynamic_next`) VALUES ('Linux system load','Current load (5 min)',43,34,0,0,300,0,'uptime | awk '{print $(NF-1)}' | tr -d ','','','','',6,2,0,'','','',0,0,1,0.00,0.00,'',0.00,0.00,'',0,'','linux','',0,0,0.000000000000000,'','nowizard','','','','',0,0,0,'','{\"going_unknown\":1}','',0,0,0,0,0,0,0,0,0,0);
INSERT INTO `tnetwork_component` (`name`, `description`, `id_group`, `type`, `max`, `min`, `module_interval`, `tcp_port`, `tcp_send`, `tcp_rcv`, `snmp_community`, `snmp_oid`, `id_module_group`, `id_modulo`, `id_plugin`, `plugin_user`, `plugin_pass`, `plugin_parameter`, `max_timeout`, `max_retries`, `history_data`, `min_warning`, `max_warning`, `max_critical`, `str_warning`, `min_ff_event`, `min_critical`, `custom_string_2`, `str_critical`, `custom_integer_1`, `custom_string_1`, `post_process`, `custom_string_3`, `wizard_level`, `custom_integer_2`, `critical_instructions`, `unit`, `unknown_instructions`, `macros`, `warning_inverse`, `warning_instructions`, `tags`, `critical_inverse`, `module_macros`, `id_category`, `min_ff_event_warning`, `disabled_types_event`, `ff_type`, `min_ff_event_normal`, `dynamic_interval`, `min_ff_event_critical`, `dynamic_min`, `each_ff`, `dynamic_two_tailed`, `dynamic_max`, `dynamic_next`) VALUES ('Linux available memory percent','Available memory %',43,34,0,0,300,0,'free | grep Mem | awk '{print $NF/$2 * 100}'','','','',4,2,0,'','','',0,0,1,0.00,0.00,'',0.00,0.00,'',0,'','linux','',0,0,0.000000000000000,'%','nowizard','','','','',0,0,0,'','{\"going_unknown\":1}','',0,0,0,0,0,0,0,0,0,0);
INSERT INTO `tnetwork_component` (`name`, `description`, `id_group`, `type`, `max`, `min`, `module_interval`, `tcp_port`, `tcp_send`, `tcp_rcv`, `snmp_community`, `snmp_oid`, `id_module_group`, `id_modulo`, `id_plugin`, `plugin_user`, `plugin_pass`, `plugin_parameter`, `max_timeout`, `max_retries`, `history_data`, `min_warning`, `max_warning`, `max_critical`, `str_warning`, `min_ff_event`, `min_critical`, `custom_string_2`, `str_critical`, `custom_integer_1`, `custom_string_1`, `post_process`, `custom_string_3`, `wizard_level`, `custom_integer_2`, `critical_instructions`, `unit`, `unknown_instructions`, `macros`, `warning_inverse`, `warning_instructions`, `tags`, `critical_inverse`, `module_macros`, `id_category`, `min_ff_event_warning`, `disabled_types_event`, `ff_type`, `min_ff_event_normal`, `dynamic_interval`, `min_ff_event_critical`, `dynamic_min`, `each_ff`, `dynamic_two_tailed`, `dynamic_max`, `dynamic_next`) VALUES ('Linux available disk /','Available free space in mountpoint /',43,34,0,0,300,0,'df / | tail -n +2 | awk '{print $(NF-1)}' | tr -d '%'','','','',4,2,0,'','','',0,0,1,0.00,0.00,'0.00',0.00,0.00,'',0,'','inherited','',0,0,0.000000000000000,'','nowizard','','nowizard','0','',0,0,0,'','{\"going_unknown\":1}','',0,0,0,0,0,0,0,0,0,0);
+
+--
+-- Dumping data for table `tpen`
+--
+
+INSERT IGNORE INTO `tpen`
+VALUES
+ (9,'cisco','Cisco System'),
+ (11,'hp','Hewlett Packard'),
+ (2021,'general_snmp','U.C. Davis, ECE Dept. Tom'),
+ (2636,'juniper','Juniper Networks'),
+ (3375,'f5','F5 Labs'),
+ (8072,'general_snmp','Net SNMP'),
+ (12356,'fortinet','Fortinet')
+;
+
+--
+-- Dumping data for table `tnetwork_profile` and `tnetwork_profile_pen`
+--
+
+SET @template_name = 'Network Management';
+SET @template_description = 'Basic network monitoring template';
+
+INSERT INTO tnetwork_profile (id_np, name, description) SELECT * FROM (SELECT '' id_np, @template_name name, @template_description description) AS tmp WHERE NOT EXISTS (SELECT id_np FROM tnetwork_profile WHERE name = @template_name);
+INSERT INTO tnetwork_profile_component (id_nc, id_np) SELECT * FROM (SELECT c.id_nc id_nc, p.id_np id_np FROM tnetwork_profile p, tnetwork_component c, tnetwork_component_group g WHERE g.id_sg = c.id_group AND p.name = @template_name AND (g.name = 'Network Management')) AS tmp WHERE NOT EXISTS (SELECT pc.id_np FROM tnetwork_profile p, tnetwork_profile_component pc WHERE p.id_np = pc.id_np AND p.name = @template_name);
+
+SET @template_name = 'Cisco MIBS';
+SET @template_description = 'Cisco devices monitoring template (SNMP)';
+
+INSERT INTO tnetwork_profile (id_np, name, description) SELECT * FROM (SELECT '' id_np, @template_name name, @template_description description) AS tmp WHERE NOT EXISTS (SELECT id_np FROM tnetwork_profile WHERE name = @template_name);
+INSERT INTO tnetwork_profile_component (id_nc, id_np) SELECT * FROM (SELECT c.id_nc id_nc, p.id_np id_np FROM tnetwork_profile p, tnetwork_component c, tnetwork_component_group g WHERE g.id_sg = c.id_group AND p.name = @template_name AND (g.name = 'Cisco MIBS' OR g.name = 'Catalyst 2900')) AS tmp WHERE NOT EXISTS (SELECT pc.id_np FROM tnetwork_profile p, tnetwork_profile_component pc WHERE p.id_np = pc.id_np AND p.name = @template_name);
+INSERT INTO tnetwork_profile_pen (pen, id_np) SELECT * FROM (SELECT p.pen pen, np.id_np id_np FROM tnetwork_profile np, tpen p WHERE np.name = @template_name AND (p.pen = 9)) AS tmp WHERE NOT EXISTS (SELECT pp.id_np FROM tnetwork_profile p, tnetwork_profile_pen pp WHERE p.id_np = pp.id_np AND p.name = @template_name);
+
+SET @template_name = 'Linux System';
+SET @template_description = 'Linux system monitoring template (SNMP)';
+
+INSERT INTO tnetwork_profile (id_np, name, description) SELECT * FROM (SELECT '' id_np, @template_name name, @template_description description) AS tmp WHERE NOT EXISTS (SELECT id_np FROM tnetwork_profile WHERE name = @template_name);
+
+SET @module_group = 'Linux';
+
+INSERT INTO tnetwork_profile_component (id_nc, id_np) SELECT * FROM (SELECT c.id_nc id_nc, p.id_np id_np FROM tnetwork_profile p, tnetwork_component c, tnetwork_component_group g WHERE g.id_sg = c.id_group AND p.name = @template_name AND (g.name = 'Linux' OR g.name = 'UCD Mibs (Linux, UCD-SNMP)')) AS tmp WHERE NOT EXISTS (SELECT pc.id_np FROM tnetwork_profile p, tnetwork_profile_component pc WHERE p.id_np = pc.id_np AND p.name = @template_name);
+INSERT INTO tnetwork_profile_pen (pen, id_np) SELECT * FROM (SELECT p.pen pen, np.id_np id_np FROM tnetwork_profile np, tpen p WHERE np.name = @template_name AND (p.pen = 2021 OR p.pen = 2636)) AS tmp WHERE NOT EXISTS (SELECT pp.id_np FROM tnetwork_profile p, tnetwork_profile_pen pp WHERE p.id_np = pp.id_np AND p.name = @template_name);
+
+SET @template_name = 'Windows System';
+SET @template_description = 'Windows system monitoring template (WMI)';
+
+INSERT INTO tnetwork_profile (id_np, name, description) SELECT * FROM (SELECT '' id_np, @template_name name, @template_description description) AS tmp WHERE NOT EXISTS (SELECT id_np FROM tnetwork_profile WHERE name = @template_name);
+INSERT INTO tnetwork_profile_component (id_nc, id_np) SELECT * FROM (SELECT c.id_nc id_nc, p.id_np id_np FROM tnetwork_profile p, tnetwork_component c, tnetwork_component_group g WHERE g.id_sg = c.id_group AND p.name = @template_name AND (g.name = 'Microsoft Windows' OR g.name = 'Windows System')) AS tmp WHERE NOT EXISTS (SELECT pc.id_np FROM tnetwork_profile p, tnetwork_profile_component pc WHERE p.id_np = pc.id_np AND p.name = @template_name);
+
+SET @template_name = 'Windows Hardware';
+SET @template_description = 'Windows hardware monitoring templae (WMI)';
+
+INSERT INTO tnetwork_profile (id_np, name, description) SELECT * FROM (SELECT '' id_np, @template_name name, @template_description description) AS tmp WHERE NOT EXISTS (SELECT id_np FROM tnetwork_profile WHERE name = @template_name);
+INSERT INTO tnetwork_profile_component (id_nc, id_np) SELECT * FROM (SELECT c.id_nc id_nc, p.id_np id_np FROM tnetwork_profile p, tnetwork_component c, tnetwork_component_group g WHERE g.id_sg = c.id_group AND p.name = @template_name AND (g.name = 'Windows Hardware Layer')) AS tmp WHERE NOT EXISTS (SELECT pc.id_np FROM tnetwork_profile p, tnetwork_profile_component pc WHERE p.id_np = pc.id_np AND p.name = @template_name);
+
+SET @template_name = 'Windows Active Directory';
+SET @template_description = 'Active directory monitoring template (WMI)';
+
+INSERT INTO tnetwork_profile (id_np, name, description) SELECT * FROM (SELECT '' id_np, @template_name name, @template_description description) AS tmp WHERE NOT EXISTS (SELECT id_np FROM tnetwork_profile WHERE name = @template_name);
+INSERT INTO tnetwork_profile_component (id_nc, id_np) SELECT * FROM (SELECT c.id_nc id_nc, p.id_np id_np FROM tnetwork_profile p, tnetwork_component c, tnetwork_component_group g WHERE g.id_sg = c.id_group AND p.name = @template_name AND (g.name = 'Windows AD' OR g.name = 'AD Counters')) AS tmp WHERE NOT EXISTS (SELECT pc.id_np FROM tnetwork_profile p, tnetwork_profile_component pc WHERE p.id_np = pc.id_np AND p.name = @template_name);
+
+SET @template_name = 'Windows IIS';
+SET @template_description = 'IIS monitoring template (WMI)';
+
+INSERT INTO tnetwork_profile (id_np, name, description) SELECT * FROM (SELECT '' id_np, @template_name name, @template_description description) AS tmp WHERE NOT EXISTS (SELECT id_np FROM tnetwork_profile WHERE name = @template_name);
+INSERT INTO tnetwork_profile_component (id_nc, id_np) SELECT * FROM (SELECT c.id_nc id_nc, p.id_np id_np FROM tnetwork_profile p, tnetwork_component c, tnetwork_component_group g WHERE g.id_sg = c.id_group AND p.name = @template_name AND (g.name = 'Windows IIS' OR g.name = 'IIS services')) AS tmp WHERE NOT EXISTS (SELECT pc.id_np FROM tnetwork_profile p, tnetwork_profile_component pc WHERE p.id_np = pc.id_np AND p.name = @template_name);
+
+SET @template_name = 'Windows Exchange';
+SET @template_description = 'Exchange monitoring template (WMI)';
+
+INSERT INTO tnetwork_profile (id_np, name, description) SELECT * FROM (SELECT '' id_np, @template_name name, @template_description description) AS tmp WHERE NOT EXISTS (SELECT id_np FROM tnetwork_profile WHERE name = @template_name);
+INSERT INTO tnetwork_profile_component (id_nc, id_np) SELECT * FROM (SELECT c.id_nc id_nc, p.id_np id_np FROM tnetwork_profile p, tnetwork_component c, tnetwork_component_group g WHERE g.id_sg = c.id_group AND p.name = @template_name AND (g.name = 'Windows Exchange' OR g.name = 'Exchange Services' OR g.name = 'Exchange TCP Ports')) AS tmp WHERE NOT EXISTS (SELECT pc.id_np FROM tnetwork_profile p, tnetwork_profile_component pc WHERE p.id_np = pc.id_np AND p.name = @template_name);
+
+SET @template_name = 'Windows LDAP';
+SET @template_description = 'LDAP monitoring template (WMI)';
+
+INSERT INTO tnetwork_profile (id_np, name, description) SELECT * FROM (SELECT '' id_np, @template_name name, @template_description description) AS tmp WHERE NOT EXISTS (SELECT id_np FROM tnetwork_profile WHERE name = @template_name);
+INSERT INTO tnetwork_profile_component (id_nc, id_np) SELECT * FROM (SELECT c.id_nc id_nc, p.id_np id_np FROM tnetwork_profile p, tnetwork_component c, tnetwork_component_group g WHERE g.id_sg = c.id_group AND p.name = @template_name AND (g.name = 'Windows LDAP')) AS tmp WHERE NOT EXISTS (SELECT pc.id_np FROM tnetwork_profile p, tnetwork_profile_component pc WHERE p.id_np = pc.id_np AND p.name = @template_name);
+
+SET @template_name = 'Windows MDSTC';
+SET @template_description = 'MDSTC monitoring template (WMI)';
+
+INSERT INTO tnetwork_profile (id_np, name, description) SELECT * FROM (SELECT '' id_np, @template_name name, @template_description description) AS tmp WHERE NOT EXISTS (SELECT id_np FROM tnetwork_profile WHERE name = @template_name);
+INSERT INTO tnetwork_profile_component (id_nc, id_np) SELECT * FROM (SELECT c.id_nc id_nc, p.id_np id_np FROM tnetwork_profile p, tnetwork_component c, tnetwork_component_group g WHERE g.id_sg = c.id_group AND p.name = @template_name AND (g.name = 'Windows MSDTC')) AS tmp WHERE NOT EXISTS (SELECT pc.id_np FROM tnetwork_profile p, tnetwork_profile_component pc WHERE p.id_np = pc.id_np AND p.name = @template_name);
+
+SET @template_name = 'Windows Printers';
+SET @template_description = 'Windows printers monitoring template (WMI)';
+
+INSERT INTO tnetwork_profile (id_np, name, description) SELECT * FROM (SELECT '' id_np, @template_name name, @template_description description) AS tmp WHERE NOT EXISTS (SELECT id_np FROM tnetwork_profile WHERE name = @template_name);
+INSERT INTO tnetwork_profile_component (id_nc, id_np) SELECT * FROM (SELECT c.id_nc id_nc, p.id_np id_np FROM tnetwork_profile p, tnetwork_component c, tnetwork_component_group g WHERE g.id_sg = c.id_group AND p.name = @template_name AND (g.name = 'Windows Printers')) AS tmp WHERE NOT EXISTS (SELECT pc.id_np FROM tnetwork_profile p, tnetwork_profile_component pc WHERE p.id_np = pc.id_np AND p.name = @template_name);
+
+SET @template_name = 'Windows DNS';
+SET @template_description = 'Windows DNS monitoring template (WMI)';
+
+INSERT INTO tnetwork_profile (id_np, name, description) SELECT * FROM (SELECT '' id_np, @template_name name, @template_description description) AS tmp WHERE NOT EXISTS (SELECT id_np FROM tnetwork_profile WHERE name = @template_name);
+INSERT INTO tnetwork_profile_component (id_nc, id_np) SELECT * FROM (SELECT c.id_nc id_nc, p.id_np id_np FROM tnetwork_profile p, tnetwork_component c, tnetwork_component_group g WHERE g.id_sg = c.id_group AND p.name = @template_name AND (g.name = 'Windows DNS' OR g.name = 'DNS Counters')) AS tmp WHERE NOT EXISTS (SELECT pc.id_np FROM tnetwork_profile p, tnetwork_profile_component pc WHERE p.id_np = pc.id_np AND p.name = @template_name);
+
+SET @template_name = 'Windows MS SQL Server';
+SET @template_description = 'MS SQL Server monitoring template (WMI)';
+
+INSERT INTO tnetwork_profile (id_np, name, description) SELECT * FROM (SELECT '' id_np, @template_name name, @template_description description) AS tmp WHERE NOT EXISTS (SELECT id_np FROM tnetwork_profile WHERE name = @template_name);
+INSERT INTO tnetwork_profile_component (id_nc, id_np) SELECT * FROM (SELECT c.id_nc id_nc, p.id_np id_np FROM tnetwork_profile p, tnetwork_component c, tnetwork_component_group g WHERE g.id_sg = c.id_group AND p.name = @template_name AND (g.name = 'MS SQL Server')) AS tmp WHERE NOT EXISTS (SELECT pc.id_np FROM tnetwork_profile p, tnetwork_profile_component pc WHERE p.id_np = pc.id_np AND p.name = @template_name);
+
+SET @template_name = 'Oracle';
+SET @template_description = 'Oracle monitoring template';
+
+INSERT INTO tnetwork_profile (id_np, name, description) SELECT * FROM (SELECT '' id_np, @template_name name, @template_description description) AS tmp WHERE NOT EXISTS (SELECT id_np FROM tnetwork_profile WHERE name = @template_name);
+INSERT INTO tnetwork_profile_component (id_nc, id_np) SELECT * FROM (SELECT c.id_nc id_nc, p.id_np id_np FROM tnetwork_profile p, tnetwork_component c, tnetwork_component_group g WHERE g.id_sg = c.id_group AND p.name = @template_name AND (g.name = 'Oracle')) AS tmp WHERE NOT EXISTS (SELECT pc.id_np FROM tnetwork_profile p, tnetwork_profile_component pc WHERE p.id_np = pc.id_np AND p.name = @template_name);
+
+SET @template_name = 'MySQL';
+SET @template_description = 'MySQL monitoring template';
+
+INSERT INTO tnetwork_profile (id_np, name, description) SELECT * FROM (SELECT '' id_np, @template_name name, @template_description description) AS tmp WHERE NOT EXISTS (SELECT id_np FROM tnetwork_profile WHERE name = @template_name);
+INSERT INTO tnetwork_profile_component (id_nc, id_np) SELECT * FROM (SELECT c.id_nc id_nc, p.id_np id_np FROM tnetwork_profile p, tnetwork_component c, tnetwork_component_group g WHERE g.id_sg = c.id_group AND p.name = @template_name AND (g.name = 'MySQL')) AS tmp WHERE NOT EXISTS (SELECT pc.id_np FROM tnetwork_profile p, tnetwork_profile_component pc WHERE p.id_np = pc.id_np AND p.name = @template_name);
+
+SET @template_name = 'Windows Antivirus';
+SET @template_description = 'Windows antivirus monitoring template (WMI)';
+
+INSERT INTO tnetwork_profile (id_np, name, description) SELECT * FROM (SELECT '' id_np, @template_name name, @template_description description) AS tmp WHERE NOT EXISTS (SELECT id_np FROM tnetwork_profile WHERE name = @template_name);
+INSERT INTO tnetwork_profile_component (id_nc, id_np) SELECT * FROM (SELECT c.id_nc id_nc, p.id_np id_np FROM tnetwork_profile p, tnetwork_component c, tnetwork_component_group g WHERE g.id_sg = c.id_group AND p.name = @template_name AND (g.name = 'Norton' OR g.name = 'Panda' OR g.name = 'McAfee' OR g.name = 'Bitdefender' OR g.name = 'BullGuard' OR g.name = 'AVG' OR g.name = 'Kaspersky')) AS tmp WHERE NOT EXISTS (SELECT pc.id_np FROM tnetwork_profile p, tnetwork_profile_component pc WHERE p.id_np = pc.id_np AND p.name = @template_name);
+
+
+-- Update widget.
+
+UPDATE twidget SET description='Show a visual console' WHERE class_name='MapsMadeByUser';
+UPDATE twidget SET description='Clock' WHERE class_name='ClockWidget';
+UPDATE twidget SET description='Group status' WHERE class_name='SystemGroupStatusWidget';
+
+
diff --git a/pandora_console/godmode/menu.php b/pandora_console/godmode/menu.php
index b370bc2ac9..7a5295f1c5 100644
--- a/pandora_console/godmode/menu.php
+++ b/pandora_console/godmode/menu.php
@@ -137,11 +137,31 @@ if (!empty($sub)) {
$sub = [];
if (check_acl($config['id_user'], 0, 'PM')) {
- $sub['godmode/modules/manage_network_components']['text'] = __('Network components');
- $sub['godmode/modules/manage_network_components']['id'] = 'Network components';
- enterprise_hook('components_submenu');
- $sub['godmode/modules/manage_network_templates']['text'] = __('Module templates');
- $sub['godmode/modules/manage_network_templates']['id'] = 'Module templates';
+ // enterprise_hook('components_submenu');
+ $sub['templates']['text'] = __('Templates');
+ $sub['templates']['id'] = 'Templates';
+ $sub['templates']['type'] = 'direct';
+ $sub['templates']['subtype'] = 'nolink';
+ $sub2 = [];
+ $sub2['godmode/modules/manage_module_templates']['text'] = __('Module templates');
+ $sub2['godmode/modules/manage_module_templates']['id'] = 'Module templates';
+ $sub2['godmode/modules/private_enterprise_numbers']['text'] = __('Private Enterprise Numbers');
+ $sub2['godmode/modules/private_enterprise_numbers']['id'] = 'Private Enterprise Numbers';
+ $sub2['enterprise/godmode/modules/local_components']['text'] = __('Local components');
+ $sub2['enterprise/godmode/modules/local_components']['id'] = 'Local components';
+ $sub2['godmode/modules/manage_network_components']['text'] = __('Remote components');
+ $sub2['godmode/modules/manage_network_components']['id'] = 'Network components';
+ $sub['templates']['sub2'] = $sub2;
+ /*
+ $sub2['godmode/modules/manage_snmp_modules']['text'] = __('SNMP Modules');
+ $sub2['godmode/modules/manage_snmp_modules']['id'] = 'SNMP Modules';
+ $sub2['godmode/modules/manage_wmi_modules']['text'] = __('WMI Modules');
+ $sub2['godmode/modules/manage_wmi_modules']['id'] = 'WMI Modules';
+ $sub['godmode/modules/manage_block_templates']['text'] = __('Module blocks');
+ $sub['godmode/modules/manage_block_templates']['id'] = 'Module blocks';
+ */
+
+
enterprise_hook('inventory_submenu');
enterprise_hook('autoconfiguration_menu');
enterprise_hook('agent_repository_menu');
diff --git a/pandora_console/godmode/modules/configuration_wizard_setup.php b/pandora_console/godmode/modules/configuration_wizard_setup.php
new file mode 100644
index 0000000000..ccf5ef04ca
--- /dev/null
+++ b/pandora_console/godmode/modules/configuration_wizard_setup.php
@@ -0,0 +1,35 @@
+ '[ModuleTemplates]'.$e->getMessage() ]);
+ exit;
+ } else {
+ echo '[ModuleTemplates]'.$e->getMessage();
+ }
+
+ // Stop this execution, but continue 'globally'.
+ return;
+}
+
+// AJAX controller.
+if (is_ajax()) {
+ $method = get_parameter('method');
+
+ if (method_exists($obj, $method) === true) {
+ $obj->{$method}();
+ } else {
+ $obj->error('Method not found. ['.$method.']');
+ }
+
+ // Stop any execution.
+ exit;
+} else {
+ // Run.
+ $obj->run();
+}
diff --git a/pandora_console/godmode/modules/manage_network_components.php b/pandora_console/godmode/modules/manage_network_components.php
index afd7c09189..baa626f1ec 100644
--- a/pandora_console/godmode/modules/manage_network_components.php
+++ b/pandora_console/godmode/modules/manage_network_components.php
@@ -66,7 +66,7 @@ if (defined('METACONSOLE')) {
}
ui_print_page_header(
- __('Module management').' » '.__('Network component management'),
+ __('Module management').' » '.__('Remote component management'),
'',
false,
$help_header,
diff --git a/pandora_console/godmode/modules/manage_network_templates.php b/pandora_console/godmode/modules/manage_network_templates.php
index eebf408caa..2050fb916c 100644
--- a/pandora_console/godmode/modules/manage_network_templates.php
+++ b/pandora_console/godmode/modules/manage_network_templates.php
@@ -45,8 +45,15 @@ ui_print_page_header(
true,
'modulemodal'
);
-
-
+/*
+ // At this moment, this message is not necessary
+ ui_print_info_message(
+ __(
+ 'This section is maintained only for legacy use. Please, keep in mind use %s for manage template blocks.',
+ 'Module Blocks'
+ )
+ );
+*/
require_once 'include/functions_network_profiles.php';
$delete_profile = (bool) get_parameter('delete_profile');
diff --git a/pandora_console/godmode/modules/private_enterprise_numbers.php b/pandora_console/godmode/modules/private_enterprise_numbers.php
new file mode 100644
index 0000000000..ca6add6640
--- /dev/null
+++ b/pandora_console/godmode/modules/private_enterprise_numbers.php
@@ -0,0 +1,68 @@
+ '[ConfigPEN]'.$e->getMessage() ]);
+ exit;
+ } else {
+ echo '[ConfigPEN]'.$e->getMessage();
+ }
+
+ // Stop this execution, but continue 'globally'.
+ return;
+}
+
+// AJAX controller.
+if (is_ajax()) {
+ $method = get_parameter('method');
+
+ if (method_exists($obj, $method) === true) {
+ $obj->{$method}();
+ } else {
+ $obj->error('Method not found. ['.$method.']');
+ }
+
+ // Stop any execution.
+ exit;
+} else {
+ // Run.
+ $obj->run();
+}
diff --git a/pandora_console/godmode/servers/discovery.php b/pandora_console/godmode/servers/discovery.php
index 7215ee7dfb..3dd8e258ee 100755
--- a/pandora_console/godmode/servers/discovery.php
+++ b/pandora_console/godmode/servers/discovery.php
@@ -1,5 +1,7 @@
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']);
+ }
}
}
diff --git a/pandora_console/godmode/wizards/DiscoveryTaskList.class.php b/pandora_console/godmode/wizards/DiscoveryTaskList.class.php
index f87b2a563e..118f604b14 100644
--- a/pandora_console/godmode/wizards/DiscoveryTaskList.class.php
+++ b/pandora_console/godmode/wizards/DiscoveryTaskList.class.php
@@ -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
{
@@ -119,8 +123,9 @@ class DiscoveryTaskList extends Wizard
}
$force_run = (bool) get_parameter('force_run');
- if ($force_run === true) {
- return $this->forceConsoleTask();
+ $force = (bool) get_parameter('force');
+ if ($force_run === true || $force === true) {
+ return $this->forceTask();
}
$delete_console_task = (bool) get_parameter('delete_console_task');
@@ -163,6 +168,16 @@ class DiscoveryTaskList extends Wizard
'attributes' => 'class="sub cancel"',
'return' => true,
],
+ ],[
+ 'class' => 'action-buttons rule-builder-actions',
+ 'arguments' => [
+ 'name' => 'refresh',
+ 'label' => __('Refresh'),
+ 'type' => 'button',
+ 'attributes' => 'class="sub upd"',
+ 'return' => true,
+ 'script' => 'location.reload();',
+ ],
],
],
];
@@ -237,7 +252,7 @@ class DiscoveryTaskList extends Wizard
*
* @return void
*/
- public function forceConsoleTask()
+ public function forceTask()
{
global $config;
@@ -252,12 +267,46 @@ class DiscoveryTaskList extends Wizard
$id_console_task = (int) get_parameter('id_console_task');
- if ($id_console_task !== null) {
+ if ($id_console_task != null) {
+ // --------------------------------
+ // FORCE A CONSOLE TASK
+ // --------------------------------
enterprise_hook('cron_task_run', [$id_console_task, true]);
// Trick to avoid double execution.
header('Location: '.$this->url);
- }
+ } else {
+ // --------------------------------
+ // FORCE A RECON TASK
+ // --------------------------------
+ if (check_acl($config['id_user'], 0, 'AW')) {
+ if (isset($_GET['force'])) {
+ $id = (int) get_parameter_get('force', 0);
+ // Schedule execution.
+ $review_mode = db_get_value(
+ 'review_mode',
+ 'trecon_task',
+ 'id_rt',
+ $id
+ );
+ if ($review_mode != DISCOVERY_STANDARD) {
+ // Force re-scan for supervised tasks.
+ $review_mode = DISCOVERY_REVIEW;
+ }
+
+ db_process_sql_update(
+ 'trecon_task',
+ [
+ 'utimestamp' => 0,
+ 'status' => 1,
+ 'review_mode' => $review_mode,
+ ],
+ ['id_rt' => $id]
+ );
+ header('Location: '.$this->url);
+ }
+ }
+ }
}
@@ -330,28 +379,7 @@ class DiscoveryTaskList extends Wizard
include_once $config['homedir'].'/include/functions_servers.php';
include_once $config['homedir'].'/include/functions_network_profiles.php';
- $modules_server = 0;
- $total_modules = 0;
- $total_modules_data = 0;
-
- // --------------------------------
- // FORCE A RECON TASK
- // --------------------------------
- if (check_acl($config['id_user'], 0, 'AW')) {
- if (isset($_GET['force'])) {
- $id = (int) get_parameter_get('force', 0);
- servers_force_recon_task($id);
- header(
- 'Location: '.ui_get_full_url(
- 'index.php?sec=gservers&sec2=godmode/servers/discovery&wiz=tasklist'
- )
- );
- }
- }
-
$recon_tasks = db_get_all_rows_sql('SELECT * FROM trecon_task');
- $user_groups = implode(',', array_keys(users_get_groups()));
-
// Show network tasks for Recon Server.
if ($recon_tasks === false) {
$recon_tasks = [];
@@ -368,18 +396,22 @@ class DiscoveryTaskList extends Wizard
$table->data = [];
$table->align = [];
$table->headstyle = [];
+ $table->style = [];
+ $table->style[4] = 'word-break: break-word;';
for ($i = 0; $i < 9; $i++) {
$table->headstyle[$i] = 'text-align: left;';
}
+ // Name.
+ $table->headstyle[4] .= 'min-width: 100px; width: 600px;';
// Status.
- $table->headstyle[5] .= 'min-width: 100px; width: 100px;';
+ $table->headstyle[5] .= 'min-width: 50px; width: 100px;';
// Task type.
- $table->headstyle[6] .= 'min-width: 200px; width: 150px;';
+ $table->headstyle[6] .= 'min-width: 150px; width: 150px;';
// Progress.
- $table->headstyle[7] .= 'min-width: 150px; width: 150px;';
+ $table->headstyle[7] .= 'min-width: 50px; width: 150px;';
// Updated at.
- $table->headstyle[8] .= 'min-width: 150px; width: 150px;';
+ $table->headstyle[8] .= 'min-width: 50px; width: 150px;';
// Operations.
$table->headstyle[9] .= 'min-width: 150px; width: 150px;';
@@ -454,11 +486,20 @@ class DiscoveryTaskList extends Wizard
if ($task['disabled'] == 0 && $server_name !== '') {
if (check_acl($config['id_user'], 0, 'AW')) {
- $data[0] = '';
+ );
+ $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] .= '';
+ $data[0] .= '';
}
} else if ($task['disabled'] == 2) {
$data[0] = ui_print_help_tip(
@@ -472,12 +513,12 @@ class DiscoveryTaskList extends Wizard
// Name task.
$data[1] = '';
if ($task['disabled'] != 2) {
- $data[1] .= '';
+ $data[1] .= '';
}
$data[1] .= ''.$task['name'].'';
if ($task['disabled'] != 2) {
- $data[1] .= '';
+ $data[1] .= '';
}
$data[2] = $server_name;
@@ -496,10 +537,38 @@ class DiscoveryTaskList extends Wizard
$data[4] = '-';
}
- if ($task['status'] <= 0) {
- $data[5] = __('Done');
+ $can_be_reviewed = false;
+ if ($task['review_mode'] == DISCOVERY_STANDARD) {
+ if ($task['status'] <= 0
+ && empty($task['summary']) === false
+ ) {
+ $data[5] = __('Done');
+ } else if ($task['utimestamp'] == 0
+ && empty($task['summary'])
+ ) {
+ $data[5] = __('Not started');
+ } else {
+ $data[5] = __('Pending');
+ }
} else {
- $data[5] = __('Pending');
+ if ($task['status'] <= 0
+ && empty($task['summary']) === false
+ ) {
+ $can_be_reviewed = true;
+ $data[5] = '';
+ $data[5] .= __('Review');
+ $data[5] .= '';
+ } else if ($task['utimestamp'] == 0
+ && empty($task['summary'])
+ ) {
+ $data[5] = __('Not started');
+ } else {
+ if ($task['review_mode'] == DISCOVERY_RESULTS) {
+ $data[5] = __('Processing');
+ } else {
+ $data[5] = __('Searching');
+ }
+ }
}
switch ($task['type']) {
@@ -573,14 +642,7 @@ class DiscoveryTaskList extends Wizard
true,
['title' => __('Discovery NetScan')]
).' ';
- $str = network_profiles_get_name(
- $task['id_network_profile']
- );
- if (!empty($str)) {
- $data[6] .= $str;
- } else {
- $data[6] .= __('Discovery.NetScan');
- }
+ $data[6] .= __('Discovery.NetScan');
} else {
// APP or external script recon task.
$data[6] = html_print_image(
@@ -595,7 +657,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' => 'taskProgress',
+ ],
+ ]
+ );
}
if ($task['utimestamp'] > 0) {
@@ -609,10 +692,22 @@ class DiscoveryTaskList extends Wizard
if (!$no_operations) {
if ($task['disabled'] != 2) {
- $data[9] = '';
+ $data[9] = '';
+ if ($can_be_reviewed) {
+ $data[9] .= '';
+ $data[9] .= html_print_image(
+ 'images/expand.png',
+ true,
+ ['title' => __('Review results')]
+ );
+ $data[9] .= '';
+ }
+
+ $data[9] .= '';
$data[9] .= html_print_image(
'images/eye.png',
- true
+ true,
+ ['title' => __('View summary')]
);
$data[9] .= '';
}
@@ -623,10 +718,11 @@ class DiscoveryTaskList extends Wizard
&& $task['type'] != DISCOVERY_CLOUD_AWS_RDS
) {
if (check_acl($config['id_user'], 0, 'MR')) {
- $data[9] .= '';
+ $data[9] .= '';
$data[9] .= html_print_image(
'images/dynamic_network_icon.png',
- true
+ true,
+ ['title' => __('View map')]
);
$data[9] .= '';
}
@@ -646,13 +742,15 @@ class DiscoveryTaskList extends Wizard
)
).'">'.html_print_image(
'images/config.png',
- true
+ true,
+ ['title' => __('Edit task')]
).'';
$data[9] .= ''.html_print_image(
'images/cross.png',
- true
+ true,
+ ['title' => __('Delete task')]
).'';
} else {
// Check if is a H&D, Cloud or Application or IPAM.
@@ -664,13 +762,15 @@ class DiscoveryTaskList extends Wizard
)
).'">'.html_print_image(
'images/config.png',
- true
+ true,
+ ['title' => __('Edit task')]
).'';
$data[9] .= ''.html_print_image(
'images/cross.png',
- true
+ true,
+ ['title' => __('Delete task')]
).'';
}
} else {
@@ -700,9 +800,15 @@ class DiscoveryTaskList extends Wizard
// Div neccesary for modal map task.
echo '
';
+ echo '';
+ echo '';
+ echo '';
+ echo '';
+ echo '';
unset($table);
+ ui_require_javascript_file('pandora_ui');
ui_require_javascript_file('pandora_taskList');
return $return;
@@ -787,4 +893,633 @@ class DiscoveryTaskList extends Wizard
}
+ /**
+ * Returns percent of completion of target task.
+ *
+ * @return void
+ */
+ public function taskProgress()
+ {
+ if (!is_ajax()) {
+ echo json_encode(['error' => true]);
+ 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 progressTaskGraph($task)
+ {
+ $result .= '';
+ $result .= '
';
+ $result .= '
'._('Overall Progress').'';
+
+ $result .= '
';
+ $result .= progress_circular_bar(
+ $task['id_rt'],
+ ($task['status'] < 0) ? 100 : $task['status'],
+ 200,
+ 200,
+ '#7eb641',
+ '%',
+ '',
+ '#3A3A3A',
+ 0
+ );
+
+ $result .= '
';
+ if ($task['status'] > 0) {
+ switch ($task['stats']['step']) {
+ case STEP_SCANNING:
+ $str = __('Scanning network');
+ break;
+
+ case STEP_CAPABILITIES:
+ $str = __('Checking');
+ 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;
+
+ case STEP_MONITORING:
+ $str = __('Testing modules...');
+ break;
+
+ case STEP_PROCESSING:
+ $str = __('Processing results...');
+ break;
+
+ default:
+ $str = __('Processing...');
+ break;
+ }
+
+ $result .= '
';
+ $result .= '
';
+ $result .= '
'.$str.' ';
+ if (empty($str) === false) {
+ $result .= $task['stats']['c_network_name'];
+ }
+
+ $result .= '';
+
+ $result .= '
';
+ $result .= progress_circular_bar(
+ $task['id_rt'].'_detail',
+ $task['stats']['c_network_percent'],
+ 200,
+ 200,
+ '#7eb641',
+ '%',
+ '',
+ '#3A3A3A',
+ 0
+ );
+ $result .= '
';
+ }
+
+ if ($task['review_mode'] == DISCOVERY_REVIEW) {
+ if ($task['status'] <= 0
+ && empty($task['summary']) === false
+ ) {
+ $result .= '
';
+ $result .= '»'.__('Review');
+ $result .= '';
+ }
+ }
+
+ $result .= '
';
+
+ return $result;
+ }
+
+
+ /**
+ * Generates a summary table for given task.
+ *
+ * @param array $task Task.
+ *
+ * @return html code with summary.
+ */
+ private function progressTaskSummary($task)
+ {
+ global $config;
+ include_once $config['homedir'].'/include/graphs/functions_d3.php';
+
+ if (is_array($task) === false) {
+ return '';
+ }
+
+ $output = '';
+
+ if (is_array($task['stats']) === false) {
+ $task['stats'] = json_decode($task['summary'], true);
+ }
+
+ 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 = [];
+
+ if ($task['review_mode'] == DISCOVERY_RESULTS) {
+ $agents_review = db_get_all_rows_filter(
+ 'tdiscovery_tmp_agents',
+ ['id_rt' => $task['id_rt']]
+ );
+
+ $agents = 0;
+ $total = 0;
+ if (is_array($agents_review)) {
+ foreach ($agents_review as $agent) {
+ $data = json_decode(base64_decode($agent['data']), true);
+
+ if (is_array($data) === false) {
+ continue;
+ }
+
+ if (is_array($data['agent']) === false) {
+ continue;
+ }
+
+ // Ensure agent_id really exists.
+ $agent_id = agents_get_agent_id(
+ $data['agent']['nombre'],
+ true
+ );
+
+ if ($agent_id > 0) {
+ $agents++;
+ }
+
+ $total++;
+ }
+ }
+
+ // Content.
+ $table->data[$i][0] = ''.__('Host&devices total').'';
+ $table->data[$i][1] = '';
+ $table->data[$i][1] .= $total;
+ $table->data[$i++][1] .= '';
+
+ $table->data[$i][0] = ''.__('Agents monitored').'';
+ $table->data[$i][1] = '';
+ $table->data[$i][1] .= $agents;
+ $table->data[$i++][1] .= '';
+
+ $table->data[$i][0] = ''.__('Agents pending').'';
+ $table->data[$i][1] = '';
+ $table->data[$i][1] .= ($total - $agents);
+ $table->data[$i++][1] .= '';
+ } else {
+ // Content.
+ $table->data[$i][0] = ''.__('Hosts discovered').'';
+ $table->data[$i][1] = '';
+ $table->data[$i][1] .= $task['stats']['summary']['discovered'];
+ $table->data[$i++][1] .= '';
+
+ $table->data[$i][0] = ''.__('Alive').'';
+ $table->data[$i][1] = '';
+ $table->data[$i][1] .= $task['stats']['summary']['alive'];
+ $table->data[$i++][1] .= '';
+
+ $table->data[$i][0] = ''.__('Not alive').'';
+ $table->data[$i][1] = '';
+ $table->data[$i][1] .= $task['stats']['summary']['not_alive'];
+ $table->data[$i++][1] .= '';
+
+ if ($task['type'] == DISCOVERY_HOSTDEVICES) {
+ $table->data[$i][0] = ''.__('Responding SNMP').'';
+ $table->data[$i][1] = '';
+ $table->data[$i][1] .= $task['stats']['summary']['SNMP'];
+ $table->data[$i++][1] .= '';
+
+ $table->data[$i][0] = ''.__('Responding WMI').'';
+ $table->data[$i][1] = '';
+ $table->data[$i][1] .= $task['stats']['summary']['WMI'];
+ $table->data[$i++][1] .= '';
+ }
+ }
+
+ $output = ''.__('Summary').'
';
+ $output .= html_print_table($table, true).'';
+ }
+
+ return $output;
+ }
+
+
+ /**
+ * Content of modal 'task progress', ajax only.
+ *
+ * @return void
+ */
+ public function progressTaskDiscovery()
+ {
+ 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);
+ $summary = $this->progressTaskSummary($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
+ ).'';
+ } else {
+ $output .= $this->progressTaskGraph($task);
+ }
+
+ $output .= $summary;
+
+ echo json_encode(['html' => $output]);
+ }
+
+
+ /**
+ * Get a map of target task.
+ *
+ * @return void
+ */
+ public function taskShowmap()
+ {
+ 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_options' => [
+ 'map_filter' => [
+ 'x_offs' => 120,
+ 'node_sep' => 10,
+ ],
+ ],
+ ]
+ );
+ $map->printMap();
+ }
+
+
+ /**
+ * Shows a modal to review results found by discovery task.
+ *
+ * @return void
+ */
+ public function showTaskReview()
+ {
+ $id_task = get_parameter('id', 0);
+ if ($id_task <= 0) {
+ ui_print_error_message(__('Invalid task'));
+ return;
+ }
+
+ $task_data = db_get_all_rows_filter(
+ 'tdiscovery_tmp_agents',
+ ['id_rt' => $id_task]
+ );
+ $task = db_get_row('trecon_task', 'id_rt', $id_task);
+
+ $simple_data = [];
+ if (is_array($task_data)) {
+ foreach ($task_data as $agent) {
+ $data = json_decode(base64_decode($agent['data']), true);
+ if (is_array($data) === false) {
+ continue;
+ }
+
+ if (is_array($data['agent']) === false) {
+ continue;
+ }
+
+ $id = $data['agent']['nombre'];
+
+ // Partial.
+ $tmp = [
+ 'id' => $id,
+ 'name' => $id,
+ 'checked' => $data['agent']['checked'],
+ ];
+
+ // Ensure agent_id really exists.
+ $agent_id = agents_get_agent_id($data['agent']['nombre'], true);
+
+ if ($agent_id > 0) {
+ $tmp['disabled'] = 1;
+ $tmp['agent_id'] = $agent_id;
+ $tmp['checked'] = 1;
+ }
+
+ // Store.
+ $simple_data[] = $tmp;
+
+ if (is_array($data['modules'])) {
+ $simple_data = array_merge(
+ $simple_data,
+ array_reduce(
+ $data['modules'],
+ function ($carry, $item) use ($id, $agent_id) {
+ if (empty($item['name'])) {
+ $item['name'] = $item['nombre'];
+ }
+
+ if ($item['name'] == 'Host Alive') {
+ return $carry;
+ }
+
+ if (empty($item['name'])) {
+ $item['name'] = $item['nombre'];
+ }
+
+ $tmp = [
+ 'name' => $item['name'],
+ 'id' => $id.'-'.$item['name'],
+ 'pid' => $id,
+ 'checked' => $item['checked'],
+ ];
+
+ $agentmodule_id = modules_get_agentmodule_id(
+ io_safe_input($item['name']),
+ $agent_id
+ );
+
+ if ($agentmodule_id > 0) {
+ $tmp['disabled'] = 1;
+ $tmp['checked'] = 1;
+ $tmp['module_id'] = $agentmodule_id;
+ }
+
+ $carry[] = $tmp;
+ return $carry;
+ },
+ []
+ )
+ );
+ }
+ }
+ }
+
+ echo '';
+ echo $this->progressTaskSummary($task);
+ echo '
';
+
+ if (count($simple_data) > 0) {
+ echo '';
+ echo '
';
+ echo __('Please select devices to be monitored');
+ echo '';
+ echo '';
+ echo '';
+ echo '';
+ echo '';
+ echo '
';
+ echo '
';
+ echo '';
+ } else {
+ echo '';
+ echo '';
+ echo __('No devices found in temporary resources, please re-launch.');
+ echo '';
+ echo '
';
+ }
+
+ }
+
+
+ /**
+ * Processes a review over temporary results found by discovery task.
+ *
+ * @return void
+ */
+ public function parseTaskReview()
+ {
+ $id_task = get_parameter('id', 0);
+ if ($id_task <= 0) {
+ echo $this->error(__('Invalid task'));
+ return;
+ }
+
+ $ids = [];
+ $n_agents = 0;
+ $selection = io_safe_output(get_parameter('tree-data-tree', ''));
+ if (empty($selection) === false) {
+ $selection = json_decode($selection, true);
+ $ids = array_reduce(
+ $selection,
+ function ($carry, $item) use (&$n_agents) {
+ // String is agent-module.
+ $fields = explode('-', $item['id']);
+ $agent_name = $fields[0];
+ $module_name = $fields[1];
+ if ($module_name === null) {
+ // Do not count if already created.
+ if (db_get_value(
+ 'id_agente',
+ 'tagente',
+ 'nombre',
+ io_safe_input($agent_name)
+ ) === false
+ ) {
+ $n_agents++;
+ }
+ }
+
+ $carry[] = $item['id'];
+ return $carry;
+ }
+ );
+ }
+
+ $task_data = db_get_all_rows_filter(
+ 'tdiscovery_tmp_agents',
+ ['id_rt' => $id_task]
+ );
+
+ // License precheck.
+ $license = enterprise_hook('license_get_info');
+
+ if (is_array($license) === true
+ && $n_agents > ($license['limit'] - $license['count'])
+ ) {
+ $limit = ($license['limit'] - $license['count']);
+ echo json_encode(
+ [
+ 'error' => __(
+ 'Your selection exceeds the agents available on your license. Limit %d',
+ $limit
+ ),
+ ]
+ );
+ return;
+ }
+
+ $summary = [];
+ if (is_array($ids)) {
+ foreach ($task_data as $row) {
+ $data = json_decode(base64_decode($row['data']), true);
+
+ if (is_array($data)) {
+ // Analize each agent.
+ $agent_name = $data['agent']['nombre'];
+ if (in_array($agent_name, $ids)) {
+ if ($data['agent']['checked'] != 1) {
+ $summary[] = ''.$agent_name.'';
+ }
+
+ $data['agent']['checked'] = 1;
+ } else {
+ if ($data['agent']['checked'] == 1) {
+ $summary[] = ''.__('Removed').' '.$agent_name.'';
+ }
+
+ $data['agent']['checked'] = 0;
+ }
+
+ // Modules.
+ if (is_array($data['modules'])) {
+ $n_modules = count($data['modules']);
+ foreach ($data['modules'] as $module_name => $module) {
+ if (in_array($agent_name.'-'.$module_name, $ids)) {
+ if ($data['modules'][$module_name]['checked'] != 1) {
+ $summary[] = ''.$agent_name.' - '.$module_name.'';
+ }
+
+ $data['modules'][$module_name]['checked'] = 1;
+ } else {
+ if ($data['modules'][$module_name]['checked'] == 1) {
+ if ($module_name != 'Host Alive') {
+ $summary[] = ''.__('Removed').' '.$agent_name.' - '.$module_name.'';
+ }
+ }
+
+ $data['modules'][$module_name]['checked'] = 0;
+ }
+ }
+ }
+
+ // Update data.
+ db_process_sql_update(
+ 'tdiscovery_tmp_agents',
+ [
+ 'data' => base64_encode(json_encode($data)),
+ 'review_date' => date('Y-m-d H:i:s'),
+ ],
+ [
+ 'id_rt' => $id_task,
+ 'label' => $agent_name,
+ ]
+ );
+ }
+ }
+ }
+
+ // Schedule execution.
+ db_process_sql_update(
+ 'trecon_task',
+ [
+ 'utimestamp' => 0,
+ 'status' => 1,
+ 'review_mode' => DISCOVERY_RESULTS,
+ ],
+ ['id_rt' => $id_task]
+ );
+
+ if (empty($summary)) {
+ $out .= __('No changes. Re-Scheduled');
+ } else {
+ $out .= __('Scheduled for creation');
+ $out .= '';
+ $out .= join('', $summary);
+ $out .= '
';
+ }
+
+ echo json_encode(
+ ['result' => $out]
+ );
+ }
+
+
}
diff --git a/pandora_console/godmode/wizards/HostDevices.class.php b/pandora_console/godmode/wizards/HostDevices.class.php
index fd7811f2e9..5f6f0c7dba 100755
--- a/pandora_console/godmode/wizards/HostDevices.class.php
+++ b/pandora_console/godmode/wizards/HostDevices.class.php
@@ -1,6 +1,6 @@
page == 0) {
// Check if we're updating a task.
$task_id = get_parameter('task', null);
@@ -297,9 +300,63 @@ class HostDevices extends Wizard
$comment = get_parameter('comment', '');
$server_id = get_parameter('id_recon_server', '');
$network = get_parameter('network', '');
+ $network_csv_enabled = (bool) get_parameter_switch(
+ 'network_csv_enabled',
+ false
+ );
$id_group = get_parameter('id_group', '');
$interval = get_parameter('interval', 0);
+ if ($network_csv_enabled) {
+ if (empty($_FILES['network_csv']['type']) === false) {
+ if ($_FILES['network_csv']['type'] != 'text/csv'
+ && $_FILES['network_csv']['type'] != 'text/plain'
+ && $_FILES['network_csv']['type'] != 'application/octet-stream'
+ && $_FILES['network_csv']['type'] != 'application/vnd.ms-excel'
+ && $_FILES['network_csv']['type'] != 'text/x-csv'
+ && $_FILES['network_csv']['type'] != 'application/csv'
+ && $_FILES['network_csv']['type'] != 'application/x-csv'
+ && $_FILES['network_csv']['type'] != 'text/csv'
+ && $_FILES['network_csv']['type'] != 'text/comma-separated-values'
+ && $_FILES['network_csv']['type'] != 'text/x-comma-separated-values'
+ && $_FILES['network_csv']['type'] != 'text/tab-separated-values'
+ ) {
+ $this->msg = __(
+ 'Invalid mimetype for csv file: %s',
+ $_FILES['network_csv']['type']
+ );
+ return false;
+ }
+
+ $network = preg_split(
+ "/\n|,|;/",
+ trim(
+ file_get_contents(
+ $_FILES['network_csv']['tmp_name']
+ )
+ )
+ );
+ unlink($_FILES['network_csv']['tmp_name']);
+ if (empty($network) || is_array($network) === false) {
+ $this->msg = __(
+ 'Invalid content readed from csv file: %s',
+ $_FILES['network_csv']['name']
+ );
+ return false;
+ }
+
+ // Sanitize.
+ $network = array_unique($network);
+ $network = array_filter(
+ $network,
+ function ($item) {
+ return (!empty($item));
+ }
+ );
+ $network = join(',', $network);
+ }
+ }
+
if (isset($task_id) === true) {
// We're updating this task.
$task = db_get_row(
@@ -333,18 +390,15 @@ class HostDevices extends Wizard
if ($task_id !== null
&& $taskname == null
&& $server_id == null
- && $id_group == null
- && $server == null
- && $datacenter == ''
- && $user == ''
- && $pass == ''
- && $encrypt == null
- && $interval == 0
+ && empty($id_group) === true
+ && empty($network) === true
+ && empty($network_csv) === true
+ && $interval === 0
) {
// Default values, no data received.
// User is accesing directly to this page.
if (check_acl(
- $config['id_usuario'],
+ $config['id_user'],
$this->task['id_group'],
$this->access
) != true
@@ -386,6 +440,7 @@ class HostDevices extends Wizard
$this->task['id_recon_server'] = $server_id;
$this->task['id_group'] = $id_group;
$this->task['interval_sweep'] = $interval;
+ $this->task['subnet_csv'] = $network_csv_enabled;
if (isset($this->task['id_rt']) === false) {
// Create.
@@ -423,7 +478,10 @@ class HostDevices extends Wizard
return false;
}
- $id_network_profile = get_parameter('id_network_profile', null);
+ $id_network_profile = get_parameter('id_network_profile', []);
+ $review_results = get_parameter_switch('review_results');
+ $review_limited = (bool) get_parameter('review_limited', 0);
+ $auto_monitor = get_parameter_switch('auto_monitor');
$autoconf_enabled = get_parameter_switch(
'autoconfiguration_enabled'
);
@@ -443,7 +501,7 @@ class HostDevices extends Wizard
$snmp_privacy_pass = get_parameter('snmp_privacy_pass', null);
$snmp_auth_method = get_parameter('snmp_auth_method', null);
$snmp_security_level = get_parameter('snmp_security_level', null);
- $auth_strings = get_parameter('auth_strings', null);
+ $auth_strings = get_parameter('auth_strings', []);
if ($snmp_version == 3) {
$this->task['snmp_community'] = $snmp_context;
@@ -452,7 +510,28 @@ class HostDevices extends Wizard
}
$this->task['autoconfiguration_enabled'] = $autoconf_enabled;
- $this->task['id_network_profile'] = $id_network_profile;
+ $this->task['id_network_profile'] = '';
+ if (is_array($id_network_profile) === true) {
+ $this->task['id_network_profile'] = join(
+ ',',
+ $id_network_profile
+ );
+ }
+
+ if ($review_limited === true) {
+ // License limited, force review.
+ $this->task['review_mode'] = DISCOVERY_REVIEW;
+ } else {
+ if ($review_results) {
+ if ($this->task['review_mode'] != DISCOVERY_RESULTS) {
+ $this->task['review_mode'] = DISCOVERY_REVIEW;
+ }
+ } else {
+ $this->task['review_mode'] = DISCOVERY_STANDARD;
+ }
+ }
+
+ $this->task['auto_monitor'] = $auto_monitor;
$this->task['snmp_enabled'] = $snmp_enabled;
$this->task['os_detect'] = $os_detect;
$this->task['parent_detection'] = $parent_detection;
@@ -467,7 +546,13 @@ class HostDevices extends Wizard
$this->task['snmp_privacy_pass'] = $snmp_privacy_pass;
$this->task['snmp_auth_method'] = $snmp_auth_method;
$this->task['snmp_security_level'] = $snmp_security_level;
- $this->task['auth_strings'] = $auth_strings;
+ $this->task['auth_strings'] = '';
+ if (is_array($auth_strings) === true) {
+ $this->task['auth_strings'] = join(
+ ',',
+ $auth_strings
+ );
+ }
if ($this->task['disabled'] == 2) {
// Wizard finished.
@@ -562,7 +647,7 @@ class HostDevices extends Wizard
// Check ACL. If user is not able to manage target task,
// redirect him to main page.
if (check_acl(
- $config['id_usuario'],
+ $config['id_user'],
$this->task['id_group'],
$this->access
) != true
@@ -598,10 +683,21 @@ class HostDevices extends Wizard
}
if ($this->page < $this->maxPagesNetScan) {
+ $title = __('NetScan');
+
+ if ($this->page == 1) {
+ $title = __(
+ '"%s" features',
+ io_safe_output(
+ $this->task['name']
+ )
+ );
+ }
+
// Avoid to print header out of wizard.
$this->prepareBreadcrum($breadcrum);
ui_print_page_header(
- __('NetScan'),
+ $title,
'',
false,
'',
@@ -678,7 +774,7 @@ class HostDevices extends Wizard
$form['rows'][0]['columns'][0] = [
'width' => '30%',
- 'style' => 'padding: 9px;',
+ 'style' => 'padding: 9px;min-width: 250px;',
'inputs' => [
'0' => [
'arguments' => [
@@ -705,7 +801,10 @@ class HostDevices extends Wizard
'name' => 'interval_manual_defined',
'return' => true,
],
- 'extra' => ''.html_print_extended_select_for_time(
+ 'extra' => ''.ui_print_help_tip(
+ __('The minimum recomended interval for Recon Task is 5 minutes'),
+ true
+ ).html_print_extended_select_for_time(
'interval',
$this->task['interval_sweep'],
'',
@@ -715,10 +814,7 @@ class HostDevices extends Wizard
true,
false,
false
- ).ui_print_help_tip(
- __('The minimum recomended interval for Recon Task is 5 minutes'),
- true
- ).'',
+ ).'
',
],
],
@@ -728,6 +824,7 @@ class HostDevices extends Wizard
'width' => '40%',
'padding-right' => '12%',
'padding-left' => '5%',
+ 'style' => 'min-width: 350px',
'inputs' => [
'0' => [
'label' => ''.__('Task name').':',
@@ -760,6 +857,54 @@ class HostDevices extends Wizard
],
],
'2' => [
+ 'label' => ''.__('Use CSV file definition').':'.ui_print_help_tip(
+ __('Define targets using csv o network definition.'),
+ true
+ ),
+ 'class' => 'no-margin',
+ 'arguments' => [
+ 'name' => 'network_csv_enabled',
+ 'value' => $this->task['subnet_csv'],
+ 'type' => 'switch',
+ 'inline' => true,
+ 'class' => 'discovery_full_width_input',
+ 'onclick' => 'toggleNetwork(this);',
+ ],
+ ],
+ '3' => [
+ 'hidden' => (($this->task['subnet_csv'] == '1') ? 0 : 1),
+ 'block_id' => 'csv_subnet',
+ 'block_content' => [
+ [
+ 'label' => ''.__('Networks (csv)').':'.ui_print_help_tip(
+ __('You can upload a CSV file. Each line must contain a network in IP/MASK format. For instance: 192.168.1.1/32'),
+ true
+ ),
+ 'arguments' => [
+ 'name' => 'network_csv',
+ 'type' => 'file',
+ 'columns' => 25,
+ 'rows' => 10,
+ 'class' => 'discovery_full_width_input',
+ ],
+ ],
+ [
+ 'label' => ''.__('Networks (current)').':'.ui_print_help_tip(
+ __('Plese upload a new file to overwrite this content.'),
+ true
+ ),
+ 'arguments' => [
+ 'attributes' => 'readonly',
+ 'type' => 'textarea',
+ 'size' => 25,
+ 'value' => $this->task['subnet'],
+ ],
+ ],
+ ],
+ ],
+ '4' => [
+ 'hidden' => (($this->task['subnet_csv'] == '1') ? 1 : 0),
+ 'id' => 'std_subnet',
'label' => ''.__('Network').':'.ui_print_help_tip(
__('You can specify several networks, separated by commas, for example: 192.168.50.0/24,192.168.60.0/24'),
true
@@ -794,6 +939,7 @@ class HostDevices extends Wizard
$form['rows'][0]['columns'][2] = [
'width' => '30%',
+ 'style' => 'min-width: 250px',
'inputs' => ['0' => $group_select],
];
@@ -823,8 +969,9 @@ class HostDevices extends Wizard
}
$form['form'] = [
- 'method' => 'POST',
- 'action' => $this->url.'&mode=netscan&page='.($this->page + 1).$task_url,
+ 'method' => 'POST',
+ 'enctype' => 'multipart/form-data',
+ 'action' => $this->url.'&mode=netscan&page='.($this->page + 1).$task_url,
];
// Default.
@@ -848,7 +995,19 @@ class HostDevices extends Wizard
$("#hidden-interval").val('.$interval.');
$("#interval_units").val('.$unit.');
}
- }).change();';
+ }).change();
+
+ function toggleNetwork(e) {
+ if (e.checked) {
+ $(\'#csv_subnet\').removeClass("hidden");
+ $(\'#std_subnet\').addClass("hidden");
+ } else {
+ $(\'#csv_subnet\').addClass("hidden");
+ $(\'#std_subnet\').removeClass("hidden");
+ }
+ };
+
+ ';
$this->printFormAsGrid($form);
$this->printGoBackButton($this->url.'&page='.($this->page - 1));
@@ -878,21 +1037,101 @@ class HostDevices extends Wizard
];
$form['inputs'][] = [
- 'extra' => 'Please, configure task '.io_safe_output($this->task['name']).'
',
+ 'label' => __('Auto discover known hardware').ui_print_help_tip(
+ __(
+ 'Targets will be monitorized based on its Private Enterprise Number. Requires SNMP.'
+ ),
+ true
+ ),
+ 'arguments' => [
+ 'name' => 'auto_monitor',
+ 'type' => 'switch',
+ 'return' => true,
+ 'value' => (isset($this->task['auto_monitor'])) ? $this->task['auto_monitor'] : 1,
+ ],
];
$form['inputs'][] = [
- 'label' => __('Module template'),
+ 'label' => __('Module templates').ui_print_help_tip(
+ __(
+ 'Module Host Alive will be added to discovered agents by default.'
+ ),
+ true
+ ),
'arguments' => [
- 'name' => 'id_network_profile',
+ 'name' => 'id_network_profile[]',
'type' => 'select_from_sql',
- 'sql' => 'SELECT id_np, name
- FROM tnetwork_profile
- ORDER BY name',
+ 'sql' => 'SELECT tn.id_np, tn.name
+ FROM tnetwork_profile tn
+ LEFT JOIN `tnetwork_profile_pen` tp
+ ON tp.id_np = tn.id_np
+ WHERE tp.id_np IS NULL
+ ORDER BY tn.name',
'return' => true,
- 'selected' => $this->task['id_network_profile'],
+ 'selected' => explode(
+ ',',
+ $this->task['id_network_profile']
+ ),
'nothing_value' => 0,
'nothing' => __('None'),
+ 'multiple' => true,
+ 'class' => 'select_multiple',
+ ],
+ ];
+
+ // License precheck.
+ $license = enterprise_hook('license_get_info');
+ $n_agents = 0;
+ foreach (explode(',', $this->task['subnet']) as $net) {
+ $mask = explode('/', $net, 2)[1];
+ if (empty($mask)) {
+ $n_agents++;
+ } else {
+ $n_agents += pow(2, (32 - $mask));
+ }
+ }
+
+ $limited = false;
+ if (is_array($license) === true
+ && $n_agents > ($license['limit'] - $license['count'])
+ ) {
+ $limit = ($license['limit'] - $license['count']);
+ $limited = true;
+ }
+
+ if ($limited === true) {
+ ui_print_warning_message(
+ __(
+ 'Configured networks could generate %d agents, your license only allows %d, \'review results\' is mandatory.',
+ $n_agents,
+ $limit
+ )
+ );
+ }
+
+ $form['inputs'][] = [
+ 'label' => __('Review results').ui_print_help_tip(
+ __(
+ 'Targets must be validated by user before create agents.'
+ ),
+ true
+ ),
+ 'arguments' => [
+ 'name' => 'review_results',
+ 'type' => 'switch',
+ 'return' => true,
+ 'value' => ($this->task['review_mode'] == DISCOVERY_STANDARD) ? (($limited) ? 1 : 0) : 1,
+ 'disabled' => $limited,
+ ],
+ ];
+
+ // Review limited.
+ $form['inputs'][] = [
+ 'arguments' => [
+ 'name' => 'review_limited',
+ 'type' => 'hidden',
+ 'return' => true,
+ 'value' => (($limited === true) ? 1 : 0),
],
];
@@ -930,7 +1169,7 @@ class HostDevices extends Wizard
// Submit button.
$form['inputs'][] = [
'arguments' => [
- 'name' => 'submit',
+ 'name' => 'submit-finish',
'label' => __('Finish'),
'type' => 'submit',
'attributes' => 'class="sub next"',
diff --git a/pandora_console/godmode/wizards/Wizard.main.php b/pandora_console/godmode/wizards/Wizard.main.php
index 2fe34770ad..7320934826 100644
--- a/pandora_console/godmode/wizards/Wizard.main.php
+++ b/pandora_console/godmode/wizards/Wizard.main.php
@@ -41,7 +41,7 @@ class Wizard
/**
* Breadcrum
*
- * @var array.
+ * @var array
*/
public $breadcrum;
@@ -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.
*
@@ -566,66 +587,40 @@ class Wizard
if (is_array($input['block_content']) === true) {
// Print independent block of inputs.
- $output .= '';
+ $output .= '';
} else {
if ($input['arguments']['type'] != 'hidden'
&& $input['arguments']['type'] != 'hidden_extended'
) {
- if ($input['arguments']['inline'] != 'true') {
- $output .= '';
- } else {
- $output .= '
';
- if (!isset($input['extra'])) {
- $output .= '
';
- }
-
- if (isset($input['extra'])) {
- $output .= '
';
- }
+ $id = '';
+ if ($input['id']) {
+ $id = $input['id'];
}
- if ($input['arguments']['inline'] == 'true' && isset($input['extra'])) {
- $output .= '
';
+ if ($input['arguments']['inline'] != 'true') {
+ $output .= '
';
- }
-
if ($input['arguments']['type'] == 'text' || $input['arguments']['type'] == 'text_extended') {
$output .= '
';
$output .= $this->printInput($input['arguments']);
$output .= '
';
} else if ($input['arguments']['inline'] == 'true') {
- if (isset($input['extra'])) {
- $output .= '
';
- $output .= '
';
- } else {
- $output .= '
';
- $output .= '
';
- }
-
+ $output .= '
';
$output .= $this->printInput($input['arguments']);
$output .= '
';
- $output .= '
';
-
- if (isset($input['extra'])) {
- $output .= '
';
- }
} else {
$output .= $this->printInput($input['arguments']);
}
@@ -800,7 +795,7 @@ class Wizard
$cb_function = $data['cb_function'];
$cb_args = $data['cb_args'];
- $output_head = '
';
- } else {
- $global_progress = -1;
- $result .= ui_print_error_message(
- __('No data to show'),
- '',
- true
- ).'
';
- }
-
- $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();
-}
diff --git a/pandora_console/include/class/AgentWizard.class.php b/pandora_console/include/class/AgentWizard.class.php
new file mode 100644
index 0000000000..f638092930
--- /dev/null
+++ b/pandora_console/include/class/AgentWizard.class.php
@@ -0,0 +1,782 @@
+ 'noaccess']);
+ }
+
+ include 'general/noaccess.php';
+ exit;
+ }
+
+ // Set baseUrl for use it in several locations in this class.
+ $this->baseUrl = ui_get_full_url('index.php?sec=gagente&sec2=godmode/agentes/configurar_agente&tab=agent_wizard');
+ // Capture all parameters before start.
+ $this->ajaxController = $ajax_controller;
+ $this->wizardSection = get_parameter('wizard_section', '');
+ $this->idAgent = get_parameter('id_agente', '');
+ return $this;
+ }
+
+
+ /**
+ * Run main page.
+ *
+ * @return void
+ */
+ public function run()
+ {
+ // CSS.
+ ui_require_css_file('wizard');
+ ui_require_css_file('discovery');
+
+ // Javascript.
+ // ui_require_javascript_file('jquery.caret.min');
+ $this->loadMainForm();
+ $this->performWizard();
+ // Load integrated JS
+ $this->loadJS();
+ }
+
+
+ /**
+ * Common Main Wizard form
+ *
+ * @return void
+ */
+ private function loadMainForm()
+ {
+ // Define name of explorer button
+ switch ($this->wizardSection) {
+ case 'snmp_explorer':
+ case 'snmp_interfaces_explorer':
+ // Define labels.
+ $this->actionType = 'snmp';
+ $this->actionLabel = __('SNMP Walk');
+ // Fill with servers to perform SNMP walk.
+ $fieldsServers = [];
+ $fieldsServers[0] = __('Local console');
+ if (enterprise_installed()) {
+ enterprise_include_once('include/functions_satellite.php');
+ // Get the servers.
+ $rows = get_proxy_servers();
+ // Check if satellite server has remote configuration enabled.
+ $satellite_remote = config_agents_has_remote_configuration($this->idAgent);
+ // Generate a list with allowed servers.
+ foreach ($rows as $row) {
+ if ($row['server_type'] == 13) {
+ $id_satellite = $row['id_server'];
+ $serverType = ' (Satellite)';
+ } else {
+ $serverType = ' (Standard)';
+ }
+
+ $fieldsServers[$row['id_server']] = $row['name'].$serverType;
+ }
+ }
+
+ // Fill with SNMP versions allowed.
+ $fieldsVersions = [
+ '1' => '1',
+ '2' => '2',
+ '2c' => '2c',
+ '3' => '3',
+ ];
+ break;
+
+ case 'wmi_explorer':
+ $this->actionType = 'wmi';
+ $this->actionLabel = __('WMI Explorer');
+ break;
+
+ default:
+ $this->actionType = 'none';
+ $this->actionLabel = __('Nothing');
+ exit;
+ break;
+ }
+
+ // Main form.
+ $form = [
+ 'action' => '',
+ // 'action' => $this->baseUrl,
+ 'id' => 'main_wizard_form',
+ 'method' => 'POST',
+ ];
+
+ // Inputs.
+ $inputs = [];
+
+ $inputs[] = [
+ 'id' => 'hdn-type-action',
+ 'arguments' => [
+ 'name' => 'type-action',
+ 'type' => 'hidden',
+ 'value' => $this->actionType,
+ 'return' => true,
+ ],
+ ];
+
+ $inputs[] = [
+ 'label' => __('Target IP'),
+ 'id' => 'txt-target-ip',
+ 'arguments' => [
+ 'name' => 'target-ip',
+ 'input_class' => 'flex-row',
+ 'type' => 'text',
+ 'class' => '',
+ 'return' => true,
+ ],
+ ];
+
+ $inputs[] = [
+ 'label' => __('Port'),
+ 'id' => 'txt-target-port',
+ 'arguments' => [
+ 'name' => 'target-port',
+ 'input_class' => 'flex-row',
+ 'type' => 'text',
+ 'size' => '20',
+ 'class' => '',
+ 'return' => true,
+ ],
+ ];
+
+ if ($this->actionType === 'snmp') {
+ $inputs[] = [
+ 'label' => __('Use agent IP'),
+ 'id' => 'txt-use-agent-ip',
+ 'arguments' => [
+ 'name' => 'use-agent-ip',
+ 'input_class' => 'flex-row',
+ 'type' => 'checkbox',
+ 'class' => '',
+ 'return' => true,
+ ],
+ ];
+ }
+
+ if ($this->actionType === 'wmi') {
+ $inputs[] = [
+ 'label' => __('Namespace'),
+ 'id' => 'txt-namespace',
+ 'arguments' => [
+ 'name' => 'namespace',
+ 'input_class' => 'flex-row',
+ 'type' => 'text',
+ 'class' => '',
+ 'return' => true,
+ ],
+ ];
+
+ $inputs[] = [
+ 'label' => __('Username'),
+ 'id' => 'txt-username',
+ 'arguments' => [
+ 'name' => 'username',
+ 'input_class' => 'flex-row',
+ 'type' => 'text',
+ 'class' => '',
+ 'return' => true,
+ ],
+ ];
+
+ $inputs[] = [
+ 'label' => __('Password'),
+ 'id' => 'txt-password',
+ 'arguments' => [
+ 'name' => 'password',
+ 'input_class' => 'flex-row',
+ 'type' => 'text',
+ 'class' => '',
+ 'return' => true,
+ ],
+ ];
+ }
+
+ $inputs[] = [
+ 'label' => __('Server to execute command'),
+ 'id' => 'txt-target-port',
+ 'arguments' => [
+ 'name' => 'target-port',
+ 'input_class' => 'flex-row',
+ 'type' => 'select',
+ 'fields' => $fieldsServers,
+ 'class' => '',
+ 'return' => true,
+ ],
+ ];
+
+ if ($this->actionType === 'snmp') {
+ $inputs[] = [
+ 'label' => __('SNMP community'),
+ 'id' => 'txt-snmp-community',
+ 'arguments' => [
+ 'name' => 'snmp-community',
+ 'input_class' => 'flex-row',
+ 'type' => 'text',
+ 'size' => '20',
+ 'class' => '',
+ 'return' => true,
+ ],
+ ];
+
+ $inputs[] = [
+ 'label' => __('SNMP version'),
+ 'id' => 'txt-snmnp-version',
+ 'arguments' => [
+ 'name' => 'snmnp-version',
+ 'input_class' => 'flex-row',
+ 'type' => 'select',
+ 'fields' => $fieldsVersions,
+ 'class' => '',
+ 'return' => true,
+ ],
+ ];
+ }
+
+ $inputs[] = [
+ 'arguments' => [
+ 'label' => $this->actionLabel,
+ 'name' => 'action',
+ 'type' => 'submit',
+ 'attributes' => 'class="sub next" onclick="performAction();return false;"',
+ 'return' => true,
+ ],
+ ];
+ // Prints main form.
+ html_print_div(
+ [
+ 'class' => 'white_box',
+ 'content' => $this->printForm(
+ [
+ 'form' => $form,
+ 'inputs' => $inputs,
+ ],
+ true
+ ),
+ ]
+ );
+ }
+
+
+ /**
+ * Undocumented function
+ *
+ * @return void
+ */
+ public function performWizard()
+ {
+ // echo json_encode(['error' => obhd($_REQUEST)]);
+ // exit;
+ $sql = sprintf(
+ 'SELECT npc.id_nc AS component_id, nc.name, nc.type, nc.description, nc.id_group AS `group`, ncg.name AS `group_name`
+ FROM tnetwork_profile_component AS npc, tnetwork_component AS nc
+ INNER JOIN tnetwork_component_group AS ncg ON ncg.id_sg = nc.id_group
+ WHERE npc.id_nc = nc.id_nc AND npc.id_np = %d',
+ 10
+ );
+ $moduleBlocks = db_get_all_rows_sql($sql);
+
+ $blockTables = [];
+ // Build the information of the blocks.
+ foreach ($moduleBlocks as $block) {
+ if (key_exists($block['group'], $blockTables) === false) {
+ $blockTables[$block['group']] = [
+ 'name' => $block['group_name'],
+ 'data' => [],
+ ];
+ }
+
+ $blockTables[$block['group']]['data'][] = [
+ 'component_id' => $block['component_id'],
+ 'name' => $block['name'],
+ 'type' => $block['type'],
+ 'description' => $block['description'],
+ ];
+ }
+
+ // Lets generate the block tables.
+ $output = '';
+ foreach ($blockTables as $id_group => $blockTable) {
+ // Data with all components.
+ $blockData = $blockTable['data'];
+ // Creation of list of all components.
+ $blockComponentList = '';
+ foreach ($blockData as $component) {
+ $blockComponentList .= $component['component_id'].',';
+ }
+
+ $blockComponentList = chop($blockComponentList, ',');
+ // Title of Block.
+ $blockTitle = $blockTable['name'];
+ $blockTitle .= html_print_div(
+ [
+ 'class' => 'white_table_header_checkbox',
+ 'content' => html_print_checkbox_switch_extended(
+ 'sel_block_'.$id_group,
+ 1,
+ 0,
+ false,
+ 'switchBlockControl(event)',
+ '',
+ true
+ ),
+ ],
+ true
+ );
+
+ $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 = [];
+
+ $table->cellpadding = 0;
+ $table->cellspacing = 0;
+ $table->width = '100%';
+ $table->class = 'info_table';
+
+ $table->head = [];
+ $table->head[0] = html_print_div(['style' => 'font-weight:700;', 'content' => __('Module Name')], true);
+ $table->head[1] = html_print_div(['style' => 'font-weight:700;text-align:center;', 'content' => __('Type')], true);
+ $table->head[2] = html_print_div(['style' => 'font-weight:700;', 'content' => __('Module info')], true);
+ $table->head[3] = html_print_div(['style' => 'font-weight:700;text-align:center;', 'content' => __('Warning')], true);
+ $table->head[4] = html_print_div(['style' => 'font-weight:700;text-align:center;', 'content' => __('Critical')], true);
+ $table->head[5] = html_print_div(['style' => 'font-weight:700;margin-right:1.2em;', 'content' => __('Active')], true);
+
+ $table->size = [];
+ $table->size[0] = '15%';
+ $table->size[1] = '3%';
+ $table->size[3] = '210px';
+ $table->size[4] = '210px';
+ $table->size[5] = '3%';
+
+ $table->align = [];
+ $table->align[5] = 'right';
+
+ $table->data = [];
+
+ foreach ($blockData as $module) {
+ // Module Name column.
+ $data[0] = $module['name'];
+ // Module Type column.
+ $data[1] = ui_print_moduletype_icon($module['type'], true);
+ // Module info column.
+ $data[2] = mb_strimwidth(io_safe_output($module['description']), 0, 150, '...');
+ // Warning column.
+ $data[3] = html_print_div(
+ [
+ 'class' => 'wizard-column-levels',
+ 'content' => 'Min: '.html_print_input_text(
+ 'warning_min_'.$module['component_id'],
+ '0',
+ '',
+ 3,
+ 4,
+ true
+ ).' ',
+ ],
+ true
+ );
+ $data[3] .= html_print_div(
+ [
+ 'class' => 'wizard-column-levels',
+ 'content' => 'Max: '.html_print_input_text(
+ 'warning_max_'.$module['component_id'],
+ '0',
+ '',
+ 3,
+ 4,
+ true
+ ),
+ ],
+ true
+ );
+ $data[3] .= html_print_div(
+ [
+ 'class' => 'wizard-column-levels',
+ 'style' => 'margin-top: 0.3em;',
+ 'content' => 'Inv: '.html_print_checkbox(
+ 'warning_inv_'.$module['component_id'],
+ 0,
+ false,
+ true,
+ false
+ ),
+ ],
+ true
+ );
+ // Critical column.
+ $data[4] = html_print_div(
+ [
+ 'class' => 'wizard-column-levels',
+ 'content' => 'Min: '.html_print_input_text(
+ 'critical_min_'.$module['component_id'],
+ '0',
+ '',
+ 3,
+ 4,
+ true
+ ).' ',
+ ],
+ true
+ );
+ $data[4] .= html_print_div(
+ [
+ 'class' => 'wizard-column-levels',
+ 'content' => 'Max: '.html_print_input_text(
+ 'critical_max_'.$module['component_id'],
+ '0',
+ '',
+ 3,
+ 4,
+ true
+ ),
+ ],
+ true
+ );
+ $data[4] .= html_print_div(
+ [
+ 'class' => 'wizard-column-levels',
+ 'style' => 'margin-top: 0.3em;',
+ 'content' => 'Inv: '.html_print_checkbox(
+ 'critical_inv_'.$module['component_id'],
+ 0,
+ false,
+ true,
+ false
+ ),
+ ],
+ true
+ );
+ // Activation column.
+ $data[5] = html_print_checkbox_switch_extended('sel_module_'.$id_group.'_'.$module['component_id'], 1, 0, false, 'switchBlockControl(event)', '', true);
+
+ array_push($table->data, $data);
+ }
+
+ $content = html_print_table($table, true);
+
+ $output .= ui_toggle($content, $blockTitle, '', '', false, true);
+ }
+
+ html_print_div(
+ [
+ 'class' => 'white_box',
+ 'style' => 'margin-top: 20px;',
+ 'content' => $output,
+ ]
+ );
+
+ // Form. Not used at this moment.
+ $form = [
+ 'action' => $this->baseUrl,
+ 'id' => 'modal_form_action_response',
+ 'method' => 'POST',
+ 'class' => 'modal',
+ 'extra' => '',
+ ];
+
+ // Inputs.
+ $inputs = [];
+
+ $inputs[] = [
+ 'id' => 'inp-id_np',
+ 'arguments' => [
+ 'name' => 'id_np',
+ 'type' => 'hidden',
+ 'value' => '69',
+ 'return' => true,
+ ],
+ ];
+
+ $this->printForm(
+ [
+ 'form' => $form,
+ 'inputs' => $inputs,
+ true
+ ]
+ );
+ }
+
+
+ /**
+ * Perform SNMP
+ *
+ * @return void
+ */
+ private function performSNMP()
+ {
+ echo 'HOLA';
+ }
+
+
+ /**
+ * Perform WMI
+ *
+ * @return void
+ */
+ private function performWMI()
+ {
+
+ }
+
+
+ /**
+ * Generate the JS needed for use inside
+ *
+ * @return void
+ */
+ private function loadJS()
+ {
+ $str = '';
+
+ ob_start();
+ ?>
+
+ ajaxController = $ajax_page;
+ $this->offset = '';
+ $this->baseUrl = ui_get_full_url(
+ 'index.php?sec=configuration_wizard_setup&sec2=godmode/modules/private_enterprise_numbers'
+ );
+
+ }
+
+
+ /**
+ * Returns an array with all the credentials matching filter and ACL.
+ *
+ * @param array $fields Fields array or 'count' keyword to retrieve count.
+ * @param array $filter Filters to be applied.
+ * @param integer $offset Offset (pagination).
+ * @param integer $limit Limit (pagination).
+ * @param string $order Sort order.
+ * @param string $sort_field Sort field.
+ *
+ * @return array With all results or false if error.
+ * @throws Exception On error.
+ */
+ public static function getAll(
+ $fields,
+ $filter=null,
+ $offset=null,
+ $limit=null,
+ $order=null,
+ $sort_field=null
+ ) {
+ $sql_filters = [];
+ $order_by = '';
+ $pagination = '';
+
+ $count = false;
+ if (!is_array($fields) && $fields == 'count') {
+ $fields = ['*'];
+ $count = true;
+ } else if (!is_array($fields)) {
+ error_log('[configPEN.getAll] Fields must be an array or "count".');
+ throw new Exception('[configPEN.getAll] Fields must be an array or "count".');
+ }
+
+ if (is_array($filter)) {
+ if (!empty($filter['free_search'])) {
+ $sql_filters[] = vsprintf(
+ ' AND (lower(`manufacturer`) like lower("%%%s%%")
+ OR pen = "%s") ',
+ array_fill(0, 2, $filter['free_search'])
+ );
+ }
+
+ if (!empty($filter['pen'])) {
+ $sql_filters[] = sprintf(
+ ' AND `pen` = %d',
+ $filter['pen']
+ );
+ }
+ }
+
+ if (isset($order)) {
+ $dir = 'asc';
+ if ($order == 'desc') {
+ $dir = 'desc';
+ };
+
+ if (in_array(
+ $sort_field,
+ [
+ 'pen',
+ 'manufacturer',
+ 'description',
+ ]
+ )
+ ) {
+ $order_by = sprintf(
+ 'ORDER BY `%s` %s',
+ $sort_field,
+ $dir
+ );
+ }
+ }
+
+ if (isset($limit) && $limit > 0
+ && isset($offset) && $offset >= 0
+ ) {
+ $pagination = sprintf(
+ ' LIMIT %d OFFSET %d ',
+ $limit,
+ $offset
+ );
+ }
+
+ $sql = sprintf(
+ 'SELECT %s
+ FROM `tpen`
+ WHERE 1=1
+ %s
+ %s
+ %s',
+ join(',', $fields),
+ join(' ', $sql_filters),
+ $order_by,
+ $pagination
+ );
+
+ if ($count) {
+ $sql = sprintf('SELECT count(*) as n FROM ( %s ) tt', $sql);
+
+ return db_get_value_sql($sql);
+ }
+
+ return db_get_all_rows_sql($sql);
+ }
+
+
+ /**
+ * AJAX: Return JSON content for datatable.
+ *
+ * @return void
+ */
+ function draw()
+ {
+ global $config;
+
+ // Datatables offset, limit and order.
+ $filter = get_parameter('filter', []);
+ $start = get_parameter('start', 0);
+ $length = get_parameter('length', $config['block_size']);
+ $order = get_datatable_order(true);
+ try {
+ ob_start();
+
+ $fields = ['*'];
+
+ // Retrieve data.
+ $data = $this->getAll(
+ // Fields.
+ $fields,
+ // Filter.
+ $filter,
+ // Offset.
+ $start,
+ // Limit.
+ $length,
+ // Order.
+ $order['direction'],
+ // Sort field.
+ $order['field']
+ );
+
+ // Retrieve counter.
+ $count = $this->getAll(
+ 'count',
+ $filter
+ );
+
+ if ($data) {
+ $data = array_reduce(
+ $data,
+ function ($carry, $item) {
+ // Transforms array of arrays $data into an array
+ // of objects, making a post-process of certain fields.
+ $tmp = (object) $item;
+
+ $tmp->description = io_safe_output($tmp->description);
+ $tmp->manufacturer = io_safe_output($tmp->manufacturer);
+
+ $tmp->options = '';
+
+ $tmp->options = '
';
+ $tmp->options .= html_print_image(
+ 'images/eye.png',
+ true,
+ ['title' => __('Show')]
+ );
+ $tmp->options .= '';
+ $tmp->options .= '
';
+ $tmp->options .= html_print_image(
+ 'images/cross.png',
+ true,
+ ['title' => __('Delete')]
+ );
+ $tmp->options .= '';
+
+ $carry[] = $tmp;
+ return $carry;
+ }
+ );
+ }
+
+ // Datatables format: RecordsTotal && recordsfiltered.
+ echo json_encode(
+ [
+ 'data' => $data,
+ 'recordsTotal' => $count,
+ 'recordsFiltered' => $count,
+ ]
+ );
+ // Capture output.
+ $response = ob_get_clean();
+ } catch (Exception $e) {
+ echo json_encode(['error' => $e->getMessage()]);
+ exit;
+ }
+
+ // If not valid, show error with issue.
+ json_decode($response);
+ if (json_last_error() == JSON_ERROR_NONE) {
+ // If valid dump.
+ echo $response;
+ } else {
+ echo json_encode(
+ ['error' => $response]
+ );
+ }
+
+ exit;
+
+ }
+
+
+ /**
+ * Run main page.
+ *
+ * @return void
+ */
+ public function run()
+ {
+ // Require specific CSS and JS.
+ ui_require_css_file('wizard');
+ ui_require_css_file('discovery');
+ ui_require_css_file('pen');
+
+ // Header section.
+ // Breadcrums.
+ $this->setBreadcrum([]);
+
+ $this->prepareBreadcrum(
+ [
+ [
+ 'link' => '',
+ 'label' => __('Configuration'),
+ 'selected' => false,
+ ],
+ [
+ 'link' => '',
+ 'label' => __('Templates'),
+ 'selected' => false,
+ ],
+ [
+ 'link' => $this->baseUrl,
+ 'label' => __('Private Enterprise Numbers'),
+ 'selected' => true,
+ ],
+ ],
+ true
+ );
+
+ ui_print_page_header(
+ __('Private Enterprise Numbers'),
+ '',
+ false,
+ '',
+ true,
+ '',
+ false,
+ '',
+ GENERIC_SIZE_TEXT,
+ '',
+ $this->printHeader(true)
+ );
+
+ // Definition for AJAX.
+ html_print_input_hidden(
+ 'ajax_file',
+ ui_get_full_url('ajax.php', false, false, false)
+ );
+
+ // Ajax page (hidden).
+ html_print_input_hidden(
+ 'ajax_page',
+ $this->ajaxController
+ );
+
+ // Allow message area.
+ html_print_div(['id' => 'message_show_area']);
+ // Prints the main table.
+ html_print_div(
+ [
+ 'id' => 'main_table_area',
+ 'content' => $this->createMainTable(),
+ ]
+ );
+ }
+
+
+ /**
+ * Load modal information for PEN management.
+ *
+ * Ajax. Direct HTML.
+ *
+ * @return void
+ */
+ public function loadModal()
+ {
+ $values = [];
+ $id = (int) get_parameter('pen', 0);
+ if ($id > 0) {
+ $values = $this->getAll(
+ // Fields.
+ ['*'],
+ // Filter.
+ ['pen' => $id]
+ );
+ if (is_array($values)) {
+ $values = $values[0];
+ }
+ }
+
+ $form = [
+ 'action' => '#',
+ 'id' => 'modal_form',
+ 'onsubmit' => 'return false;',
+ 'class' => '',
+ ];
+
+ $inputs = [];
+
+ $arguments = [
+ 'name' => 'pen',
+ 'type' => 'number',
+ 'value' => $values['pen'],
+ 'required' => true,
+ 'return' => true,
+ 'size' => 50,
+ ];
+
+ if ((bool) $values['pen']) {
+ $arguments['disabled'] = true;
+ }
+
+ $inputs[] = [
+ 'label' => __('PEN'),
+ 'class' => 'flex-row',
+ 'id' => 'div-pen',
+ 'arguments' => $arguments,
+ ];
+
+ $inputs[] = [
+ 'label' => __('Manufacturer'),
+ 'class' => 'flex-row',
+ 'arguments' => [
+ 'name' => 'manufacturer',
+ 'id' => 'manufacturer',
+ 'type' => 'text',
+ 'required' => true,
+ 'value' => io_safe_output($values['manufacturer']),
+ 'return' => true,
+ ],
+ ];
+
+ $inputs[] = [
+ 'label' => __('Description'),
+ 'class' => 'flex-row',
+ 'arguments' => [
+ 'name' => 'description',
+ 'id' => 'description',
+ 'type' => 'textarea',
+ 'value' => io_safe_output($values['description']),
+ 'return' => true,
+ 'rows' => 50,
+ 'columns' => 30,
+ ],
+ ];
+
+ echo '
';
+ echo parent::printForm(
+ [
+ 'form' => $form,
+ 'inputs' => $inputs,
+ ],
+ true
+ );
+ echo '
';
+ }
+
+
+ /**
+ * Delete a manufacturer register from db.
+ *
+ * @return void
+ */
+ public function delete()
+ {
+ $pen = get_parameter('pen', 0);
+
+ if (empty($pen)) {
+ echo json_encode(['error' => __('PEN is required')]);
+ } else {
+ if (db_process_sql_delete('tpen', ['pen' => $pen]) !== false) {
+ echo json_encode(['result' => __('Successfully deleted')]);
+ } else {
+ global $config;
+ echo json_encode(['error' => $config['dbconnection']->error]);
+ }
+ }
+
+ }
+
+
+ /**
+ * Add or update a manufacturer to private enterprise numbers.
+ *
+ * @return void
+ */
+ public function add()
+ {
+ $pen = get_parameter('pen', 0);
+ $manufacturer = get_parameter('manufacturer', '');
+ $description = get_parameter('description', '');
+ $is_new = (bool) get_parameter('is_new', false);
+
+ if (empty($pen)) {
+ $error = __('PEN is required.');
+ }
+
+ if (empty($manufacturer)) {
+ $error = __('Manufacturer is required');
+ }
+
+ if (!empty($error)) {
+ echo json_encode(
+ ['error' => $error]
+ );
+ }
+
+ // Add if not exists.
+ $current = $this->getAll(['pen'], ['pen' => $pen]);
+
+ if ($current === false) {
+ // New.
+ if ($is_new === false) {
+ echo json_encode(
+ [
+ 'error' => __('This PEN definition does not exist'),
+ ]
+ );
+ exit;
+ }
+
+ $rs = db_process_sql_insert(
+ 'tpen',
+ [
+ 'pen' => $pen,
+ 'manufacturer' => $manufacturer,
+ 'description' => $description,
+ ]
+ );
+ $str = __('created');
+ } else {
+ // Update.
+ if ($is_new === true) {
+ echo json_encode(
+ [
+ 'error' => __('This PEN definition already exists'),
+ ]
+ );
+ exit;
+ }
+
+ $rs = db_process_sql_update(
+ 'tpen',
+ [
+ 'manufacturer' => $manufacturer,
+ 'description' => $description,
+ ],
+ ['pen' => $pen]
+ );
+ $str = __('updated');
+ }
+
+ if ($rs === false) {
+ global $config;
+ echo json_encode(['error' => $config['dbconnection']->error]);
+ } else {
+ echo json_encode(['result' => __('Succesfully %s', $str)]);
+ }
+ }
+
+
+ /**
+ * Create the main table with the PENs info
+ *
+ * @return string Return entire the table
+ */
+ public function createMainTable()
+ {
+ global $config;
+
+ $output = '';
+
+ // Datatables list.
+ try {
+ $columns = [
+ 'pen',
+ 'manufacturer',
+ 'description',
+ 'options',
+ ];
+
+ $column_names = [
+ __('PEN'),
+ __('Manufacturer'),
+ __('Description'),
+ [
+ 'text' => __('Options'),
+ 'class' => 'action_buttons',
+ ],
+ ];
+
+ $this->tableId = 'keystore';
+ // Load datatables user interface.
+ $output .= ui_print_datatable(
+ [
+ 'id' => $this->tableId,
+ 'return' => true,
+ 'class' => 'info_table',
+ 'style' => 'width: 100%',
+ 'columns' => $columns,
+ 'column_names' => $column_names,
+ 'ajax_url' => $this->ajaxController,
+ 'ajax_data' => ['method' => 'draw'],
+ 'no_sortable_columns' => [-1],
+ 'order' => [
+ 'field' => 'pen',
+ 'direction' => 'asc',
+ ],
+ 'search_button_class' => 'sub filter float-right',
+ 'form' => [
+ 'inputs' => [
+ [
+ 'label' => __('Free search'),
+ 'type' => 'text',
+ 'class' => 'mw250px',
+ 'id' => 'free_search',
+ 'name' => 'free_search',
+ ],
+ ],
+ ],
+ ]
+ );
+ } catch (Exception $e) {
+ echo $e->getMessage();
+ }
+
+ // Auxiliar div.
+ $output .= '
';
+ $output .= '
';
+ $output .= '
';
+
+ // Create button.
+ $output .= parent::printInput(
+ [
+ 'type' => 'submit',
+ 'name' => 'create',
+ 'label' => __('Register manufacturer'),
+ 'attributes' => 'class="sub next"',
+ 'return' => true,
+ ]
+ );
+
+ ob_start();
+ ?>
+
+ ui_print_error_message($message, '', true),
+ ]
+ );
+ } else {
+ return ui_print_error_message($message, '', true);
+ }
+ }
+
+
/**
* Print input using functions html lib.
*
@@ -725,6 +746,7 @@ class HTML
) {
$form = $data['form'];
$inputs = $data['inputs'];
+ $rawInputs = $data['rawInputs'];
$js = $data['js'];
$rawjs = $data['js_block'];
$cb_function = $data['cb_function'];
@@ -767,6 +789,11 @@ class HTML
$output .= '';
+ // There is possible add raw inputs for this form.
+ if (empty($rawInputs) === false) {
+ $output .= $rawInputs;
+ }
+
if ($print_white_box === true) {
$output .= '
';
}
@@ -800,7 +827,7 @@ class HTML
$form = $data['form'];
$rows = $data['rows'];
-
+ $rawInputs = $data['rawInputs'];
$js = $data['js'];
$rawjs = $data['js_block'];
$cb_function = $data['cb_function'];
@@ -875,6 +902,11 @@ class HTML
}
}
+ // There is possible add raw inputs for this form.
+ if (empty($rawInputs) === false) {
+ $output .= $rawInputs;
+ }
+
$output .= '
';
$output .= '
';
@@ -905,6 +937,7 @@ class HTML
{
$form = $data['form'];
$inputs = $data['inputs'];
+ $rawInputs = $data['rawInputs'];
$js = $data['js'];
$rawjs = $data['js_block'];
$cb_function = $data['cb_function'];
@@ -940,7 +973,13 @@ class HTML
}
$output .= '';
+ // There is possible add raw inputs for this form.
+ if (empty($rawInputs) === false) {
+ $output .= $rawInputs;
+ }
+
$output .= '
';
+
$output .= '
';
$output .= '';
$output .= '';
@@ -1000,4 +1039,72 @@ class HTML
}
+ /**
+ * Returns a n-dimensional array (data) into a html tree structure.
+ *
+ * Advanced documentation:
+ * https://www.jqueryscript.net/other/Checkable-Hierarchical-Tree.html
+ *
+ * @param string $target Target DOM id.
+ * @param array $data N-dimensional array.
+ * @param string $onclick Onclick function.
+ * @param string $onchange Onchange function.
+ *
+ * @return string
+ */
+ public static function printTree(
+ $target,
+ $data,
+ $onclick='',
+ $onchange=''
+ ) {
+ ui_require_css_file('simTree');
+ ui_require_javascript_file('simTree');
+
+ /*
+ * SAMPLE SELECT ALL.
+ *
+ * echo '
';
+ * echo '
';
+ * echo __('Please select devices to be monitored');
+ * echo '';
+ * echo '';
+ * echo '';
+ * echo '
';
+ * echo '
';
+ *
+ * END SAMPLE SELECT ALL.
+ */
+
+ $output = '
+';
+
+ return $output;
+ }
+
+
}
diff --git a/pandora_console/include/class/ModuleTemplates.class.php b/pandora_console/include/class/ModuleTemplates.class.php
new file mode 100644
index 0000000000..585a40aa13
--- /dev/null
+++ b/pandora_console/include/class/ModuleTemplates.class.php
@@ -0,0 +1,1429 @@
+ 'noaccess']);
+ }
+
+ include 'general/noaccess.php';
+ exit;
+ }
+
+ // Set baseUrl for use it in several locations in this class.
+ $this->baseUrl = ui_get_full_url('index.php?sec=gmodules&sec2=godmode/modules/manage_module_templates');
+ // Capture all parameters before start.
+ $this->id_np = get_parameter('id_np', -1);
+ $this->action = get_parameter('action_button', '');
+ // Profile exists. Set the attributes with the info.
+ if ($this->id_np > 0 || empty($this->action)) {
+ $this->setNetworkProfile();
+ }
+
+ $this->offset = (int) get_parameter('offset', 0);
+ $this->ajaxController = $ajax_controller;
+ // Get all of PENs valid for autocomplete.
+ $getPENs = db_get_all_rows_sql('SELECT pen,manufacturer FROM tpen');
+ $outputPENs = [];
+
+ $this->validPen = '';
+ $this->penRefs = [];
+ foreach ($getPENs as $pen) {
+ $this->validPen .= ((int) $pen['pen']).',';
+ $this->penRefs[] = [
+ 'label' => io_safe_output($pen['manufacturer']),
+ 'value' => $pen['pen'],
+ ];
+ // Reverse autocompletion.
+ $this->penRefs[] = [
+ 'label' => $pen['pen'],
+ 'value' => $pen['pen'],
+ ];
+ }
+
+ chop($this->validPen);
+
+ return $this;
+ }
+
+
+ /**
+ * Run main page.
+ *
+ * @return void
+ */
+ public function run()
+ {
+ // CSS.
+ ui_require_css_file('wizard');
+ ui_require_css_file('discovery');
+
+ // Javascript.
+ ui_require_javascript_file('jquery.caret.min');
+
+ // Breadcrums.
+ $this->setBreadcrum([]);
+
+ if ($this->id_np > 0) {
+ // Add a breadcrumb with the current template.
+ $urlToGo = $this->baseUrl.'&id_np='.$this->id_np;
+
+ $this->prepareBreadcrum(
+ [
+ ['label' => __('Configuration')],
+ ['label' => __('Templates')],
+ [
+ 'link' => $this->baseUrl,
+ 'label' => __('Module template management'),
+ 'selected' => false,
+ ],
+ [
+ 'link' => $urlToGo,
+ 'label' => $this->name,
+ 'selected' => true,
+ ],
+ ],
+ true
+ );
+ } else {
+ $this->prepareBreadcrum(
+ [
+ ['label' => __('Configuration')],
+ ['label' => __('Templates')],
+ [
+ 'link' => $this->baseUrl,
+ 'label' => __('Module template management'),
+ 'selected' => true,
+ ],
+ ],
+ true
+ );
+ }
+
+ // Prints the header.
+ ui_print_page_header(
+ __('Module template management'),
+ '',
+ false,
+ '',
+ true,
+ '',
+ false,
+ '',
+ GENERIC_SIZE_TEXT,
+ '',
+ $this->printHeader(true)
+ );
+
+ // Process the data if action is required.
+ if (!empty($this->action)) {
+ $this->processData();
+ }
+
+ if ($this->id_np === -1) {
+ // List all Module Blocks.
+ $this->moduleTemplateList();
+ } else {
+ // Show form for create or update template.
+ $this->moduleTemplateForm();
+ }
+
+ $this->loadJS();
+ }
+
+
+ /**
+ * Minor function to dump json message as ajax response.
+ *
+ * @param string $type Type: result || error.
+ * @param string $msg Message.
+ *
+ * @return void
+ */
+ private function ajaxMsg($type, $msg)
+ {
+ if ($type == 'error') {
+ echo json_encode(
+ [
+ $type => ui_print_error_message(
+ __($msg),
+ '',
+ true
+ ),
+ ]
+ );
+ } else {
+ echo json_encode(
+ [
+ $type => ui_print_success_message(
+ __($msg),
+ '',
+ true
+ ),
+ ]
+ );
+ }
+
+ exit;
+ }
+
+
+ /**
+ * Save or Update the data received.
+ *
+ * @return void
+ */
+ public function processData()
+ {
+ // Only needed if process data.
+ $modulesToAdd = get_parameter('add-modules-components', '');
+ // Evaluate the modules allowed.
+ if (!empty($this->action)) {
+ // Success variable.
+ $success = false;
+ $this->name = get_parameter('name', '');
+ $this->description = get_parameter('description', '');
+ $this->pen = get_parameter('pen', '');
+
+ switch ($this->action) {
+ case 'Update':
+ $dbResult_tnp = db_process_sql_update(
+ 'tnetwork_profile',
+ [
+ 'name' => $this->name,
+ 'description' => $this->description,
+ ],
+ ['id_np' => $this->id_np]
+ );
+ if ($dbResult_tnp === false) {
+ $success = false;
+ } else {
+ db_process_sql_delete('tnetwork_profile_pen', ['id_np' => $this->id_np]);
+ if (empty($this->pen)) {
+ $success = true;
+ } else {
+ $pensList = explode(',', $this->pen);
+ // Set again the new PENs associated.
+ foreach ($pensList as $currentPen) {
+ $dbResult_pen = db_process_sql_insert(
+ 'tnetwork_profile_pen',
+ [
+ 'pen' => $currentPen,
+ 'id_np' => $this->id_np,
+ ]
+ );
+ if ($dbResult_pen === false) {
+ $success = false;
+ break;
+ }
+
+ $success = true;
+ }
+ }
+ }
+
+ if ($success === true) {
+ $msg = __('Template %s successfully updated', $this->name);
+ } else {
+ $msg = __('Error updating template');
+ }
+ break;
+
+ case 'Create':
+ $dbResult_tnp = db_process_sql_insert(
+ 'tnetwork_profile',
+ [
+ 'name' => $this->name,
+ 'description' => $this->description,
+ ]
+ );
+ // The insert gone fine!
+ if ($dbResult_tnp != false) {
+ // Set the new id_np.
+ $this->id_np = $dbResult_tnp;
+ if (empty($this->pen)) {
+ $success = true;
+ } else {
+ $pensList = explode(',', $this->pen);
+ // Insert all of new PENs associated with this id_np.
+ foreach ($pensList as $currentPen) {
+ $dbResult_pen = db_process_sql_insert(
+ 'tnetwork_profile_pen',
+ [
+ 'pen' => $currentPen,
+ 'id_np' => $this->id_np,
+ ]
+ );
+ // If something is wrong, is better stop.
+ if ($dbResult_pen === false) {
+ break;
+ }
+
+ $success = true;
+ }
+ }
+ }
+
+ if ($success === true) {
+ $msg = __('Template %s successfully created', $this->name);
+ } else {
+ $msg = __('Error creating template');
+ }
+ break;
+
+ case 'Delete':
+ $success = db_process_sql_delete('tnetwork_profile', ['id_np' => $this->id_np]);
+
+ if ($success != false) {
+ $msg = __('Template %s successfully deleted', $this->name);
+ } else {
+ $msg = __('Error deleting %s template', $this->name);
+ }
+
+ // Reset id_np for show the templates list.
+ $this->id_np = -1;
+ break;
+
+ case 'Export':
+ global $config;
+
+ $id_network_profile = safe_int($this->id_np);
+ if (empty($id_network_profile)) {
+ return false;
+ }
+
+ $filter['id_np'] = $id_network_profile;
+
+ $profile_info = @db_get_row_filter('tnetwork_profile', $filter, false);
+
+ if (empty($profile_info)) {
+ $success = false;
+ // ui_print_error_message(__('This template does not exist'));
+ return;
+ }
+
+ // It's important to keep the structure and order in the same way for backwards compatibility.
+ switch ($config['dbtype']) {
+ case 'mysql':
+ $sql = sprintf(
+ '
+ SELECT components.name, components.description, components.type, components.max, components.min, components.module_interval,
+ components.tcp_port, components.tcp_send, components.tcp_rcv, components.snmp_community, components.snmp_oid,
+ components.id_module_group, components.id_modulo, components.plugin_user, components.plugin_pass, components.plugin_parameter,
+ components.max_timeout, components.max_retries, components.history_data, components.min_warning, components.max_warning, components.str_warning, components.min_critical,
+ components.max_critical, components.str_critical, components.min_ff_event, components.dynamic_interval, components.dynamic_max, components.dynamic_min, components.dynamic_two_tailed, comp_group.name AS group_name, components.critical_instructions, components.warning_instructions, components.unknown_instructions
+ FROM `tnetwork_component` AS components, tnetwork_profile_component AS tpc, tnetwork_component_group AS comp_group
+ WHERE tpc.id_nc = components.id_nc
+ AND components.id_group = comp_group.id_sg
+ AND tpc.id_np = %d',
+ $this->id_np
+ );
+ break;
+
+ case 'postgresql':
+ $sql = sprintf(
+ '
+ SELECT components.name, components.description, components.type, components.max, components.min, components.module_interval,
+ components.tcp_port, components.tcp_send, components.tcp_rcv, components.snmp_community, components.snmp_oid,
+ components.id_module_group, components.id_modulo, components.plugin_user, components.plugin_pass, components.plugin_parameter,
+ components.max_timeout, components.max_retries, components.history_data, components.min_warning, components.max_warning, components.str_warning, components.min_critical,
+ components.max_critical, components.str_critical, components.min_ff_event, comp_group.name AS group_name, components.critical_instructions, components.warning_instructions, components.unknown_instructions
+ FROM "tnetwork_component" AS components, tnetwork_profile_component AS tpc, tnetwork_component_group AS comp_group
+ WHERE tpc.id_nc = components.id_nc
+ AND components.id_group = comp_group.id_sg
+ AND tpc.id_np = %d',
+ $this->id_np
+ );
+ break;
+
+ case 'oracle':
+ $sql = sprintf(
+ '
+ SELECT components.name, components.description, components.type, components.max, components.min, components.module_interval,
+ components.tcp_port, components.tcp_send, components.tcp_rcv, components.snmp_community, components.snmp_oid,
+ components.id_module_group, components.id_modulo, components.plugin_user, components.plugin_pass, components.plugin_parameter,
+ components.max_timeout, components.max_retries, components.history_data, components.min_warning, components.max_warning, components.str_warning, components.min_critical,
+ components.max_critical, components.str_critical, components.min_ff_event, comp_group.name AS group_name, components.critical_instructions, components.warning_instructions, components.unknown_instructions
+ FROM tnetwork_component AS components, tnetwork_profile_component AS tpc, tnetwork_component_group AS comp_group
+ WHERE tpc.id_nc = components.id_nc
+ AND components.id_group = comp_group.id_sg
+ AND tpc.id_np = %d',
+ $this->id_np
+ );
+ break;
+ }
+
+ $components = db_get_all_rows_sql($sql);
+
+ $row_names = [];
+ $inv_names = [];
+ // Find the names of the rows that we are getting and throw away the duplicate numeric keys
+ foreach ($components[0] as $row_name => $detail) {
+ if (is_numeric($row_name)) {
+ $inv_names[] = $row_name;
+ } else {
+ $row_names[] = $row_name;
+ }
+ }
+
+ $fileName = io_safe_output($profile_info['name']);
+ // Send headers to tell the browser we're sending a file
+ header('Content-type: application/octet-stream');
+ header('Content-Disposition: attachment; filename='.preg_replace('/\s/', '_', $fileName).'.csv');
+ header('Pragma: no-cache');
+ header('Expires: 0');
+
+ // Clean up output buffering
+ while (@ob_end_clean()) {
+ }
+
+ // Then print the first line (row names)
+ echo '"'.implode('","', $row_names).'"';
+ echo "\n";
+
+ // Then print the rest of the data. Encapsulate in quotes in case we have comma's in any of the descriptions
+ foreach ($components as $row) {
+ foreach ($inv_names as $bad_key) {
+ unset($row[$bad_key]);
+ }
+
+ echo '"'.implode('","', $row).'"';
+ echo "\n";
+ }
+
+ // We're done here. The original page will still be there
+ exit;
+
+ break;
+
+ default:
+ // There is possible want do an action detailed.
+ $action_detailed = explode('_', $this->action);
+ // Action deletion.
+ if ($action_detailed[0] === 'del') {
+ // Block or Module is affected.
+ switch ($action_detailed[1]) {
+ case 'module':
+ $success = db_process_sql_delete(
+ 'tnetwork_profile_component',
+ 'id_nc='.$action_detailed[2].' AND id_np='.$this->id_np
+ );
+
+ if ($success != false) {
+ $msg = __('Module successfully deleted');
+ } else {
+ $msg = __('Error deleting module');
+ }
+ break;
+
+ case 'block':
+ $success = db_process_sql_delete(
+ 'tnetwork_profile_component',
+ 'id_nc in ('.$action_detailed[2].') AND id_np='.$this->id_np
+ );
+
+ if ($success != false) {
+ $msg = __('Block successfully deleted');
+ } else {
+ $msg = __('Error deleting block');
+ }
+ break;
+
+ case 'template':
+ if ($action_detailed[2] === 'all') {
+ $success = db_process_sql_delete(
+ 'tnetwork_profile',
+ ['1' => 1]
+ );
+
+ if ($success != false) {
+ $msg = __('All templates deleted');
+ } else {
+ $msg = __('Error deleting all templates');
+ }
+ } else {
+ $success = db_process_sql_delete(
+ 'tnetwork_profile',
+ 'id_np in ('.$action_detailed[2].')'
+ );
+
+ if ($success != false) {
+ $msg = __('Selected templates deleted');
+ } else {
+ $msg = __('Error deleting selected templates');
+ }
+ }
+
+ $this->id_np = -1;
+ break;
+
+ default:
+ // Do nothing.
+ break;
+ }
+ } else {
+ $msg = __('Something gone wrong. Please, try again');
+ }
+ break;
+ }
+
+ if ($success === false) {
+ ui_print_error_message($msg);
+ } else {
+ ui_print_success_message($msg);
+ }
+ } else if ($modulesToAdd != '') {
+ $modulesToAddList = explode(',', $modulesToAdd);
+ foreach ($modulesToAddList as $module) {
+ db_process_sql_insert(
+ 'tnetwork_profile_component',
+ [
+ 'id_nc' => $module,
+ 'id_np' => $this->id_np,
+ ]
+ );
+ }
+
+ $this->ajaxMsg('result', __('Components added sucessfully'));
+ }
+ }
+
+
+ /**
+ * Show the adding modules form
+ *
+ * @return void
+ */
+ public function addingModulesForm()
+ {
+ // Get the groups for select input.
+ $result = db_get_all_rows_in_table('tnetwork_component_group', 'name');
+ if ($result === false) {
+ $result = [];
+ }
+
+ // 2 arrays. 1 with the groups, 1 with the groups by parent
+ $groups = [];
+ $groups_compound = [];
+
+ foreach ($result as $row) {
+ $groups[$row['id_sg']] = $row['name'];
+ }
+
+ foreach ($result as $row) {
+ if ($row['parent'] > 1) {
+ $groups_compound[$row['id_sg']] = $groups[$row['parent']].' / '.$row['name'];
+ } else {
+ $groups_compound[$row['id_sg']] = $row['name'];
+ }
+ }
+
+ $result = db_get_all_rows_sql(
+ 'SELECT id_nc, name, id_group
+ FROM tnetwork_component
+ ORDER BY name'
+ );
+
+ $entireComponentsList = [];
+ $components = [];
+ if ($result === false) {
+ $result = [];
+ }
+
+ foreach ($result as $row) {
+ $strIdGroup = (string) $row['id_group'];
+ if (!isset($entireComponentsList[$strIdGroup])) {
+ $entireComponentsList[$strIdGroup] = $row['id_nc'];
+ } else {
+ $entireComponentsList[$strIdGroup] .= ','.$row['id_nc'];
+ }
+
+ $components[$row['id_nc']] = $row['name'];
+ }
+
+ $entireComponentsList = json_encode($entireComponentsList);
+
+ // Main form.
+ $form = [
+ 'action' => $this->baseUrl,
+ 'id' => 'add_module_form',
+ 'method' => 'POST',
+ 'class' => 'modal',
+ 'extra' => '',
+ ];
+
+ // Inputs.
+ $inputs = [];
+
+ $inputs[] = [
+ 'id' => 'inp-id_np',
+ 'arguments' => [
+ 'name' => 'id_np',
+ 'type' => 'hidden',
+ 'value' => $this->id_np,
+ 'return' => true,
+ ],
+ ];
+
+ $inputs[] = [
+ 'label' => __('Filter'),
+ 'id' => 'txt-add-modules-filter',
+ 'arguments' => [
+ 'input_class' => 'flex-row',
+ 'name' => 'filter',
+ 'type' => 'text',
+ 'size' => '40',
+ 'class' => 'float-right',
+ 'onKeyDown' => 'filterTextComponents(event);',
+ 'value' => '',
+ 'return' => true,
+ ],
+ ];
+
+ $inputs[] = [
+ 'label' => __('Group'),
+ 'id' => 'add-modules-group',
+ 'arguments' => [
+ 'input_class' => 'flex-row',
+ 'type' => 'select',
+ 'script' => 'filterGroupComponents(event);',
+ 'class' => 'float-right',
+ 'fields' => $groups_compound,
+ 'nothing' => 'Group - All',
+ 'return' => true,
+ ],
+ ];
+
+ $inputs[] = [
+ 'id' => 'group-components',
+ 'arguments' => [
+ 'name' => 'group-components',
+ 'type' => 'hidden',
+ 'value' => $entireComponentsList,
+ 'return' => true,
+ ],
+ ];
+
+ $inputs[] = [
+ 'label' => __('Components'),
+ 'id' => 'slc-add-modules-components',
+ 'arguments' => [
+ 'name' => 'add-modules-components',
+ 'input_class' => 'flex-row',
+ 'style' => 'width:100%;margin-top: 1em;',
+ 'type' => 'select',
+ 'multiple' => true,
+ 'fields' => $components,
+ 'return' => true,
+ ],
+ ];
+
+ $this->printForm(
+ [
+ 'form' => $form,
+ 'inputs' => $inputs,
+ true
+ ]
+ );
+ }
+
+
+ /**
+ * General setter
+ *
+ * @return void
+ */
+ private function setNetworkProfile()
+ {
+ $profileInfo = db_get_row('tnetwork_profile', 'id_np', $this->id_np);
+ $this->name = $profileInfo['name'];
+ $this->description = $profileInfo['description'];
+
+ $penInfo = db_get_all_rows_filter('tnetwork_profile_pen', ['id_np' => $this->id_np]);
+ $penList = [];
+ foreach ($penInfo as $pen) {
+ $penList[] = $pen['pen'];
+ }
+
+ $this->pen = implode(',', $penList);
+ }
+
+
+ /**
+ * Create the table with the list of Blocks Templates
+ *
+ * @return void
+ */
+ public function moduleTemplateList()
+ {
+ global $config;
+ // Get the count of Blocks.
+ $countModuleTemplates = db_get_value(
+ 'count(*)',
+ 'tnetwork_profile'
+ );
+
+ // Get all the data.
+ $resultModuleTemplatesTable = db_get_all_rows_filter(
+ 'tnetwork_profile',
+ [
+ 'order' => 'name',
+ 'limit' => $config['block_size'],
+ 'offset' => $this->offset,
+ ]
+ );
+
+ ui_pagination($countModuleTemplates, $this->baseUrl, $this->offset);
+ // Create the table with Module Block list.
+ $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 = [];
+
+ $table->cellpadding = 0;
+ $table->cellspacing = 0;
+ $table->width = '100%';
+ $table->class = 'info_table';
+
+ $table->head = [];
+ $table->head[0] = html_print_checkbox('all_delete', 0, false, true, false);
+
+ $table->head[1] = __('Name');
+ $table->head[2] = __('Description');
+ $table->head[3] = '
'.__('Action').'';
+ $table->size = [];
+ $table->size[0] = '20px';
+ $table->size[2] = '65%';
+ $table->size[3] = '15%';
+
+ $table->align = [];
+ $table->align[3] = 'left';
+
+ $table->data = [];
+
+ foreach ($resultModuleTemplatesTable as $row) {
+ $data = [];
+ $data[0] = html_print_checkbox_extended('delete_multiple[]', $row['id_np'], false, false, '', 'class="check_delete"', true);
+ $data[1] = '
'.io_safe_output($row['name']).'';
+ $data[2] = ui_print_truncate_text(io_safe_output($row['description']), 'description', true, true, true, '[…]');
+ $table->cellclass[][3] = 'action_buttons';
+ $data[3] = html_print_input_image(
+ 'delete_profile',
+ 'images/cross.png',
+ $row['id_np'],
+ '',
+ true,
+ ['onclick' => 'if (!confirm(\''.__('Are you sure?').'\')) return false;']
+ );
+ $data[3] .= html_print_input_image(
+ 'export_profile',
+ 'images/csv.png',
+ $row['id_np'],
+ '',
+ true,
+ ['title' => 'Export to CSV']
+ );
+ $data[3] = '
'.html_print_image('images/cross.png', true, ['title' => __('Delete')]).'';
+ $data[3] .= '
'.html_print_image('images/csv.png', true, ['title' => __('Export to CSV')]).'';
+
+ array_push($table->data, $data);
+ }
+
+ html_print_table($table);
+
+ $output = '
';
+
+ $form = [
+ 'method' => 'POST',
+ 'action' => $this->baseUrl,
+ 'id' => 'main_management_form',
+ ];
+
+ $inputs[] = [
+ 'arguments' => [
+ 'name' => 'id_np',
+ 'type' => 'hidden',
+ 'value' => 0,
+ 'return' => true,
+ ],
+ ];
+
+ $inputs[] = [
+ 'arguments' => [
+ 'label' => __('Create'),
+ 'name' => 'crt',
+ 'type' => 'submit',
+ 'attributes' => 'class="sub wand"',
+ 'return' => true,
+ ],
+ ];
+
+ $inputs[] = [
+ 'arguments' => [
+ 'label' => __('Delete selected'),
+ 'name' => 'erase',
+ 'type' => 'button',
+ 'attributes' => 'class="sub cancel"',
+ 'return' => true,
+ ],
+ ];
+
+ $output .= $this->printForm(
+ [
+ 'form' => $form,
+ 'inputs' => $inputs,
+ ],
+ true
+ );
+
+ $output .= '
';
+
+ echo $output;
+ }
+
+
+ /**
+ * Prints Form for template management
+ *
+ * @return mixed
+ */
+ public function moduleTemplateForm()
+ {
+ $createNewTemplate = ($this->id_np == 0) ? true : false;
+
+ if ($createNewTemplate) {
+ // Assignation for submit button.
+ $formButtonClass = 'sub wand';
+ $formButtonValue = 'create';
+ $formButtonLabel = __('Create');
+ } else {
+ // Assignation for submit button.
+ $formButtonClass = 'sub upd';
+ $formButtonValue = 'update';
+ $formButtonLabel = __('Update');
+ }
+
+ // Main form.
+ $form = [
+ 'action' => $this->baseUrl,
+ 'id' => 'module_template_form',
+ 'method' => 'POST',
+ 'class' => 'databox filters',
+ 'extra' => 'id="module_template_form"',
+ ];
+
+ // Inputs.
+ $inputs = [];
+ // Inputs.
+ $rawInputs = '';
+
+ $inputs[] = [
+ 'id' => 'inp-id_np',
+ 'arguments' => [
+ 'name' => 'id_np',
+ 'type' => 'hidden',
+ 'value' => $this->id_np,
+ 'return' => true,
+ ],
+ ];
+
+ $inputs[] = [
+ 'id' => 'inp-valid-pen',
+ 'arguments' => [
+ 'name' => 'valid-pen',
+ 'type' => 'hidden',
+ 'value' => $this->validPen,
+ 'return' => true,
+ ],
+ ];
+
+ $inputs[] = [
+ 'label' => __('Name'),
+ 'id' => 'inp-name',
+ 'arguments' => [
+ 'name' => 'name',
+ 'input_class' => 'flex-row',
+ 'type' => 'text',
+ 'value' => $this->name,
+ 'return' => true,
+ ],
+ ];
+
+ $inputs[] = [
+ 'label' => __('Description'),
+ 'id' => 'inp-description',
+ 'arguments' => [
+ 'name' => 'description',
+ 'input_class' => 'flex-row',
+ 'type' => 'textarea',
+ 'value' => $this->description,
+ 'return' => true,
+ ],
+ ];
+
+ $inputs[] = [
+ 'label' => __('PEN'),
+ 'id' => 'inp-pen',
+ 'arguments' => [
+ 'name' => 'pen',
+ 'input_class' => 'flex-row',
+ 'type' => 'text',
+ 'value' => $this->pen,
+ 'return' => true,
+ ],
+ ];
+
+ $availableButtons = [];
+
+ $availableButtons[] = [
+ 'arguments' => [
+ 'name' => 'action_button',
+ 'label' => $formButtonLabel,
+ 'type' => 'submit',
+ 'value' => $formButtonValue,
+ 'attributes' => 'class="float-right '.$formButtonClass.'"',
+ 'return' => true,
+ ],
+ ];
+
+ if ($createNewTemplate === false) {
+ $availableButtons[] = [
+ 'arguments' => [
+ 'name' => 'add_components_button',
+ 'label' => __('Add components'),
+ 'type' => 'button',
+ 'attributes' => 'class="float-right sub cog"',
+ 'script' => 'showAddComponent();',
+ 'return' => true,
+ ],
+ ];
+ }
+
+ $inputs[] = [
+ 'class' => 'action_button_list',
+ 'direct' => false,
+ 'wrapper' => 'div',
+ 'block_content' => $availableButtons,
+ ];
+
+ // Required for PEN field.
+ ui_require_jquery_file('tag-editor');
+ ui_require_css_file('jquery.tag-editor');
+
+ if ($createNewTemplate === false) {
+ // Get the data.
+ $sql = sprintf(
+ 'SELECT npc.id_nc AS component_id, nc.name, nc.type, nc.description, nc.id_group AS `group`, nc.id_modulo AS `id_format`, ncg.name AS `group_name`
+ FROM tnetwork_profile_component AS npc, tnetwork_component AS nc
+ INNER JOIN tnetwork_component_group AS ncg ON ncg.id_sg = nc.id_group
+ WHERE npc.id_nc = nc.id_nc AND npc.id_np = %d',
+ $this->id_np
+ );
+ $moduleBlocks = db_get_all_rows_sql($sql);
+
+ if ($moduleBlocks) {
+ $blockTables = [];
+ // Build the information of the blocks.
+ foreach ($moduleBlocks as $block) {
+ if (key_exists($block['group'], $blockTables) === false) {
+ $blockTables[$block['group']] = [
+ 'name' => $block['group_name'],
+ 'data' => [],
+ ];
+ }
+
+ $blockTables[$block['group']]['data'][] = [
+ 'component_id' => $block['component_id'],
+ 'name' => $block['name'],
+ 'type' => $block['type'],
+ 'description' => $block['description'],
+ 'id_format' => $block['id_format'],
+ ];
+ }
+
+ if (count($blockTables) === 0) {
+ ui_print_info_message(__('No module blocks for this profile'));
+ } else {
+ foreach ($blockTables as $id_group => $blockTable) {
+ // Data with all components.
+ $blockData = $blockTable['data'];
+ // Creation of list of all components.
+ $blockComponentList = '';
+ foreach ($blockData as $component) {
+ $blockComponentList .= $component['component_id'].',';
+ }
+
+ $blockComponentList = chop($blockComponentList, ',');
+ // Title of Block.
+ $blockTitle = '
';
+ $blockTitle .= $blockTable['name'];
+ $blockTitle .= '
';
+
+ $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 = [];
+
+ $table->cellpadding = 0;
+ $table->cellspacing = 0;
+ $table->width = '100%';
+ $table->class = 'info_table';
+
+ $table->head = [];
+ $table->head[0] = __('Module Name');
+ $table->head[1] = '
'.__('Format').'';
+ $table->head[2] = '
'.__('Type').'';
+ $table->head[3] = __('Description');
+ $table->head[4] = '
'.__('Delete').'';
+
+ $table->size = [];
+ $table->size[0] = '15%';
+ $table->size[3] = '65%';
+ $table->size[4] = '15%';
+
+ $table->align = [];
+ $table->align[4] = 'right';
+
+ $table->style = [];
+ $table->style[4] = 'padding-right:2em';
+
+ $table->data = [];
+
+ foreach ($blockData as $module) {
+ $data[0] = '
'.$module['name'].'';
+ switch ($module['id_format']) {
+ case MODULE_NETWORK:
+ $formatInfo = html_print_image(
+ 'images/network.png',
+ true,
+ ['title' => __('Network module')]
+ );
+ break;
+
+ case MODULE_WMI:
+ $formatInfo = html_print_image(
+ 'images/wmi.png',
+ true,
+ ['title' => __('WMI module')]
+ );
+ break;
+
+ case MODULE_PLUGIN:
+ $formatInfo = html_print_image(
+ 'images/plugin.png',
+ true,
+ ['title' => __('Plug-in module')]
+ );
+ break;
+
+ default:
+ $formatInfo = $module['id_format'];
+ break;
+ }
+
+ $data[1] = html_print_div(
+ [
+ 'style' => 'margin: 0 auto;width: 50%;',
+ 'content' => $formatInfo,
+ ],
+ true
+ );
+ $data[2] = ui_print_moduletype_icon($module['type'], true);
+ $data[3] = mb_strimwidth(io_safe_output($module['description']), 0, 150, '...');
+ $data[4] = html_print_input_image(
+ 'del_module_'.$module['component_id'].'_',
+ 'images/cross.png',
+ 1,
+ '',
+ true,
+ [
+ 'title' => __('Delete this module'),
+ 'onclick' => 'if(confirm(\''.__('Do you want delete this module?').'\')){deleteModuleTemplate(\'module\','.$module['component_id'].')};return false;',
+ ]
+ );
+
+ array_push($table->data, $data);
+ }
+
+ $content = html_print_table($table, true);
+
+ $rawInputs .= ui_toggle($content, $blockTitle, '', '', false, true);
+ }
+ }
+ } else {
+ ui_print_info_message(__('No module blocks for this profile'));
+ }
+ }
+
+ $this->printFormAsList(
+ [
+ 'form' => $form,
+ 'inputs' => $inputs,
+ 'rawInputs' => $rawInputs,
+ true
+ ]
+ );
+
+ if ($createNewTemplate === false) {
+ echo '
';
+ echo '
';
+ }
+
+ $this->printGoBackButton($this->baseUrl);
+ }
+
+
+ /**
+ * Loads JS and return code.
+ *
+ * @return string
+ */
+ public function loadJS()
+ {
+ $str = '';
+
+ ob_start();
+ ?>
+
+
+ ';
+ return $imgbase64;
}
}
diff --git a/pandora_console/include/functions_html.php b/pandora_console/include/functions_html.php
index b4d3011fdb..76e06c77df 100644
--- a/pandora_console/include/functions_html.php
+++ b/pandora_console/include/functions_html.php
@@ -722,6 +722,7 @@ function html_print_select(
* @param string $style The string of style.
* @param mixed $size Max elements showed in select or default (size=10)
* @param integer $truncante_size Truncate size of the element, by default is set to GENERIC_SIZE_TEXT constant
+ * @param integer $class Class to apply.
*
* @return string HTML code if return parameter is true.
*/
@@ -738,7 +739,8 @@ function html_print_select_from_sql(
$disabled=false,
$style=false,
$size=false,
- $trucate_size=GENERIC_SIZE_TEXT
+ $trucate_size=GENERIC_SIZE_TEXT,
+ $class=''
) {
global $config;
@@ -770,7 +772,7 @@ function html_print_select_from_sql(
$return,
$multiple,
$sort,
- '',
+ $class,
$disabled,
$style,
'',
@@ -1087,7 +1089,7 @@ function html_print_extended_select_for_time(
ob_start();
// Use the no_meta parameter because this image is only in the base console
- echo '
';
+ echo '
';
html_print_select(
$fields,
$uniq_name.'_select',
@@ -1121,7 +1123,7 @@ function html_print_extended_select_for_time(
echo '
';
- echo '
';
+ echo '
';
html_print_input_text($uniq_name.'_text', $selected, '', $size, 255, false, $readonly, false, '', $class);
html_print_input_hidden($name, $selected, false, $uniq_name);
@@ -1159,8 +1161,8 @@ function html_print_extended_select_for_time(
$('#text-".$uniq_name."_text').val(seconds);
adjustTextUnits('".$uniq_name."');
calculateSeconds('".$uniq_name."');
- $('#".$uniq_name."_manual').show();
- $('#".$uniq_name."_default').hide();
+ $('#".$uniq_name."_manual').css('display', 'flex');
+ $('#".$uniq_name."_default').css('display', 'none');
}
";
$returnString = ob_get_clean();
@@ -1334,6 +1336,7 @@ function html_print_input_text_extended(
'onkeyup',
'required',
'autocomplete',
+ 'form',
];
$output = '
cellstyle[0][2] = 'text-align:center;';
// This extra div that can be handled by jquery's dialog.
- $output = '
';
+ $output = '
';
$output .= '
';
$output .= '
';
$output .= html_print_table($table, true);
diff --git a/pandora_console/include/functions_treeview.php b/pandora_console/include/functions_treeview.php
index 3217a544bf..32688a25ea 100755
--- a/pandora_console/include/functions_treeview.php
+++ b/pandora_console/include/functions_treeview.php
@@ -123,11 +123,11 @@ function treeview_printModuleTable($id_module, $server_data=false, $no_head=fals
$row['data'] = $module_group;
$table->data['module_group'] = $row;
- // Description
+ // Description.
$row = [];
$row['title'] = __('Description');
$row['data'] = ui_print_truncate_text(
- $module['descripcion'];,
+ $module['descripcion'],
'description',
true,
true,
@@ -761,21 +761,25 @@ function treeview_printTable($id_agente, $server_data=[], $no_head=false)
}
}
- // End of table advanced
+ // End of table advanced.
$table_advanced = html_print_table($table, true);
$table_advanced .= '
';
ui_toggle($table_advanced, __('Advanced information'));
if ($config['agentaccess']) {
- $access_graph = '
';
+ $access_graph = '
';
$access_graph .= graphic_agentaccess(
$id_agente,
SECONDS_1DAY,
- true
+ false
);
$access_graph .= '
';
- ui_toggle($access_graph, __('Agent access rate (24h)'));
+
+ ui_toggle(
+ $access_graph,
+ __('Agent access rate (24h)')
+ );
}
$events_graph = '
';
diff --git a/pandora_console/include/functions_ui.php b/pandora_console/include/functions_ui.php
index f46089d735..0ce95daf78 100755
--- a/pandora_console/include/functions_ui.php
+++ b/pandora_console/include/functions_ui.php
@@ -2848,6 +2848,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,
@@ -2881,56 +2882,99 @@ function ui_progress(
$text = $progress.'%';
}
+ $id = uniqid();
+
ui_require_css_file('progress');
- $output .= '
';
- $output .= '';
+ $output .= '';
$output .= '';
if ($ajax !== false && is_array($ajax)) {
- $output .= '';
+ } else {
+ $output .= '';
+ }
}
if (!$return) {
@@ -3469,10 +3513,13 @@ function ui_print_datatable(array $parameters)
ui_require_javascript_file('buttons.html5.min');
ui_require_javascript_file('buttons.print.min');
- $output = $include.$output;
+ if (isset($parameters['return']) && $parameters['return'] == true) {
+ // Compat.
+ $parameters['print'] = false;
+ }
// Print datatable if needed.
- if (isset($parameters['print']) === false || $parameters['print'] === false) {
+ if (isset($parameters['print']) === false || $parameters['print'] === true) {
echo $output;
}
@@ -3673,8 +3720,8 @@ function ui_toggle(
// Generate unique Id.
$uniqid = uniqid('');
- $image_a = html_print_image($img_a, true, false, true);
- $image_b = html_print_image($img_b, true, false, true);
+ $image_a = html_print_image($img_a, true, [ 'style' => 'object-fit: contain;' ], true);
+ $image_b = html_print_image($img_b, true, [ 'style' => 'object-fit: contain;' ], true);
// Options.
if ($hidden_default) {
$style = 'display:none';
@@ -3698,6 +3745,7 @@ function ui_toggle(
$original,
true,
[
+ 'style' => 'object-fit: contain;',
'title' => $title,
'id' => 'image_'.$uniqid,
]
diff --git a/pandora_console/include/javascript/jquery.caret.min.js b/pandora_console/include/javascript/jquery.caret.min.js
new file mode 100644
index 0000000000..0f9ef48d6e
--- /dev/null
+++ b/pandora_console/include/javascript/jquery.caret.min.js
@@ -0,0 +1,2 @@
+// http://code.accursoft.com/caret - 1.3.3
+!function(e){e.fn.caret=function(e){var t=this[0],n="true"===t.contentEditable;if(0==arguments.length){if(window.getSelection){if(n){t.focus();var o=window.getSelection().getRangeAt(0),r=o.cloneRange();return r.selectNodeContents(t),r.setEnd(o.endContainer,o.endOffset),r.toString().length}return t.selectionStart}if(document.selection){if(t.focus(),n){var o=document.selection.createRange(),r=document.body.createTextRange();return r.moveToElementText(t),r.setEndPoint("EndToEnd",o),r.text.length}var e=0,c=t.createTextRange(),r=document.selection.createRange().duplicate(),a=r.getBookmark();for(c.moveToBookmark(a);0!==c.moveStart("character",-1);)e++;return e}return t.selectionStart?t.selectionStart:0}if(-1==e&&(e=this[n?"text":"val"]().length),window.getSelection)n?(t.focus(),window.getSelection().collapse(t.firstChild,e)):t.setSelectionRange(e,e);else if(document.body.createTextRange)if(n){var c=document.body.createTextRange();c.moveToElementText(t),c.moveStart("character",e),c.collapse(!0),c.select()}else{var c=t.createTextRange();c.move("character",e),c.select()}return n||t.focus(),e}}(jQuery);
diff --git a/pandora_console/include/javascript/jquery.tag-editor.js b/pandora_console/include/javascript/jquery.tag-editor.js
new file mode 100644
index 0000000000..719ae04225
--- /dev/null
+++ b/pandora_console/include/javascript/jquery.tag-editor.js
@@ -0,0 +1,370 @@
+/*
+ jQuery tagEditor v1.0.21
+ Copyright (c) 2014 Simon Steinberger / Pixabay
+ GitHub: https://github.com/Pixabay/jQuery-tagEditor
+ License: http://www.opensource.org/licenses/mit-license.php
+*/
+
+(function($){
+ // auto grow input (stackoverflow.com/questions/931207)
+ $.fn.tagEditorInput=function(){var t=" ",e=$(this),n=parseInt(e.css("fontSize")),i=$("
").css({position:"absolute",top:-9999,left:-9999,width:"auto",fontSize:e.css("fontSize"),fontFamily:e.css("fontFamily"),fontWeight:e.css("fontWeight"),letterSpacing:e.css("letterSpacing"),whiteSpace:"nowrap"}),s=function(){if(t!==(t=e.val())){i.text(t);var s=i.width()+n;20>s&&(s=20),s!=e.width()&&e.width(s)}};return i.insertAfter(e),e.bind("keyup keydown focus",s)};
+
+ // plugin with val as parameter for public methods
+ $.fn.tagEditor = function(options, val, blur){
+
+ // helper
+ function escape(tag) {
+ return tag.replace(/&/g, "&").replace(//g, ">").replace(/"/g, """).replace(/'/g, "'");
+ }
+
+ // build options dictionary with default values
+ var blur_result, o = $.extend({}, $.fn.tagEditor.defaults, options), selector = this;
+
+ // store regex and default delimiter in options for later use
+ o.dregex = new RegExp('['+o.delimiter.replace('-', '\-')+']', 'g');
+
+ // public methods
+ if (typeof options == 'string') {
+ // depending on selector, response may contain tag lists of multiple editor instances
+ var response = [];
+ selector.each(function(){
+ // the editor is the next sibling to the hidden, original field
+ var el = $(this), o = el.data('options'), ed = el.next('.tag-editor');
+ if (options == 'getTags')
+ response.push({field: el[0], editor: ed, tags: ed.data('tags')});
+ else if (options == 'addTag') {
+ if (o.maxTags && ed.data('tags').length >= o.maxTags) return false;
+ // insert new tag
+ $('
'+o.delimiter[0]+'
').appendTo(ed).find('.tag-editor-tag')
+ .html('
').addClass('active').find('input').val(val).blur();
+ if (!blur) ed.click();
+ else $('.placeholder', ed).remove();
+ } else if (options == 'removeTag') {
+ // trigger delete on matching tag, then click editor to create a new tag
+ $('.tag-editor-tag', ed).filter(function(){return $(this).text()==val;}).closest('li').find('.tag-editor-delete').click();
+ if (!blur) ed.click();
+ } else if (options == 'destroy') {
+ el.removeClass('tag-editor-hidden-src').removeData('options').off('focus.tag-editor').next('.tag-editor').remove();
+ }
+ });
+ return options == 'getTags' ? response : this;
+ }
+
+ // delete selected tags on backspace, delete, ctrl+x
+ if (window.getSelection) $(document).off('keydown.tag-editor').on('keydown.tag-editor', function(e){
+ if (e.which == 8 || e.which == 46 || e.ctrlKey && e.which == 88) {
+ try {
+ var sel = getSelection(), el = document.activeElement.tagName != 'INPUT' ? $(sel.getRangeAt(0).startContainer.parentNode).closest('.tag-editor') : 0;
+ } catch(e){ el = 0; }
+ if (sel.rangeCount > 0 && el && el.length) {
+ var tags = [], splits = sel.toString().split(el.prev().data('options').dregex);
+ for (i=0; i
').insertAfter(el);
+ el.addClass('tag-editor-hidden-src') // hide original field
+ .data('options', o) // set data on hidden field
+ .on('focus.tag-editor', function(){ ed.click(); }); // simulate tabindex
+
+ // add dummy item for min-height on empty editor
+ ed.append(' ');
+
+ // markup for new tag
+ var new_tag = ' '+o.delimiter[0]+'
';
+
+ // helper: update global data
+ function set_placeholder(){
+ if (o.placeholder && !tag_list.length && !$('.deleted, .placeholder, input', ed).length)
+ ed.append(''+o.placeholder+'
');
+ }
+
+ // helper: update global data
+ function update_globals(init){
+ var old_tags = tag_list.toString();
+ tag_list = $('.tag-editor-tag:not(.deleted)', ed).map(function(i, e) {
+ var val = $.trim($(this).hasClass('active') ? $(this).find('input').val() : $(e).text());
+ if (val) return val;
+ }).get();
+ ed.data('tags', tag_list);
+ el.val(tag_list.join(o.delimiter[0]));
+ // change callback except for plugin init
+ if (!init) if (old_tags != tag_list.toString()) o.onChange(el, ed, tag_list);
+ set_placeholder();
+ }
+
+ ed.click(function(e, closest_tag){
+ var d, dist = 99999, loc;
+
+ // do not create tag when user selects tags by text selection
+ if (window.getSelection && getSelection() != '') return;
+
+ if (o.maxTags && ed.data('tags').length >= o.maxTags) { ed.find('input').blur(); return false; }
+
+ blur_result = true
+ $('input:focus', ed).blur();
+ if (!blur_result) return false;
+ blur_result = true
+
+ // always remove placeholder on click
+ $('.placeholder', ed).remove();
+ if (closest_tag && closest_tag.length)
+ loc = 'before';
+ else {
+ // calculate tag closest to click position
+ $('.tag-editor-tag', ed).each(function(){
+ var tag = $(this), to = tag.offset(), tag_x = to.left, tag_y = to.top;
+ if (e.pageY >= tag_y && e.pageY <= tag_y+tag.height()) {
+ if (e.pageX < tag_x) loc = 'before', d = tag_x - e.pageX;
+ else loc = 'after', d = e.pageX - tag_x - tag.width();
+ if (d < dist) dist = d, closest_tag = tag;
+ }
+ });
+ }
+
+ if (loc == 'before') {
+ $(new_tag).insertBefore(closest_tag.closest('li')).find('.tag-editor-tag').click();
+ } else if (loc == 'after')
+ $(new_tag).insertAfter(closest_tag.closest('li')).find('.tag-editor-tag').click();
+ else // empty editor
+ $(new_tag).appendTo(ed).find('.tag-editor-tag').click();
+ return false;
+ });
+
+ ed.on('click', '.tag-editor-delete', function(e){
+ // delete icon is hidden when input is visible; place cursor near invisible delete icon on click
+ if ($(this).prev().hasClass('active')) { $(this).closest('li').find('input').caret(-1); return false; }
+
+ var li = $(this).closest('li'), tag = li.find('.tag-editor-tag');
+ if (o.beforeTagDelete(el, ed, tag_list, tag.text()) === false) return false;
+ tag.addClass('deleted').animate({width: 0}, o.animateDelete, function(){ li.remove(); set_placeholder(); });
+ update_globals();
+ return false;
+ });
+
+ // delete on right mouse click or ctrl+click
+ if (o.clickDelete)
+ ed.on('mousedown', '.tag-editor-tag', function(e){
+ if (e.ctrlKey || e.which > 1) {
+ var li = $(this).closest('li'), tag = li.find('.tag-editor-tag');
+ if (o.beforeTagDelete(el, ed, tag_list, tag.text()) === false) return false;
+ tag.addClass('deleted').animate({width: 0}, o.animateDelete, function(){ li.remove(); set_placeholder(); });
+ update_globals();
+ return false;
+ }
+ });
+
+ ed.on('click', '.tag-editor-tag', function(e){
+ // delete on right click or ctrl+click -> exit
+ if (o.clickDelete && (e.ctrlKey || e.which > 1)) return false;
+
+ if (!$(this).hasClass('active')) {
+ var tag = $(this).text();
+ // guess cursor position in text input
+ var left_percent = Math.abs(($(this).offset().left - e.pageX)/$(this).width()), caret_pos = parseInt(tag.length*left_percent),
+ input = $(this).html('').addClass('active').find('input');
+ input.data('old_tag', tag).tagEditorInput().focus().caret(caret_pos);
+ if (o.autocomplete) {
+ var aco = $.extend({}, o.autocomplete);
+ // extend user provided autocomplete select method
+ var ac_select = 'select' in aco ? o.autocomplete.select : '';
+ aco.select = function(e, ui){ if (ac_select) ac_select(e, ui); setTimeout(function(){
+ ed.trigger('click', [$('.active', ed).find('input').closest('li').next('li').find('.tag-editor-tag')]);
+ }, 20); };
+ input.autocomplete(aco);
+ }
+ }
+ return false;
+ });
+
+ // helper: split into multiple tags, e.g. after paste
+ function split_cleanup(input){
+ var li = input.closest('li'), sub_tags = input.val().replace(/ +/, ' ').split(o.dregex),
+ old_tag = input.data('old_tag'), old_tags = tag_list.slice(0), exceeded = false, cb_val; // copy tag_list
+ for (var i=0; i '+o.delimiter[0]+'
'+escape(tag)+'
');
+ if (o.maxTags && old_tags.length >= o.maxTags) { exceeded = true; break; }
+ }
+ input.attr('maxlength', o.maxLength).removeData('old_tag').val('')
+ if (exceeded) input.blur(); else input.focus();
+ update_globals();
+ }
+
+ ed.on('blur', 'input', function(e){
+ e.stopPropagation();
+ var input = $(this), old_tag = input.data('old_tag'), tag = $.trim(input.val().replace(/ +/, ' ').replace(o.dregex, o.delimiter[0]));
+ if (!tag) {
+ if (old_tag && o.beforeTagDelete(el, ed, tag_list, old_tag) === false) {
+ input.val(old_tag).focus();
+ blur_result = false;
+ update_globals();
+ return;
+ }
+ try { input.closest('li').remove(); } catch(e){}
+ if (old_tag) update_globals();
+ }
+ else if (tag.indexOf(o.delimiter[0])>=0) { split_cleanup(input); return; }
+ else if (tag != old_tag) {
+ if (o.forceLowercase) tag = tag.toLowerCase();
+ cb_val = o.beforeTagSave(el, ed, tag_list, old_tag, tag);
+ tag = cb_val || tag;
+ if (cb_val === false) {
+ if (old_tag) {
+ input.val(old_tag).focus();
+ blur_result = false;
+ update_globals();
+ return;
+ }
+ try { input.closest('li').remove(); } catch(e){}
+ if (old_tag) update_globals();
+ }
+ // remove duplicates
+ else if (o.removeDuplicates)
+ $('.tag-editor-tag:not(.active)', ed).each(function(){ if ($(this).text() == tag) $(this).closest('li').remove(); });
+ }
+ input.parent().html(escape(tag)).removeClass('active');
+ if (tag != old_tag) update_globals();
+ set_placeholder();
+ });
+
+ var pasted_content;
+ ed.on('paste', 'input', function(e){
+ $(this).removeAttr('maxlength');
+ pasted_content = $(this);
+ setTimeout(function(){ split_cleanup(pasted_content); }, 30);
+ });
+
+ // keypress delimiter
+ var inp;
+ ed.on('keypress', 'input', function(e){
+ if (o.delimiter.indexOf(String.fromCharCode(e.which))>=0) {
+ inp = $(this);
+ setTimeout(function(){ split_cleanup(inp); }, 20);
+ }
+ });
+
+ ed.on('keydown', 'input', function(e){
+ var $t = $(this);
+
+ // left/up key + backspace key on empty field
+ if ((e.which == 37 || !o.autocomplete && e.which == 38) && !$t.caret() || e.which == 8 && !$t.val()) {
+ var prev_tag = $t.closest('li').prev('li').find('.tag-editor-tag');
+ if (prev_tag.length) prev_tag.click().find('input').caret(-1);
+ else if ($t.val() && !(o.maxTags && ed.data('tags').length >= o.maxTags)) $(new_tag).insertBefore($t.closest('li')).find('.tag-editor-tag').click();
+ return false;
+ }
+ // right/down key
+ else if ((e.which == 39 || !o.autocomplete && e.which == 40) && ($t.caret() == $t.val().length)) {
+ var next_tag = $t.closest('li').next('li').find('.tag-editor-tag');
+ if (next_tag.length) next_tag.click().find('input').caret(0);
+ else if ($t.val()) ed.click();
+ return false;
+ }
+ // tab key
+ else if (e.which == 9) {
+ // shift+tab
+ if (e.shiftKey) {
+ var prev_tag = $t.closest('li').prev('li').find('.tag-editor-tag');
+ if (prev_tag.length) prev_tag.click().find('input').caret(0);
+ else if ($t.val() && !(o.maxTags && ed.data('tags').length >= o.maxTags)) $(new_tag).insertBefore($t.closest('li')).find('.tag-editor-tag').click();
+ // allow tabbing to previous element
+ else {
+ el.attr('disabled', 'disabled');
+ setTimeout(function(){ el.removeAttr('disabled'); }, 30);
+ return;
+ }
+ return false;
+ // tab
+ } else {
+ var next_tag = $t.closest('li').next('li').find('.tag-editor-tag');
+ if (next_tag.length) next_tag.click().find('input').caret(0);
+ else if ($t.val()) ed.click();
+ else return; // allow tabbing to next element
+ return false;
+ }
+ }
+ // del key
+ else if (e.which == 46 && (!$.trim($t.val()) || ($t.caret() == $t.val().length))) {
+ var next_tag = $t.closest('li').next('li').find('.tag-editor-tag');
+ if (next_tag.length) next_tag.click().find('input').caret(0);
+ else if ($t.val()) ed.click();
+ return false;
+ }
+ // enter key
+ else if (e.which == 13) {
+ ed.trigger('click', [$t.closest('li').next('li').find('.tag-editor-tag')]);
+
+ // trigger blur if maxTags limit is reached
+ if (o.maxTags && ed.data('tags').length >= o.maxTags) ed.find('input').blur();
+
+ return false;
+ }
+ // pos1
+ else if (e.which == 36 && !$t.caret()) ed.find('.tag-editor-tag').first().click();
+ // end
+ else if (e.which == 35 && $t.caret() == $t.val().length) ed.find('.tag-editor-tag').last().click();
+ // esc
+ else if (e.which == 27) {
+ $t.val($t.data('old_tag') ? $t.data('old_tag') : '').blur();
+ return false;
+ }
+ });
+
+ // create initial tags
+ var tags = o.initialTags.length ? o.initialTags : el.val().split(o.dregex);
+ for (var i=0; i= o.maxTags) break;
+ var tag = $.trim(tags[i].replace(/ +/, ' '));
+ if (tag) {
+ if (o.forceLowercase) tag = tag.toLowerCase();
+ tag_list.push(tag);
+ ed.append(' '+o.delimiter[0]+'
'+escape(tag)+'
');
+ }
+ }
+ update_globals(true); // true -> no onChange callback
+
+ // init sortable
+ if (o.sortable && $.fn.sortable) ed.sortable({
+ distance: 5, cancel: '.tag-editor-spacer, input', helper: 'clone',
+ update: function(){ update_globals(); }
+ });
+ });
+ };
+
+ $.fn.tagEditor.defaults = {
+ initialTags: [],
+ maxTags: 0,
+ maxLength: 50,
+ delimiter: ',;',
+ placeholder: '',
+ forceLowercase: true,
+ removeDuplicates: true,
+ clickDelete: false,
+ animateDelete: 175,
+ sortable: true, // jQuery UI sortable
+ autocomplete: null, // options dict for jQuery UI autocomplete
+
+ // callbacks
+ onChange: function(){},
+ beforeTagSave: function(){},
+ beforeTagDelete: function(){}
+ };
+}(jQuery));
diff --git a/pandora_console/include/javascript/jquery.tag-editor.min.js b/pandora_console/include/javascript/jquery.tag-editor.min.js
new file mode 100644
index 0000000000..94293448f0
--- /dev/null
+++ b/pandora_console/include/javascript/jquery.tag-editor.min.js
@@ -0,0 +1,3 @@
+// jQuery tagEditor v1.0.21
+// https://github.com/Pixabay/jQuery-tagEditor
+!function(t){t.fn.tagEditorInput=function(){var e=" ",i=t(this),a=parseInt(i.css("fontSize")),r=t("").css({position:"absolute",top:-9999,left:-9999,width:"auto",fontSize:i.css("fontSize"),fontFamily:i.css("fontFamily"),fontWeight:i.css("fontWeight"),letterSpacing:i.css("letterSpacing"),whiteSpace:"nowrap"}),l=function(){if(e!==(e=i.val())){r.text(e);var t=r.width()+a;20>t&&(t=20),t!=i.width()&&i.width(t)}};return r.insertAfter(i),i.bind("keyup keydown focus",l)},t.fn.tagEditor=function(e,a,r){function l(t){return t.replace(/&/g,"&").replace(//g,">").replace(/"/g,""").replace(/'/g,"'")}var n,o=t.extend({},t.fn.tagEditor.defaults,e),c=this;if(o.dregex=new RegExp("["+o.delimiter.replace("-","-")+"]","g"),"string"==typeof e){var s=[];return c.each(function(){var i=t(this),l=i.data("options"),n=i.next(".tag-editor");if("getTags"==e)s.push({field:i[0],editor:n,tags:n.data("tags")});else if("addTag"==e){if(l.maxTags&&n.data("tags").length>=l.maxTags)return!1;t(' '+l.delimiter[0]+'
').appendTo(n).find(".tag-editor-tag").html('').addClass("active").find("input").val(a).blur(),r?t(".placeholder",n).remove():n.click()}else"removeTag"==e?(t(".tag-editor-tag",n).filter(function(){return t(this).text()==a}).closest("li").find(".tag-editor-delete").click(),r||n.click()):"destroy"==e&&i.removeClass("tag-editor-hidden-src").removeData("options").off("focus.tag-editor").next(".tag-editor").remove()}),"getTags"==e?s:this}return window.getSelection&&t(document).off("keydown.tag-editor").on("keydown.tag-editor",function(e){if(8==e.which||46==e.which||e.ctrlKey&&88==e.which){try{var a=getSelection(),r="INPUT"!=document.activeElement.tagName?t(a.getRangeAt(0).startContainer.parentNode).closest(".tag-editor"):0}catch(e){r=0}if(a.rangeCount>0&&r&&r.length){var l=[],n=a.toString().split(r.prev().data("options").dregex);for(i=0;i'+o.placeholder+"
")}function i(i){var a=c.toString();c=t(".tag-editor-tag:not(.deleted)",s).map(function(e,i){var a=t.trim(t(this).hasClass("active")?t(this).find("input").val():t(i).text());return a?a:void 0}).get(),s.data("tags",c),r.val(c.join(o.delimiter[0])),i||a!=c.toString()&&o.onChange(r,s,c),e()}function a(e){for(var a,n=e.closest("li"),d=e.val().replace(/ +/," ").split(o.dregex),g=e.data("old_tag"),f=c.slice(0),h=!1,u=0;u '+o.delimiter[0]+'
'+l(v)+'
'),o.maxTags&&f.length>=o.maxTags)){h=!0;break}e.attr("maxlength",o.maxLength).removeData("old_tag").val(""),h?e.blur():e.focus(),i()}var r=t(this),c=[],s=t("').insertAfter(r);r.addClass("tag-editor-hidden-src").data("options",o).on("focus.tag-editor",function(){s.click()}),s.append(' ');var d=' '+o.delimiter[0]+'
';s.click(function(e,i){var a,r,l=99999;if(!window.getSelection||""==getSelection())return o.maxTags&&s.data("tags").length>=o.maxTags?(s.find("input").blur(),!1):(n=!0,t("input:focus",s).blur(),n?(n=!0,t(".placeholder",s).remove(),i&&i.length?r="before":t(".tag-editor-tag",s).each(function(){var n=t(this),o=n.offset(),c=o.left,s=o.top;e.pageY>=s&&e.pageY<=s+n.height()&&(e.pageXa&&(l=a,i=n))}),"before"==r?t(d).insertBefore(i.closest("li")).find(".tag-editor-tag").click():"after"==r?t(d).insertAfter(i.closest("li")).find(".tag-editor-tag").click():t(d).appendTo(s).find(".tag-editor-tag").click(),!1):!1)}),s.on("click",".tag-editor-delete",function(){if(t(this).prev().hasClass("active"))return t(this).closest("li").find("input").caret(-1),!1;var a=t(this).closest("li"),l=a.find(".tag-editor-tag");return o.beforeTagDelete(r,s,c,l.text())===!1?!1:(l.addClass("deleted").animate({width:0},o.animateDelete,function(){a.remove(),e()}),i(),!1)}),o.clickDelete&&s.on("mousedown",".tag-editor-tag",function(a){if(a.ctrlKey||a.which>1){var l=t(this).closest("li"),n=l.find(".tag-editor-tag");return o.beforeTagDelete(r,s,c,n.text())===!1?!1:(n.addClass("deleted").animate({width:0},o.animateDelete,function(){l.remove(),e()}),i(),!1)}}),s.on("click",".tag-editor-tag",function(e){if(o.clickDelete&&(e.ctrlKey||e.which>1))return!1;if(!t(this).hasClass("active")){var i=t(this).text(),a=Math.abs((t(this).offset().left-e.pageX)/t(this).width()),r=parseInt(i.length*a),n=t(this).html('').addClass("active").find("input");if(n.data("old_tag",i).tagEditorInput().focus().caret(r),o.autocomplete){var c=t.extend({},o.autocomplete),d="select"in c?o.autocomplete.select:"";c.select=function(e,i){d&&d(e,i),setTimeout(function(){s.trigger("click",[t(".active",s).find("input").closest("li").next("li").find(".tag-editor-tag")])},20)},n.autocomplete(c)}}return!1}),s.on("blur","input",function(d){d.stopPropagation();var g=t(this),f=g.data("old_tag"),h=t.trim(g.val().replace(/ +/," ").replace(o.dregex,o.delimiter[0]));if(h){if(h.indexOf(o.delimiter[0])>=0)return void a(g);if(h!=f)if(o.forceLowercase&&(h=h.toLowerCase()),cb_val=o.beforeTagSave(r,s,c,f,h),h=cb_val||h,cb_val===!1){if(f)return g.val(f).focus(),n=!1,void i();try{g.closest("li").remove()}catch(d){}f&&i()}else o.removeDuplicates&&t(".tag-editor-tag:not(.active)",s).each(function(){t(this).text()==h&&t(this).closest("li").remove()})}else{if(f&&o.beforeTagDelete(r,s,c,f)===!1)return g.val(f).focus(),n=!1,void i();try{g.closest("li").remove()}catch(d){}f&&i()}g.parent().html(l(h)).removeClass("active"),h!=f&&i(),e()});var g;s.on("paste","input",function(){t(this).removeAttr("maxlength"),g=t(this),setTimeout(function(){a(g)},30)});var f;s.on("keypress","input",function(e){o.delimiter.indexOf(String.fromCharCode(e.which))>=0&&(f=t(this),setTimeout(function(){a(f)},20))}),s.on("keydown","input",function(e){var i=t(this);if((37==e.which||!o.autocomplete&&38==e.which)&&!i.caret()||8==e.which&&!i.val()){var a=i.closest("li").prev("li").find(".tag-editor-tag");return a.length?a.click().find("input").caret(-1):!i.val()||o.maxTags&&s.data("tags").length>=o.maxTags||t(d).insertBefore(i.closest("li")).find(".tag-editor-tag").click(),!1}if((39==e.which||!o.autocomplete&&40==e.which)&&i.caret()==i.val().length){var l=i.closest("li").next("li").find(".tag-editor-tag");return l.length?l.click().find("input").caret(0):i.val()&&s.click(),!1}if(9==e.which){if(e.shiftKey){var a=i.closest("li").prev("li").find(".tag-editor-tag");if(a.length)a.click().find("input").caret(0);else{if(!i.val()||o.maxTags&&s.data("tags").length>=o.maxTags)return r.attr("disabled","disabled"),void setTimeout(function(){r.removeAttr("disabled")},30);t(d).insertBefore(i.closest("li")).find(".tag-editor-tag").click()}return!1}var l=i.closest("li").next("li").find(".tag-editor-tag");if(l.length)l.click().find("input").caret(0);else{if(!i.val())return;s.click()}return!1}if(!(46!=e.which||t.trim(i.val())&&i.caret()!=i.val().length)){var l=i.closest("li").next("li").find(".tag-editor-tag");return l.length?l.click().find("input").caret(0):i.val()&&s.click(),!1}if(13==e.which)return s.trigger("click",[i.closest("li").next("li").find(".tag-editor-tag")]),o.maxTags&&s.data("tags").length>=o.maxTags&&s.find("input").blur(),!1;if(36!=e.which||i.caret()){if(35==e.which&&i.caret()==i.val().length)s.find(".tag-editor-tag").last().click();else if(27==e.which)return i.val(i.data("old_tag")?i.data("old_tag"):"").blur(),!1}else s.find(".tag-editor-tag").first().click()});for(var h=o.initialTags.length?o.initialTags:r.val().split(o.dregex),u=0;u=o.maxTags);u++){var v=t.trim(h[u].replace(/ +/," "));v&&(o.forceLowercase&&(v=v.toLowerCase()),c.push(v),s.append(' '+o.delimiter[0]+'
'+l(v)+'
'))}i(!0),o.sortable&&t.fn.sortable&&s.sortable({distance:5,cancel:".tag-editor-spacer, input",helper:"clone",update:function(){i()}})})},t.fn.tagEditor.defaults={initialTags:[],maxTags:0,maxLength:50,delimiter:",;",placeholder:"",forceLowercase:!0,removeDuplicates:!0,clickDelete:!1,animateDelete:175,sortable:!0,autocomplete:null,onChange:function(){},beforeTagSave:function(){},beforeTagDelete:function(){}}}(jQuery);
\ No newline at end of file
diff --git a/pandora_console/include/javascript/pandora.js b/pandora_console/include/javascript/pandora.js
index 9a9c8bcba0..c91339f0c6 100644
--- a/pandora_console/include/javascript/pandora.js
+++ b/pandora_console/include/javascript/pandora.js
@@ -837,8 +837,8 @@ function post_process_select_events(name) {
*/
function period_select_init(name, allow_zero) {
// Manual mode is hidden by default
- $("#" + name + "_manual").hide();
- $("#" + name + "_default").show();
+ $("#" + name + "_manual").css("display", "none");
+ $("#" + name + "_default").css("display", "flex");
// If the text input is empty, we put on it 5 minutes by default
if ($("#text-" + name + "_text").val() == "") {
@@ -852,8 +852,8 @@ function period_select_init(name, allow_zero) {
}
} else if ($("#text-" + name + "_text").val() == 0 && allow_zero != true) {
$("#" + name + "_units option:last").prop("selected", false);
- $("#" + name + "_manual").show();
- $("#" + name + "_default").hide();
+ $("#" + name + "_manual").css("display", "flex");
+ $("#" + name + "_default").css("display", "none");
}
}
@@ -941,13 +941,13 @@ function selectFirst(name) {
*/
function toggleBoth(name) {
if ($("#" + name + "_default").css("display") == "none") {
- $("#" + name + "_default").css("display", "inline");
+ $("#" + name + "_default").css("display", "flex");
} else {
$("#" + name + "_default").css("display", "none");
}
if ($("#" + name + "_manual").css("display") == "none") {
- $("#" + name + "_manual").css("display", "inline");
+ $("#" + name + "_manual").css("display", "flex");
} else {
$("#" + name + "_manual").css("display", "none");
}
diff --git a/pandora_console/include/javascript/pandora_taskList.js b/pandora_console/include/javascript/pandora_taskList.js
index a3f31cff96..0d0b1f8298 100644
--- a/pandora_console/include/javascript/pandora_taskList.js
+++ b/pandora_console/include/javascript/pandora_taskList.js
@@ -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: "progressTaskDiscovery",
id: id
},
type: "POST",
- url: "ajax.php",
+ url: $("#ajax-url").val(),
dataType: "json",
success: function(data) {
callback(null, data);
@@ -95,12 +100,13 @@ function show_map(id, name) {
jQuery.ajax({
data: {
- page: "include/ajax/task_list.ajax",
- showmap: 1,
+ page: "godmode/servers/discovery",
+ wiz: "tasklist",
+ method: "taskShowmap",
id: id
},
type: "POST",
- url: "ajax.php",
+ url: $("#ajax-url").val(),
dataType: "html",
success: function(data) {
$("#map_task")
@@ -109,3 +115,106 @@ 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 += "
" + item;
+ });
+ }
+
+ $("#msg").empty();
+ $("#msg").html(text);
+ $("#msg").dialog({
+ width: 450,
+ position: {
+ my: "center",
+ at: "center",
+ of: window,
+ collision: "fit"
+ },
+ maxHeight: 400,
+ 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");
+ $("#task_review").empty();
+ location.reload();
+ } else {
+ $(this).dialog("close");
+ }
+ }
+ }
+ ]
+ });
+ },
+ extradata: [
+ {
+ name: "id",
+ value: id
+ },
+ {
+ name: "wiz",
+ value: "tasklist"
+ }
+ ],
+ onshow: {
+ page: "godmode/servers/discovery",
+ method: "showTaskReview",
+ maxHeight: 800
+ },
+ onsubmit: {
+ page: "godmode/servers/discovery",
+ method: "parseTaskReview"
+ }
+ });
+}
+
+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);
+ }
+}
diff --git a/pandora_console/include/javascript/pandora_ui.js b/pandora_console/include/javascript/pandora_ui.js
index 14804d7ab5..70ffd40f7f 100644
--- a/pandora_console/include/javascript/pandora_ui.js
+++ b/pandora_console/include/javascript/pandora_ui.js
@@ -319,6 +319,21 @@ function load_modal(settings) {
contentType: false,
data: data,
success: function(data) {
+ if (settings.onshow.parser) {
+ data = settings.onshow.parser(data);
+ } else {
+ data = (function(d) {
+ try {
+ d = JSON.parse(d);
+ } catch (e) {
+ // Not JSON
+ return d;
+ }
+ if (d.error) return d.error;
+
+ if (d.result) return d.result;
+ })(data);
+ }
settings.target.html(data);
if (settings.onload != undefined) {
settings.onload(data);
@@ -338,6 +353,12 @@ function load_modal(settings) {
? settings.onshow.maxHeight
: "auto",
overlay: settings.modal.overlay,
+ position: {
+ my: "top+20%",
+ at: "top",
+ of: window,
+ collision: "fit"
+ },
buttons: required_buttons,
closeOnEscape: true,
open: function() {
@@ -386,6 +407,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();
}
},
@@ -395,6 +417,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();
}
}
diff --git a/pandora_console/include/javascript/simTree.js b/pandora_console/include/javascript/simTree.js
new file mode 100644
index 0000000000..7dfdd35739
--- /dev/null
+++ b/pandora_console/include/javascript/simTree.js
@@ -0,0 +1,441 @@
+/**
+ * IMPORTANT. Official plugin does not allow string ids
+ * This modificated one yes.
+ */
+!(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 =
+ '{{text}}',
+ b = e === this.$el,
+ y = $(i.createElement("ul")),
+ w = f.childNodeAsy ? "asy" : "";
+ for (
+ f.check ||
+ (C = C.replace('', ""));
+ 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) {}
+]);
diff --git a/pandora_console/include/lib/Dashboard/Widgets/events_list.php b/pandora_console/include/lib/Dashboard/Widgets/events_list.php
index 31e66dd3fe..1d0d4a3563 100644
--- a/pandora_console/include/lib/Dashboard/Widgets/events_list.php
+++ b/pandora_console/include/lib/Dashboard/Widgets/events_list.php
@@ -416,7 +416,12 @@ class EventsListWidget extends Widget
$filter['limit'] = $this->values['limit'];
$filter['order'] = '`utimestamp` DESC';
- if ((int) $this->values['severity'] !== -1) {
+ if ((int) $this->values['severity'] === 20) {
+ $filter['criticity'] = [
+ EVENT_CRIT_WARNING,
+ EVENT_CRIT_CRITICAL,
+ ];
+ } else if ((int) $this->values['severity'] !== -1) {
$filter['criticity'] = $this->values['severity'];
}
diff --git a/pandora_console/include/lib/Dashboard/Widgets/graph_module_histogram.php b/pandora_console/include/lib/Dashboard/Widgets/graph_module_histogram.php
index 7e99294311..067bbef1fd 100644
--- a/pandora_console/include/lib/Dashboard/Widgets/graph_module_histogram.php
+++ b/pandora_console/include/lib/Dashboard/Widgets/graph_module_histogram.php
@@ -309,12 +309,6 @@ class GraphModuleHistogramWidget extends Widget
$size = parent::getSize();
// Desactive scroll bars only this item.
- $output .= '';
$id_agent = $this->values['agentId'];
$id_module = $this->values['moduleId'];
$period = $this->values['period'];
diff --git a/pandora_console/include/lib/Dashboard/Widgets/maps_made_by_user.php b/pandora_console/include/lib/Dashboard/Widgets/maps_made_by_user.php
index baa6765789..f285abdc08 100644
--- a/pandora_console/include/lib/Dashboard/Widgets/maps_made_by_user.php
+++ b/pandora_console/include/lib/Dashboard/Widgets/maps_made_by_user.php
@@ -206,9 +206,9 @@ class MapsMadeByUser extends Widget
$fields = \visual_map_get_user_layouts($config['id_user'], true);
- // Event Type.
+ // Visual console.
$inputs[] = [
- 'label' => __('Event type'),
+ 'label' => __('Visual console'),
'arguments' => [
'type' => 'select',
'fields' => $fields,
diff --git a/pandora_console/include/lib/Dashboard/Widgets/system_group_status.php b/pandora_console/include/lib/Dashboard/Widgets/system_group_status.php
index 9691c3e81a..65df0b83d4 100644
--- a/pandora_console/include/lib/Dashboard/Widgets/system_group_status.php
+++ b/pandora_console/include/lib/Dashboard/Widgets/system_group_status.php
@@ -439,7 +439,7 @@ class SystemGroupStatusWidget extends Widget
}
}
- $height = (count($result_groups) * 30);
+ $height = (count($table->data) * 30);
$style = 'min-width:200px; min-height:'.$height.'px;';
$output = '';
if ($flag_groups === true) {
diff --git a/pandora_console/include/styles/dashboards.css b/pandora_console/include/styles/dashboards.css
index e77b016359..0db5cd6cb3 100644
--- a/pandora_console/include/styles/dashboards.css
+++ b/pandora_console/include/styles/dashboards.css
@@ -339,10 +339,8 @@ table.widget_maps_status tr td:first-child {
table.widget_maps_status tr td a {
font-family: "lato-lighter", "Open Sans", sans-serif;
letter-spacing: 0.03pt;
- font-size: 11pt;
+ font-size: 9pt;
text-decoration: none;
- color: #3f3f3f;
- font-weight: bolder;
}
table.widget_maps_status tr td img {
diff --git a/pandora_console/include/styles/discovery.css b/pandora_console/include/styles/discovery.css
index fc5749b4a8..158a75a009 100644
--- a/pandora_console/include/styles/discovery.css
+++ b/pandora_console/include/styles/discovery.css
@@ -169,6 +169,7 @@ span.breadcrumb_link {
form.discovery * {
font-size: 10pt;
+ font-family: "lato", "Open Sans", sans-serif;
}
form.discovery .label_select b {
diff --git a/pandora_console/include/styles/hostdevices.css b/pandora_console/include/styles/hostdevices.css
index 461327705e..e378e24d97 100644
--- a/pandora_console/include/styles/hostdevices.css
+++ b/pandora_console/include/styles/hostdevices.css
@@ -1,3 +1,14 @@
/*
* TODO: This may be at hostdevices.css
*/
+
+select.select_multiple {
+ min-width: 500px;
+ width: 50%;
+ height: 250px;
+}
+
+.indented select.select_multiple {
+ min-width: calc(500px - 1em);
+ width: calc(50% - 1em);
+}
diff --git a/pandora_console/include/styles/jquery.tag-editor.css b/pandora_console/include/styles/jquery.tag-editor.css
new file mode 100644
index 0000000000..0823e50d2e
--- /dev/null
+++ b/pandora_console/include/styles/jquery.tag-editor.css
@@ -0,0 +1,146 @@
+/* surrounding tag container */
+.tag-editor {
+ list-style-type: none;
+ padding: 0 5px 0 0;
+ margin: 0;
+ overflow: hidden;
+ border: 1px solid #eee;
+ cursor: text;
+ font: normal 14px sans-serif;
+ color: #555;
+ background: #fff;
+ line-height: 20px;
+}
+
+/* core styles usually need no change */
+.tag-editor li {
+ display: block;
+ float: left;
+ overflow: hidden;
+ margin: 3px 0;
+}
+.tag-editor div {
+ float: left;
+ padding: 0 4px;
+}
+.tag-editor .placeholder {
+ padding: 0 8px;
+ color: #bbb;
+}
+.tag-editor .tag-editor-spacer {
+ padding: 0;
+ width: 8px;
+ overflow: hidden;
+ color: transparent;
+ background: none;
+}
+.tag-editor input {
+ vertical-align: inherit;
+ border: 0;
+ outline: none;
+ padding: 0;
+ margin: 0;
+ cursor: text;
+ font-family: inherit;
+ font-weight: inherit;
+ font-size: inherit;
+ font-style: inherit;
+ box-shadow: none;
+ background: none;
+ color: #444;
+}
+/* hide original input field or textarea visually to allow tab navigation */
+.tag-editor-hidden-src {
+ position: absolute !important;
+ left: -99999px;
+}
+/* hide IE10 "clear field" X */
+.tag-editor ::-ms-clear {
+ display: none;
+}
+
+/* tag style */
+.tag-editor .tag-editor-tag {
+ padding-left: 5px;
+ color: #46799b;
+ background: #e0eaf1;
+ white-space: nowrap;
+ overflow: hidden;
+ cursor: pointer;
+ border-radius: 2px 0 0 2px;
+}
+
+/* delete icon */
+.tag-editor .tag-editor-delete {
+ background: #e0eaf1;
+ cursor: pointer;
+ border-radius: 0 2px 2px 0;
+ padding-left: 3px;
+ padding-right: 4px;
+}
+.tag-editor .tag-editor-delete i {
+ line-height: 18px;
+ display: inline-block;
+}
+.tag-editor .tag-editor-delete i:before {
+ font-size: 16px;
+ color: #8ba7ba;
+ content: "×";
+ font-style: normal;
+}
+.tag-editor .tag-editor-delete:hover i:before {
+ color: #d65454;
+}
+.tag-editor .tag-editor-tag.active + .tag-editor-delete,
+.tag-editor .tag-editor-tag.active + .tag-editor-delete i {
+ visibility: hidden;
+ cursor: text;
+}
+
+.tag-editor .tag-editor-tag.active {
+ background: none !important;
+}
+
+/* jQuery UI autocomplete - code.jquery.com/ui/1.10.2/themes/smoothness/jquery-ui.css */
+.ui-autocomplete {
+ position: absolute;
+ top: 0;
+ left: 0;
+ cursor: default;
+ font-size: 14px;
+}
+.ui-front {
+ z-index: 9999;
+}
+.ui-menu {
+ list-style: none;
+ padding: 1px;
+ margin: 0;
+ display: block;
+ outline: none;
+}
+.ui-menu .ui-menu-item a {
+ text-decoration: none;
+ display: block;
+ padding: 2px 0.4em;
+ line-height: 1.4;
+ min-height: 0; /* support: IE7 */
+}
+.ui-widget-content {
+ border: 1px solid #bbb;
+ background: #fff;
+ color: #555;
+}
+.ui-widget-content a {
+ color: #46799b;
+}
+.ui-widget-content .ui-state-hover,
+.ui-widget-header .ui-state-hover,
+.ui-state-focus,
+.ui-widget-content .ui-state-focus,
+.ui-widget-header .ui-state-focus {
+ background: #e0eaf1;
+}
+.ui-helper-hidden-accessible {
+ display: none;
+}
diff --git a/pandora_console/include/styles/pandora.css b/pandora_console/include/styles/pandora.css
index 62984d075d..b9f3b2a1ed 100644
--- a/pandora_console/include/styles/pandora.css
+++ b/pandora_console/include/styles/pandora.css
@@ -628,6 +628,9 @@ select:-internal-list-box {
.float-right {
float: right;
}
+.invisible {
+ display: none;
+}
div#page {
background: #fbfbfb;
@@ -5647,6 +5650,11 @@ div#status_pie {
.white_table_graph_header b {
font-size: 10pt;
font-weight: 600;
+ width: 100%;
+}
+
+.white_table_graph_header div.white_table_header_checkbox {
+ float: right;
}
.white_table_graph_header div#bullets_modules {
diff --git a/pandora_console/include/styles/pen.css b/pandora_console/include/styles/pen.css
new file mode 100644
index 0000000000..72701bd01e
--- /dev/null
+++ b/pandora_console/include/styles/pen.css
@@ -0,0 +1,38 @@
+ul.wizard li > label:not(.p-switch) {
+ width: auto;
+}
+
+form.top-action-buttons ul.wizard {
+ display: flex;
+ flex-direction: row;
+}
+
+ul.wizard li {
+ margin-right: 1em;
+}
+
+form.modal ul.wizard li {
+ display: flex;
+ flex-direction: row;
+ width: 90%;
+ margin: 0 auto;
+ justify-items: center;
+}
+
+form.modal ul.wizard li * {
+ flex: 1;
+}
+
+ul.wizard li.flex-indep {
+ flex: 1;
+ margin: 0;
+}
+
+div#div-form {
+ padding: 0 2em;
+}
+
+div#div-form textarea {
+ width: 100%;
+ margin-top: 1em;
+}
diff --git a/pandora_console/include/styles/simTree.css b/pandora_console/include/styles/simTree.css
new file mode 100644
index 0000000000..0cb03527c6
--- /dev/null
+++ b/pandora_console/include/styles/simTree.css
@@ -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;
+}
diff --git a/pandora_console/include/styles/task_list.css b/pandora_console/include/styles/task_list.css
index d3ffb5d546..01f7a82549 100644
--- a/pandora_console/include/styles/task_list.css
+++ b/pandora_console/include/styles/task_list.css
@@ -36,7 +36,77 @@ ul.progress_task_discovery {
flex-direction: column;
}
+div.subtitle {
+ width: 100%;
+ margin-top: 40px;
+ text-align: center;
+}
+
+div.subtitle span {
+ font-size: 1.9em;
+ font-family: "lato-bolder", "Open Sans", sans-serif;
+}
+
+div.subtitle div.manage {
+ text-align: center;
+ padding-top: 2em;
+ padding-bottom: 1em;
+}
+
+div.subtitle div.manage button {
+ font-size: 1.2em;
+ font-family: "lato", "Open Sans", sans-serif;
+ display: inline-block;
+ margin-right: 1em;
+ cursor: pointer;
+ text-align: left;
+ border-radius: 21px;
+ box-shadow: 0 0 10px -5px #888;
+ padding: 0.5em 1em;
+ border: 1px solid #ddd;
+ user-select: none;
+ color: #424242;
+}
+
+div.subtitle .link.review {
+ margin: 15px 0 -30px;
+ display: block;
+ font-weight: bold;
+}
+
+#msg ul li {
+ margin-left: 3em;
+}
+
+li.added {
+ list-style: url("../../images/header_ready.png");
+}
+li.removed {
+ list-style: url("../../images/header_down.png");
+}
+
+#msg ul {
+ list-style: url("../../images/header_ready.png");
+}
+
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;
+}
+
+#review {
+ padding-top: 2em;
+ padding-left: 6.7em;
+}
diff --git a/pandora_console/include/styles/wizard.css b/pandora_console/include/styles/wizard.css
index 029addf5cb..3d66e165ff 100644
--- a/pandora_console/include/styles/wizard.css
+++ b/pandora_console/include/styles/wizard.css
@@ -2,7 +2,11 @@
* Discovery > Wizard css global style
*/
+#main > form.discovery.wizard > .white_box {
+ min-width: 1024px;
+}
ul.wizard {
+ list-style-type: none;
}
ul.wizard li {
@@ -23,6 +27,100 @@ ul.wizard li > textarea {
font-family: monospace;
}
-.hidden {
+.wizard .hidden {
display: none;
}
+
+.wizard .indented {
+ margin-left: 1em;
+}
+
+.wizard .std_input {
+ display: flex;
+ margin-bottom: 25px;
+ flex-wrap: wrap;
+ justify-content: space-between;
+}
+
+.wizard .std_input > .label_select {
+ flex: 1 1 100%;
+}
+.wizard .std_input > * {
+ flex: 1 1 auto;
+ align-self: baseline;
+}
+
+.wizard .inline_input.no-margin {
+ margin-bottom: 0px;
+}
+.wizard .inline_input {
+ display: flex;
+ margin-bottom: 25px;
+ flex-wrap: wrap;
+ justify-content: space-between;
+ align-items: baseline;
+}
+
+.wizard .inline_input * {
+ flex: 1 1 auto;
+}
+
+.wizard .discovery_inline_input {
+ display: flex;
+ align-content: end;
+ flex: 0;
+ align-self: flex-start;
+}
+
+/* override tag-editor styles */
+.wizard .tag-editor.ui-sortable {
+ width: 450px;
+ display: inline-block;
+}
+
+.wizard .tag-editor .tag-editor-tag {
+ padding: 5px;
+ color: #fff;
+ background: #82b92e;
+}
+
+.wizard .tag-editor .tag-editor-delete i {
+ line-height: inherit;
+}
+.wizard .tag-editor .tag-editor-delete i:before {
+ color: #ccc;
+}
+.wizard .tag-editor .tag-editor-delete:hover i:before {
+ color: #fff;
+}
+
+.wizard .tag-editor .tag-editor-delete {
+ padding: 5px;
+ background: #e63c52;
+}
+
+.wizard .time_selection_container {
+ display: flex;
+ align-items: baseline;
+ justify-items: center;
+ align-content: space-between;
+ margin-top: 1em;
+}
+
+.wizard #interval_manual_container #interval_manual > * {
+ flex: 1 1 auto;
+}
+
+.wizard-column-levels {
+ float: left;
+ width: 33%;
+ text-align: center;
+}
+
+.action_button_list {
+ height: 60px;
+}
+
+.action_button_list li {
+ display: inline;
+}
diff --git a/pandora_console/install.php b/pandora_console/install.php
index ec4b256695..26de845c43 100644
--- a/pandora_console/install.php
+++ b/pandora_console/install.php
@@ -129,7 +129,7 @@
meta = is_metaconsole();
if (is_metaconsole()) {
@@ -360,7 +362,10 @@ if (is_ajax()) {
true
);
- $tmp->data = format_numeric($tmp->data, 1);
+ $tmp->data = format_numeric(
+ $tmp->data,
+ $config['graph_precision']
+ );
$tmp->instructions = events_get_instructions($item);
diff --git a/pandora_console/operation/messages/message_edit.php b/pandora_console/operation/messages/message_edit.php
index 039222436e..0b9bca18ad 100644
--- a/pandora_console/operation/messages/message_edit.php
+++ b/pandora_console/operation/messages/message_edit.php
@@ -127,17 +127,7 @@ if ($read_message) {
).' '.$user_name;
}
- $order = [
- "\r\n",
- "\n",
- "\r",
- ];
- $replace = '
';
- $parsed_message = str_replace(
- $order,
- $replace,
- trim(io_safe_output($row['message']))
- );
+ $parsed_message = nl2br(htmlspecialchars(trim(io_safe_output($row['message']))));
echo '
';
echo '
'.$parsed_message.'
';
diff --git a/pandora_console/pandora_console.redhat.spec b/pandora_console/pandora_console.redhat.spec
index 46c2707672..c36a64c969 100644
--- a/pandora_console/pandora_console.redhat.spec
+++ b/pandora_console/pandora_console.redhat.spec
@@ -3,7 +3,7 @@
#
%define name pandorafms_console
%define version 7.0NG.744
-%define release 200413
+%define release 200414
# User and Group under which Apache is running
%define httpd_name httpd
diff --git a/pandora_console/pandora_console.rhel7.spec b/pandora_console/pandora_console.rhel7.spec
index e357814f65..ea0486171b 100644
--- a/pandora_console/pandora_console.rhel7.spec
+++ b/pandora_console/pandora_console.rhel7.spec
@@ -3,7 +3,7 @@
#
%define name pandorafms_console
%define version 7.0NG.744
-%define release 200413
+%define release 200414
# User and Group under which Apache is running
%define httpd_name httpd
diff --git a/pandora_console/pandora_console.spec b/pandora_console/pandora_console.spec
index 72726fb317..6843fd4f62 100644
--- a/pandora_console/pandora_console.spec
+++ b/pandora_console/pandora_console.spec
@@ -3,7 +3,7 @@
#
%define name pandorafms_console
%define version 7.0NG.744
-%define release 200413
+%define release 200414
%define httpd_name httpd
# User and Group under which Apache is running
%define httpd_name apache2
diff --git a/pandora_console/pandoradb.sql b/pandora_console/pandoradb.sql
index 6fbcb0ec2c..c698f0d6a9 100644
--- a/pandora_console/pandoradb.sql
+++ b/pandora_console/pandoradb.sql
@@ -773,14 +773,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,
+ `review_mode` tinyint(1) unsigned NOT NULL default 1,
+ `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),
@@ -788,31 +788,59 @@ 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',
+ `auto_monitor` TINYINT(1) UNSIGNED DEFAULT 1,
+ `autoconfiguration_enabled` tinyint(1) unsigned default 0,
`summary` text,
`type` int NOT NULL default 0,
+ `subnet_csv` TINYINT(1) UNSIGNED 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` MEDIUMTEXT,
+ `review_date` datetime DEFAULT NULL,
+ `created` datetime DEFAULT NULL,
+ 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` int(10) unsigned NOT NULL AUTO_INCREMENT,
+ `id_rt` int(10) unsigned NOT NULL,
+ `dev_1` text,
+ `dev_2` text,
+ `if_1` text,
+ `if_2` text,
+ PRIMARY KEY (`id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+
-- ----------------------------------------------------------------------
-- Table `tmodule_relationship`
-- ----------------------------------------------------------------------
@@ -926,6 +954,28 @@ CREATE TABLE IF NOT EXISTS `tnetwork_profile_component` (
KEY `id_np` (`id_np`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+-- ----------------------------------------------------------------------
+-- Table `tpen`
+-- ----------------------------------------------------------------------
+CREATE TABLE IF NOT EXISTS `tpen` (
+ `pen` int(10) unsigned NOT NULL,
+ `manufacturer` TEXT,
+ `description` TEXT,
+ PRIMARY KEY (`pen`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+
+-- ----------------------------------------------------------------------
+-- Table `tnetwork_profile_pen`
+-- ----------------------------------------------------------------------
+CREATE TABLE IF NOT EXISTS `tnetwork_profile_pen` (
+ `pen` int(10) unsigned NOT NULL,
+ `id_np` int(10) unsigned NOT NULL,
+ CONSTRAINT `fk_network_profile_pen_pen` FOREIGN KEY (`pen`)
+ REFERENCES `tpen` (`pen`) ON DELETE CASCADE ON UPDATE CASCADE,
+ CONSTRAINT `fk_network_profile_pen_id_np` FOREIGN KEY (`id_np`)
+ REFERENCES `tnetwork_profile` (`id_np`) ON DELETE CASCADE ON UPDATE CASCADE
+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+
-- ----------------------------------------------------------------------
-- Table `tnota`
-- ----------------------------------------------------------------------
diff --git a/pandora_console/pandoradb_data.sql b/pandora_console/pandoradb_data.sql
index 1095a32cba..29c7b6b6c6 100644
--- a/pandora_console/pandoradb_data.sql
+++ b/pandora_console/pandoradb_data.sql
@@ -1594,3 +1594,123 @@ VALUES
(254,6,848,943,0,0,'','white',19,3600,0,0,0,0,1,0,0,0,0,'line','down','','#FFFFFF',0,0,'default',0,0.000,0.000,0,0,'digital_1','time','Europe/Madrid',0,0),
(255,5,846,941,0,0,'','white',19,3600,0,0,0,0,1,0,0,0,0,'line','down','','#FFFFFF',0,0,'default',0,0.000,0.000,0,0,'digital_1','time','Europe/Madrid',0,0)
;
+
+--
+-- Dumping data for table `tpen`
+--
+
+INSERT INTO `tpen`
+VALUES
+ (9,'cisco','Cisco System'),
+ (11,'hp','Hewlett Packard'),
+ (2021,'general_snmp','U.C. Davis, ECE Dept. Tom'),
+ (2636,'juniper','Juniper Networks'),
+ (3375,'f5','F5 Labs'),
+ (8072,'general_snmp','Net SNMP'),
+ (12356,'fortinet','Fortinet')
+;
+
+--
+-- Dumping data for table `tnetwork_profile` and `tnetwork_profile_pen`
+--
+
+SET @template_name = 'Network Management';
+SET @template_description = 'Basic network monitoring template';
+
+INSERT INTO tnetwork_profile (id_np, name, description) SELECT * FROM (SELECT '' id_np, @template_name name, @template_description description) AS tmp WHERE NOT EXISTS (SELECT id_np FROM tnetwork_profile WHERE name = @template_name);
+INSERT INTO tnetwork_profile_component (id_nc, id_np) SELECT * FROM (SELECT c.id_nc id_nc, p.id_np id_np FROM tnetwork_profile p, tnetwork_component c, tnetwork_component_group g WHERE g.id_sg = c.id_group AND p.name = @template_name AND (g.name = 'Network Management')) AS tmp WHERE NOT EXISTS (SELECT pc.id_np FROM tnetwork_profile p, tnetwork_profile_component pc WHERE p.id_np = pc.id_np AND p.name = @template_name);
+
+SET @template_name = 'Cisco MIBS';
+SET @template_description = 'Cisco devices monitoring template (SNMP)';
+
+INSERT INTO tnetwork_profile (id_np, name, description) SELECT * FROM (SELECT '' id_np, @template_name name, @template_description description) AS tmp WHERE NOT EXISTS (SELECT id_np FROM tnetwork_profile WHERE name = @template_name);
+INSERT INTO tnetwork_profile_component (id_nc, id_np) SELECT * FROM (SELECT c.id_nc id_nc, p.id_np id_np FROM tnetwork_profile p, tnetwork_component c, tnetwork_component_group g WHERE g.id_sg = c.id_group AND p.name = @template_name AND (g.name = 'Cisco MIBS' OR g.name = 'Catalyst 2900')) AS tmp WHERE NOT EXISTS (SELECT pc.id_np FROM tnetwork_profile p, tnetwork_profile_component pc WHERE p.id_np = pc.id_np AND p.name = @template_name);
+INSERT INTO tnetwork_profile_pen (pen, id_np) SELECT * FROM (SELECT p.pen pen, np.id_np id_np FROM tnetwork_profile np, tpen p WHERE np.name = @template_name AND (p.pen = 9)) AS tmp WHERE NOT EXISTS (SELECT pp.id_np FROM tnetwork_profile p, tnetwork_profile_pen pp WHERE p.id_np = pp.id_np AND p.name = @template_name);
+
+SET @template_name = 'Linux System';
+SET @template_description = 'Linux system monitoring template (SNMP)';
+
+INSERT INTO tnetwork_profile (id_np, name, description) SELECT * FROM (SELECT '' id_np, @template_name name, @template_description description) AS tmp WHERE NOT EXISTS (SELECT id_np FROM tnetwork_profile WHERE name = @template_name);
+
+SET @module_group = 'Linux';
+
+INSERT INTO tnetwork_profile_component (id_nc, id_np) SELECT * FROM (SELECT c.id_nc id_nc, p.id_np id_np FROM tnetwork_profile p, tnetwork_component c, tnetwork_component_group g WHERE g.id_sg = c.id_group AND p.name = @template_name AND (g.name = 'Linux' OR g.name = 'UCD Mibs (Linux, UCD-SNMP)')) AS tmp WHERE NOT EXISTS (SELECT pc.id_np FROM tnetwork_profile p, tnetwork_profile_component pc WHERE p.id_np = pc.id_np AND p.name = @template_name);
+INSERT INTO tnetwork_profile_pen (pen, id_np) SELECT * FROM (SELECT p.pen pen, np.id_np id_np FROM tnetwork_profile np, tpen p WHERE np.name = @template_name AND (p.pen = 2021 OR p.pen = 2636)) AS tmp WHERE NOT EXISTS (SELECT pp.id_np FROM tnetwork_profile p, tnetwork_profile_pen pp WHERE p.id_np = pp.id_np AND p.name = @template_name);
+
+SET @template_name = 'Windows System';
+SET @template_description = 'Windows system monitoring template (WMI)';
+
+INSERT INTO tnetwork_profile (id_np, name, description) SELECT * FROM (SELECT '' id_np, @template_name name, @template_description description) AS tmp WHERE NOT EXISTS (SELECT id_np FROM tnetwork_profile WHERE name = @template_name);
+INSERT INTO tnetwork_profile_component (id_nc, id_np) SELECT * FROM (SELECT c.id_nc id_nc, p.id_np id_np FROM tnetwork_profile p, tnetwork_component c, tnetwork_component_group g WHERE g.id_sg = c.id_group AND p.name = @template_name AND (g.name = 'Microsoft Windows' OR g.name = 'Windows System')) AS tmp WHERE NOT EXISTS (SELECT pc.id_np FROM tnetwork_profile p, tnetwork_profile_component pc WHERE p.id_np = pc.id_np AND p.name = @template_name);
+
+SET @template_name = 'Windows Hardware';
+SET @template_description = 'Windows hardware monitoring templae (WMI)';
+
+INSERT INTO tnetwork_profile (id_np, name, description) SELECT * FROM (SELECT '' id_np, @template_name name, @template_description description) AS tmp WHERE NOT EXISTS (SELECT id_np FROM tnetwork_profile WHERE name = @template_name);
+INSERT INTO tnetwork_profile_component (id_nc, id_np) SELECT * FROM (SELECT c.id_nc id_nc, p.id_np id_np FROM tnetwork_profile p, tnetwork_component c, tnetwork_component_group g WHERE g.id_sg = c.id_group AND p.name = @template_name AND (g.name = 'Windows Hardware Layer')) AS tmp WHERE NOT EXISTS (SELECT pc.id_np FROM tnetwork_profile p, tnetwork_profile_component pc WHERE p.id_np = pc.id_np AND p.name = @template_name);
+
+SET @template_name = 'Windows Active Directory';
+SET @template_description = 'Active directory monitoring template (WMI)';
+
+INSERT INTO tnetwork_profile (id_np, name, description) SELECT * FROM (SELECT '' id_np, @template_name name, @template_description description) AS tmp WHERE NOT EXISTS (SELECT id_np FROM tnetwork_profile WHERE name = @template_name);
+INSERT INTO tnetwork_profile_component (id_nc, id_np) SELECT * FROM (SELECT c.id_nc id_nc, p.id_np id_np FROM tnetwork_profile p, tnetwork_component c, tnetwork_component_group g WHERE g.id_sg = c.id_group AND p.name = @template_name AND (g.name = 'Windows AD' OR g.name = 'AD Counters')) AS tmp WHERE NOT EXISTS (SELECT pc.id_np FROM tnetwork_profile p, tnetwork_profile_component pc WHERE p.id_np = pc.id_np AND p.name = @template_name);
+
+SET @template_name = 'Windows IIS';
+SET @template_description = 'IIS monitoring template (WMI)';
+
+INSERT INTO tnetwork_profile (id_np, name, description) SELECT * FROM (SELECT '' id_np, @template_name name, @template_description description) AS tmp WHERE NOT EXISTS (SELECT id_np FROM tnetwork_profile WHERE name = @template_name);
+INSERT INTO tnetwork_profile_component (id_nc, id_np) SELECT * FROM (SELECT c.id_nc id_nc, p.id_np id_np FROM tnetwork_profile p, tnetwork_component c, tnetwork_component_group g WHERE g.id_sg = c.id_group AND p.name = @template_name AND (g.name = 'Windows IIS' OR g.name = 'IIS services')) AS tmp WHERE NOT EXISTS (SELECT pc.id_np FROM tnetwork_profile p, tnetwork_profile_component pc WHERE p.id_np = pc.id_np AND p.name = @template_name);
+
+SET @template_name = 'Windows Exchange';
+SET @template_description = 'Exchange monitoring template (WMI)';
+
+INSERT INTO tnetwork_profile (id_np, name, description) SELECT * FROM (SELECT '' id_np, @template_name name, @template_description description) AS tmp WHERE NOT EXISTS (SELECT id_np FROM tnetwork_profile WHERE name = @template_name);
+INSERT INTO tnetwork_profile_component (id_nc, id_np) SELECT * FROM (SELECT c.id_nc id_nc, p.id_np id_np FROM tnetwork_profile p, tnetwork_component c, tnetwork_component_group g WHERE g.id_sg = c.id_group AND p.name = @template_name AND (g.name = 'Windows Exchange' OR g.name = 'Exchange Services' OR g.name = 'Exchange TCP Ports')) AS tmp WHERE NOT EXISTS (SELECT pc.id_np FROM tnetwork_profile p, tnetwork_profile_component pc WHERE p.id_np = pc.id_np AND p.name = @template_name);
+
+SET @template_name = 'Windows LDAP';
+SET @template_description = 'LDAP monitoring template (WMI)';
+
+INSERT INTO tnetwork_profile (id_np, name, description) SELECT * FROM (SELECT '' id_np, @template_name name, @template_description description) AS tmp WHERE NOT EXISTS (SELECT id_np FROM tnetwork_profile WHERE name = @template_name);
+INSERT INTO tnetwork_profile_component (id_nc, id_np) SELECT * FROM (SELECT c.id_nc id_nc, p.id_np id_np FROM tnetwork_profile p, tnetwork_component c, tnetwork_component_group g WHERE g.id_sg = c.id_group AND p.name = @template_name AND (g.name = 'Windows LDAP')) AS tmp WHERE NOT EXISTS (SELECT pc.id_np FROM tnetwork_profile p, tnetwork_profile_component pc WHERE p.id_np = pc.id_np AND p.name = @template_name);
+
+SET @template_name = 'Windows MDSTC';
+SET @template_description = 'MDSTC monitoring template (WMI)';
+
+INSERT INTO tnetwork_profile (id_np, name, description) SELECT * FROM (SELECT '' id_np, @template_name name, @template_description description) AS tmp WHERE NOT EXISTS (SELECT id_np FROM tnetwork_profile WHERE name = @template_name);
+INSERT INTO tnetwork_profile_component (id_nc, id_np) SELECT * FROM (SELECT c.id_nc id_nc, p.id_np id_np FROM tnetwork_profile p, tnetwork_component c, tnetwork_component_group g WHERE g.id_sg = c.id_group AND p.name = @template_name AND (g.name = 'Windows MSDTC')) AS tmp WHERE NOT EXISTS (SELECT pc.id_np FROM tnetwork_profile p, tnetwork_profile_component pc WHERE p.id_np = pc.id_np AND p.name = @template_name);
+
+SET @template_name = 'Windows Printers';
+SET @template_description = 'Windows printers monitoring template (WMI)';
+
+INSERT INTO tnetwork_profile (id_np, name, description) SELECT * FROM (SELECT '' id_np, @template_name name, @template_description description) AS tmp WHERE NOT EXISTS (SELECT id_np FROM tnetwork_profile WHERE name = @template_name);
+INSERT INTO tnetwork_profile_component (id_nc, id_np) SELECT * FROM (SELECT c.id_nc id_nc, p.id_np id_np FROM tnetwork_profile p, tnetwork_component c, tnetwork_component_group g WHERE g.id_sg = c.id_group AND p.name = @template_name AND (g.name = 'Windows Printers')) AS tmp WHERE NOT EXISTS (SELECT pc.id_np FROM tnetwork_profile p, tnetwork_profile_component pc WHERE p.id_np = pc.id_np AND p.name = @template_name);
+
+SET @template_name = 'Windows DNS';
+SET @template_description = 'Windows DNS monitoring template (WMI)';
+
+INSERT INTO tnetwork_profile (id_np, name, description) SELECT * FROM (SELECT '' id_np, @template_name name, @template_description description) AS tmp WHERE NOT EXISTS (SELECT id_np FROM tnetwork_profile WHERE name = @template_name);
+INSERT INTO tnetwork_profile_component (id_nc, id_np) SELECT * FROM (SELECT c.id_nc id_nc, p.id_np id_np FROM tnetwork_profile p, tnetwork_component c, tnetwork_component_group g WHERE g.id_sg = c.id_group AND p.name = @template_name AND (g.name = 'Windows DNS' OR g.name = 'DNS Counters')) AS tmp WHERE NOT EXISTS (SELECT pc.id_np FROM tnetwork_profile p, tnetwork_profile_component pc WHERE p.id_np = pc.id_np AND p.name = @template_name);
+
+SET @template_name = 'Windows MS SQL Server';
+SET @template_description = 'MS SQL Server monitoring template (WMI)';
+
+INSERT INTO tnetwork_profile (id_np, name, description) SELECT * FROM (SELECT '' id_np, @template_name name, @template_description description) AS tmp WHERE NOT EXISTS (SELECT id_np FROM tnetwork_profile WHERE name = @template_name);
+INSERT INTO tnetwork_profile_component (id_nc, id_np) SELECT * FROM (SELECT c.id_nc id_nc, p.id_np id_np FROM tnetwork_profile p, tnetwork_component c, tnetwork_component_group g WHERE g.id_sg = c.id_group AND p.name = @template_name AND (g.name = 'MS SQL Server')) AS tmp WHERE NOT EXISTS (SELECT pc.id_np FROM tnetwork_profile p, tnetwork_profile_component pc WHERE p.id_np = pc.id_np AND p.name = @template_name);
+
+SET @template_name = 'Oracle';
+SET @template_description = 'Oracle monitoring template';
+
+INSERT INTO tnetwork_profile (id_np, name, description) SELECT * FROM (SELECT '' id_np, @template_name name, @template_description description) AS tmp WHERE NOT EXISTS (SELECT id_np FROM tnetwork_profile WHERE name = @template_name);
+INSERT INTO tnetwork_profile_component (id_nc, id_np) SELECT * FROM (SELECT c.id_nc id_nc, p.id_np id_np FROM tnetwork_profile p, tnetwork_component c, tnetwork_component_group g WHERE g.id_sg = c.id_group AND p.name = @template_name AND (g.name = 'Oracle')) AS tmp WHERE NOT EXISTS (SELECT pc.id_np FROM tnetwork_profile p, tnetwork_profile_component pc WHERE p.id_np = pc.id_np AND p.name = @template_name);
+
+SET @template_name = 'MySQL';
+SET @template_description = 'MySQL monitoring template';
+
+INSERT INTO tnetwork_profile (id_np, name, description) SELECT * FROM (SELECT '' id_np, @template_name name, @template_description description) AS tmp WHERE NOT EXISTS (SELECT id_np FROM tnetwork_profile WHERE name = @template_name);
+INSERT INTO tnetwork_profile_component (id_nc, id_np) SELECT * FROM (SELECT c.id_nc id_nc, p.id_np id_np FROM tnetwork_profile p, tnetwork_component c, tnetwork_component_group g WHERE g.id_sg = c.id_group AND p.name = @template_name AND (g.name = 'MySQL')) AS tmp WHERE NOT EXISTS (SELECT pc.id_np FROM tnetwork_profile p, tnetwork_profile_component pc WHERE p.id_np = pc.id_np AND p.name = @template_name);
+
+SET @template_name = 'Windows Antivirus';
+SET @template_description = 'Windows antivirus monitoring template (WMI)';
+
+INSERT INTO tnetwork_profile (id_np, name, description) SELECT * FROM (SELECT '' id_np, @template_name name, @template_description description) AS tmp WHERE NOT EXISTS (SELECT id_np FROM tnetwork_profile WHERE name = @template_name);
+INSERT INTO tnetwork_profile_component (id_nc, id_np) SELECT * FROM (SELECT c.id_nc id_nc, p.id_np id_np FROM tnetwork_profile p, tnetwork_component c, tnetwork_component_group g WHERE g.id_sg = c.id_group AND p.name = @template_name AND (g.name = 'Norton' OR g.name = 'Panda' OR g.name = 'McAfee' OR g.name = 'Bitdefender' OR g.name = 'BullGuard' OR g.name = 'AVG' OR g.name = 'Kaspersky')) AS tmp WHERE NOT EXISTS (SELECT pc.id_np FROM tnetwork_profile p, tnetwork_profile_component pc WHERE p.id_np = pc.id_np AND p.name = @template_name);
\ No newline at end of file
diff --git a/pandora_plugins/Autodiscover services/autodiscover.py b/pandora_plugins/Autodiscover services/autodiscover.py
deleted file mode 100644
index 78a70cddba..0000000000
--- a/pandora_plugins/Autodiscover services/autodiscover.py
+++ /dev/null
@@ -1,398 +0,0 @@
-#!/usr/bin/env python3
-###################################################
-#
-# Pandora FMS Autodiscovery plugin.
-# Checks the status of the services in list and monitors CPU and Memory for each of them.
-#
-# (c) A. Kevin Rojas
-#
-# TO DO LIST:
-# - Enable child services detection (Windows)
-# - Make CPU/Memory usage available for child services (Windows)
-#
-###################################################
-
-from sys import argv, path, stderr, exit
-import psutil
-from subprocess import *
-
-global module_list
-module_list = []
-
-
-#########################################################################################
-# Powershell class
-#########################################################################################
-class PSCheck:
- @staticmethod
- def check_service(servicename, option=False, memcpu=False):
- """Check services with powershell by parsing their DisplayName. Returns a dict\
- list with the name of the service and a boolean with its status.\n
- Requires service name (case insensitive)."""
- pscall = Popen(["powershell", "Get-Service", "-Name", "'*"+ str(servicename) + "*'",
- "|", "Select-Object", "-ExpandProperty", "Name"],
- stdout=PIPE, stdin=DEVNULL, stderr=DEVNULL, universal_newlines=True)
- result = pscall.communicate()
- result = str(result[0]).strip().split("\n")
- procname = ''
- if result != '':
- output = []
- for element in result:
- if element != '':
- # Get process name
- procname = PSCheck.get_serviceprocess(element)
- # Get process status
- parstatus = PSCheck.getstatus(element)
- if memcpu == True and parstatus == 1:
- usage = get_memcpu(str(procname), str(element))
- output += usage
- # Generate module with name and status
- parent = service_module(str(element), parstatus)
- output += parent
- if option == True:
- children = PSCheck.getchildren(element, memcpu)
- if type(children) == list and len(children) > 1:
- for child in children:
- output += child
- else:
- output += children
- else:
- next
-
- #if output != '':
- if output and element and procname:
- return ({"name" : element, "process" : procname, "modules": output})
- else:
- return (None)
-
- @staticmethod
- def getchildren(servicename, memcpu=False):
- """Gets Dependent services of a given Windows service"""
- pschild = Popen(["powershell", "Get-Service", "-Name '" + str(servicename) +
- "' -DS", "|", "Select-Object", "-ExpandProperty", "Name"],
- stdout=PIPE, stdin=DEVNULL, stderr=DEVNULL, universal_newlines=True)
- children = pschild.communicate()[0].strip()
- kids = []
- for child in (children.split("\n") if children != "" else []):
- status = PSCheck.getstatus(child)
- kids += service_module(str(child), status, "Service " + str(servicename) + " - Status")
- if status:
- if memcpu == True:
- kidsusage = get_memcpu(str(child))
- for usage in kidsusage:
- kids += usage
- else:
- next
- return (kids)
-
- @staticmethod
- def getstatus(servicename):
- """Gets the status of a given Windows service"""
- running = Popen(["powershell", "Get-Service", "-Name '" + str(servicename) +
- "' |", "Select-Object", "-ExpandProperty", "Status"],
- stdout=PIPE, stdin=DEVNULL, stderr=DEVNULL, universal_newlines=True)
- status = running.communicate()[0].strip()
- return (int(status == "Running"))
-
- @staticmethod
- def get_serviceprocess(servicename):
- """Gets name of the process of the service"""
- service = psutil.win_service_get(servicename)
- srv_pid = service.pid()
- process = psutil.Process(srv_pid)
- proc_name = process.name()
- return (proc_name)
-
-
-#########################################################################################
-# Services creation
-#########################################################################################
-
-def service_module(name, value, parent=None):
- #print ("service_module BEGIN "+str(now(0,1)))
- module = [{
- "name" : "Service "+ name + " - Status",
- "type" : "generic_proc",
- "value" : value,
- "module_parent" : parent,
- }]
- #print ("service_module END "+str(now(0,1)))
- return (module)
-
-def get_memcpu (process, servicename):
- """Creates a module for Memory and CPU for a given process. Returns a list of dictionaries."""
- modules = []
- if process:
- if servicename != None:
- parentname = servicename
- else:
- parentname = process
- modules += [{
- "name" : "Service "+ process + " - Memory usage",
- "type" : "generic_data",
- "value" : proc_percentbyname(process)[0],
- "unit" : "%",
- "module_parent" : "Service "+ parentname + " - Status",
- },
- {"name" : "Service "+ process + " - CPU usage",
- "type" : "generic_data",
- "value" : proc_percentbyname(process)[1],
- "unit" : "%",
- "module_parent" : "Service "+ parentname + " - Status",
- }]
- return (modules)
-
-def proc_percentbyname(procname): ############# 03/03/2020
- """Gets Memory and CPU usage for a given process. Returns a list."""
- #print ("proc_percentbyname BEGIN "+str(now(0,1)))
- procs = [p for p in psutil.process_iter() if procname in p.name().lower()]
- memory = []
- cpu = []
- try:
- for proc in procs:
- if proc.name() == procname:
- cpu.append(proc.cpu_percent(interval=0.5))
- memory.append(proc.memory_percent())
- else:
- next
- except psutil.NoSuchProcess:
- next
- #print ("proc_percentbyname END "+str(now(0,1)))
- return ([sum(memory),sum(cpu)])
-
-def win_service(servicelist, option=False, memcpu=False):
- """Creates modules for Windows servers."""
- modules = []
- for srvc in servicelist:
- if srvc and len(srvc) > 2:
- output = PSCheck.check_service(srvc, option, memcpu)
- if output != None and output["modules"]:
- modules += PSCheck.check_service(srvc.strip(), option, memcpu)["modules"]
- module_list.append(srvc)
- winprocess = output["name"]
- #if memcpu == True:
- # modules += get_memcpu(winprocess) ## Only available for parent service ATM.
- else:
- next
- else:
- next
- for module in modules:
- print_module(module, 1)
-
-
-def lnx_service(services_list, memcpu=False):
- """Creates modules for Linux servers"""
- modules = []
- sysctl = getstatusoutput("command -v systemctl")[0]
- servic = getstatusoutput("command -v service")[0]
- for srvc in services_list:
- status = None
- if sysctl == 0:
- ### Systemd available
- syscall = Popen(["systemctl", "is-active", srvc], stdout=PIPE,
- stdin=DEVNULL, universal_newlines=True)
- result = syscall.communicate()
- result = result[0].strip().lower()
- if result == "active":
- modules += service_module(srvc, 1)
- status = 1
- elif result == "inactive":
- modules += service_module(srvc, 0)
- status = 0
- elif result == "unknown":
- next
- elif sysctl != 0 and servic == 0:
- ### Systemd not available, switch to service command
- syscall = Popen(["service", srvc, "status"], stdout=PIPE,
- stdin=DEVNULL, stderr=DEVNULL, universal_newlines=True)
- result = syscall.communicate()[0].lower()
- if "is running" in result:
- modules += service_module(srvc, 1)
- status = 1
- elif "is stopped" in result:
- modules += service_module(srvc, 0)
- status = 0
- else:
- next
- else:
- print ("No systemd or service commands available. Exiting...", file=stderr)
- exit()
- if status:
- module_list.append(srvc)
- if memcpu == True:
- modules += get_memcpu(srvc, None)
-
- for m in modules:
- print_module (m, 1)
-
-
-#########################################################################################
-# print_module function
-#########################################################################################
-def print_module(module, str_flag=False):
- """Returns module in XML format. Accepts only {dict}.\n
- + Only works with one module at a time: otherwise iteration is needed.
- + Module "value" field accepts str type or [list] for datalists.
- + Use not_print_flag to avoid printing the XML (only populates variables).
- """
- data = dict(module)
- module_xml = ("\n"
- "\t\n"
- "\t" + str(data["type"]) + "\n"
- )
- #### Strip spaces if module not generic_data_string
- if type(data["type"]) is not str and "string" not in data["type"]:
- data["value"] = data["value"].strip()
- if isinstance(data["value"], list): # Checks if value is a list
- module_xml += "\t\n"
-
- #### Print flag
- if str_flag is not False:
- print (module_xml)
-
- return (module_xml)
-
-
-#########################################################################################
-# MAIN
-#########################################################################################
-
-def main():
- """Checks OS and calls the discover function."""
- if psutil.WINDOWS:
- OS = "Windows"
- service_list = ["MySQL", "postgresql", "pgsql", "oracle", "MSSQL", "IISADMIN",
- "apache", "nginx", "W3svc", "NTDS", "Netlogon", "DNS", "MSExchangeADTopology",
- "MSExchangeServiceHost", "MSExchangeSA", "MSExchangeTransport"]
- discover(OS, service_list)
- elif psutil.LINUX:
- OS = "Linux"
- service_list = ["httpd", "apache2", "nginx", "ldap", "docker",
- "postfix", "mysqld", "postgres", "oracle", "mongod"]
- discover(OS, service_list)
- else:
- print ("OS not recognized. Exiting...", file=stderr)
- exit()
-
-def discover(osyst, servicelist):
- """Shows help and triggers the creation of service modules"""
- if "--usage" in argv:
- memcpu = True
- else:
- memcpu = False
- if len(argv) > 2 and argv[1] == "--list":
- servicelist = argv[2].split(",")
- if osyst == "Windows":
- win_service(servicelist, False, memcpu) ## False won't get children
- elif osyst == "Linux":
- lnx_service(servicelist, memcpu)
- elif len(argv) > 1 and argv[1] == "--default":
- if osyst == "Windows":
- win_service(servicelist, False, memcpu) ## False won't get children
- elif osyst == "Linux":
- lnx_service(servicelist, memcpu)
- else:
- print ("\nPandora FMS Autodiscovery plugin.")
- print ("Checks the status of the services in list and monitors CPU and Memory for each of them.\n")
- print ("Usage:")
- print ("{} [options] [--usage]".format(argv[0]))
- print ("--help")
- print ("\tPrints this help screen")
- print ("--default")
- print ("\tRuns this tool with default monitoring.".format(argv[0]))
- print ("\tServices monitored by default for {}:".format(osyst))
- print ("\t",", ".join(servicelist))
- print ("--list \"\"")
- print ("\tReplaces default services for a given list (comma-separated)")
- if osyst == "Windows":
- print ("\tEach element of the list will be treated as a regexp, but they must be over 2 characters.")
- print ("\tElements under 2 characters will be discarded.")
- print ("--usage")
- print ("\tAdds modules for CPU and Memory usage per service/process (optional, can take some time).\n")
-
-
-##### RUN ####
-main()
\ No newline at end of file
diff --git a/pandora_server/DEBIAN/control b/pandora_server/DEBIAN/control
index c05ca1876b..3f9a16fafa 100644
--- a/pandora_server/DEBIAN/control
+++ b/pandora_server/DEBIAN/control
@@ -1,5 +1,5 @@
package: pandorafms-server
-Version: 7.0NG.744-200413
+Version: 7.0NG.744-200414
Architecture: all
Priority: optional
Section: admin
diff --git a/pandora_server/DEBIAN/make_deb_package.sh b/pandora_server/DEBIAN/make_deb_package.sh
index 8632c7a578..cc120882c3 100644
--- a/pandora_server/DEBIAN/make_deb_package.sh
+++ b/pandora_server/DEBIAN/make_deb_package.sh
@@ -14,7 +14,7 @@
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
-pandora_version="7.0NG.744-200413"
+pandora_version="7.0NG.744-200414"
package_cpan=0
package_pandora=1
diff --git a/pandora_server/lib/PandoraFMS/Config.pm b/pandora_server/lib/PandoraFMS/Config.pm
index fd90a0d379..78d7a80081 100644
--- a/pandora_server/lib/PandoraFMS/Config.pm
+++ b/pandora_server/lib/PandoraFMS/Config.pm
@@ -45,7 +45,7 @@ our @EXPORT = qw(
# version: Defines actual version of Pandora Server for this module only
my $pandora_version = "7.0NG.744";
-my $pandora_build = "200413";
+my $pandora_build = "200414";
our $VERSION = $pandora_version." ".$pandora_build;
# Setup hash
diff --git a/pandora_server/lib/PandoraFMS/Core.pm b/pandora_server/lib/PandoraFMS/Core.pm
index b41aec461e..b395ec9574 100644
--- a/pandora_server/lib/PandoraFMS/Core.pm
+++ b/pandora_server/lib/PandoraFMS/Core.pm
@@ -270,7 +270,9 @@ our @EXPORT = qw(
pandora_delete_custom_graph
pandora_edit_custom_graph
notification_set_targets
- );
+ notification_get_users
+ notification_get_groups
+);
# Some global variables
our @DayNames = qw(sunday monday tuesday wednesday thursday friday saturday);
@@ -1646,6 +1648,17 @@ sub pandora_process_module ($$$$$$$$$;$) {
"' for agent " .
(defined ($agent) && $agent ne '' ? "'" . safe_output($agent->{'nombre'}) . "'" : 'ID ' . $module->{'id_agente'}) . ".",
10);
+
+ # Ensure default values.
+ $module->{'min_ff_event'} = 0 unless defined($module->{'min_ff_event'});
+ $module->{'ff_timeout'} = 0 unless defined($module->{'ff_timeout'});
+ $module->{'module_interval'} = 0 unless defined($module->{'module_interval'});
+
+ if (ref($agent) eq 'HASH') {
+ if (!defined($agent->{'interval'}) && defined($agent->{'interval'})) {
+ $agent->{'intervalo'} = $agent->{'interval'};
+ }
+ }
# Get agent information
if (! defined ($agent) || $agent eq '') {
@@ -3134,6 +3147,8 @@ sub pandora_create_module_from_network_component ($$$$) {
pandora_create_module_tags ($pa_config, $dbh, $module_id, $component_tags);
logger($pa_config, 'Creating module ' . safe_output ($component->{'nombre'}) . " (ID $module_id) for agent $addr from network component.", 10);
+
+ return $module_id;
}
##########################################################################
@@ -3141,7 +3156,7 @@ sub pandora_create_module_from_network_component ($$$$) {
##########################################################################
sub pandora_create_module_from_hash ($$$) {
my ($pa_config, $parameters, $dbh) = @_;
-
+
logger($pa_config,
"Creating module '$parameters->{'nombre'}' for agent ID $parameters->{'id_agente'}.", 10);
@@ -3172,8 +3187,12 @@ sub pandora_create_module_from_hash ($$$) {
}
# Encrypt SNMP v3 passwords.
- if ($parameters->{'id_tipo_modulo'} >= 15 && $parameters->{'id_tipo_modulo'} <= 18 &&
- $parameters->{'tcp_send'} eq '3') {
+ if (defined($parameters->{'tcp_send'})
+ && $parameters->{'tcp_send'} eq '3'
+ && defined($parameters->{'id_tipo_modulo'})
+ && $parameters->{'id_tipo_modulo'} >= 15
+ && $parameters->{'id_tipo_modulo'} <= 18
+ ) {
$parameters->{'custom_string_2'} = pandora_input_password($pa_config, $parameters->{'custom_string_2'});
}
@@ -3181,7 +3200,11 @@ sub pandora_create_module_from_hash ($$$) {
'tagente_modulo', $parameters);
my $status = 4;
- if (defined ($parameters->{'id_tipo_modulo'}) && ($parameters->{'id_tipo_modulo'} == 21 || $parameters->{'id_tipo_modulo'} == 22 || $parameters->{'id_tipo_modulo'} == 23)) {
+ if (defined ($parameters->{'id_tipo_modulo'})
+ && ($parameters->{'id_tipo_modulo'} == 21
+ || $parameters->{'id_tipo_modulo'} == 22
+ || $parameters->{'id_tipo_modulo'} == 23)
+ ) {
$status = 0;
}
@@ -3333,7 +3356,7 @@ sub pandora_create_agent ($$$$$$$$$$;$$$$$$$$$$) {
$agent_mode = 1 unless defined($agent_mode);
$alias = $agent_name unless defined($alias);
- $description = "Created by $server_name" unless ($description ne '');
+ $description = "Created by $server_name" unless (defined($description) && $description ne '');
my ($columns, $values) = db_insert_get_values ({ 'nombre' => safe_input($agent_name),
'direccion' => $address,
'comentarios' => $description,
@@ -6295,6 +6318,63 @@ sub notification_set_targets {
return 1;
}
+##########################################################################
+
+=head2 C<< notification_get_users (I<$dbh>, I<$source>) >>
+Get targets for given sources
+=cut
+
+##########################################################################
+sub notification_get_users {
+ my ($dbh, $source) = @_;
+
+ my @results = get_db_rows(
+ $dbh,
+ 'SELECT id_user
+ FROM tnotification_source_user nsu
+ INNER JOIN tnotification_source ns ON nsu.id_source=ns.id
+ WHERE ns.description = ?
+ ',
+ safe_input($source)
+ );
+
+ @results = map {
+ if(ref($_) eq 'HASH') { $_->{'id_user'} }
+ else {}
+ } @results;
+
+ return @results;
+}
+
+##########################################################################
+
+=head2 C<< notification_get_groups (I<$dbh>, I<$source>) >>
+Get targets for given sources
+=cut
+
+##########################################################################
+sub notification_get_groups {
+ my ($dbh, $source) = @_;
+
+ my @results = get_db_rows(
+ $dbh,
+ 'SELECT id_group
+ FROM tnotification_source_group nsg
+ INNER JOIN tnotification_source ns ON nsg.id_source=ns.id
+ WHERE ns.description = ?
+ ',
+ safe_input($source)
+ );
+
+ @results = map {
+ if(ref($_) eq 'HASH') { $_->{'id_group'} }
+ else {}
+ } @results;
+
+ return @results;
+}
+
+
# End of function declaration
# End of defined Code
diff --git a/pandora_server/lib/PandoraFMS/DB.pm b/pandora_server/lib/PandoraFMS/DB.pm
index 63c756e5ae..e5c63615e0 100644
--- a/pandora_server/lib/PandoraFMS/DB.pm
+++ b/pandora_server/lib/PandoraFMS/DB.pm
@@ -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;
@@ -80,6 +81,8 @@ our @EXPORT = qw(
get_module_id
get_module_name
get_nc_profile_name
+ get_pen_templates
+ get_nc_profile_advanced
get_os_id
get_os_name
get_plugin_id
@@ -656,6 +659,48 @@ sub get_nc_profile_name ($$) {
return get_db_value ($dbh, "SELECT * FROM tnetwork_profile WHERE id_np = ?", $nc_id);
}
+##########################################################################
+## Return all network component's profile ids matching given PEN.
+##########################################################################
+sub get_pen_templates($$) {
+ my ($dbh, $pen) = @_;
+
+ my @results = get_db_rows(
+ $dbh,
+ 'SELECT t.`id_np`
+ FROM `tnetwork_profile` t
+ INNER JOIN `tnetwork_profile_pen` pp ON pp.`id_np` = t.`id_np`
+ INNER JOIN `tpen` p ON pp.pen = p.pen
+ WHERE p.`pen` = ?',
+ $pen
+ );
+
+ @results = map {
+ if (ref($_) eq 'HASH') { $_->{'id_np'} }
+ else {}
+ } @results;
+
+
+ return @results;
+}
+
+##########################################################################
+## Return a network component's profile data and pen list, given its ID.
+##########################################################################
+sub get_nc_profile_advanced($$) {
+ my ($dbh, $id_nc) = @_;
+ return get_db_single_row(
+ $dbh,
+ 'SELECT t.*,GROUP_CONCAT(p.pen) AS "pen"
+ FROM `tnetwork_profile` t
+ LEFT JOIN `tnetwork_profile_pen` pp ON t.id_np = pp.id_np
+ LEFT JOIN `tpen` p ON pp.pen = p.pen
+ WHERE t.`id_np` = ?
+ GROUP BY t.`id_np`',
+ $id_nc
+ );
+}
+
##########################################################################
## Return user profile ID given the user id, group id and profile id.
##########################################################################
@@ -894,7 +939,7 @@ sub db_insert ($$$;@) {
$insert_id = $dbh->{'mysql_insertid'};
}
else {
- die($exception);
+ croak (join(', ', @_));
}
}
@@ -917,7 +962,7 @@ sub db_update ($$;@) {
$rows = $dbh->do($query, undef, @values);
}
else {
- die($exception);
+ croak (join(', ', @_));
}
}
@@ -1163,7 +1208,7 @@ sub db_do ($$;@) {
$dbh->do($query, undef, @values);
}
else {
- die($exception);
+ croak (join(', ', @_));
}
}
}
diff --git a/pandora_server/lib/PandoraFMS/DiscoveryServer.pm b/pandora_server/lib/PandoraFMS/DiscoveryServer.pm
index 87b1df711e..903a9014c3 100644
--- a/pandora_server/lib/PandoraFMS/DiscoveryServer.pm
+++ b/pandora_server/lib/PandoraFMS/DiscoveryServer.pm
@@ -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;
@@ -40,9 +40,6 @@ use PandoraFMS::ProducerConsumerServer;
use PandoraFMS::GIS;
use PandoraFMS::Recon::Base;
-# Patched Nmap::Parser. See http://search.cpan.org/dist/Nmap-Parser/.
-use PandoraFMS::NmapParser;
-
# Inherits from PandoraFMS::ProducerConsumerServer
our @ISA = qw(PandoraFMS::ProducerConsumerServer);
@@ -54,408 +51,862 @@ my $TaskSem :shared;
# IDs from tconfig_os.
use constant {
- OS_OTHER => 10,
- OS_ROUTER => 17,
- OS_SWITCH => 18,
- STEP_SCANNING => 1,
- STEP_AFT => 2,
- STEP_TRACEROUTE => 3,
- STEP_GATEWAY => 4,
- STEP_STATISTICS => 1,
- STEP_APP_SCAN => 2,
- STEP_CUSTOM_QUERIES => 3,
- DISCOVERY_HOSTDEVICES => 0,
- DISCOVERY_HOSTDEVICES_CUSTOM => 1,
- DISCOVERY_CLOUD_AWS => 2,
- DISCOVERY_APP_VMWARE => 3,
- DISCOVERY_APP_MYSQL => 4,
- DISCOVERY_APP_ORACLE => 5,
- DISCOVERY_CLOUD_AWS_EC2 => 6,
- DISCOVERY_CLOUD_AWS_RDS => 7,
- DISCOVERY_CLOUD_AZURE_COMPUTE => 8,
- DISCOVERY_DEPLOY_AGENTS => 9,
- DISCOVERY_APP_SAP => 10,
+ OS_OTHER => 10,
+ OS_ROUTER => 17,
+ OS_SWITCH => 18,
+ STEP_SCANNING => 1,
+ STEP_AFT => 2,
+ STEP_TRACEROUTE => 3,
+ STEP_GATEWAY => 4,
+ STEP_MONITORING => 5,
+ STEP_PROCESSING => 6,
+ STEP_STATISTICS => 1,
+ STEP_APP_SCAN => 2,
+ STEP_CUSTOM_QUERIES => 3,
+ DISCOVERY_HOSTDEVICES => 0,
+ DISCOVERY_HOSTDEVICES_CUSTOM => 1,
+ DISCOVERY_CLOUD_AWS => 2,
+ DISCOVERY_APP_VMWARE => 3,
+ DISCOVERY_APP_MYSQL => 4,
+ DISCOVERY_APP_ORACLE => 5,
+ DISCOVERY_CLOUD_AWS_EC2 => 6,
+ DISCOVERY_CLOUD_AWS_RDS => 7,
+ DISCOVERY_CLOUD_AZURE_COMPUTE => 8,
+ DISCOVERY_DEPLOY_AGENTS => 9,
+ DISCOVERY_APP_SAP => 10,
+ DISCOVERY_REVIEW => 0,
+ DISCOVERY_STANDARD => 1,
+ DISCOVERY_RESULTS => 2,
};
-########################################################################################
+################################################################################
# Discovery Server class constructor.
-########################################################################################
+################################################################################
sub new ($$$$$$) {
- my ($class, $config, $dbh) = @_;
-
- return undef unless (defined($config->{'reconserver'}) && $config->{'reconserver'} == 1)
- || (defined($config->{'discoveryserver'}) && $config->{'discoveryserver'} == 1);
-
- if (! -e $config->{'nmap'}) {
- logger ($config, ' [E] ' . $config->{'nmap'} . " needed by " . $config->{'rb_product_name'} . " Discovery Server not found.", 1);
- print_message ($config, ' [E] ' . $config->{'nmap'} . " needed by " . $config->{'rb_product_name'} . " Discovery Server not found.", 1);
- return undef;
- }
+ my ($class, $config, $dbh) = @_;
+
+ return undef unless (defined($config->{'reconserver'}) && $config->{'reconserver'} == 1)
+ || (defined($config->{'discoveryserver'}) && $config->{'discoveryserver'} == 1);
+
+ if (! -e $config->{'nmap'}) {
+ logger ($config, ' [E] ' . $config->{'nmap'} . " needed by " . $config->{'rb_product_name'} . " Discovery Server not found.", 1);
+ print_message ($config, ' [E] ' . $config->{'nmap'} . " needed by " . $config->{'rb_product_name'} . " Discovery Server not found.", 1);
+ return undef;
+ }
- # Initialize semaphores and queues
- @TaskQueue = ();
- %PendingTasks = ();
- $Sem = Thread::Semaphore->new;
- $TaskSem = Thread::Semaphore->new (0);
-
- # Restart automatic recon tasks.
- db_do ($dbh, 'UPDATE trecon_task SET utimestamp = 0 WHERE id_recon_server = ? AND status <> -1 AND interval_sweep > 0',
- get_server_id ($dbh, $config->{'servername'}, DISCOVERYSERVER));
+ # Initialize semaphores and queues
+ @TaskQueue = ();
+ %PendingTasks = ();
+ $Sem = Thread::Semaphore->new;
+ $TaskSem = Thread::Semaphore->new (0);
+
+ # Restart automatic recon tasks.
+ db_do ($dbh, 'UPDATE trecon_task SET utimestamp = 0 WHERE id_recon_server = ? AND status <> -1 AND interval_sweep > 0',
+ get_server_id ($dbh, $config->{'servername'}, DISCOVERYSERVER));
- # Reset (but do not restart) manual recon tasks.
- db_do ($dbh, 'UPDATE trecon_task SET status = -1 WHERE id_recon_server = ? AND status <> -1 AND interval_sweep = 0',
- get_server_id ($dbh, $config->{'servername'}, DISCOVERYSERVER));
+ # Reset (but do not restart) manual recon tasks.
+ db_do ($dbh, 'UPDATE trecon_task SET status = -1 WHERE id_recon_server = ? AND status <> -1 AND interval_sweep = 0',
+ get_server_id ($dbh, $config->{'servername'}, DISCOVERYSERVER));
- # Call the constructor of the parent class
- my $self = $class->SUPER::new($config, DISCOVERYSERVER, \&PandoraFMS::DiscoveryServer::data_producer, \&PandoraFMS::DiscoveryServer::data_consumer, $dbh);
-
- bless $self, $class;
- return $self;
+ # Call the constructor of the parent class
+ my $self = $class->SUPER::new($config, DISCOVERYSERVER, \&PandoraFMS::DiscoveryServer::data_producer, \&PandoraFMS::DiscoveryServer::data_consumer, $dbh);
+
+ bless $self, $class;
+ return $self;
}
-###############################################################################
+################################################################################
# Run.
-###############################################################################
+################################################################################
sub run ($) {
- my $self = shift;
- my $pa_config = $self->getConfig ();
- my $dbh = $self->getDBH();
-
- print_message ($pa_config, " [*] Starting " . $pa_config->{'rb_product_name'} . " Discovery Server.", 1);
- my $threads = $pa_config->{'recon_threads'};
+ my $self = shift;
+ my $pa_config = $self->getConfig ();
+ my $dbh = $self->getDBH();
+
+ print_message ($pa_config, " [*] Starting " . $pa_config->{'rb_product_name'} . " Discovery Server.", 1);
+ my $threads = $pa_config->{'recon_threads'};
- # Use hightest value
- if ($pa_config->{'discovery_threads'} > $pa_config->{'recon_threads'}) {
- $threads = $pa_config->{'discovery_threads'};
- }
- $self->setNumThreads($threads);
- $self->SUPER::run (\@TaskQueue, \%PendingTasks, $Sem, $TaskSem);
+ # Use hightest value
+ if ($pa_config->{'discovery_threads'} > $pa_config->{'recon_threads'}) {
+ $threads = $pa_config->{'discovery_threads'};
+ }
+ $self->setNumThreads($threads);
+ $self->SUPER::run (\@TaskQueue, \%PendingTasks, $Sem, $TaskSem);
}
-###############################################################################
+################################################################################
# Data producer.
-###############################################################################
+################################################################################
sub data_producer ($) {
- my $self = shift;
- my ($pa_config, $dbh) = ($self->getConfig (), $self->getDBH ());
-
- my @tasks;
-
- my $server_id = get_server_id ($dbh, $pa_config->{'servername'}, $self->getServerType ());
- return @tasks unless defined ($server_id);
-
- # Manual tasks have interval_sweep = 0
- # Manual tasks are "forced" like the other, setting the utimestamp to 1
- # By default, after create a tasks it takes the utimestamp to 0
- # Status -1 means "done".
- my @rows;
- if (pandora_is_master($pa_config) == 0) {
- @rows = get_db_rows ($dbh, 'SELECT * FROM trecon_task
- WHERE id_recon_server = ?
- AND disabled = 0
- AND ((utimestamp = 0 AND interval_sweep != 0 OR status = 1)
- OR (status = -1 AND interval_sweep > 0 AND (utimestamp + interval_sweep) < UNIX_TIMESTAMP()))', $server_id);
- } else {
- @rows = get_db_rows ($dbh, 'SELECT * FROM trecon_task
- WHERE (id_recon_server = ? OR id_recon_server = ANY(SELECT id_server FROM tserver WHERE status = 0 AND server_type = ?))
- AND disabled = 0
- AND ((utimestamp = 0 AND interval_sweep != 0 OR status = 1)
- OR (status = -1 AND interval_sweep > 0 AND (utimestamp + interval_sweep) < UNIX_TIMESTAMP()))', $server_id, DISCOVERYSERVER);
- }
+ my $self = shift;
+ my ($pa_config, $dbh) = ($self->getConfig (), $self->getDBH ());
+
+ my @tasks;
+
+ my $server_id = get_server_id ($dbh, $pa_config->{'servername'}, $self->getServerType ());
+ return @tasks unless defined ($server_id);
+
+ # Manual tasks have interval_sweep = 0
+ # Manual tasks are "forced" like the other, setting the utimestamp to 1
+ # By default, after create a tasks it takes the utimestamp to 0
+ # Status -1 means "done".
+ my @rows;
+ if (pandora_is_master($pa_config) == 0) {
+ @rows = get_db_rows ($dbh, 'SELECT * FROM trecon_task
+ WHERE id_recon_server = ?
+ AND disabled = 0
+ AND ((utimestamp = 0 AND interval_sweep != 0 OR status = 1)
+ OR (status = -1 AND interval_sweep > 0 AND (utimestamp + interval_sweep) < UNIX_TIMESTAMP()))', $server_id);
+ } else {
+ @rows = get_db_rows ($dbh, 'SELECT * FROM trecon_task
+ WHERE (id_recon_server = ? OR id_recon_server = ANY(SELECT id_server FROM tserver WHERE status = 0 AND server_type = ?))
+ AND disabled = 0
+ AND ((utimestamp = 0 AND interval_sweep != 0 OR status = 1)
+ OR (status = -1 AND interval_sweep > 0 AND (utimestamp + interval_sweep) < UNIX_TIMESTAMP()))', $server_id, DISCOVERYSERVER);
+ }
- foreach my $row (@rows) {
-
- # Update task status
- update_recon_task ($dbh, $row->{'id_rt'}, 1);
-
- push (@tasks, $row->{'id_rt'});
- }
+ foreach my $row (@rows) {
- return @tasks;
+ # Update task status
+ update_recon_task ($dbh, $row->{'id_rt'}, 1);
+
+ push (@tasks, $row->{'id_rt'});
+ }
+
+ return @tasks;
}
-###############################################################################
+################################################################################
# Data consumer.
-###############################################################################
+################################################################################
sub data_consumer ($$) {
- my ($self, $task_id) = @_;
- my ($pa_config, $dbh) = ($self->getConfig (), $self->getDBH ());
+ my ($self, $task_id) = @_;
+ my ($pa_config, $dbh) = ($self->getConfig (), $self->getDBH ());
- # Get server id.
- my $server_id = get_server_id($dbh, $pa_config->{'servername'}, $self->getServerType());
+ # Get server id.
+ my $server_id = get_server_id($dbh, $pa_config->{'servername'}, $self->getServerType());
- # Get recon task data
- my $task = get_db_single_row ($dbh, 'SELECT * FROM trecon_task WHERE id_rt = ?', $task_id);
- return -1 unless defined ($task);
+ # Get recon task data
+ my $task = get_db_single_row ($dbh, 'SELECT * FROM trecon_task WHERE id_rt = ?', $task_id);
+ return -1 unless defined ($task);
- # Is it a recon script?
- if (defined ($task->{'id_recon_script'}) && ($task->{'id_recon_script'} != 0)) {
- exec_recon_script ($pa_config, $dbh, $task);
- return;
- } else {
- logger($pa_config, 'Starting recon task for net ' . $task->{'subnet'} . '.', 10);
+ # Is it a recon script?
+ if (defined ($task->{'id_recon_script'}) && ($task->{'id_recon_script'} != 0)) {
+ exec_recon_script ($pa_config, $dbh, $task);
+ return;
+ } else {
+ logger($pa_config, 'Starting recon task for net ' . $task->{'subnet'} . '.', 10);
+ }
+
+ eval {
+ my @subnets = split(/,/, safe_output($task->{'subnet'}));
+ my @communities = split(/,/, safe_output($task->{'snmp_community'}));
+ my @auth_strings = ();
+ if(defined($task->{'auth_strings'})) {
+ @auth_strings = split(/,/, safe_output($task->{'auth_strings'}));
}
- eval {
- my @subnets = split(/,/, safe_output($task->{'subnet'}));
- my @communities = split(/,/, safe_output($task->{'snmp_community'}));
- my @auth_strings = ();
- if(defined($task->{'auth_strings'})) {
- @auth_strings = split(/,/, safe_output($task->{'auth_strings'}));
- }
+ my $main_event = pandora_event($pa_config,
+ "[Discovery] Execution summary",
+ $task->{'id_group'}, 0, 0, 0, 0, 'system', 0, $dbh
+ );
- my $main_event = pandora_event($pa_config, "[Discovery] Execution summary",$task->{'id_group'}, 0, 0, 0, 0, 'system', 0, $dbh);
-
- my %cnf_extra;
-
- my $r = enterprise_hook('discovery_generate_extra_cnf',[$pa_config, $dbh, $task, \%cnf_extra]);
- if (defined($r) && $r eq 'ERR') {
- # Could not generate extra cnf, skip this task.
- return;
- }
-
-
- if ($task->{'type'} == DISCOVERY_APP_SAP) {
- # SAP TASK, retrieve license.
- $task->{'sap_license'} = pandora_get_config_value(
- $dbh,
- 'sap_license'
- );
-
- # Retrieve credentials for task (optional).
- if (defined($task->{'auth_strings'})
- && $task->{'auth_strings'} ne ''
- ) {
- my $key = credential_store_get_key(
- $pa_config,
- $dbh,
- $task->{'auth_strings'}
- );
-
- # Inside an eval, here it shouln't fail unless bad configured.
- $task->{'username'} = $key->{'username'};
- $task->{'password'} = $key->{'password'};
-
- }
- }
-
- my $recon = new PandoraFMS::Recon::Base(
- communities => \@communities,
- dbh => $dbh,
- group_id => $task->{'id_group'},
- id_os => $task->{'id_os'},
- id_network_profile => $task->{'id_network_profile'},
- os_detection => $task->{'os_detect'},
- parent_detection => $task->{'parent_detection'},
- parent_recursion => $task->{'parent_recursion'},
- pa_config => $pa_config,
- recon_ports => $task->{'recon_ports'},
- resolve_names => $task->{'resolve_names'},
- snmp_auth_user => $task->{'snmp_auth_user'},
- snmp_auth_pass => $task->{'snmp_auth_pass'},
- snmp_auth_method => $task->{'snmp_auth_method'},
- snmp_checks => $task->{'snmp_checks'},
- snmp_enabled => $task->{'snmp_enabled'},
- snmp_privacy_method => $task->{'snmp_privacy_method'},
- snmp_privacy_pass => $task->{'snmp_privacy_pass'},
- snmp_security_level => $task->{'snmp_security_level'},
- snmp_timeout => $task->{'snmp_timeout'},
- snmp_version => $task->{'snmp_version'},
- subnets => \@subnets,
- task_id => $task->{'id_rt'},
- vlan_cache_enabled => $task->{'vlan_enabled'},
- wmi_enabled => $task->{'wmi_enabled'},
- auth_strings_array => \@auth_strings,
- autoconfiguration_enabled => $task->{'autoconfiguration_enabled'},
- main_event_id => $main_event,
- server_id => $server_id,
- %{$pa_config},
- task_data => $task,
- public_url => PandoraFMS::Config::pandora_get_tconfig_token($dbh, 'public_url', ''),
- %cnf_extra
- );
-
- $recon->scan();
-
- # Clean tmp file.
- if (defined($cnf_extra{'creds_file'})
- && -f $cnf_extra{'creds_file'}) {
- unlink($cnf_extra{'creds_file'});
- }
-
-
- # Clean one shot tasks
- if ($task->{'type'} eq DISCOVERY_DEPLOY_AGENTS) {
- db_delete_limit($dbh, ' trecon_task ', ' id_rt = ? ', 1, $task->{'id_rt'});
- }
- };
- if ($@) {
- logger(
- $pa_config,
- 'Cannot execute Discovery task: ' . safe_output($task->{'name'}) . $@,
- 10
- );
- update_recon_task ($dbh, $task_id, -1);
- return;
+ my %cnf_extra;
+
+ my $r = enterprise_hook(
+ 'discovery_generate_extra_cnf',
+ [
+ $pa_config,
+ $dbh, $task,
+ \%cnf_extra
+ ]
+ );
+ if (defined($r) && $r eq 'ERR') {
+ # Could not generate extra cnf, skip this task.
+ return;
}
+
+ if ($task->{'type'} == DISCOVERY_APP_SAP) {
+ # SAP TASK, retrieve license.
+ $task->{'sap_license'} = pandora_get_config_value(
+ $dbh,
+ 'sap_license'
+ );
+
+ # Retrieve credentials for task (optional).
+ if (defined($task->{'auth_strings'})
+ && $task->{'auth_strings'} ne ''
+ ) {
+ my $key = credential_store_get_key(
+ $pa_config,
+ $dbh,
+ $task->{'auth_strings'}
+ );
+
+ # Inside an eval, here it shouln't fail unless bad configured.
+ $task->{'username'} = $key->{'username'};
+ $task->{'password'} = $key->{'password'};
+
+ }
+ }
+
+ my $recon = new PandoraFMS::Recon::Base(
+ communities => \@communities,
+ dbh => $dbh,
+ group_id => $task->{'id_group'},
+ id_os => $task->{'id_os'},
+ id_network_profile => $task->{'id_network_profile'},
+ os_detection => $task->{'os_detect'},
+ parent_detection => $task->{'parent_detection'},
+ parent_recursion => $task->{'parent_recursion'},
+ pa_config => $pa_config,
+ recon_ports => $task->{'recon_ports'},
+ resolve_names => $task->{'resolve_names'},
+ snmp_auth_user => $task->{'snmp_auth_user'},
+ snmp_auth_pass => $task->{'snmp_auth_pass'},
+ snmp_auth_method => $task->{'snmp_auth_method'},
+ snmp_checks => $task->{'snmp_checks'},
+ snmp_enabled => $task->{'snmp_enabled'},
+ snmp_privacy_method => $task->{'snmp_privacy_method'},
+ snmp_privacy_pass => $task->{'snmp_privacy_pass'},
+ snmp_security_level => $task->{'snmp_security_level'},
+ snmp_timeout => $task->{'snmp_timeout'},
+ snmp_version => $task->{'snmp_version'},
+ subnets => \@subnets,
+ task_id => $task->{'id_rt'},
+ vlan_cache_enabled => $task->{'vlan_enabled'},
+ wmi_enabled => $task->{'wmi_enabled'},
+ auth_strings_array => \@auth_strings,
+ autoconfiguration_enabled => $task->{'autoconfiguration_enabled'},
+ main_event_id => $main_event,
+ server_id => $server_id,
+ %{$pa_config},
+ task_data => $task,
+ public_url => PandoraFMS::Config::pandora_get_tconfig_token($dbh, 'public_url', ''),
+ %cnf_extra
+ );
+
+ $recon->scan();
+
+ # Clean tmp file.
+ if (defined($cnf_extra{'creds_file'})
+ && -f $cnf_extra{'creds_file'}) {
+ unlink($cnf_extra{'creds_file'});
+ }
+
+
+ # Clean one shot tasks
+ if ($task->{'type'} eq DISCOVERY_DEPLOY_AGENTS) {
+ db_delete_limit($dbh, ' trecon_task ', ' id_rt = ? ', 1, $task->{'id_rt'});
+ }
+ };
+ if ($@) {
+ logger(
+ $pa_config,
+ 'Cannot execute Discovery task: ' . safe_output($task->{'name'}) . $@,
+ 10
+ );
+ update_recon_task ($dbh, $task_id, -1);
+ return;
+ }
}
-##########################################################################
+################################################################################
# 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);
+ 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) = @_;
-
- # Get recon plugin data
- my $script = get_db_single_row ($dbh, 'SELECT * FROM trecon_script WHERE id_recon_script = ?', $task->{'id_recon_script'});
- return -1 unless defined ($script);
-
- logger($pa_config, 'Executing recon script ' . safe_output($script->{'name'}), 10);
-
- my $command = safe_output($script->{'script'});
-
- my $macros = safe_output($task->{'macros'});
+ my ($pa_config, $dbh, $task) = @_;
+
+ # Get recon plugin data
+ my $script = get_db_single_row ($dbh, 'SELECT * FROM trecon_script WHERE id_recon_script = ?', $task->{'id_recon_script'});
+ return -1 unless defined ($script);
+
+ logger($pa_config, 'Executing recon script ' . safe_output($script->{'name'}), 10);
+
+ my $command = safe_output($script->{'script'});
+
+ my $macros = safe_output($task->{'macros'});
- # \r and \n should be escaped for decode_json().
- $macros =~ s/\n/\\n/g;
- $macros =~ s/\r/\\r/g;
- my $decoded_macros;
-
- if ($macros) {
- eval {
- $decoded_macros = decode_json(encode_utf8($macros));
- };
- }
-
- my $macros_parameters = '';
-
- # Add module macros as parameter
- if(ref($decoded_macros) eq "HASH") {
- # Convert the hash to a sorted array
- my @sorted_macros;
- while (my ($i, $m) = each (%{$decoded_macros})) {
- $sorted_macros[$i] = $m;
- }
-
- # Remove the 0 position
- shift @sorted_macros;
-
- foreach my $m (@sorted_macros) {
- $macros_parameters = $macros_parameters . ' "' . $m->{"value"} . '"';
- }
+ # \r and \n should be escaped for decode_json().
+ $macros =~ s/\n/\\n/g;
+ $macros =~ s/\r/\\r/g;
+ my $decoded_macros;
+
+ if ($macros) {
+ eval {
+ $decoded_macros = decode_json(encode_utf8($macros));
+ };
+ }
+
+ my $macros_parameters = '';
+
+ # Add module macros as parameter
+ if(ref($decoded_macros) eq "HASH") {
+ # Convert the hash to a sorted array
+ my @sorted_macros;
+ while (my ($i, $m) = each (%{$decoded_macros})) {
+ $sorted_macros[$i] = $m;
}
- my $ent_script = 0;
- my $args = enterprise_hook('discovery_custom_recon_scripts',[$pa_config, $dbh, $task, $script]);
- if (!$args) {
- $args = "$task->{'id_rt'} $task->{'id_group'} $task->{'create_incident'} $macros_parameters";
- } else {
- $ent_script = 1;
- }
-
- if (-x $command) {
- my $exec_output = `$command $args`;
- logger($pa_config, "Execution output: \n". $exec_output, 10);
- } else {
- logger($pa_config, "Cannot execute recon task command $command.", 10);
- }
-
- # Only update the timestamp in case something went wrong. The script should set the status.
- db_do ($dbh, 'UPDATE trecon_task SET utimestamp = ? WHERE id_rt = ?', time (), $task->{'id_rt'});
+ # Remove the 0 position
+ shift @sorted_macros;
- if ($ent_script == 1) {
- enterprise_hook('discovery_clean_custom_recon',[$pa_config, $dbh, $task, $script]);
+ foreach my $m (@sorted_macros) {
+ $macros_parameters = $macros_parameters . ' "' . $m->{"value"} . '"';
}
-
- logger($pa_config, 'Done executing recon script ' . safe_output($script->{'name'}), 10);
- return 0;
+ }
+
+ my $ent_script = 0;
+ my $args = enterprise_hook(
+ 'discovery_custom_recon_scripts',
+ [$pa_config, $dbh, $task, $script]
+ );
+ if (!$args) {
+ $args = '"'.$task->{'id_rt'}.'" ';
+ $args .= '"'.$task->{'id_group'}.'" ';
+ $args .= $macros_parameters;
+ } else {
+ $ent_script = 1;
+ }
+
+ if (-x $command) {
+ my $exec_output = `$command $args`;
+ logger($pa_config, "Execution output: \n". $exec_output, 10);
+ } else {
+ logger($pa_config, "Cannot execute recon task command $command.", 10);
+ }
+
+ # Only update the timestamp in case something went wrong. The script should set the status.
+ db_do ($dbh, 'UPDATE trecon_task SET utimestamp = ? WHERE id_rt = ?', time (), $task->{'id_rt'});
+
+ if ($ent_script == 1) {
+ enterprise_hook('discovery_clean_custom_recon',[$pa_config, $dbh, $task, $script]);
+ }
+
+ logger($pa_config, 'Done executing recon script ' . safe_output($script->{'name'}), 10);
+ return 0;
}
-##########################################################################
+################################################################################
# Guess the OS using xprobe2 or nmap.
-##########################################################################
+################################################################################
sub PandoraFMS::Recon::Base::guess_os($$) {
- my ($self, $device) = @_;
+ my ($self, $device) = @_;
- $DEVNULL = '/dev/null' if (!defined($DEVNULL));
- $DEVNULL = '/NUL' if ($^O =~ /win/i && !defined($DEVNULL));
+ $DEVNULL = '/dev/null' if (!defined($DEVNULL));
+ $DEVNULL = '/NUL' if ($^O =~ /win/i && !defined($DEVNULL));
- # OS detection disabled. Use the device type.
- if ($self->{'os_detection'} == 0) {
- my $device_type = $self->get_device_type($device);
- return OS_OTHER unless defined($device_type);
-
- return OS_ROUTER if ($device_type eq 'router');
- return OS_SWITCH if ($device_type eq 'switch');
- return OS_OTHER;
- }
-
- # Use xprobe2 if available
- if (-x $self->{'pa_config'}->{'xprobe2'}) {
- my $return = `"$self->{pa_config}->{xprobe2}" $device 2>$DEVNULL`;
- if ($? == 0) {
- if($return =~ /Running OS:(.*)/) {
- return pandora_get_os($self->{'dbh'}, $1);
- }
- }
- }
-
- # Use nmap by default
- if (-x $self->{'pa_config'}->{'nmap'}) {
- my $return = `"$self->{pa_config}->{nmap}" -F -O $device 2>$DEVNULL`;
- return OS_OTHER if ($? != 0);
-
- if ($return =~ /Aggressive OS guesses:\s*(.*)/) {
- return pandora_get_os($self->{'dbh'}, $1);
- }
- }
+ # OS detection disabled. Use the device type.
+ if ($self->{'os_detection'} == 0) {
+ my $device_type = $self->get_device_type($device);
+ return OS_OTHER unless defined($device_type);
+ return OS_ROUTER if ($device_type eq 'router');
+ return OS_SWITCH if ($device_type eq 'switch');
return OS_OTHER;
+ }
+
+ # Use xprobe2 if available
+ if (-x $self->{'pa_config'}->{'xprobe2'}) {
+ my $return = `"$self->{pa_config}->{xprobe2}" $device 2>$DEVNULL`;
+ if ($? == 0) {
+ if($return =~ /Running OS:(.*)/) {
+ return pandora_get_os($self->{'dbh'}, $1);
+ }
+ }
+ }
+
+ # Use nmap by default
+ if (-x $self->{'pa_config'}->{'nmap'}) {
+ my $return = `"$self->{pa_config}->{nmap}" -F -O $device 2>$DEVNULL`;
+ return OS_OTHER if ($? != 0);
+
+ if ($return =~ /Aggressive OS guesses:\s*(.*)/) {
+ return pandora_get_os($self->{'dbh'}, $1);
+ }
+ }
+
+ return OS_OTHER;
}
-##############################################################################
+################################################################################
# Returns the number of open ports from the given list.
-##############################################################################
+################################################################################
sub PandoraFMS::Recon::Base::tcp_scan ($$) {
- my ($self, $host) = @_;
+ my ($self, $host) = @_;
- my $r = `"$self->{pa_config}->{nmap}" -p$self->{recon_ports} $host`;
+ my $r = `"$self->{pa_config}->{nmap}" -p$self->{recon_ports} $host`;
- # Same as ""| grep open | wc -l" but multi-OS;
- my $open_ports = () = $r =~ /open/gm;
+ # Same as ""| grep open | wc -l" but multi-OS;
+ my $open_ports = () = $r =~ /open/gm;
- return $open_ports;
+ 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);
-
- # 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) {
+################################################################################
+# Verifies if a module will be normal.
+################################################################################
+sub PandoraFMS::Recon::Base::test_module($$) {
+ my ($self, $addr, $module) = @_;
- # Get network component data
- my $component = get_db_single_row($self->{'dbh'}, 'SELECT * FROM tnetwork_component WHERE id_nc = ?', $np_component->{'id_nc'});
- if (!defined ($component)) {
- $self->call('message', "Network component ID " . $np_component->{'id_nc'} . " not found.", 5);
- next;
+ # Default values.
+ my $test = {
+ %{$module},
+ 'ip_target' => $addr,
+ };
+
+ if (is_enabled($module->{'__module_component'})) {
+ # Component. Translate some fields.
+ $test->{'id_tipo_modulo'} = $module->{'type'};
+ } else {
+ # Module.
+ $module->{'type'} = $module->{'module_type'} if is_empty($module->{'type'});
+
+ if (defined($module->{'type'})) {
+ if(!defined($self->{'module_types'}{$module->{'type'}})) {
+ $self->{'module_types'}{$module->{'type'}} = get_module_id(
+ $self->{'dbh'},$module->{'type'}
+ );
+ }
+
+ $test->{'id_tipo_modulo'} = $self->{'module_types'}{$module->{'type'}};
+ }
+ }
+
+ my $value;
+
+ # 1. Try to retrieve value.
+ if ($test->{'id_tipo_modulo'} >= 15 && $test->{'id_tipo_modulo'} <= 18) {
+ # SNMP
+ $value = $self->call(
+ 'snmp_get_value',
+ $test->{'ip_target'},
+ $test->{'snmp_oid'}
+ );
+ } elsif ($test->{'id_tipo_modulo'} == 6) {
+ # ICMP - alive - already tested.
+ $value = 1;
+
+ } elsif ($test->{'id_tipo_modulo'} == 7) {
+ # ICMP - latency
+ $value = pandora_ping_latency(
+ $self->{'pa_config'},
+ $test->{'ip_target'},
+ $test->{'max_timeout'},
+ $test->{'max_retries'},
+ );
+
+ } elsif (($test->{'id_tipo_modulo'} >= 1 && $test->{'id_tipo_modulo'} <= 5)
+ || ($test->{'id_tipo_modulo'} >= 21 && $test->{'id_tipo_modulo'} <= 23)
+ ) {
+ # Generic, plugins. (21-23 ASYNC)
+ if ($test->{'id_modulo'} == 6) {
+ # WMI commands.
+ $value = $self->call(
+ 'wmi_get_value',
+ $test->{'ip_target'},
+ # WMI query.
+ $test->{'snmp_oid'},
+ # Column
+ $test->{'tcp_port'}
+ );
+ } elsif(is_enabled($test->{'id_plugin'})) {
+ # XXX TODO: Test plugins. How to identify arguments? and values?
+ # Disabled until we can ensure result.
+ return 0;
+ }
+
+ } elsif ($test->{'id_tipo_modulo'} >= 34 && $test->{'id_tipo_modulo'} <= 37) {
+ # Remote command.
+ # XXX TODO: Test remote commands.
+ # Disabled until we can ensure result.
+ return 0;
+
+ } elsif ($test->{'id_tipo_modulo'} >= 8 && $test->{'id_tipo_modulo'} <= 11) {
+ # TCP
+ return 0 unless is_numeric($test->{'tcp_port'})
+ && $test->{'tcp_port'} > 0
+ && $test->{'tcp_port'} <= 65535;
+
+ my $result;
+
+ PandoraFMS::NetworkServer::pandora_query_tcp(
+ $self->{'pa_config'},
+ $test->{'tcp_port'},
+ $test->{'ip_target'},
+ \$result,
+ \$value,
+ $test->{'tcp_send'},
+ $test->{'tcp_rcv'},
+ $test->{'id_tipo_modulo'},
+ $test->{'max_timeout'},
+ $test->{'max_retries'},
+ '',
+ );
+
+ # Result 0 is OK, 1 failed
+ return 0 unless defined($result) && $result == 0;
+ return 0 unless defined($value);
+
+ }
+
+ # Invalid data (empty or not defined)
+ return 0 if is_empty($value);
+
+ # 2. Check if value matches type definition and fits thresholds.
+ if (is_in_array(
+ [1,2,4,5,6,7,8,9,11,15,16,18,21,22,25,30,31,32,34,35,37],
+ $test->{'id_tipo_modulo'}
+ )
+ ) {
+ # Numeric. Remove " symbols if any.
+ $value =~ s/\"//g;
+ return 0 unless is_numeric($value);
+
+ if (is_in_array([2,6,9,18,21,31,35], $test->{'id_tipo_modulo'})) {
+ # Boolean.
+ if (!is_enabled($test->{'critical_inverse'})) {
+ return 0 if $value == 0;
+ } else {
+ return 0 if $value != 0;
+ }
+ }
+
+ my $thresholds_defined = 0;
+
+ if ((!defined($test->{'min_critical'}) || $test->{'min_critical'} == 0)
+ && (!defined($test->{'max_critical'}) || $test->{'max_critical'} == 0)
+ ) {
+ # In Default 0,0 do not test.or not defined
+ $thresholds_defined = 0;
+ } else {
+ # min or max are diferent from 0
+ $thresholds_defined = 1;
+ }
+
+ if ($thresholds_defined > 0) {
+ # Check thresholds.
+ if (!is_enabled($test->{'critical_inverse'})) {
+ return 0 if $value >= $test->{'min_critical'} && $value <= $test->{'max_critical'};
+ } else {
+ return 0 if $value < $test->{'min_critical'} && $value > $test->{'max_critical'};
+ }
+ }
+
+ } else {
+ # String.
+ if (!is_enabled($test->{'critical_inverse'})) {
+ return 0 if !is_empty($test->{'str_critical'}) && $value =~ /$test->{'str_critical'}/;
+ } else {
+ return 0 if !is_empty($test->{'str_critical'}) && $value !~ /$test->{'str_critical'}/;
+ }
+
+ }
+
+ # Success.
+ return 1;
+
+}
+
+################################################################################
+# Create interface modules for the given agent (if needed).
+################################################################################
+sub PandoraFMS::Recon::Base::create_interface_modules($$) {
+ my ($self, $device) = @_;
+
+ # Add interfaces to the agent if it responds to SNMP.
+ return unless ($self->is_snmp_discovered($device));
+ my $community = $self->get_community($device);
+
+ my @output = $self->snmp_get_value_array($device, $PandoraFMS::Recon::Base::IFINDEX);
+ foreach my $if_index (@output) {
+ next unless ($if_index =~ /^[0-9]+$/);
+
+ # Check the status of the interface.
+ my $if_status = $self->snmp_get_value($device, "$PandoraFMS::Recon::Base::IFOPERSTATUS.$if_index");
+ next unless $if_status == 1;
+
+ # Fill the module description with the IP and MAC addresses.
+ my $mac = $self->get_if_mac($device, $if_index);
+ my $ip = $self->get_if_ip($device, $if_index);
+ my $if_desc = ($mac ne '' ? "MAC $mac " : '') . ($ip ne '' ? "IP $ip" : '');
+
+ # Get the name of the network interface.
+ my $if_name = $self->snmp_get_value($device, "$PandoraFMS::Recon::Base::IFNAME.$if_index");
+ $if_name = "if$if_index" unless defined ($if_name);
+ $if_name =~ s/"//g;
+ $if_name = clean_blank($if_name);
+
+ # Interface status module.
+ $self->call(
+ 'add_module',
+ $device,
+ {
+ 'id_tipo_modulo' => 18,
+ 'id_modulo' => 2,
+ 'name' => $if_name."_ifOperStatus",
+ 'descripcion' => safe_input(
+ $if_desc
+ ),
+ 'ip_target' => $device,
+ 'tcp_send' => $self->{'task_data'}{'snmp_version'},
+ 'custom_string_1' => $self->{'task_data'}{'snmp_privacy_method'},
+ 'custom_string_2' => $self->{'task_data'}{'snmp_privacy_pass'},
+ 'custom_string_3' => $self->{'task_data'}{'snmp_security_level'},
+ 'plugin_parameter' => $self->{'task_data'}{'snmp_auth_method'},
+ 'plugin_user' => $self->{'task_data'}{'snmp_auth_user'},
+ 'plugin_pass' => $self->{'task_data'}{'snmp_auth_pass'},
+ 'snmp_community' => $community,
+ 'snmp_oid' => "$PandoraFMS::Recon::Base::IFOPERSTATUS.$if_index"
+ }
+ );
+
+ # Incoming traffic module.
+ my $if_hc_in_octets = $self->snmp_get_value($device, "$PandoraFMS::Recon::Base::IFHCINOCTECTS.$if_index");
+ if (defined($if_hc_in_octets)) {
+ # Use HC counters.
+ # ifHCInOctets
+ $self->call(
+ 'add_module',
+ $device,
+ {
+ 'id_tipo_modulo' => 16,
+ 'id_modulo' => 2,
+ 'name' => $if_name."_ifHCInOctets",
+ 'descripcion' => safe_input(
+ 'The total number of octets received on the interface, including framing characters. This object is a 64-bit version of ifInOctets.'
+ ),
+ 'ip_target' => $device,
+ 'tcp_send' => $self->{'task_data'}{'snmp_version'},
+ 'custom_string_1' => $self->{'task_data'}{'snmp_privacy_method'},
+ 'custom_string_2' => $self->{'task_data'}{'snmp_privacy_pass'},
+ 'custom_string_3' => $self->{'task_data'}{'snmp_security_level'},
+ 'plugin_parameter' => $self->{'task_data'}{'snmp_auth_method'},
+ 'plugin_user' => $self->{'task_data'}{'snmp_auth_user'},
+ 'plugin_pass' => $self->{'task_data'}{'snmp_auth_pass'},
+ 'snmp_community' => $community,
+ 'snmp_oid' => "$PandoraFMS::Recon::Base::IFHCINOCTECTS.$if_index"
}
+ );
+ } else {
+ # Use 32b counters.
+ # ifInOctets
+ $self->call(
+ 'add_module',
+ $device,
+ {
+ 'id_tipo_modulo' => 16,
+ 'id_modulo' => 2,
+ 'name' => $if_name."_ifInOctets",
+ 'descripcion' => safe_input(
+ 'The total number of octets received on the interface, including framing characters.'
+ ),
+ 'ip_target' => $device,
+ 'tcp_send' => $self->{'task_data'}{'snmp_version'},
+ 'custom_string_1' => $self->{'task_data'}{'snmp_privacy_method'},
+ 'custom_string_2' => $self->{'task_data'}{'snmp_privacy_pass'},
+ 'custom_string_3' => $self->{'task_data'}{'snmp_security_level'},
+ 'plugin_parameter' => $self->{'task_data'}{'snmp_auth_method'},
+ 'plugin_user' => $self->{'task_data'}{'snmp_auth_user'},
+ 'plugin_pass' => $self->{'task_data'}{'snmp_auth_pass'},
+ 'snmp_community' => $community,
+ 'snmp_oid' => "$PandoraFMS::Recon::Base::IFINOCTECTS.$if_index"
+ }
+ );
+ }
- # Use snmp_community from network task instead the component snmp_community
+ # Outgoing traffic module.
+ my $if_hc_out_octets = $self->snmp_get_value($device, "$PandoraFMS::Recon::Base::IFHCOUTOCTECTS.$if_index");
+ if (defined($if_hc_out_octets)) {
+ # Use HC counters.
+ # ifHCOutOctets
+ $self->call(
+ 'add_module',
+ $device,
+ {
+ 'id_tipo_modulo' => 16,
+ 'id_modulo' => 2,
+ 'name' => $if_name."_ifHCOutOctets",
+ 'descripcion' => safe_input(
+ 'The total number of octets received on the interface, including framing characters. This object is a 64-bit version of ifOutOctets.'
+ ),
+ 'ip_target' => $device,
+ 'tcp_send' => $self->{'task_data'}{'snmp_version'},
+ 'custom_string_1' => $self->{'task_data'}{'snmp_privacy_method'},
+ 'custom_string_2' => $self->{'task_data'}{'snmp_privacy_pass'},
+ 'custom_string_3' => $self->{'task_data'}{'snmp_security_level'},
+ 'plugin_parameter' => $self->{'task_data'}{'snmp_auth_method'},
+ 'plugin_user' => $self->{'task_data'}{'snmp_auth_user'},
+ 'plugin_pass' => $self->{'task_data'}{'snmp_auth_pass'},
+ 'snmp_community' => $community,
+ 'snmp_oid' => "$PandoraFMS::Recon::Base::IFHCOUTOCTECTS.$if_index"
+ }
+ );
+ } else {
+ # Use 32b counters.
+ # ifOutOctets
+ $self->call(
+ 'add_module',
+ $device,
+ {
+ 'id_tipo_modulo' => 16,
+ 'id_modulo' => 2,
+ 'name' => $if_name."_ifOutOctets",
+ 'descripcion' => safe_input(
+ 'The total number of octets received on the interface, including framing characters.'
+ ),
+ 'ip_target' => $device,
+ 'tcp_send' => $self->{'task_data'}{'snmp_version'},
+ 'custom_string_1' => $self->{'task_data'}{'snmp_privacy_method'},
+ 'custom_string_2' => $self->{'task_data'}{'snmp_privacy_pass'},
+ 'custom_string_3' => $self->{'task_data'}{'snmp_security_level'},
+ 'plugin_parameter' => $self->{'task_data'}{'snmp_auth_method'},
+ 'plugin_user' => $self->{'task_data'}{'snmp_auth_user'},
+ 'plugin_pass' => $self->{'task_data'}{'snmp_auth_pass'},
+ 'snmp_community' => $community,
+ 'snmp_oid' => "$PandoraFMS::Recon::Base::IFOUTOCTECTS.$if_index"
+ }
+ );
+ }
+ }
+
+}
+
+################################################################################
+# Add wmi modules to the given host.
+################################################################################
+sub PandoraFMS::Recon::Base::create_wmi_modules {
+ my ($self, $target) = @_;
+
+ # Add modules to the agent if it responds to WMI.
+ return unless ($self->wmi_responds($target));
+
+ my $key = $self->wmi_credentials_key($target);
+ my $creds = $self->call('get_credentials', $key);
+
+ # Add modules.
+ # CPU.
+ my @cpus = $self->wmi_get_value_array($target, 'SELECT DeviceId FROM Win32_Processor', 0);
+ foreach my $cpu (@cpus) {
+ $self->add_module(
+ $target,
+ {
+ 'ip_target' => $target,
+ 'snmp_oid' => "SELECT LoadPercentage FROM Win32_Processor WHERE DeviceId=\'$cpu\'",
+ 'plugin_user' => $creds->{'username'},
+ 'plugin_pass' => $creds->{'password'},
+ 'tcp_port' => 1,
+ 'name' => "CPU Load $cpu",
+ 'descripcion' => safe_input("Load for $cpu (%)"),
+ 'id_tipo_modulo' => 1,
+ 'id_modulo' => 6,
+ 'unit' => '%',
+ }
+ );
+ }
+
+ # Memory.
+ my $mem = $self->wmi_get_value($target, 'SELECT FreePhysicalMemory FROM Win32_OperatingSystem', 0);
+ if (defined($mem)) {
+ $self->add_module(
+ $target,
+ {
+ 'ip_target' => $target,
+ 'snmp_oid' => "SELECT FreePhysicalMemory, TotalVisibleMemorySize FROM Win32_OperatingSystem",
+ 'plugin_user' => $creds->{'username'},
+ 'plugin_pass' => $creds->{'password'},
+ 'tcp_port' => 0,
+ 'name' => 'FreeMemory',
+ 'descripcion' => safe_input('Free memory'),
+ 'id_tipo_modulo' => 1,
+ 'id_modulo' => 6,
+ 'unit' => 'KB',
+ }
+ );
+ }
+
+ # Disk.
+ my @units = $self->wmi_get_value_array($target, 'SELECT DeviceID FROM Win32_LogicalDisk', 0);
+ foreach my $unit (@units) {
+ $self->add_module(
+ $target,
+ {
+ 'ip_target' => $target,
+ 'snmp_oid' => "SELECT FreeSpace FROM Win32_LogicalDisk WHERE DeviceID='$unit'",
+ 'plugin_user' => $creds->{'username'},
+ 'plugin_pass' => $creds->{'password'},
+ 'tcp_port' => 1,
+ 'name' => "FreeDisk $unit",
+ 'descripcion' => safe_input('Available disk space in kilobytes'),
+ 'id_tipo_modulo' => 1,
+ 'id_modulo' => 6,
+ 'unit' => 'KB',
+ }
+ );
+ }
+
+}
+
+################################################################################
+# Create network profile modules for the given agent.
+################################################################################
+sub PandoraFMS::Recon::Base::create_network_profile_modules($$) {
+ my ($self, $device) = @_;
+
+ my @template_ids = ();
+
+ if (is_enabled($self->{'task_data'}{'auto_monitor'})) {
+ # Apply PEN monitoring template (HW).
+ my @pen_templates= get_pen_templates($self->{'dbh'}, $self->get_pen($device));
+ # Join.
+ @template_ids = (@template_ids, @pen_templates);
+ } else {
+ # Return if no specific templates are selected.
+ return if is_empty($self->{'id_network_profile'});
+ }
+
+ push @template_ids, split /,/, $self->{'id_network_profile'}
+ unless is_empty($self->{'id_network_profile'});
+
+ my $data = $self->{'agents_found'}{$device};
+
+ foreach my $t_id (@template_ids) {
+ # 1. Retrieve template info.
+ my $template = get_nc_profile_advanced($self->{'dbh'}, $t_id);
+
+ # 2. Verify Private Enterprise Number matches (PEN)
+ if (defined($template->{'pen'})) {
+ my @penes = split(',', $template->{'pen'});
+
+ next unless (is_in_array(\@penes, $self->get_pen($device)));
+ }
+
+ # 3. Retrieve module list from target template.
+ my @np_components = get_db_rows(
+ $self->{'dbh'},
+ 'SELECT * FROM tnetwork_profile_component WHERE id_np = ?',
+ $t_id
+ );
+
+ foreach my $np_component (@np_components) {
+ # 4. Register each module (candidate). 'add_module' will test them.
+ my $component = get_db_single_row(
+ $self->{'dbh'},
+ 'SELECT * FROM tnetwork_component WHERE id_nc = ?',
+ $np_component->{'id_nc'}
+ );
+
+ $component->{'name'} = safe_output($component->{'name'});
+ if ($component->{'type'} >= 15 && $component->{'type'} <= 18) {
$component->{'snmp_community'} = safe_output($self->get_community($device));
$component->{'tcp_send'} = $self->{'snmp_version'};
$component->{'custom_string_1'} = $self->{'snmp_privacy_method'};
@@ -464,566 +915,726 @@ sub PandoraFMS::Recon::Base::create_network_profile_modules($$$) {
$component->{'plugin_parameter'} = $self->{'snmp_auth_method'};
$component->{'plugin_user'} = $self->{'snmp_auth_user'};
$component->{'plugin_pass'} = $self->{'snmp_auth_pass'};
+ }
- pandora_create_module_from_network_component($self->{'pa_config'}, $component, $agent_id, $self->{'dbh'});
+ $component->{'__module_component'} = 1;
+
+ # 3. Try to register module into monitoring list.
+ $self->call('add_module', $device, $component);
}
+ }
+
}
-##########################################################################
+################################################################################
+# Retrieve a key from credential store.
+################################################################################
+sub PandoraFMS::Recon::Base::get_credentials {
+ my ($self, $key_index) = @_;
+
+ return credential_store_get_key(
+ $self->{'pa_config'},
+ $self->{'dbh'},
+ $key_index
+ );
+}
+
+################################################################################
+# Create agents and modules reported by Recon::Base.
+################################################################################
+sub PandoraFMS::Recon::Base::report_scanned_agents($;$) {
+ my ($self,$force) = @_;
+
+ my $force_creation = $force;
+ $force_creation = 0 unless (is_enabled($force));
+
+ #
+ # Creation
+ #
+
+ if($force_creation == 1
+ || (defined($self->{'task_data'}{'review_mode'})
+ && $self->{'task_data'}{'review_mode'} == DISCOVERY_RESULTS)
+ ) {
+
+ # Load cache.
+ my @rows = get_db_rows(
+ $self->{'dbh'},
+ 'SELECT * FROM tdiscovery_tmp_agents WHERE `id_rt`=?',
+ $self->{'task_data'}{'id_rt'}
+ );
+
+ # Return if no entries.
+ return unless scalar @rows > 0;
+
+ my @agents;
+
+ my $progress = 0;
+ my $step = 100.00 / scalar @rows;
+ foreach my $row (@rows) {
+ $progress += $step;
+ $self->call('update_progress', $progress);
+
+ my $name = safe_output($row->{'label'});
+ my $checked = 0;
+ my $data;
+ eval {
+ local $SIG{__DIE__};
+ $data = decode_json(decode_base64($row->{'data'}));
+ };
+ if ($@) {
+ $self->call('message', "ERROR JSON: $@", 3);
+ }
+
+ # Agent could be 'not checked' unless all modules are selected.
+ if (ref($data->{'modules'}) eq 'HASH') {
+ my @map = map {
+ my $name = $_->{'name'};
+ $name = $_->{'nombre'} if is_empty($name);
+
+ if (is_enabled($_->{'checked'})
+ && $name ne 'Host Alive'
+ ) {
+ $name;
+ } else {}
+
+ } values %{$data->{'modules'}};
+
+ $checked = scalar @map;
+ }
+
+ $checked = $data->{'agent'}{'checked'} if
+ is_enabled($data->{'agent'}{'checked'})
+ && $checked < $data->{'agent'}{'checked'};
+
+ # Register target agent if enabled.
+ if (is_enabled($checked)
+ || $force_creation
+ ) {
+ my $parent_id;
+ my $os_id = $self->guess_os($data->{'agent'}{'direccion'});
+
+ $self->call('message', "Agent accepted: ".$data->{'agent'}{'nombre'}, 5);
+
+ # Agent creation.
+ my $agent_id = $data->{'agent'}{'agent_id'};
+ my $agent_learning;
+
+ if (defined($agent_id) && $agent_id > 0) {
+ $agent_learning = get_db_value(
+ $self->{'dbh'},
+ 'SELECT modo FROM tagente WHERE id_agente = ?',
+ $agent_id
+ );
+ }
+
+ if (!defined($agent_learning)) {
+ # Agent id does not exists or is invalid.
+
+ # Check if has been created by another process.
+ $agent_id = get_db_value(
+ $self->{'dbh'},
+ 'SELECT id_agente FROM tagente WHERE nombre = ?',
+ safe_input($data->{'agent'}{'nombre'})
+ );
+
+ if (!defined($agent_id) || $agent_id <= 0) {
+ # Agent creation.
+ $agent_id = pandora_create_agent(
+ $self->{'pa_config'}, $self->{'servername'}, $data->{'agent'}{'nombre'},
+ $data->{'agent'}{'direccion'}, $self->{'task_data'}{'id_group'}, $parent_id,
+ $os_id, $data->{'agent'}->{'description'},
+ $data->{'agent'}{'interval'}, $self->{'dbh'},
+ $data->{'agent'}{'timezone_offset'}
+ );
+
+ # Agent autoconfiguration.
+ if (is_enabled($self->{'autoconfiguration_enabled'})) {
+ my $agent_data = PandoraFMS::DB::get_db_single_row(
+ $self->{'dbh'},
+ 'SELECT * FROM tagente WHERE id_agente = ?',
+ $agent_id
+ );
+
+ # Update agent configuration once, after create agent.
+ enterprise_hook(
+ 'autoconfigure_agent',
+ [
+ $self->{'pa_config'},
+ $data->{'agent'}{'direccion'},
+ $agent_id,
+ $agent_data,
+ $self->{'dbh'},
+ 1
+ ]
+ );
+ }
+
+ if (defined($self->{'main_event_id'})) {
+ my $addresses_str = join(
+ ',',
+ $self->get_addresses(safe_output($data->{'agent'}{'nombre'}))
+ );
+
+ pandora_extended_event(
+ $self->{'pa_config'}, $self->{'dbh'},
+ $self->{'main_event_id'},"[Discovery] New "
+ . $self->get_device_type(safe_output($data->{'agent'}{'nombre'}))
+ . " found " . $data->{'agent'}{'nombre'} . " (" . $addresses_str
+ . ") Agent $agent_id."
+ );
+ }
+
+ $agent_learning = 1;
+ } else {
+ # Read from effective agent_id.
+ $agent_learning = get_db_value(
+ $self->{'dbh'},
+ 'SELECT modo FROM tagente WHERE id_agente = ?',
+ $agent_id
+ );
+ }
+
+ $data->{'agent'}{'agent_id'} = $agent_id;
+ }
+
+ $data->{'agent'}{'modo'} = $agent_learning;
+ $self->call('message', "Agent id: ".$data->{'agent'}{'agent_id'}, 5);
+
+ # Create selected modules.
+ if(ref($data->{'modules'}) eq "HASH") {
+ foreach my $i (keys %{$data->{'modules'}}) {
+ my $module = $data->{'modules'}{$i};
+
+ $module->{'name'} = $module->{'nombre'} if is_empty($module->{'name'});
+
+ # Do not create any modules if the agent is not in learning mode.
+ next unless ($agent_learning == 1);
+
+ # Host alive is always being created.
+ if ($module->{'name'} ne 'Host Alive') {
+ next unless (is_enabled($module->{'checked'}) || $force_creation);
+ }
+
+ $self->call('message', "[$agent_id] Module: ".$module->{'name'}, 5);
+
+ my $agentmodule_id = get_db_value(
+ $self->{'dbh'},
+ 'SELECT id_agente_modulo FROM tagente_modulo
+ WHERE id_agente = ? AND nombre = ?',
+ $agent_id,
+ safe_input($module->{'name'})
+ );
+
+ if (!is_enabled($agentmodule_id)) {
+ # Create.
+
+ # Delete unwanted fields.
+ delete $module->{'agentmodule_id'};
+ delete $module->{'checked'};
+
+ my $id_tipo_modulo = $module->{'id_tipo_modulo'};
+ $id_tipo_modulo = get_module_id($self->{'dbh'}, $module->{'type'})
+ if is_empty($id_tipo_modulo);
+
+ my $description = safe_output($module->{'description'});
+ $description = '' if is_empty($description);
+
+ if (is_enabled($module->{'__module_component'})) {
+ # Module from network component.
+ delete $module->{'__module_component'};
+ $agentmodule_id = pandora_create_module_from_network_component(
+ $self->{'pa_config'},
+ # Send a copy, not original, because of 'deletes'
+ {
+ %{$module},
+ 'name' => safe_input($module->{'name'}),
+ },
+ $agent_id,
+ $self->{'dbh'}
+ );
+
+ # Restore.
+ $module->{'__module_component'} = 1;
+ } else {
+ # Create module - Direct.
+ my $name = $module->{'name'};
+ delete $module->{'name'};
+ delete $module->{'description'};
+ $agentmodule_id = pandora_create_module_from_hash(
+ $self->{'pa_config'},
+ {
+ %{$module},
+ 'id_tipo_modulo' => $id_tipo_modulo,
+ 'id_modulo' => $module->{'id_modulo'},
+ 'nombre' => safe_input($name),
+ 'descripcion' => safe_input($description),
+ 'id_agente' => $agent_id,
+ 'ip_target' => $data->{'agent'}{'direccion'}
+ },
+ $self->{'dbh'}
+ );
+
+ $module->{'name'} = $name;
+ $module->{'description'} = safe_output($description);
+ }
+
+ # Restore.
+ $module->{'checked'} = 1;
+
+ # Store.
+ $data->{'modules'}{$i}{'agentmodule_id'} = $agentmodule_id;
+
+ $self->call(
+ 'message',
+ "[$agent_id] Module: ".$module->{'name'}." ID: $agentmodule_id",
+ 5
+ );
+ }
+ }
+ }
+
+ my $encoded;
+ eval {
+ local $SIG{__DIE__};
+ $encoded = encode_base64(
+ encode_json($data)
+ );
+ };
+
+ push @agents, $data->{'agent'};
+
+ # Update.
+ db_do(
+ $self->{'dbh'},
+ 'UPDATE tdiscovery_tmp_agents SET `data` = ? '
+ .'WHERE `id_rt` = ? AND `label` = ?',
+ $encoded,
+ $self->{'task_data'}{'id_rt'},
+ $name
+ );
+
+ }
+
+ }
+
+ # Update parent relationships.
+ foreach my $agent (@agents) {
+
+ # Avoid processing if does not exist.
+ next unless (defined($agent->{'agent_id'}));
+
+ # Avoid processing undefined parents.
+ next unless defined($agent->{'parent'});
+
+ # Get parent id.
+ my $parent = get_agent_from_addr($self->{'dbh'}, $agent->{'parent'});
+ if (!defined($parent)) {
+ $parent = get_agent_from_name($self->{'dbh'}, $agent->{'parent'});
+ }
+ next unless defined($parent);
+
+ # Is the agent in learning mode?
+ next unless ($agent->{'modo'} == 1);
+
+ # Connect the host to its parent.
+ db_do($self->{'dbh'},
+ 'UPDATE tagente SET id_parent=? WHERE id_agente=?',
+ $parent->{'id_agente'}, $agent->{'agent_id'}
+ );
+ }
+
+ # Connect agents.
+ my @connections = get_db_rows(
+ $self->{'dbh'},
+ 'SELECT * FROM tdiscovery_tmp_connections WHERE id_rt = ?',
+ $self->{'task_data'}{'id_rt'}
+ );
+
+ foreach my $cn (@connections) {
+ $self->call('connect_agents',
+ $cn->{'dev_1'},
+ $cn->{'if_1'},
+ $cn->{'dev_2'},
+ $cn->{'if_2'},
+ # Force creation if direct.
+ $force_creation
+ );
+ }
+
+ # Data creation finished.
+ return;
+ }
+
+
+ #
+ # Cleanup previous results.
+ #
+ $self->call('message', "Cleanup previous results", 6);
+ db_do(
+ $self->{'dbh'},
+ 'DELETE FROM tdiscovery_tmp_agents '
+ .'WHERE `id_rt` = ?',
+ $self->{'task_data'}{'id_rt'}
+ );
+
+ #
+ # Store and review.
+ #
+
+ $self->call('message', "Storing results", 6);
+ my @hosts = keys %{$self->{'agents_found'}};
+ $self->{'step'} = STEP_PROCESSING;
+ my ($progress, $step) = (90, 10.0 / scalar(@hosts)); # From 90% to 100%.
+ foreach my $label (keys %{$self->{'agents_found'}}) {
+ $self->call('update_progress', $progress);
+ $progress += $step;
+ # Store temporally. Wait user approval.
+ my $encoded;
+ eval {
+ local $SIG{__DIE__};
+ $encoded = encode_base64(
+ encode_json($self->{'agents_found'}->{$label})
+ );
+ };
+
+ 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
+ );
+ }
+
+
+ if(defined($self->{'task_data'}{'review_mode'})
+ && $self->{'task_data'}{'review_mode'} == DISCOVERY_REVIEW
+ ) {
+ # Notify.
+ my $notification = {};
+ $notification->{'subject'} = safe_input('Discovery task ');
+ $notification->{'subject'} .= $self->{'task_data'}{'name'};
+ $notification->{'subject'} .= safe_input(' review pending');
+ $notification->{'url'} = ui_get_full_url(
+ 'index.php?sec=gservers&sec2=godmode/servers/discovery&wiz=tasklist#'
+ );
+
+ $notification->{'mensaje'} = safe_input(
+ 'Discovery task (host&devices) \''.safe_output($self->{'task_data'}{'name'})
+ .'\' has been completed. Please review the results.'
+ );
+
+ $notification->{'id_source'} = get_db_value(
+ $self->{'dbh'},
+ 'SELECT id FROM tnotification_source WHERE description = ?',
+ safe_input('System status')
+ );
+
+ # Create message
+ my $notification_id = db_process_insert(
+ $self->{'dbh'},
+ 'id_mensaje',
+ 'tmensajes',
+ $notification
+ );
+
+ if (is_enabled($notification_id)) {
+ my @users = notification_get_users($self->{'dbh'}, 'System status');
+ my @groups = notification_get_groups($self->{'dbh'}, 'System status');
+
+ notification_set_targets(
+ $self->{'pa_config'}, $self->{'dbh'},
+ $notification_id, \@users, \@groups
+ );
+ }
+ }
+
+ $self->call('message', "Completed", 5);
+}
+
+################################################################################
+# Apply monitoring templates selected to detected agents.
+################################################################################
+sub PandoraFMS::Recon::Base::apply_monitoring($) {
+ my ($self) = @_;
+
+ my @hosts = keys %{$self->{'agents_found'}};
+
+ $self->{'step'} = STEP_MONITORING;
+ # From 80% to 90%.
+ my ($progress, $step) = (80, 10.0 / scalar(@hosts));
+ my ($partial, $sub_step) = (0, 100 / scalar(@hosts));
+
+ foreach my $label (keys %{$self->{'agents_found'}}) {
+ $self->{'c_network_percent'} = $partial;
+ $self->{'c_network_name'} = $label;
+ $self->call('update_progress', $progress);
+ $progress += $step;
+ $partial += $sub_step;
+ $self->call('message', "Checking modules for $label", 5);
+
+ # Monitorization selected.
+ $self->call('create_network_profile_modules', $label);
+
+ # Monitorization - interfaces
+ $self->call('create_interface_modules', $label);
+
+ # Monitorization - WMI modules.
+ $self->call('create_wmi_modules', $label);
+
+ }
+
+ $self->{'c_network_percent'} = 100;
+ $self->call('update_progress', $progress);
+}
+
+################################################################################
# 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) = @_;
+################################################################################
+sub PandoraFMS::Recon::Base::connect_agents($$$$$;$) {
+ my ($self, $dev_1, $if_1, $dev_2, $if_2, $force) = @_;
- # Get the agent for the first device.
- my $agent_1 = get_agent_from_addr($self->{'dbh'}, $dev_1);
- if (!defined($agent_1)) {
- $agent_1 = get_agent_from_name($self->{'dbh'}, $dev_1);
- }
- return unless defined($agent_1);
+ if($self->{'task_data'}{'review_mode'} == DISCOVERY_REVIEW
+ || is_enabled($force)
+ ) {
+ # Store in tdiscovery_tmp_connections;
- # Get the agent for the second device.
- my $agent_2 = get_agent_from_addr($self->{'dbh'}, $dev_2);
- if (!defined($agent_2)) {
- $agent_2 = get_agent_from_name($self->{'dbh'}, $dev_2);
- }
- return unless defined($agent_2);
+ db_process_insert(
+ $self->{'dbh'},
+ 'id',
+ 'tdiscovery_tmp_connections',
+ {
+ 'id_rt' => $self->{'task_data'}{'id_rt'},
+ 'dev_1' => $dev_1,
+ 'if_1' => $if_1,
+ 'dev_2' => $dev_2,
+ 'if_2' => $if_2,
+ }
+ );
- # Use ping modules by default.
- $if_1 = 'ping' if ($if_1 eq '');
- $if_2 = 'ping' if ($if_2 eq '');
+ return;
+ }
- # 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_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);
- return;
- }
- my $module_id_2 = get_agent_module_id($self->{'dbh'}, $module_name_2, $agent_2->{'id_agente'});
- if ($module_id_2 <= 0) {
- $self->call('message', "ERROR: Module " . safe_output($module_name_2) . " does not exist for agent $dev_2.", 5);
- return;
- }
+ # Get the agent for the first device.
+ my $agent_1 = get_agent_from_addr($self->{'dbh'}, $dev_1);
+ if (!defined($agent_1)) {
+ $agent_1 = get_agent_from_name($self->{'dbh'}, $dev_1);
+ }
+ return unless defined($agent_1);
- # Connect the modules if they are not already connected.
- my $connection_id = get_db_value($self->{'dbh'}, 'SELECT id FROM tmodule_relationship WHERE (module_a = ? AND module_b = ? AND `type` = "direct") OR (module_b = ? AND module_a = ? AND `type` = "direct")', $module_id_1, $module_id_2, $module_id_1, $module_id_2);
- if (! defined($connection_id)) {
- db_do($self->{'dbh'}, 'INSERT INTO tmodule_relationship (`module_a`, `module_b`, `id_rt`) VALUES(?, ?, ?)', $module_id_1, $module_id_2, $self->{'task_id'});
- }
+ # Get the agent for the second device.
+ my $agent_2 = get_agent_from_addr($self->{'dbh'}, $dev_2);
+ if (!defined($agent_2)) {
+ $agent_2 = get_agent_from_name($self->{'dbh'}, $dev_2);
+ }
+ return unless defined($agent_2);
+
+ # Use ping modules by default.
+ $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 '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);
+ return;
+ }
+ my $module_id_2 = get_agent_module_id($self->{'dbh'}, $module_name_2, $agent_2->{'id_agente'});
+ if ($module_id_2 <= 0) {
+ $self->call('message', "ERROR: Module " . safe_output($module_name_2) . " does not exist for agent $dev_2.", 5);
+ return;
+ }
+
+ # Connect the modules if they are not already connected.
+ my $connection_id = get_db_value($self->{'dbh'}, 'SELECT id FROM tmodule_relationship WHERE (module_a = ? AND module_b = ? AND `type` = "direct") OR (module_b = ? AND module_a = ? AND `type` = "direct")', $module_id_1, $module_id_2, $module_id_1, $module_id_2);
+ if (! defined($connection_id)) {
+ db_do($self->{'dbh'}, 'INSERT INTO tmodule_relationship (`module_a`, `module_b`, `id_rt`) VALUES(?, ?, ?)', $module_id_1, $module_id_2, $self->{'task_id'});
+ }
}
-##########################################################################
+################################################################################
# Create agents from db_scan. Uses DataServer methods.
# data = [
# 'agent_data' => {},
# 'module_data' => []
# ]
-##########################################################################
+################################################################################
sub PandoraFMS::Recon::Base::create_agents($$) {
- my ($self, $data) = @_;
+ my ($self, $data) = @_;
- my $pa_config = $self->{'pa_config'};
- my $dbh = $self->{'dbh'};
- my $server_id = $self->{'server_id'};
+ my $pa_config = $self->{'pa_config'};
+ my $dbh = $self->{'dbh'};
+ my $server_id = $self->{'server_id'};
- return undef if (ref($data) ne "ARRAY");
+ return undef if (ref($data) ne "ARRAY");
- foreach my $information (@{$data}) {
- my $agent = $information->{'agent_data'};
- my $modules = $information->{'module_data'};
- my $force_processing = 0;
+ foreach my $information (@{$data}) {
+ my $agent = $information->{'agent_data'};
+ my $modules = $information->{'module_data'};
+ my $force_processing = 0;
- # Search agent
- my $current_agent = PandoraFMS::Core::locate_agent(
- $pa_config, $dbh, $agent->{'agent_name'}
- );
-
- my $parent_id;
- if (defined($agent->{'parent_agent_name'})) {
- $parent_id = PandoraFMS::Core::locate_agent(
- $pa_config, $dbh, $agent->{'parent_agent_name'}
- );
- if ($parent_id) {
- $parent_id = $parent_id->{'id_agente'};
- }
- }
-
- my $agent_id;
- my $os_id = get_os_id($dbh, $agent->{'os'});
-
- if ($os_id < 0) {
- $os_id = get_os_id($dbh, 'Other');
- }
-
- if (!$current_agent) {
- # Create agent.
- $agent_id = pandora_create_agent(
- $pa_config, $pa_config->{'servername'}, $agent->{'agent_name'},
- $agent->{'address'}, $agent->{'id_group'}, $parent_id,
- $os_id, $agent->{'description'},
- $agent->{'interval'}, $dbh, $agent->{'timezone_offset'}
- );
-
- $current_agent = $parent_id = PandoraFMS::Core::locate_agent(
- $pa_config, $dbh, $agent->{'agent_name'}
- );
-
- $force_processing = 1;
-
- } else {
- $agent_id = $current_agent->{'id_agente'};
- }
-
- if (!defined($agent_id)) {
- return undef;
- }
-
- if (defined($agent->{'address'}) && $agent->{'address'} ne '') {
- pandora_add_agent_address(
- $pa_config, $agent_id, $agent->{'agent_name'},
- $agent->{'address'}, $dbh
- );
- }
-
- # Update agent information
- pandora_update_agent(
- $pa_config, strftime("%Y-%m-%d %H:%M:%S", localtime()), $agent_id,
- $agent->{'os_version'}, $agent->{'agent_version'},
- $agent->{'interval'}, $dbh, undef, $parent_id
- );
-
- # Add modules.
- if (ref($modules) eq "ARRAY") {
- foreach my $module (@{$modules}) {
- next unless ref($module) eq 'HASH';
- # Translate data structure to simulate XML parser return.
- my %data_translated = map { $_ => [ $module->{$_} ] } keys %{$module};
-
- # Process modules.
- PandoraFMS::DataServer::process_module_data (
- $pa_config, \%data_translated,
- $server_id, $current_agent,
- $module->{'name'}, $module->{'type'},
- $agent->{'interval'},
- strftime ("%Y/%m/%d %H:%M:%S", localtime()),
- $dbh, $force_processing
- );
- }
- }
- }
-
-}
-
-
-##########################################################################
-# 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) = @_;
-
- # Clean name.
- $device = clean_blank($device);
-
- # Resolve hostnames.
- my $host_name = (($self->{'resolve_names'} == 1) ? gethostbyaddr(inet_aton($device), AF_INET) : $device);
- # Fallback to device IP if host name could not be resolved.
- $host_name = $device if (!defined($host_name) || $host_name eq '');
- my $agent = locate_agent($self->{'pa_config'}, $self->{'dbh'}, $host_name);
-
- my ($agent_id, $agent_learning);
- if (!defined($agent)) {
- $host_name = $device unless defined ($host_name);
-
- # Guess the OS.
- my $id_os = $self->guess_os($device);
-
- # Are we filtering hosts by OS?
- return if ($self->{'id_os'} > 0 && $id_os != $self->{'id_os'});
-
- # Are we filtering hosts by TCP port?
- return if ($self->{'recon_ports'} ne '' && $self->tcp_scan($device) == 0);
- my $location = get_geoip_info($self->{'pa_config'}, $device);
- $agent_id = pandora_create_agent(
- $self->{'pa_config'}, $self->{'pa_config'}->{'servername'},
- $host_name, $device, $self->{'group_id'}, 0, $id_os,
- '', 300, $self->{'dbh'}, undef, $location->{'longitude'},
- $location->{'latitude'}
- );
- return undef unless defined ($agent_id) and ($agent_id > 0);
-
- # Autoconfigure agent
- if (defined($self->{'autoconfiguration_enabled'}) && $self->{'autoconfiguration_enabled'} == 1) {
- my $agent_data = PandoraFMS::DB::get_db_single_row($self->{'dbh'}, 'SELECT * FROM tagente WHERE id_agente = ?', $agent_id);
- # Update agent configuration once, after create agent.
- enterprise_hook('autoconfigure_agent', [$self->{'pa_config'}, $host_name, $agent_id, $agent_data, $self->{'dbh'}, 1]);
- }
-
- if (defined($self->{'main_event_id'})) {
- my $addresses_str = join(',', safe_output($self->get_addresses($device)));
- pandora_extended_event(
- $self->{'pa_config'}, $self->{'dbh'}, $self->{'main_event_id'},
- "[Discovery] New " . safe_output($self->get_device_type($device)) . " found " . $host_name . " (" . $addresses_str . ") Agent $agent_id."
- );
-
- }
-
- $agent_learning = 1;
-
- # Create network profile modules for the agent
- $self->create_network_profile_modules($agent_id, $device);
- }
- else {
- $agent_id = $agent->{'id_agente'};
- $agent_learning = $agent->{'modo'};
- }
-
- # Do not create any modules if the agent is not in learning mode.
- return unless ($agent_learning == 1);
-
- # Add found IP addresses to the agent.
- foreach my $ip_addr ($self->get_addresses($device)) {
- my $addr_id = get_addr_id($self->{'dbh'}, $ip_addr);
- $addr_id = add_address($self->{'dbh'}, $ip_addr) unless ($addr_id > 0);
- next unless ($addr_id > 0);
-
- # Assign the new address to the agent
- my $agent_addr_id = get_agent_addr_id($self->{'dbh'}, $addr_id, $agent_id);
- if ($agent_addr_id <= 0) {
- db_do($self->{'dbh'}, 'INSERT INTO taddress_agent (`id_a`, `id_agent`)
- VALUES (?, ?)', $addr_id, $agent_id);
- }
- }
-
- # Create a ping module.
- my $module_id = get_agent_module_id($self->{'dbh'}, "ping", $agent_id);
- if ($module_id <= 0) {
- my %module = ('id_tipo_modulo' => 6,
- 'id_modulo' => 2,
- 'nombre' => "ping",
- 'descripcion' => '',
- 'id_agente' => $agent_id,
- 'ip_target' => $device);
- pandora_create_module_from_hash ($self->{'pa_config'}, \%module, $self->{'dbh'});
- }
-
- # Add interfaces to the agent if it responds to SNMP.
- return $agent_id unless ($self->is_snmp_discovered($device));
- my $community = $self->get_community($device);
-
- my @output = $self->snmp_get_value_array($device, $PandoraFMS::Recon::Base::IFINDEX);
- foreach my $if_index (@output) {
- next unless ($if_index =~ /^[0-9]+$/);
-
- # Check the status of the interface.
- if ($self->{'all_ifaces'} == 0) {
- my $if_status = $self->snmp_get_value($device, "$PandoraFMS::Recon::Base::IFOPERSTATUS.$if_index");
- next unless $if_status == 1;
- }
-
- # Fill the module description with the IP and MAC addresses.
- my $mac = $self->get_if_mac($device, $if_index);
- my $ip = $self->get_if_ip($device, $if_index);
- my $if_desc = ($mac ne '' ? "MAC $mac " : '') . ($ip ne '' ? "IP $ip" : '');
-
- # Get the name of the network interface.
- my $if_name = $self->snmp_get_value($device, "$PandoraFMS::Recon::Base::IFNAME.$if_index");
- $if_name = "if$if_index" unless defined ($if_name);
- $if_name =~ s/"//g;
- $if_name = clean_blank($if_name);
-
- # Check whether the module already exists.
- my $module_id = get_agent_module_id($self->{'dbh'}, $if_name.'_ifOperStatus', $agent_id);
-
- next if ($module_id > 0 && !$agent_learning);
-
- # Encode problematic characters.
- $if_desc = safe_input($if_desc);
-
- # Interface status module.
- $module_id = get_agent_module_id($self->{'dbh'}, $if_name.'_ifOperStatus', $agent_id);
- if ($module_id <= 0) {
- my %module = ('id_tipo_modulo' => 18,
- 'id_modulo' => 2,
- 'nombre' => safe_input($if_name)."_ifOperStatus",
- 'descripcion' => $if_desc,
- 'id_agente' => $agent_id,
- 'ip_target' => $device,
- 'tcp_send' => $self->{'snmp_version'},
- 'custom_string_1' => $self->{'snmp_privacy_method'},
- 'custom_string_2' => $self->{'snmp_privacy_pass'},
- 'custom_string_3' => $self->{'snmp_security_level'},
- 'plugin_parameter' => $self->{'snmp_auth_method'},
- 'plugin_user' => $self->{'snmp_auth_user'},
- 'plugin_pass' => $self->{'snmp_auth_pass'},
- 'snmp_community' => $community,
- 'snmp_oid' => "$PandoraFMS::Recon::Base::IFOPERSTATUS.$if_index"
- );
- pandora_create_module_from_hash ($self->{'pa_config'}, \%module, $self->{'dbh'});
- } else {
- my %module = (
- 'descripcion' => $if_desc,
- 'ip_target' => $device,
- 'snmp_community' => $community,
- 'tcp_send' => $self->{'snmp_version'},
- 'custom_string_1' => $self->{'snmp_privacy_method'},
- 'custom_string_2' => $self->{'snmp_privacy_pass'},
- 'custom_string_3' => $self->{'snmp_security_level'},
- 'plugin_parameter' => $self->{'snmp_auth_method'},
- 'plugin_user' => $self->{'snmp_auth_user'},
- 'plugin_pass' => $self->{'snmp_auth_pass'},
- 'tcp_send' => $self->{'snmp_version'},
- );
- pandora_update_module_from_hash ($self->{'pa_config'}, \%module, 'id_agente_modulo', $module_id, $self->{'dbh'});
- }
-
- # Incoming traffic module.
- my $if_hc_in_octets = $self->snmp_get_value($device, "$PandoraFMS::Recon::Base::IFHCINOCTECTS.$if_index");
- if (defined($if_hc_in_octets)) {
- $module_id = get_agent_module_id($self->{'dbh'}, $if_name.'_ifHCInOctets', $agent_id);
- if ($module_id <= 0) {
- my %module = ('id_tipo_modulo' => 16,
- 'id_modulo' => 2,
- 'nombre' => safe_input($if_name)."_ifHCInOctets",
- 'descripcion' => 'The total number of octets received on the interface, including framing characters. This object is a 64-bit version of ifInOctets.',
- 'id_agente' => $agent_id,
- 'ip_target' => $device,
- 'tcp_send' => $self->{'snmp_version'},
- 'custom_string_1' => $self->{'snmp_privacy_method'},
- 'custom_string_2' => $self->{'snmp_privacy_pass'},
- 'custom_string_3' => $self->{'snmp_security_level'},
- 'plugin_parameter' => $self->{'snmp_auth_method'},
- 'plugin_user' => $self->{'snmp_auth_user'},
- 'plugin_pass' => $self->{'snmp_auth_pass'},
- 'snmp_community' => $community,
- 'snmp_oid' => "$PandoraFMS::Recon::Base::IFHCINOCTECTS.$if_index");
- pandora_create_module_from_hash ($self->{'pa_config'}, \%module, $self->{'dbh'});
- } else {
- my %module = (
- 'ip_target' => $device,
- 'snmp_community' => $community,
- 'tcp_send' => $self->{'snmp_version'},
- 'custom_string_1' => $self->{'snmp_privacy_method'},
- 'custom_string_2' => $self->{'snmp_privacy_pass'},
- 'custom_string_3' => $self->{'snmp_security_level'},
- 'plugin_parameter' => $self->{'snmp_auth_method'},
- 'plugin_user' => $self->{'snmp_auth_user'},
- 'plugin_pass' => $self->{'snmp_auth_pass'},
- );
- pandora_update_module_from_hash ($self->{'pa_config'}, \%module, 'id_agente_modulo', $module_id, $self->{'dbh'});
- }
- }
- # ifInOctets
- elsif (defined($self->snmp_get_value($device, "$PandoraFMS::Recon::Base::IFINOCTECTS.$if_index"))) {
- $module_id = get_agent_module_id($self->{'dbh'}, $if_name.'_ifInOctets', $agent_id);
- if ($module_id <= 0) {
- my %module = ('id_tipo_modulo' => 16,
- 'id_modulo' => 2,
- 'nombre' => safe_input($if_name)."_ifInOctets",
- 'descripcion' => 'The total number of octets received on the interface, including framing characters.',
- 'id_agente' => $agent_id,
- 'ip_target' => $device,
- 'tcp_send' => $self->{'snmp_version'},
- 'custom_string_1' => $self->{'snmp_privacy_method'},
- 'custom_string_2' => $self->{'snmp_privacy_pass'},
- 'custom_string_3' => $self->{'snmp_security_level'},
- 'plugin_parameter' => $self->{'snmp_auth_method'},
- 'plugin_user' => $self->{'snmp_auth_user'},
- 'plugin_pass' => $self->{'snmp_auth_pass'},
- 'snmp_community' => $community,
- 'snmp_oid' => "$PandoraFMS::Recon::Base::IFINOCTECTS.$if_index");
- pandora_create_module_from_hash ($self->{'pa_config'}, \%module, $self->{'dbh'});
- } else {
- my %module = (
- 'ip_target' => $device,
- 'snmp_community' => $community,
- 'tcp_send' => $self->{'snmp_version'},
- 'custom_string_1' => $self->{'snmp_privacy_method'},
- 'custom_string_2' => $self->{'snmp_privacy_pass'},
- 'custom_string_3' => $self->{'snmp_security_level'},
- 'plugin_parameter' => $self->{'snmp_auth_method'},
- 'plugin_user' => $self->{'snmp_auth_user'},
- 'plugin_pass' => $self->{'snmp_auth_pass'},
- );
- pandora_update_module_from_hash ($self->{'pa_config'}, \%module, 'id_agente_modulo', $module_id, $self->{'dbh'});
- }
- }
-
- # Outgoing traffic module.
- my $if_hc_out_octets = $self->snmp_get_value($device, "$PandoraFMS::Recon::Base::IFHCOUTOCTECTS.$if_index");
- if (defined($if_hc_out_octets)) {
- $module_id = get_agent_module_id($self->{'dbh'}, $if_name.'_ifHCOutOctets', $agent_id);
- if ($module_id <= 0) {
- my %module = ('id_tipo_modulo' => 16,
- 'id_modulo' => 2,
- 'nombre' => safe_input($if_name)."_ifHCOutOctets",
- 'descripcion' => 'The total number of octets received on the interface, including framing characters. This object is a 64-bit version of ifOutOctets.',
- 'id_agente' => $agent_id,
- 'ip_target' => $device,
- 'tcp_send' => $self->{'snmp_version'},
- 'custom_string_1' => $self->{'snmp_privacy_method'},
- 'custom_string_2' => $self->{'snmp_privacy_pass'},
- 'custom_string_3' => $self->{'snmp_security_level'},
- 'plugin_parameter' => $self->{'snmp_auth_method'},
- 'plugin_user' => $self->{'snmp_auth_user'},
- 'plugin_pass' => $self->{'snmp_auth_pass'},
- 'snmp_community' => $community,
- 'snmp_oid' => "$PandoraFMS::Recon::Base::IFHCOUTOCTECTS.$if_index");
- pandora_create_module_from_hash ($self->{'pa_config'}, \%module, $self->{'dbh'});
- } else {
- my %module = (
- 'ip_target' => $device,
- 'snmp_community' => $community,
- 'tcp_send' => $self->{'snmp_version'},
- 'tcp_send' => $self->{'snmp_version'},
- 'custom_string_1' => $self->{'snmp_privacy_method'},
- 'custom_string_2' => $self->{'snmp_privacy_pass'},
- 'custom_string_3' => $self->{'snmp_security_level'},
- 'plugin_parameter' => $self->{'snmp_auth_method'},
- 'plugin_user' => $self->{'snmp_auth_user'},
- 'plugin_pass' => $self->{'snmp_auth_pass'},
- );
- pandora_update_module_from_hash ($self->{'pa_config'}, \%module, 'id_agente_modulo', $module_id, $self->{'dbh'});
- }
- }
- # ifOutOctets
- elsif (defined($self->snmp_get_value($device, "$PandoraFMS::Recon::Base::IFOUTOCTECTS.$if_index"))) {
- $module_id = get_agent_module_id($self->{'dbh'}, "${if_name}_ifOutOctets", $agent_id);
- if ($module_id <= 0) {
- my %module = ('id_tipo_modulo' => 16,
- 'id_modulo' => 2,
- 'nombre' => safe_input($if_name)."_ifOutOctets",
- 'descripcion' => 'The total number of octets received on the interface, including framing characters.',
- 'id_agente' => $agent_id,
- 'ip_target' => $device,
- 'tcp_send' => $self->{'snmp_version'},
- 'custom_string_1' => $self->{'snmp_privacy_method'},
- 'custom_string_2' => $self->{'snmp_privacy_pass'},
- 'custom_string_3' => $self->{'snmp_security_level'},
- 'plugin_parameter' => $self->{'snmp_auth_method'},
- 'plugin_user' => $self->{'snmp_auth_user'},
- 'plugin_pass' => $self->{'snmp_auth_pass'},
- 'snmp_community' => $community,
- 'snmp_oid' => "$PandoraFMS::Recon::Base::IFOUTOCTECTS.$if_index");
- pandora_create_module_from_hash ($self->{'pa_config'}, \%module, $self->{'dbh'});
- } else {
- my %module = (
- 'ip_target' => $device,
- 'snmp_community' => $community,
- 'tcp_send' => $self->{'snmp_version'},
- 'tcp_send' => $self->{'snmp_version'},
- 'custom_string_1' => $self->{'snmp_privacy_method'},
- 'custom_string_2' => $self->{'snmp_privacy_pass'},
- 'custom_string_3' => $self->{'snmp_security_level'},
- 'plugin_parameter' => $self->{'snmp_auth_method'},
- 'plugin_user' => $self->{'snmp_auth_user'},
- 'plugin_pass' => $self->{'snmp_auth_pass'},
- );
- pandora_update_module_from_hash ($self->{'pa_config'}, \%module, 'id_agente_modulo', $module_id, $self->{'dbh'});
- }
- }
- }
-
- return $agent_id;
-}
-
-##########################################################################
-# Delete already existing connections.
-##########################################################################
-sub PandoraFMS::Recon::Base::delete_connections($) {
- my ($self) = @_;
-
- $self->call('message', "Deleting connections...", 10);
- 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) = @_;
-
- return unless ($self->{'parent_detection'} == 1);
-
- # Get the agent for the host.
- my $agent = get_agent_from_addr($self->{'dbh'}, $host);
- if (!defined($agent)) {
- $agent = get_agent_from_name($self->{'dbh'}, $host);
- }
- return unless defined($agent);
-
- # Check if the parent agent exists.
- my $agent_parent = get_agent_from_addr($self->{'dbh'}, $parent);
- if (!defined($agent_parent)) {
- $agent_parent = get_agent_from_name($self->{'dbh'}, $parent);
- }
- return unless (defined ($agent_parent));
-
- # Is the agent in learning mode?
- return unless ($agent_parent->{'modo'} == 1);
-
- # Connect the host to its 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) = @_;
-
- # Check whether the module already exists.
- my $module_id = get_agent_module_id($self->{'dbh'}, $module_name, $agent_id);
- return if ($module_id > 0);
-
- my ($user, $pass) = ($wmi_auth ne '') ? split('%', $wmi_auth) : (undef, undef);
- my %module = (
- 'descripcion' => safe_input($module_description),
- 'id_agente' => $agent_id,
- 'id_modulo' => 6,
- 'id_tipo_modulo' => get_module_id($self->{'dbh'}, $module_type),
- 'ip_target' => $target,
- 'nombre' => safe_input($module_name),
- 'plugin_pass' => defined($pass) ? $pass : '',
- 'plugin_user' => defined($user) ? $user : '',
- 'snmp_oid' => $wmi_query,
- 'tcp_port' => $column,
- 'unit' => defined($unit) ? $unit : ''
+ # Search agent
+ my $current_agent = PandoraFMS::Core::locate_agent(
+ $pa_config, $dbh, $agent->{'agent_name'}
);
-
- pandora_create_module_from_hash($self->{'pa_config'}, \%module, $self->{'dbh'});
+
+ my $parent_id;
+ if (defined($agent->{'parent_agent_name'})) {
+ $parent_id = PandoraFMS::Core::locate_agent(
+ $pa_config, $dbh, $agent->{'parent_agent_name'}
+ );
+ if ($parent_id) {
+ $parent_id = $parent_id->{'id_agente'};
+ }
+ }
+
+ my $agent_id;
+ my $os_id = get_os_id($dbh, $agent->{'os'});
+
+ if ($os_id < 0) {
+ $os_id = get_os_id($dbh, 'Other');
+ }
+
+ if (!$current_agent) {
+ # Create agent.
+ $agent_id = pandora_create_agent(
+ $pa_config, $pa_config->{'servername'}, $agent->{'agent_name'},
+ $agent->{'address'}, $agent->{'id_group'}, $parent_id,
+ $os_id, $agent->{'description'},
+ $agent->{'interval'}, $dbh, $agent->{'timezone_offset'}
+ );
+
+ $current_agent = $parent_id = PandoraFMS::Core::locate_agent(
+ $pa_config, $dbh, $agent->{'agent_name'}
+ );
+
+ $force_processing = 1;
+
+ } else {
+ $agent_id = $current_agent->{'id_agente'};
+ }
+
+ if (!defined($agent_id)) {
+ return undef;
+ }
+
+ if (defined($agent->{'address'}) && $agent->{'address'} ne '') {
+ pandora_add_agent_address(
+ $pa_config, $agent_id, $agent->{'agent_name'},
+ $agent->{'address'}, $dbh
+ );
+ }
+
+ # Update agent information
+ pandora_update_agent(
+ $pa_config, strftime("%Y-%m-%d %H:%M:%S", localtime()), $agent_id,
+ $agent->{'os_version'}, $agent->{'agent_version'},
+ $agent->{'interval'}, $dbh, undef, $parent_id
+ );
+
+ # Add modules.
+ if (ref($modules) eq "ARRAY") {
+ foreach my $module (@{$modules}) {
+ next unless ref($module) eq 'HASH';
+ # Translate data structure to simulate XML parser return.
+ my %data_translated = map { $_ => [ $module->{$_} ] } keys %{$module};
+
+ # Process modules.
+ PandoraFMS::DataServer::process_module_data (
+ $pa_config, \%data_translated,
+ $server_id, $current_agent,
+ $module->{'name'}, $module->{'type'},
+ $agent->{'interval'},
+ strftime ("%Y/%m/%d %H:%M:%S", localtime()),
+ $dbh, $force_processing
+ );
+ }
+ }
+ }
+
}
-##########################################################################
+################################################################################
+# Delete already existing connections.
+################################################################################
+sub PandoraFMS::Recon::Base::delete_connections($) {
+ my ($self) = @_;
+
+ $self->call('message', "Deleting connections...", 10);
+ 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) = @_;
+
+ return unless ($self->{'parent_detection'} == 1);
+
+ # Do not edit 'not scaned' agents.
+ return if is_empty($self->{'agents_found'}{$host}{'agent'});
+
+ $self->{'agents_found'}{$host}{'agent'}{'parent'} = $parent;
+
+}
+
+################################################################################
# Update recon task status.
-##########################################################################
+################################################################################
sub PandoraFMS::Recon::Base::update_progress ($$) {
- my ($self, $progress) = @_;
+ my ($self, $progress) = @_;
- my $stats = {};
- if (defined($self->{'summary'}) && $self->{'summary'} ne '') {
- $stats->{'summary'} = $self->{'summary'};
- }
- $stats->{'step'} = $self->{'step'};
- $stats->{'c_network_name'} = $self->{'c_network_name'};
- $stats->{'c_network_percent'} = $self->{'c_network_percent'};
+ my $stats = {};
+ if (defined($self->{'summary'}) && $self->{'summary'} ne '') {
+ $stats->{'summary'} = $self->{'summary'};
+ }
- # Store progress, last contact and overall status.
- db_do ($self->{'dbh'}, 'UPDATE trecon_task SET utimestamp = ?, status = ?, summary = ? WHERE id_rt = ?',
- time (), $progress, encode_json($stats), $self->{'task_id'});
+ $stats->{'step'} = $self->{'step'};
+ $stats->{'c_network_name'} = $self->{'c_network_name'};
+ $stats->{'c_network_percent'} = $self->{'c_network_percent'};
+
+ # Store progress, last contact and overall status.
+ db_do ($self->{'dbh'}, 'UPDATE trecon_task SET utimestamp = ?, status = ?, summary = ? WHERE id_rt = ?',
+ time (), $progress, encode_json($stats), $self->{'task_id'});
}
1;
diff --git a/pandora_server/lib/PandoraFMS/NetworkServer.pm b/pandora_server/lib/PandoraFMS/NetworkServer.pm
index 216a7ae4d1..0bca799815 100644
--- a/pandora_server/lib/PandoraFMS/NetworkServer.pm
+++ b/pandora_server/lib/PandoraFMS/NetworkServer.pm
@@ -384,6 +384,7 @@ sub pandora_query_snmp ($$$$) {
my $output; # Command output
# If not defined, always snmp v1 (standard)
+ $snmp_version = '1' unless defined($snmp_version);
if ($snmp_version ne '1' && $snmp_version ne '2'
&& $snmp_version ne '2c' && $snmp_version ne '3') {
$snmp_version = '1';
@@ -470,7 +471,9 @@ sub exec_network_module ($$$$) {
my $retries = $module->{'max_retries'};
my $target_os = pandora_get_os($dbh, $module->{'custom_string_2'});
- if ($module->{'custom_string_2'} eq "inherited" ) {
+ if (defined($module->{'custom_string_2'})
+ && $module->{'custom_string_2'} eq "inherited"
+ ) {
$target_os = $agent_row->{'id_os'};
} elsif (!defined($target_os) || "$target_os" eq '0') {
$target_os = $agent_row->{'id_os'};
@@ -589,7 +592,7 @@ sub exec_network_module ($$$$) {
my %data = ("data" => $module_data);
pandora_process_module ($pa_config, \%data, '', $module, '', $timestamp, $utimestamp, $server_id, $dbh);
- if ($agent_os_version eq ''){
+ if (!defined($agent_os_version) || $agent_os_version eq ''){
$agent_os_version = $pa_config->{'servername'}.'_Net';
}
diff --git a/pandora_server/lib/PandoraFMS/PluginTools.pm b/pandora_server/lib/PandoraFMS/PluginTools.pm
index 662ac96f09..fb688f9c61 100644
--- a/pandora_server/lib/PandoraFMS/PluginTools.pm
+++ b/pandora_server/lib/PandoraFMS/PluginTools.pm
@@ -33,7 +33,7 @@ our @ISA = qw(Exporter);
# version: Defines actual version of Pandora Server for this module only
my $pandora_version = "7.0NG.744";
-my $pandora_build = "200413";
+my $pandora_build = "200414";
our $VERSION = $pandora_version." ".$pandora_build;
our %EXPORT_TAGS = ( 'all' => [ qw() ] );
diff --git a/pandora_server/lib/PandoraFMS/Recon/Base.pm b/pandora_server/lib/PandoraFMS/Recon/Base.pm
index ce6048a6f9..01f8e824b8 100644
--- a/pandora_server/lib/PandoraFMS/Recon/Base.pm
+++ b/pandora_server/lib/PandoraFMS/Recon/Base.pm
@@ -7,34 +7,45 @@ 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 {
- STEP_SCANNING => 1,
- STEP_AFT => 2,
- STEP_TRACEROUTE => 3,
- STEP_GATEWAY => 4,
- STEP_STATISTICS => 1,
- STEP_APP_SCAN => 2,
- STEP_CUSTOM_QUERIES => 3,
- DISCOVERY_HOSTDEVICES => 0,
- DISCOVERY_HOSTDEVICES_CUSTOM => 1,
- DISCOVERY_CLOUD_AWS => 2,
- DISCOVERY_APP_VMWARE => 3,
- DISCOVERY_APP_MYSQL => 4,
- DISCOVERY_APP_ORACLE => 5,
- DISCOVERY_CLOUD_AWS_EC2 => 6,
- DISCOVERY_CLOUD_AWS_RDS => 7,
- DISCOVERY_CLOUD_AZURE_COMPUTE => 8,
- DISCOVERY_DEPLOY_AGENTS => 9,
- DISCOVERY_APP_SAP => 10,
+ STEP_SCANNING => 1,
+ STEP_CAPABILITIES => 7,
+ STEP_AFT => 2,
+ STEP_TRACEROUTE => 3,
+ STEP_GATEWAY => 4,
+ STEP_MONITORING => 5,
+ STEP_PROCESSING => 6,
+ STEP_STATISTICS => 1,
+ STEP_APP_SCAN => 2,
+ STEP_CUSTOM_QUERIES => 3,
+ DISCOVERY_HOSTDEVICES => 0,
+ DISCOVERY_HOSTDEVICES_CUSTOM => 1,
+ DISCOVERY_CLOUD_AWS => 2,
+ DISCOVERY_APP_VMWARE => 3,
+ DISCOVERY_APP_MYSQL => 4,
+ DISCOVERY_APP_ORACLE => 5,
+ DISCOVERY_CLOUD_AWS_EC2 => 6,
+ DISCOVERY_CLOUD_AWS_RDS => 7,
+ DISCOVERY_CLOUD_AZURE_COMPUTE => 8,
+ DISCOVERY_DEPLOY_AGENTS => 9,
+ DISCOVERY_APP_SAP => 10,
+ DISCOVERY_REVIEW => 0,
+ DISCOVERY_STANDARD => 1,
+ DISCOVERY_RESULTS => 2,
+ WMI_UNREACHABLE => 1,
+ WMI_BAD_PASSWORD => 2,
+ WMI_GENERIC_ERROR => 3,
+ WMI_OK => 0,
};
# $DEVNULL
@@ -67,6 +78,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( )] );
@@ -98,2060 +110,2272 @@ our @EXPORT = qw(
$SYSUPTIME
);
-#######################################################################
+################################################################################
# Create a new ReconTask object.
-#######################################################################
+################################################################################
sub new {
- my $class = shift;
+ my $class = shift;
- my $self = {
+ my $self = {
- # Known aliases (multiple IP addresses for the same host.
- aliases => {},
+ # Known aliases (multiple IP addresses for the same host.
+ aliases => {},
- # Keep our own ARP cache to connect hosts to switches/routers.
- arp_cache => {},
+ # Keep our own ARP cache to connect hosts to switches/routers.
+ arp_cache => {},
- # Found children.
- children => {},
+ # Found children.
+ children => {},
- # Working SNMP community for each device.
- community_cache => {},
+ # Working SNMP community for each device.
+ community_cache => {},
- # Cache of deviced discovered.
- dicovered_cache => {},
+ # Cache of deviced discovered.
+ dicovered_cache => {},
- # Connections between devices.
- connections => {},
+ # Connections between devices.
+ connections => {},
- # Devices by type.
- hosts => [],
- routers => [],
- switches => [],
+ # Devices by type.
+ hosts => [],
+ routers => [],
+ switches => [],
- # Found interfaces.
- ifaces => {},
+ # Found interfaces.
+ ifaces => {},
- # Found parents.
- parents => {},
+ # Found parents.
+ parents => {},
- # Route cache.
- routes => [],
- default_gw => undef,
+ # Route cache.
+ routes => [],
+ default_gw => undef,
- # SNMP query cache.
- snmp_cache => {},
+ # SNMP query cache.
+ snmp_cache => {},
- # Globally enable/disable SNMP scans.
- snmp_enabled => 1,
+ # Globally enable/disable SNMP scans.
+ snmp_enabled => 1,
- # Globally enable/disable WMI scans.
- wmi_enabled => 0,
- auth_strings_array => [],
- wmi_timeout => 3,
- timeout_cmd => '',
+ # Globally enable/disable WMI scans.
+ wmi_enabled => 0,
+ auth_strings_array => [],
+ wmi_timeout => 3,
+ timeout_cmd => '',
- # Switch to switch connections. Used to properly connect hosts
- # that are connected to a switch wich is in turn connected to another switch,
- # since the hosts will show up in the latter's switch AFT too.
- switch_to_switch => {},
+ # Switch to switch connections. Used to properly connect hosts
+ # that are connected to a switch wich is in turn connected to another switch,
+ # since the hosts will show up in the latter's switch AFT too.
+ switch_to_switch => {},
- # Visited devices (initially empty).
- visited_devices => {},
+ # Visited devices (initially empty).
+ visited_devices => {},
- # Per device VLAN cache.
- vlan_cache => {},
- vlan_cache_enabled => 1, # User configuration. Globally disables the VLAN cache.
- __vlan_cache_enabled__ => 0, # Internal state. Allows us to enable/disable the VLAN cache on a per SNMP query basis.
+ # Per device VLAN cache.
+ vlan_cache => {},
+ vlan_cache_enabled => 1, # User configuration. Globally disables the VLAN cache.
+ __vlan_cache_enabled__ => 0, # Internal state. Allows us to enable/disable the VLAN cache on a per SNMP query basis.
- # Configuration parameters.
- all_ifaces => 0,
- communities => [],
- icmp_checks => 2,
- icmp_timeout => 2,
- id_os => 0,
- id_network_profile => 0,
- nmap => '/usr/bin/nmap',
- parent_detection => 1,
- parent_recursion => 5,
- os_detection => 0,
- recon_timing_template => 3,
- recon_ports => '',
- resolve_names => 0,
- snmp_auth_user => '',
- snmp_auth_pass => '',
- snmp_auth_method => '',
- snmp_checks => 2,
- snmp_privacy_method => '',
- snmp_privacy_pass => '',
- snmp_security_level => '',
- snmp_timeout => 2,
- snmp_version => 1,
- subnets => [],
- autoconfiguration_enabled => 0,
+ # Configuration parameters.
+ all_ifaces => 0,
+ communities => [],
+ icmp_checks => 2,
+ icmp_timeout => 2,
+ id_os => 0,
+ id_network_profile => 0,
+ nmap => '/usr/bin/nmap',
+ parent_detection => 1,
+ parent_recursion => 5,
+ os_detection => 0,
+ recon_timing_template => 3,
+ recon_ports => '',
+ resolve_names => 0,
+ snmp_auth_user => '',
+ snmp_auth_pass => '',
+ snmp_auth_method => '',
+ snmp_checks => 2,
+ snmp_privacy_method => '',
+ snmp_privacy_pass => '',
+ snmp_security_level => '',
+ snmp_timeout => 2,
+ snmp_version => 1,
+ subnets => [],
+ autoconfiguration_enabled => 0,
- # Store progress summary - Discovery progress view.
- step => 0,
- c_network_name => '',
- c_network_percent => 0.0,
- summary => {
- SNMP => 0,
- WMI => 0,
- discovered => 0,
- alive => 0,
- not_alive => 0
- },
- @_,
+ # Store progress summary - Discovery progress view.
+ step => 0,
+ c_network_name => '',
+ c_network_percent => 0.0,
+ summary => {
+ SNMP => 0,
+ WMI => 0,
+ discovered => 0,
+ alive => 0,
+ not_alive => 0
+ },
+ @_,
- };
+ };
- # Perform some sanity checks.
- die("No subnet was specified.") unless defined($self->{'subnets'});
+ # Perform some sanity checks.
+ die("No subnet was specified.") unless defined($self->{'subnets'});
- $self = bless($self, $class);
+ $self = bless($self, $class);
- # Check SNMP params id SNMP is enabled
- if ($self->{'snmp_enabled'}) {
+ # Check SNMP params id SNMP is enabled
+ if ($self->{'snmp_enabled'}) {
- # Check SNMP version
- if ( $self->{'snmp_version'} ne '1'
- && $self->{'snmp_version'} ne '2'
- && $self->{'snmp_version'} ne '2c'
- && $self->{'snmp_version'} ne '3') {
- $self->{'snmp_enabled'} = 0;
- $self->call('message', "SNMP version " . $self->{'snmp_version'} . " not supported (only 1, 2, 2c and 3).", 5);
- }
+ # Check SNMP version
+ if ( $self->{'snmp_version'} ne '1'
+ && $self->{'snmp_version'} ne '2'
+ && $self->{'snmp_version'} ne '2c'
+ && $self->{'snmp_version'} ne '3') {
+ $self->{'snmp_enabled'} = 0;
+ $self->call('message', "SNMP version " . $self->{'snmp_version'} . " not supported (only 1, 2, 2c and 3).", 5);
+ }
- # Check the version 3 parameters
- if ($self->{'snmp_version'} eq '3') {
+ # Check the version 3 parameters
+ if ($self->{'snmp_version'} eq '3') {
- # Fixed some vars
- $self->{'communities'} = [];
+ # Fixed some vars
+ $self->{'communities'} = [];
- # SNMP v3 checks
- if ( $self->{'snmp_security_level'} ne 'noAuthNoPriv'
- &&$self->{'snmp_security_level'} ne 'authNoPriv'
- &&$self->{'snmp_security_level'} ne 'authPriv') {
- $self->{'snmp_enabled'} = 0;
- $self->call('message', "Invalid SNMP security level " . $self->{'snmp_security_level'} . ".", 5);
- }
- if ($self->{'snmp_privacy_method'} ne 'DES' && $self->{'snmp_privacy_method'} ne 'AES') {
- $self->{'snmp_enabled'} = 0;
- $self->call('message', "Invalid SNMP privacy method " . $self->{'snmp_privacy_method'} . ".", 5);
- }
- if ($self->{'snmp_auth_method'} ne 'MD5' && $self->{'snmp_auth_method'} ne 'SHA') {
- $self->{'snmp_enabled'} = 0;
- $self->call('message', "Invalid SNMP authentication method " . $self->{'snmp_auth_method'} . ".", 5);
- }
- } else {
+ # SNMP v3 checks
+ if ( $self->{'snmp_security_level'} ne 'noAuthNoPriv'
+ &&$self->{'snmp_security_level'} ne 'authNoPriv'
+ &&$self->{'snmp_security_level'} ne 'authPriv') {
+ $self->{'snmp_enabled'} = 0;
+ $self->call('message', "Invalid SNMP security level " . $self->{'snmp_security_level'} . ".", 5);
+ }
+ if ($self->{'snmp_privacy_method'} ne 'DES' && $self->{'snmp_privacy_method'} ne 'AES') {
+ $self->{'snmp_enabled'} = 0;
+ $self->call('message', "Invalid SNMP privacy method " . $self->{'snmp_privacy_method'} . ".", 5);
+ }
+ if ($self->{'snmp_auth_method'} ne 'MD5' && $self->{'snmp_auth_method'} ne 'SHA') {
+ $self->{'snmp_enabled'} = 0;
+ $self->call('message', "Invalid SNMP authentication method " . $self->{'snmp_auth_method'} . ".", 5);
+ }
+ } else {
- # Fixed some vars
- $self->{'snmp_auth_user'} = '';
- $self->{'snmp_auth_pass'} = '';
- $self->{'snmp_auth_method'} = '';
- $self->{'snmp_privacy_method'} = '';
- $self->{'snmp_privacy_pass'} = '';
- $self->{'snmp_security_level'} = '';
+ # Fixed some vars
+ $self->{'snmp_auth_user'} = '';
+ $self->{'snmp_auth_pass'} = '';
+ $self->{'snmp_auth_method'} = '';
+ $self->{'snmp_privacy_method'} = '';
+ $self->{'snmp_privacy_pass'} = '';
+ $self->{'snmp_security_level'} = '';
- # Disable SNMP scans if no community was given.
- if (ref($self->{'communities'}) ne "ARRAY" || scalar(@{$self->{'communities'}}) == 0) {
- $self->{'snmp_enabled'} = 0;
- $self->call('message', "There is no SNMP community configured.", 5);
+ # Disable SNMP scans if no community was given.
+ if (ref($self->{'communities'}) ne "ARRAY" || scalar(@{$self->{'communities'}}) == 0) {
+ $self->{'snmp_enabled'} = 0;
+ $self->call('message', "There is no SNMP community configured.", 5);
- }
- }
- }
+ }
+ }
+ }
- # Prepare auth array.
- # WMI could be launched with '-N' - no pass - argument.
- if ($self->{'wmi_enabled'} == 1){
- if (defined($self->{'auth_strings_str'})) {
- @{$self->{'auth_strings_array'}} = split(',', $self->{'auth_strings_str'});
- }
+ # Prepare auth array.
+ # WMI could be launched with '-N' - no pass - argument.
+ if ($self->{'wmi_enabled'} == 1){
+ if (defined($self->{'auth_strings_str'})) {
+ @{$self->{'auth_strings_array'}} = split(',', $self->{'auth_strings_str'});
+ }
- # Timeout available only in linux environments.
- if ($^O =~ /lin/i && defined($self->{'plugin_exec'}) && defined($self->{'wmi_timeout'})) {
- $self->{'timeout_cmd'} = $self->{'plugin_exec'}.' '.$self->{'wmi_timeout'}.' ';
- }
- }
+ # Timeout available only in linux environments.
+ if ($^O =~ /lin/i && defined($self->{'plugin_exec'}) && defined($self->{'wmi_timeout'})) {
+ $self->{'timeout_cmd'} = $self->{'plugin_exec'}.' '.$self->{'wmi_timeout'}.' ';
+ }
+ }
- # Remove all snmp related values if disabled
- if (!$self->{'snmp_enabled'}) {
- $self->{'communities'} = [];
- $self->{'snmp_auth_user'} = '';
- $self->{'snmp_auth_pass'} = '';
- $self->{'snmp_auth_method'} = '';
- $self->{'snmp_privacy_method'} = '';
- $self->{'snmp_privacy_pass'} = '';
- $self->{'snmp_security_level'} = '';
- }
+ # Remove all snmp related values if disabled
+ if (!$self->{'snmp_enabled'}) {
+ $self->{'communities'} = [];
+ $self->{'snmp_auth_user'} = '';
+ $self->{'snmp_auth_pass'} = '';
+ $self->{'snmp_auth_method'} = '';
+ $self->{'snmp_privacy_method'} = '';
+ $self->{'snmp_privacy_pass'} = '';
+ $self->{'snmp_security_level'} = '';
+ }
- return $self;
+ return $self;
}
-########################################################################################
+################################################################################
# Add an address to a device.
-########################################################################################
+################################################################################
sub add_addresses($$$) {
- my ($self, $device, $ip_address) = @_;
+ my ($self, $device, $ip_address) = @_;
- $self->{'visited_devices'}->{$device}->{'addr'}->{$ip_address} = '';
+ $self->{'visited_devices'}->{$device}->{'addr'}->{$ip_address} = '';
}
-########################################################################################
+################################################################################
# Add a MAC/IP address to the ARP cache.
-########################################################################################
+################################################################################
sub add_mac($$$) {
- my ($self, $mac, $ip_addr) = @_;
+ my ($self, $mac, $ip_addr) = @_;
- $mac = parse_mac($mac);
- $self->{'arp_cache'}->{$mac} = $ip_addr;
+ $mac = parse_mac($mac);
+ $self->{'arp_cache'}->{$mac} = $ip_addr;
}
-########################################################################################
+################################################################################
# Add an interface/MAC to the interface cache.
-########################################################################################
+################################################################################
sub add_iface($$$) {
- my ($self, $iface, $mac) = @_;
+ my ($self, $iface, $mac) = @_;
- $iface =~ s/"//g;
- $self->{'ifaces'}->{$mac} = $iface;
+ $iface =~ s/"//g;
+ $self->{'ifaces'}->{$mac} = $iface;
}
-########################################################################################
+################################################################################
# Discover connectivity from address forwarding tables.
-########################################################################################
+################################################################################
sub aft_connectivity($$) {
- my ($self, $switch) = @_;
- my (%mac_temp, @aft_temp);
+ my ($self, $switch) = @_;
+ my (%mac_temp, @aft_temp);
- return unless ($self->is_snmp_discovered($switch));
+ return unless ($self->is_snmp_discovered($switch));
- $self->enable_vlan_cache();
+ $self->enable_vlan_cache();
- # Get the address forwarding table (AFT) of each switch.
- my @aft;
- foreach my $mac ($self->snmp_get_value_array($switch, $DOT1DTPFDBADDRESS)) {
- push(@aft, parse_mac($mac));
- }
+ # Get the address forwarding table (AFT) of each switch.
+ my @aft;
+ foreach my $mac ($self->snmp_get_value_array($switch, $DOT1DTPFDBADDRESS)) {
+ push(@aft, parse_mac($mac));
+ }
- # Search for matching entries.
- foreach my $aft_mac (@aft) {
+ # Search for matching entries.
+ foreach my $aft_mac (@aft) {
- # Do we know who this is?
- my $host = $self->get_ip_from_mac($aft_mac);
- next unless defined($host) and $host ne '';
+ # Do we know who this is?
+ my $host = $self->get_ip_from_mac($aft_mac);
+ next unless defined($host) and $host ne '';
- # Get the name of the host interface if available.
- my $host_if_name = $self->get_iface($aft_mac);
- $host_if_name = defined($host_if_name) ? $host_if_name : 'ping';
+ # Get the name of the host interface if available.
+ my $host_if_name = $self->get_iface($aft_mac);
+ $host_if_name = defined($host_if_name) ? $host_if_name : 'Host Alive';
- # Get the interface associated to the port were we found the MAC address.
- my $switch_if_name = $self->get_if_from_aft($switch, $aft_mac);
- next unless defined($switch_if_name) and ($switch_if_name ne '');
+ # Get the interface associated to the port were we found the MAC address.
+ my $switch_if_name = $self->get_if_from_aft($switch, $aft_mac);
+ next unless defined($switch_if_name) and ($switch_if_name ne '');
- # Do not connect a host to a switch twice using the same interface.
- # The switch is probably connected to another switch.
- next if ($self->is_switch_connected($host, $host_if_name));
- $self->mark_switch_connected($host, $host_if_name);
+ # Do not connect a host to a switch twice using the same interface.
+ # The switch is probably connected to another switch.
+ next if ($self->is_switch_connected($host, $host_if_name));
+ $self->mark_switch_connected($host, $host_if_name);
- # The switch and the host are already connected.
- next if ($self->are_connected($switch, $switch_if_name, $host, $host_if_name));
+ # The switch and the host are already connected.
+ next if ($self->are_connected($switch, $switch_if_name, $host, $host_if_name));
- # Connect!
- $self->mark_connected($switch, $switch_if_name, $host, $host_if_name);
- $self->call('message', "Switch $switch (if $switch_if_name) is connected to host $host (if $host_if_name).", 5);
- }
+ # Connect!
+ $self->mark_connected($switch, $switch_if_name, $host, $host_if_name);
+ $self->call('message', "Switch $switch (if $switch_if_name) is connected to host $host (if $host_if_name).", 5);
+ }
- $self->disable_vlan_cache();
+ $self->disable_vlan_cache();
}
-########################################################################################
+################################################################################
# Return 1 if the given devices are connected to each other, 0 otherwise.
-########################################################################################
+################################################################################
sub are_connected($$$$$) {
- my ($self, $dev_1, $if_1, $dev_2, $if_2) = @_;
+ my ($self, $dev_1, $if_1, $dev_2, $if_2) = @_;
- # Check for aliases!
- $dev_1 = $self->{'aliases'}->{$dev_1} if defined($self->{'aliases'}->{$dev_1});
- $dev_2 = $self->{'aliases'}->{$dev_2} if defined($self->{'aliases'}->{$dev_2});
+ # Check for aliases!
+ $dev_1 = $self->{'aliases'}->{$dev_1} if defined($self->{'aliases'}->{$dev_1});
+ $dev_2 = $self->{'aliases'}->{$dev_2} if defined($self->{'aliases'}->{$dev_2});
- # Use ping modules when interfaces are unknown.
- $if_1 = "ping" if $if_1 eq '';
- $if_2 = "ping" if $if_2 eq '';
+ # Use Host Alive modules when interfaces are unknown.
+ $if_1 = "Host Alive" if $if_1 eq '';
+ $if_2 = "Host Alive" if $if_2 eq '';
- if ( defined($self->{'connections'}->{"${dev_1}\t${if_1}\t${dev_2}\t${if_2}"})
- ||defined($self->{'connections'}->{"${dev_2}\t${if_2}\t${dev_1}\t${if_1}"})) {
- return 1;
- }
+ if ( defined($self->{'connections'}->{"${dev_1}\t${if_1}\t${dev_2}\t${if_2}"})
+ ||defined($self->{'connections'}->{"${dev_2}\t${if_2}\t${dev_1}\t${if_1}"})) {
+ return 1;
+ }
- return 0;
+ return 0;
}
-########################################################################################
-# Discover as much information as possible from the given device using SNMP.
-########################################################################################
-sub snmp_discovery($$) {
- my ($self, $device) = @_;
-
- # Have we already visited this device?
- return if ($self->is_visited($device));
-
- # Mark the device as visited.
- $self->mark_visited($device);
-
- # Are SNMP scans enabled?
- if ($self->{'snmp_enabled'} == 1) {
-
- # Try to find the MAC with an ARP request.
- $self->get_mac_from_ip($device);
-
- # Check if the device responds to SNMP.
- if ($self->snmp_responds($device)) {
- $self->{'summary'}->{'SNMP'} += 1;
-
- # Fill the VLAN cache.
- $self->find_vlans($device);
-
- # Guess the device type.
- $self->guess_device_type($device);
-
- # Find aliases for the device.
- $self->find_aliases($device);
-
- # Find interfaces for the device.
- $self->find_ifaces($device);
-
- # Check remote ARP caches.
- $self->remote_arp($device);
- }
- }
+################################################################################
+# Initialize tmp pool for addr.
+# Already discovered by scan_subnet. Registration only.
+################################################################################
+sub icmp_discovery($$) {
+ my ($self, $addr) = @_;
# Create an agent for the device and add it to the list of known hosts.
- push(@{$self->{'hosts'}}, $device);
+ push(@{$self->{'hosts'}}, $addr);
+
+ # Create an agent for the device and add it to the list of known hosts.
+ $self->add_agent($addr);
+
+ $self->add_module($addr,
+ {
+ 'ip_target' => $addr,
+ 'name' => "Host Alive",
+ 'description' => '',
+ 'type' => 'remote_icmp_proc',
+ 'id_modulo' => 2,
+ }
+ );
- $self->call('create_agent', $device);
}
-#######################################################################
+################################################################################
+# Discover as much information as possible from the given device using SNMP.
+################################################################################
+sub snmp_discovery($$) {
+ my ($self, $device) = @_;
+
+ # Have we already visited this device?
+ return if ($self->is_visited($device));
+
+ # Mark the device as visited.
+ $self->mark_visited($device);
+
+ # Are SNMP scans enabled?
+ if ($self->{'snmp_enabled'} == 1) {
+
+ # Try to find the MAC with an ARP request.
+ $self->get_mac_from_ip($device);
+
+ # Check if the device responds to SNMP.
+ if ($self->snmp_responds($device)) {
+ $self->{'summary'}->{'SNMP'} += 1;
+
+ # Fill the VLAN cache.
+ $self->find_vlans($device);
+
+ # Guess the device type.
+ $self->guess_device_type($device);
+
+ # Find aliases for the device.
+ $self->find_aliases($device);
+
+ # Find interfaces for the device.
+ $self->find_ifaces($device);
+
+ # Check remote ARP caches.
+ $self->remote_arp($device);
+
+ # Get PEN.
+ $self->snmp_pen($device);
+ }
+ }
+}
+
+################################################################################
# Try to call the given function on the given object.
-#######################################################################
+################################################################################
sub call {
- my $self = shift;
- my $func = shift;
- my @params = @_;
+ my $self = shift;
+ my $func = shift;
+ my @params = @_;
- if ($self->can($func)) {
- $self->$func(@params);
- }
+ if ($self->can($func)) {
+ $self->$func(@params);
+ }
}
-########################################################################################
+################################################################################
# Disable the VLAN cache.
-########################################################################################
+################################################################################
sub disable_vlan_cache($$) {
- my ($self, $device) = @_;
+ my ($self, $device) = @_;
- $self->{'__vlan_cache_enabled__'} = 0;
+ $self->{'__vlan_cache_enabled__'} = 0;
}
-########################################################################################
+################################################################################
# Enable the VLAN cache.
-########################################################################################
+################################################################################
sub enable_vlan_cache($$) {
- my ($self, $device) = @_;
+ my ($self, $device) = @_;
- return if ($self->{'vlan_cache_enabled'} == 0);
- $self->{'__vlan_cache_enabled__'} = 1;
+ return if ($self->{'vlan_cache_enabled'} == 0);
+ $self->{'__vlan_cache_enabled__'} = 1;
}
-##########################################################################
+################################################################################
# Connect the given hosts to its gateway.
-##########################################################################
+################################################################################
sub gateway_connectivity($$) {
- my ($self, $host) = @_;
+ my ($self, $host) = @_;
- my $gw = $self->get_gateway($host);
- return unless defined($gw);
+ my $gw = $self->get_gateway($host);
+ return unless defined($gw);
- # Check for aliases!
- $host = $self->{'aliases'}->{$host} if defined($self->{'aliases'}->{$host});
- $gw = $self->{'aliases'}->{$gw} if defined($self->{'aliases'}->{$gw});
+ # Check for aliases!
+ $host = $self->{'aliases'}->{$host} if defined($self->{'aliases'}->{$host});
+ $gw = $self->{'aliases'}->{$gw} if defined($self->{'aliases'}->{$gw});
- # Same host, different IP addresses.
- return if ($host eq $gw);
+ # Same host, different IP addresses.
+ return if ($host eq $gw);
- $self->call('message', "Host $host is reached via gateway $gw.", 5);
- $self->mark_connected($gw, '', $host, '');
+ $self->call('message', "Host $host is reached via gateway $gw.", 5);
+ $self->mark_connected($gw, '', $host, '');
}
-########################################################################################
+################################################################################
# Find IP address aliases for the given device.
-########################################################################################
+################################################################################
sub find_aliases($$) {
- my ($self, $device) = @_;
+ my ($self, $device) = @_;
- # Get ARP cache.
- my @ip_addresses = $self->snmp_get_value_array($device, $IPENTADDR);
- foreach my $ip_address (@ip_addresses) {
+ # Get ARP cache.
+ my @ip_addresses = $self->snmp_get_value_array($device, $IPENTADDR);
+ foreach my $ip_address (@ip_addresses) {
- # Skip broadcast and localhost addresses.
- next if ($ip_address =~ m/\.255$|\.0$|127\.0\.0\.1$/);
+ # Skip broadcast and localhost addresses.
+ next if ($ip_address =~ m/\.255$|\.0$|127\.0\.0\.1$/);
- # Sometimes we find the same IP address we had.
- next if ($ip_address eq $device);
+ # Sometimes we find the same IP address we had.
+ next if ($ip_address eq $device);
- $self->add_addresses($device, $ip_address);
+ $self->add_addresses($device, $ip_address);
- # Try to find the MAC with an ARP request.
- $self->get_mac_from_ip($ip_address);
+ # Try to find the MAC with an ARP request.
+ $self->get_mac_from_ip($ip_address);
- $self->call('message', "Found address $ip_address for host $device.", 5);
+ $self->call('message', "Found address $ip_address for host $device.", 5);
- # Is this address an alias itself?
- $device = $self->{'aliases'}->{$device} if defined($self->{'aliases'}->{$device});
- next if ($ip_address eq $device);
+ # Is this address an alias itself?
+ $device = $self->{'aliases'}->{$device} if defined($self->{'aliases'}->{$device});
+ next if ($ip_address eq $device);
- # Link the two addresses.
- $self->{'aliases'}->{$ip_address} = $device;
- }
+ # Link the two addresses.
+ $self->{'aliases'}->{$ip_address} = $device;
+ }
}
-########################################################################################
+################################################################################
# Find all the interfaces for the given host.
-########################################################################################
+################################################################################
sub find_ifaces($$) {
- my ($self, $device) = @_;
+ my ($self, $device) = @_;
- # Does it respond to SNMP?
- return unless ($self->is_snmp_discovered($device));
+ # Does it respond to SNMP?
+ return unless ($self->is_snmp_discovered($device));
- my @output = $self->snmp_get_value_array($device, $PandoraFMS::Recon::Base::IFINDEX);
- foreach my $if_index (@output) {
+ my @output = $self->snmp_get_value_array($device, $PandoraFMS::Recon::Base::IFINDEX);
+ foreach my $if_index (@output) {
- next unless ($if_index =~ /^[0-9]+$/);
+ next unless ($if_index =~ /^[0-9]+$/);
- # Ignore virtual interfaces.
- next if ($self->get_if_type($device, $if_index) eq '53');
+ # Ignore virtual interfaces.
+ next if ($self->get_if_type($device, $if_index) eq '53');
- # Get the MAC.
- my $mac = $self->get_if_mac($device, $if_index);
- next unless (defined($mac) && $mac ne '');
+ # Get the MAC.
+ my $mac = $self->get_if_mac($device, $if_index);
+ next unless (defined($mac) && $mac ne '');
- # Save it.
- $self->add_mac($mac, $device);
+ # Save it.
+ $self->add_mac($mac, $device);
- # Get the name of the network interface.
- my $if_name = $self->snmp_get_value($device, "$PandoraFMS::Recon::Base::IFNAME.$if_index");
- next unless defined($if_name);
+ # Get the name of the network interface.
+ my $if_name = $self->snmp_get_value($device, "$PandoraFMS::Recon::Base::IFNAME.$if_index");
+ next unless defined($if_name);
- # Save it.
- $self->add_iface($if_name, $mac);
+ # Save it.
+ $self->add_iface($if_name, $mac);
- $self->call('message', "Found interface $if_name MAC $mac for host $device.", 5);
- }
+ $self->call('message', "Found interface $if_name MAC $mac for host $device.", 5);
+ }
}
-########################################################################################
+################################################################################
# Find the device's VLANs and fill the VLAN cache.
-########################################################################################
+################################################################################
sub find_vlans ($$) {
- my ($self, $device) = @_;
- my %vlan_hash;
+ my ($self, $device) = @_;
+ my %vlan_hash;
- foreach my $vlan ($self->snmp_get_value_array($device, $VTPVLANIFINDEX)) {
- next if $vlan eq '0';
- $vlan_hash{$vlan} = 1;
- }
- my @vlans = keys(%vlan_hash);
+ foreach my $vlan ($self->snmp_get_value_array($device, $VTPVLANIFINDEX)) {
+ next if $vlan eq '0';
+ $vlan_hash{$vlan} = 1;
+ }
+ my @vlans = keys(%vlan_hash);
- $self->{'vlan_cache'}->{$device} = [];
- push(@{$self->{'vlan_cache'}->{$device}}, @vlans) if (scalar(@vlans) > 0);
+ $self->{'vlan_cache'}->{$device} = [];
+ push(@{$self->{'vlan_cache'}->{$device}}, @vlans) if (scalar(@vlans) > 0);
}
-########################################################################################
+################################################################################
# Return the addresses of the given device as an array.
-########################################################################################
+################################################################################
sub get_addresses($$) {
- my ($self, $device) = @_;
+ my ($self, $device) = @_;
- if (defined($self->{'visited_devices'}->{$device})) {
- return keys(%{$self->{'visited_devices'}->{$device}->{'addr'}});
- }
+ if (defined($self->{'visited_devices'}->{$device})) {
+ return keys(%{$self->{'visited_devices'}->{$device}->{'addr'}});
+ }
- # By default return the given address.
- return ($device);
+ # By default return the given address.
+ return ($device);
}
-########################################################################################
+################################################################################
# Return a device structure from an IP address.
-########################################################################################
+################################################################################
sub get_device($$) {
- my ($self, $addr) = @_;
+ my ($self, $addr) = @_;
- if (defined($self->{'visited_devices'}->{$addr})) {
- return $self->{'visited_devices'}->{$addr};
- }
+ if (defined($self->{'visited_devices'}->{$addr})) {
+ return $self->{'visited_devices'}->{$addr};
+ }
- return undef;
+ return undef;
}
-########################################################################################
+################################################################################
# Get the SNMP community of the given device. Returns undef if no community was found.
-########################################################################################
+################################################################################
sub get_community($$) {
- my ($self, $device) = @_;
+ my ($self, $device) = @_;
- return '' if ($self->{'snmp_version'} eq "3");
+ return '' if ($self->{'snmp_version'} eq "3");
- if (defined($self->{'community_cache'}->{$device})) {
- return $self->{'community_cache'}->{$device};
- }
+ if (defined($self->{'community_cache'}->{$device})) {
+ return $self->{'community_cache'}->{$device};
+ }
- return '';
+ return '';
}
-########################################################################################
+################################################################################
# Return the connection hash.
-########################################################################################
+################################################################################
sub get_connections($) {
- my ($self) = @_;
+ my ($self) = @_;
- return $self->{'connections'};
+ return $self->{'connections'};
}
-########################################################################################
+################################################################################
+# Return the PEN associated to target host.
+################################################################################
+sub get_pen($$) {
+ my ($self, $host) = @_;
+
+ return undef unless ref($self->{'pen'}) eq 'HASH';
+
+ return $self->{'pen'}->{$host};
+}
+
+################################################################################
# Return the parent relationship hash.
-########################################################################################
+################################################################################
sub get_parents($) {
- my ($self) = @_;
+ my ($self) = @_;
- return $self->{'parents'};
+ return $self->{'parents'};
}
-########################################################################################
+################################################################################
# Get the type of the given device.
-########################################################################################
+################################################################################
sub get_device_type($$) {
- my ($self, $device) = @_;
+ my ($self, $device) = @_;
- if (defined($self->{'visited_devices'}->{$device})) {
- return $self->{'visited_devices'}->{$device}->{'type'};
- }
+ if (defined($self->{'visited_devices'}->{$device})) {
+ if (defined($self->{'visited_devices'}->{$device}->{'type'})) {
+ return $self->{'visited_devices'}->{$device}->{'type'};
+ } else {
+ $self->{'visited_devices'}->{$device}->{'type'} = 'host';
+ }
+ }
- # Assume 'host' by default.
- return 'host';
+ # Assume 'host' by default.
+ return 'host';
}
-########################################################################################
+################################################################################
# Return all known hosts that are not switches or routers.
-########################################################################################
+################################################################################
sub get_hosts($) {
- my ($self) = @_;
+ my ($self) = @_;
- return $self->{'hosts'};
+ return $self->{'hosts'};
}
-########################################################################################
+################################################################################
# Add an interface/MAC to the interface cache.
-########################################################################################
+################################################################################
sub get_iface($$) {
- my ($self, $mac) = @_;
+ my ($self, $mac) = @_;
- return undef unless defined($self->{'ifaces'}->{$mac});
+ return undef unless defined($self->{'ifaces'}->{$mac});
- return $self->{'ifaces'}->{$mac};
+ return $self->{'ifaces'}->{$mac};
}
-########################################################################################
+################################################################################
# Get an interface name from an AFT entry. Returns undef on error.
-########################################################################################
+################################################################################
sub get_if_from_aft($$$) {
- my ($self, $switch, $mac) = @_;
+ my ($self, $switch, $mac) = @_;
- # Get the port associated to the MAC.
- my $port = $self->snmp_get_value($switch, "$DOT1DTPFDBPORT." . mac_to_dec($mac));
- return '' unless defined($port);
+ # Get the port associated to the MAC.
+ my $port = $self->snmp_get_value($switch, "$DOT1DTPFDBPORT." . mac_to_dec($mac));
+ return '' unless defined($port);
- # Get the interface index associated to the port.
- my $if_index = $self->snmp_get_value($switch, "$DOT1DBASEPORTIFINDEX.$port");
- return '' unless defined($if_index);
+ # Get the interface index associated to the port.
+ my $if_index = $self->snmp_get_value($switch, "$DOT1DBASEPORTIFINDEX.$port");
+ return '' unless defined($if_index);
- # Get the interface name.
- my $if_name = $self->snmp_get_value($switch, "$IFNAME.$if_index");
- return "if$if_index" unless defined($if_name);
+ # Get the interface name.
+ my $if_name = $self->snmp_get_value($switch, "$IFNAME.$if_index");
+ return "if$if_index" unless defined($if_name);
- $if_name =~ s/"//g;
- return $if_name;
+ $if_name =~ s/"//g;
+ return $if_name;
}
-########################################################################################
+################################################################################
# Get an interface name from an IP address.
-########################################################################################
+################################################################################
sub get_if_from_ip($$$) {
- my ($self, $device, $ip_addr) = @_;
+ my ($self, $device, $ip_addr) = @_;
- # Get the port associated to the IP address.
- my $if_index = $self->snmp_get_value($device, "$IPROUTEIFINDEX.$ip_addr");
- return '' unless defined($if_index);
+ # Get the port associated to the IP address.
+ my $if_index = $self->snmp_get_value($device, "$IPROUTEIFINDEX.$ip_addr");
+ return '' unless defined($if_index);
- # Get the name of the interface associated to the port.
- my $if_name = $self->snmp_get_value($device, "$IFNAME.$if_index");
- return '' unless defined($if_name);
+ # Get the name of the interface associated to the port.
+ my $if_name = $self->snmp_get_value($device, "$IFNAME.$if_index");
+ return '' unless defined($if_name);
- $if_name =~ s/"//g;
- return $if_name;
+ $if_name =~ s/"//g;
+ return $if_name;
}
-########################################################################################
+################################################################################
# Get an interface name from a MAC address.
-########################################################################################
+################################################################################
sub get_if_from_mac($$$) {
- my ($self, $device, $mac) = @_;
+ my ($self, $device, $mac) = @_;
- # Get the port associated to the IP address.
- my @output = $self->snmp_get($device, $IFPHYSADDRESS);
- foreach my $line (@output) {
- chomp($line);
- next unless $line =~ /^IFPHYSADDRESS.(\S+)\s+=\s+\S+:\s+(.*)$/;
- my ($if_index, $if_mac) = ($1, $2);
+ # Get the port associated to the IP address.
+ my @output = $self->snmp_get($device, $IFPHYSADDRESS);
+ foreach my $line (@output) {
+ chomp($line);
+ next unless $line =~ /^IFPHYSADDRESS.(\S+)\s+=\s+\S+:\s+(.*)$/;
+ my ($if_index, $if_mac) = ($1, $2);
- # Make sure the MAC addresses match.
- next unless (mac_matches($mac, $if_mac) == 1);
+ # Make sure the MAC addresses match.
+ next unless (mac_matches($mac, $if_mac) == 1);
- # Pupulate the ARP cache.
- $self->add_mac($mac, $device);
+ # Pupulate the ARP cache.
+ $self->add_mac($mac, $device);
- # Get the name of the interface associated to the port.
- my $if_name = $self->snmp_get_value($device, "$IFNAME.$if_index");
- return '' unless defined($if_name);
+ # Get the name of the interface associated to the port.
+ my $if_name = $self->snmp_get_value($device, "$IFNAME.$if_index");
+ return '' unless defined($if_name);
- $if_name =~ s/"//g;
- return $if_name;
- }
+ $if_name =~ s/"//g;
+ return $if_name;
+ }
- return '';
+ return '';
}
-########################################################################################
+################################################################################
# Get an interface name from a port number. Returns '' on error.
-########################################################################################
+################################################################################
sub get_if_from_port($$$) {
- my ($self, $switch, $port) = @_;
+ my ($self, $switch, $port) = @_;
- # Get the interface index associated to the port.
- my $if_index = $self->snmp_get_value($switch, "$DOT1DBASEPORTIFINDEX.$port");
- return '' unless defined($if_index);
+ # Get the interface index associated to the port.
+ my $if_index = $self->snmp_get_value($switch, "$DOT1DBASEPORTIFINDEX.$port");
+ return '' unless defined($if_index);
- # Get the interface name.
- my $if_name = $self->snmp_get_value($switch, "$IFNAME.$if_index");
- return "if$if_index" unless defined($if_name);
+ # Get the interface name.
+ my $if_name = $self->snmp_get_value($switch, "$IFNAME.$if_index");
+ return "if$if_index" unless defined($if_name);
- $if_name =~ s/"//g;
- return $if_name;
+ $if_name =~ s/"//g;
+ return $if_name;
}
-########################################################################################
+################################################################################
# Returns the IP address of the given interface (by index).
-########################################################################################
+################################################################################
sub get_if_ip($$$) {
- my ($self, $device, $if_index) = @_;
+ my ($self, $device, $if_index) = @_;
- my @output = $self->snmp_get($device, $IPADENTIFINDEX);
- foreach my $line (@output) {
- chomp($line);
- return $1 if ($line =~ m/^$IPADENTIFINDEX.(\S+)\s+=\s+\S+:\s+$if_index$/);
- }
+ my @output = $self->snmp_get($device, $IPADENTIFINDEX);
+ foreach my $line (@output) {
+ chomp($line);
+ return $1 if ($line =~ m/^$IPADENTIFINDEX.(\S+)\s+=\s+\S+:\s+$if_index$/);
+ }
- return '';
+ return '';
}
-########################################################################################
+################################################################################
# Returns the MAC address of the given interface (by index).
-########################################################################################
+################################################################################
sub get_if_mac($$$) {
- my ($self, $device, $if_index) = @_;
+ my ($self, $device, $if_index) = @_;
- my $mac = $self->snmp_get_value($device, "$IFPHYSADDRESS.$if_index");
- return '' unless defined($mac);
+ my $mac = $self->snmp_get_value($device, "$IFPHYSADDRESS.$if_index");
+ return '' unless defined($mac);
- # Clean-up the MAC address.
- $mac = parse_mac($mac);
+ # Clean-up the MAC address.
+ $mac = parse_mac($mac);
- return $mac;
+ return $mac;
}
-########################################################################################
+################################################################################
# Returns the type of the given interface (by index).
-########################################################################################
+################################################################################
sub get_if_type($$$) {
- my ($self, $device, $if_index) = @_;
+ my ($self, $device, $if_index) = @_;
- my $type = $self->snmp_get_value($device, "$IFTYPE.$if_index");
- return '' unless defined($type);
+ my $type = $self->snmp_get_value($device, "$IFTYPE.$if_index");
+ return '' unless defined($type);
- return $type;
+ return $type;
}
-########################################################################################
+################################################################################
# Get an IP address from the ARP cache given the MAC address.
-########################################################################################
+################################################################################
sub get_ip_from_mac($$) {
- my ($self, $mac_addr) = @_;
+ my ($self, $mac_addr) = @_;
- if (defined($self->{'arp_cache'}->{$mac_addr})) {
- return $self->{'arp_cache'}->{$mac_addr};
- }
+ if (defined($self->{'arp_cache'}->{$mac_addr})) {
+ return $self->{'arp_cache'}->{$mac_addr};
+ }
- return undef;
+ return undef;
}
-########################################################################################
+################################################################################
# Attemtps to find
-########################################################################################
+################################################################################
sub get_mac_from_ip($$) {
- my ($self, $host) = @_;
- my $mac = undef;
+ my ($self, $host) = @_;
+ my $mac = undef;
- eval {
- $mac = `arping -c 1 -r $host 2>$DEVNULL`;
- $mac = undef unless ($? == 0);
- };
+ eval {
+ $mac = `arping -c 1 $host 2>$DEVNULL`;
+ $mac = undef unless ($? == 0);
+ };
- return unless defined($mac);
+ return unless defined($mac);
- # Clean-up the MAC address.
- chomp($mac);
- $mac = parse_mac($mac);
- $self->add_mac($mac, $host);
+ ($mac) = $mac =~ /\[(.*?)\]/ if defined($mac);
- $self->call('message', "Found MAC $mac for host $host in the local ARP cache.", 5);
+ # Clean-up the MAC address.
+ chomp($mac);
+ $mac = parse_mac($mac);
+ $self->add_mac($mac, $host);
+
+ $self->call('message', "Found MAC $mac for host $host in the local ARP cache.", 5);
}
-########################################################################################
+################################################################################
# Get a port number from an AFT entry. Returns undef on error.
-########################################################################################
+################################################################################
sub get_port_from_aft($$$) {
- my ($self, $switch, $mac) = @_;
+ my ($self, $switch, $mac) = @_;
- # Get the port associated to the MAC.
- my $port = $self->snmp_get_value($switch, "$DOT1DTPFDBPORT." . mac_to_dec($mac));
- return '' unless defined($port);
+ # Get the port associated to the MAC.
+ my $port = $self->snmp_get_value($switch, "$DOT1DTPFDBPORT." . mac_to_dec($mac));
+ return '' unless defined($port);
- return $port;
+ return $port;
}
-########################################################################################
+################################################################################
# Fill the route cache.
-########################################################################################
+################################################################################
sub get_routes($) {
- my ($self) = @_;
+ my ($self) = @_;
- # Empty the current route cache.
- $self->{'routes'} = [];
+ # Empty the current route cache.
+ $self->{'routes'} = [];
- # Parse route's output.
- my @output = `route -n 2>$DEVNULL`;
- foreach my $line (@output) {
- chomp($line);
- if ($line =~ /^0\.0\.0\.0\s+(\d+\.\d+\.\d+\.\d+).*/) {
- $self->{'default_gw'} = $1;
- } elsif ($line =~ /^(\d+\.\d+\.\d+\.\d+)\s+(\d+\.\d+\.\d+\.\d+)\s+(\d+\.\d+\.\d+\.\d+).*/) {
- push(@{$self->{'routes'}}, { dest => $1, gw => $2, mask => $3 });
- }
- }
+ # Parse route's output.
+ my @output = `route -n 2>$DEVNULL`;
+ foreach my $line (@output) {
+ chomp($line);
+ if ($line =~ /^0\.0\.0\.0\s+(\d+\.\d+\.\d+\.\d+).*/) {
+ $self->{'default_gw'} = $1;
+ } elsif ($line =~ /^(\d+\.\d+\.\d+\.\d+)\s+(\d+\.\d+\.\d+\.\d+)\s+(\d+\.\d+\.\d+\.\d+).*/) {
+ push(@{$self->{'routes'}}, { dest => $1, gw => $2, mask => $3 });
+ }
+ }
- # Replace 0.0.0.0 with the default gateway's IP.
- return unless defined($self->{'default_gw'});
- foreach my $route (@{$self->{'routes'}}) {
- $route->{gw} = $self->{'default_gw'} if ($route->{'gw'} eq '0.0.0.0');
- }
+ # Replace 0.0.0.0 with the default gateway's IP.
+ return unless defined($self->{'default_gw'});
+ foreach my $route (@{$self->{'routes'}}) {
+ $route->{gw} = $self->{'default_gw'} if ($route->{'gw'} eq '0.0.0.0');
+ }
}
-########################################################################################
+################################################################################
# Get the gateway to reach the given host.
-########################################################################################
+################################################################################
sub get_gateway($) {
- my ($self, $host) = @_;
+ my ($self, $host) = @_;
- # Look for a specific route to the given host.
- foreach my $route (@{$self->{'routes'}}) {
- if (subnet_matches($host, $route->{'dest'}, $route->{'mask'})) {
- return $route->{'gw'};
- }
- }
+ # Look for a specific route to the given host.
+ foreach my $route (@{$self->{'routes'}}) {
+ if (subnet_matches($host, $route->{'dest'}, $route->{'mask'})) {
+ return $route->{'gw'};
+ }
+ }
- # Return the default gateway.
- return $self->{'default_gw'} if defined($self->{'default_gw'});
+ # Return the default gateway.
+ return $self->{'default_gw'} if defined($self->{'default_gw'});
- # Ops!
- return undef;
+ # Ops!
+ return undef;
}
-########################################################################################
+################################################################################
# Return a pointer to an array containing configured subnets.
-########################################################################################
+################################################################################
sub get_subnets($) {
- my ($self) = @_;
+ my ($self) = @_;
- return $self->{'subnets'};
+ return $self->{'subnets'};
}
-########################################################################################
+################################################################################
# Get an array of all the visited devices.
# NOTE: This functions returns the whole device structures, not just address
# like get_hosts, get_switches, get_routers and get_all_devices.
-########################################################################################
+################################################################################
sub get_visited_devices($) {
- my ($self) = @_;
+ my ($self) = @_;
- return $self->{'visited_devices'};
+ return $self->{'visited_devices'};
}
-########################################################################################
+################################################################################
# Returns an array of found VLAN IDs.
-########################################################################################
+################################################################################
sub get_vlans($$) {
- my ($self, $device) = @_;
+ my ($self, $device) = @_;
- # Disabled in verison 3
- return () if ($self->{'snmp_version'} eq "3");
+ # Disabled in verison 3
+ return () if ($self->{'snmp_version'} eq "3");
- # Is the VLAN cache disabled?
- return () unless ($self->{'__vlan_cache_enabled__'} == 1);
+ # Is the VLAN cache disabled?
+ return () unless ($self->{'__vlan_cache_enabled__'} == 1);
- return () unless defined($self->{'vlan_cache'}->{$device});
+ return () unless defined($self->{'vlan_cache'}->{$device});
- return @{$self->{'vlan_cache'}->{$device}};
+ return @{$self->{'vlan_cache'}->{$device}};
}
-########################################################################################
+################################################################################
# Guess the type of the given device.
-########################################################################################
+################################################################################
sub guess_device_type($$) {
- my ($self, $device) = @_;
+ my ($self, $device) = @_;
- # Get the value of sysServices.
- my $services = $self->snmp_get_value($device, "$SYSSERVICES.0");
- return unless defined($services);
+ # Get the value of sysServices.
+ my $services = $self->snmp_get_value($device, "$SYSSERVICES.0");
+ return unless defined($services);
- # Check the individual bits.
- my @service_bits = split('', unpack('b8', pack('C', $services)));
+ # Check the individual bits.
+ my @service_bits = split('', unpack('b8', pack('C', $services)));
- # Check for layer 2 connectivity support.
- my $bridge_mib = $self->snmp_get_value($device, $DOT1DBASEBRIDGEADDRESS);
+ # Check for layer 2 connectivity support.
+ my $bridge_mib = $self->snmp_get_value($device, $DOT1DBASEBRIDGEADDRESS);
- # L2?
- my $device_type;
- if ($service_bits[1] == 1) {
+ # L2?
+ my $device_type;
+ if ($service_bits[1] == 1) {
- # L3?
- if ($service_bits[2] == 1) {
+ # L3?
+ if ($service_bits[2] == 1) {
- # Bridge MIB?
- if (defined($bridge_mib)) {
- $device_type = 'switch';
- } else {
+ # Bridge MIB?
+ if (defined($bridge_mib)) {
+ $device_type = 'switch';
+ } else {
- # L7?
- if ($service_bits[6] == 1) {
- $device_type = 'host';
- } else {
- $device_type = 'router';
- }
- }
- }else {
+ # L7?
+ if ($service_bits[6] == 1) {
+ $device_type = 'host';
+ } else {
+ $device_type = 'router';
+ }
+ }
+ }else {
- # Bridge MIB?
- if (defined($bridge_mib)) {
- $device_type = 'switch';
- } else {
- $device_type = 'host';
- }
- }
- }else {
+ # Bridge MIB?
+ if (defined($bridge_mib)) {
+ $device_type = 'switch';
+ } else {
+ $device_type = 'host';
+ }
+ }
+ }else {
- # L3?
- if ($service_bits[2] == 1) {
+ # L3?
+ if ($service_bits[2] == 1) {
- # L4?
- if ($service_bits[3] == 1) {
- $device_type = 'switch';
- } else {
+ # L4?
+ if ($service_bits[3] == 1) {
+ $device_type = 'switch';
+ } else {
- # L7?
- if ($service_bits[6] == 1) {
- $device_type = 'host';
- } else {
- $device_type = 'router';
- }
- }
- }else {
+ # L7?
+ if ($service_bits[6] == 1) {
+ $device_type = 'host';
+ } else {
+ $device_type = 'router';
+ }
+ }
+ }else {
- # Printer MIB?
- my $printer_mib = $self->snmp_get_value($device, $PRTMARKERINDEX);
- if (defined($printer_mib)) {
- $device_type = 'printer';
- } else {
- $device_type = 'host';
- }
- }
- }
+ # Printer MIB?
+ my $printer_mib = $self->snmp_get_value($device, $PRTMARKERINDEX);
+ if (defined($printer_mib)) {
+ $device_type = 'printer';
+ } else {
+ $device_type = 'host';
+ }
+ }
+ }
- # Set the type of the device.
- $self->set_device_type($device, $device_type);
+ # Set the type of the device.
+ $self->set_device_type($device, $device_type);
}
-########################################################################################
+################################################################################
# Return 1 if the given device has children.
-########################################################################################
+################################################################################
sub has_children($$) {
- my ($self, $device) = @_;
+ my ($self, $device) = @_;
- # Check for aliases!
- $device = $self->{'aliases'}->{$device} if defined($self->{'aliases'}->{$device});
+ # Check for aliases!
+ $device = $self->{'aliases'}->{$device} if defined($self->{'aliases'}->{$device});
- return 1 if (defined($self->{'children'}->{$device}));
+ return 1 if (defined($self->{'children'}->{$device}));
- return 0;
+ return 0;
}
-########################################################################################
+################################################################################
# Return 1 if the given device has a parent.
-########################################################################################
+################################################################################
sub has_parent($$) {
- my ($self, $device) = @_;
+ my ($self, $device) = @_;
- # Check for aliases!
- $device = $self->{'aliases'}->{$device} if defined($self->{'aliases'}->{$device});
+ # Check for aliases!
+ $device = $self->{'aliases'}->{$device} if defined($self->{'aliases'}->{$device});
- return 1 if (defined($self->{'parents'}->{$device}));
+ return 1 if (defined($self->{'parents'}->{$device}));
- return 0;
+ return 0;
}
-########################################################################################
+################################################################################
# Returns 1 if the device belongs to one of the scanned subnets.
-########################################################################################
+################################################################################
sub in_subnet($$) {
- my ($self, $device) = @_;
- $device = ip_to_long($device);
+ my ($self, $device) = @_;
+ $device = ip_to_long($device);
- # No subnets specified.
- return 1 if (scalar(@{$self->{'subnets'}}) <= 0);
+ # No subnets specified.
+ return 1 if (scalar(@{$self->{'subnets'}}) <= 0);
- foreach my $subnet (@{$self->{'subnets'}}) {
- if (subnet_matches($device, $subnet)) {
- return 1;
- }
- }
+ foreach my $subnet (@{$self->{'subnets'}}) {
+ if (subnet_matches($device, $subnet)) {
+ return 1;
+ }
+ }
- return 0;
+ return 0;
}
-##########################################################################
+################################################################################
# Check for switches that are connected to other switches/routers and show
# up in a switch/router's port.
-##########################################################################
+################################################################################
sub is_switch_connected($$$) {
- my ($self, $device, $iface) = @_;
+ my ($self, $device, $iface) = @_;
- # Check for aliases!
- $device = $self->{'aliases'}->{$device} if defined($self->{'aliases'}->{$device});
+ # Check for aliases!
+ $device = $self->{'aliases'}->{$device} if defined($self->{'aliases'}->{$device});
- return 1 if defined($self->{'switch_to_switch'}->{"${device}\t${iface}"});
+ return 1 if defined($self->{'switch_to_switch'}->{"${device}\t${iface}"});
- return 0;
+ return 0;
}
-########################################################################################
+################################################################################
# Returns 1 if the given device has already been visited, 0 otherwise.
-########################################################################################
+################################################################################
sub is_visited($$) {
- my ($self, $device) = @_;
+ my ($self, $device) = @_;
- # Check for aliases!
- $device = $self->{'aliases'}->{$device} if defined($self->{'aliases'}->{$device});
+ # Check for aliases!
+ $device = $self->{'aliases'}->{$device} if defined($self->{'aliases'}->{$device});
- if (defined($self->{'visited_devices'}->{$device})) {
- return 1;
- }
+ if (defined($self->{'visited_devices'}->{$device})) {
+ return 1;
+ }
- return 0;
+ return 0;
}
-########################################################################################
+################################################################################
# Returns 1 if the given device has responded successfully to a snmp request
# Returns 0 otherwise.
-########################################################################################
+################################################################################
sub is_snmp_discovered($$) {
- my ($self, $device) = @_;
+ my ($self, $device) = @_;
- # Check if device is into discovered cache
- return (defined($self->{'discovered_cache'}->{$device})) ? 1 : 0;
+ # Check if device is into discovered cache
+ return (defined($self->{'discovered_cache'}->{$device})) ? 1 : 0;
}
-########################################################################################
+################################################################################
# Mark the given devices as connected to each other on the given interfaces.
-########################################################################################
+################################################################################
sub mark_connected($$;$$$) {
- my ($self, $parent, $parent_if, $child, $child_if) = @_;
+ my ($self, $parent, $parent_if, $child, $child_if) = @_;
- # Check for aliases!
- $parent = $self->{'aliases'}->{$parent} if defined($self->{'aliases'}->{$parent});
- $child = $self->{'aliases'}->{$child} if defined($self->{'aliases'}->{$child});
+ # Check for aliases!
+ $parent = $self->{'aliases'}->{$parent} if defined($self->{'aliases'}->{$parent});
+ $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 '';
+ # Use ping modules when interfaces are unknown.
+ $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") {
- $self->{'connections'}->{"${parent}\t${parent_if}\t${child}\t${child_if}"} = 1;
- $self->call('connect_agents', $parent, $parent_if, $child, $child_if);
- }
+ # Do not connect devices using ping modules. A parent-child relationship is enough.
+ 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);
+ }
- # Prevent parent-child loops.
- if (!defined($self->{'parents'}->{$parent})
- ||$self->{'parents'}->{$parent} ne $child) {
+ # Prevent parent-child loops.
+ if (!defined($self->{'parents'}->{$parent})
+ ||$self->{'parents'}->{$parent} ne $child) {
- # A parent-child relationship is always created to help complete the map with
- # layer 3 information.
- $self->{'parents'}->{$child} = $parent;
- $self->{'children'}->{$parent} = $child;
- $self->call('set_parent', $child, $parent);
- }
+ # A parent-child relationship is always created to help complete the map with
+ # layer 3 information.
+ $self->{'parents'}->{$child} = $parent;
+ $self->{'children'}->{$parent} = $child;
+ $self->call('set_parent', $child, $parent);
+ }
}
-########################################################################################
+################################################################################
# Mark the given switch as having a connection on the given interface.
-########################################################################################
+################################################################################
sub mark_switch_connected($$$) {
- my ($self, $device, $iface) = @_;
+ my ($self, $device, $iface) = @_;
- # Check for aliases!
- $device = $self->{'aliases'}->{$device} if defined($self->{'aliases'}->{$device});
- $self->{'switch_to_switch'}->{"${device}\t${iface}"} = 1;
+ # Check for aliases!
+ $device = $self->{'aliases'}->{$device} if defined($self->{'aliases'}->{$device});
+ $self->{'switch_to_switch'}->{"${device}\t${iface}"} = 1;
}
-########################################################################################
+################################################################################
# Mark the given device as visited.
-########################################################################################
+################################################################################
sub mark_visited($$) {
- my ($self, $device) = @_;
+ my ($self, $device) = @_;
- $self->{'visited_devices'}->{$device} = {
- 'addr' => { $device => '' },
- 'type' => 'host'
- };
+ $self->{'visited_devices'}->{$device} = {
+ 'addr' => { $device => '' },
+ 'type' => 'host'
+ };
}
-########################################################################################
+################################################################################
# Mark the given device as snmp discovered.
-########################################################################################
+################################################################################
sub mark_discovered($$) {
- my ($self, $device) = @_;
+ my ($self, $device) = @_;
- $self->{'discovered_cache'}->{$device} = 1;
+ $self->{'discovered_cache'}->{$device} = 1;
}
-########################################################################################
+################################################################################
# Validate the configuration for the given device.
# Returns 1 if successfull snmp contact, 0 otherwise.
# Updates the SNMP community cache on v1, v2 and v2c.
-########################################################################################
+################################################################################
sub snmp_responds($$) {
- my ($self, $device) = @_;
+ my ($self, $device) = @_;
- return 1 if($self->is_snmp_discovered($device));
+ return 1 if($self->is_snmp_discovered($device));
- return ($self->{'snmp_version'} eq "3")
- ? $self->snmp_responds_v3($device)
- : $self->snmp_responds_v122c($device);
+ return ($self->{'snmp_version'} eq "3")
+ ? $self->snmp_responds_v3($device)
+ : $self->snmp_responds_v122c($device);
}
-########################################################################################
+################################################################################
# Looks for a working SNMP community for the given device. Returns 1 if one is
# found, 0 otherwise. Updates the SNMP community cache.
-########################################################################################
+################################################################################
sub snmp_responds_v122c($$) {
- my ($self, $device) = @_;
+ my ($self, $device) = @_;
- foreach my $community (@{$self->{'communities'}}) {
+ foreach my $community (@{$self->{'communities'}}) {
- # Clean blanks.
- $community =~ s/\s+//g;
+ # Clean blanks.
+ $community =~ s/\s+//g;
- my $command = $self->snmp_get_command($device, ".0", $community);
- `$command`;
- if ($? == 0) {
- $self->set_community($device, $community);
- $self->mark_discovered($device);
- return 1;
- }
- }
+ my $command = $self->snmp_get_command($device, ".0", $community);
+ `$command`;
+ if ($? == 0) {
+ $self->set_community($device, $community);
+ $self->mark_discovered($device);
+ return 1;
+ }
+ }
- return 0;
+ return 0;
}
-########################################################################################
+################################################################################
# Validate the SNMP v3 configuration for a device.
# Returns 1 if successfull snmp contact, 0 otherwise.
-########################################################################################
+################################################################################
sub snmp_responds_v3($$) {
- my ($self, $device) = @_;
+ my ($self, $device) = @_;
- my $command = $self->snmp_get_command($device, ".0");
- `$command`;
+ my $command = $self->snmp_get_command($device, ".0");
+ `$command`;
- if ($? == 0) {
- $self->mark_discovered($device);
- return 1;
- }
+ if ($? == 0) {
+ $self->mark_discovered($device);
+ return 1;
+ }
- return 0;
+ return 0;
}
-##############################################################################
+################################################################################
# Parse the local ARP cache.
-##############################################################################
+################################################################################
sub local_arp($) {
- my ($self) = @_;
+ my ($self) = @_;
- my @output = `arp -an 2>$DEVNULL`;
- foreach my $line (@output) {
- next unless ($line =~ m/\((\S+)\) at ([0-9a-f]+:[0-9a-f]+:[0-9a-f]+:[0-9a-f]+:[0-9a-f]+:[0-9a-f]+)/);
- $self->add_mac(parse_mac($2), $1);
- }
+ my @output = `arp -an 2>$DEVNULL`;
+ foreach my $line (@output) {
+ next unless ($line =~ m/\((\S+)\) at ([0-9a-f]+:[0-9a-f]+:[0-9a-f]+:[0-9a-f]+:[0-9a-f]+:[0-9a-f]+)/);
+ $self->add_mac(parse_mac($2), $1);
+ }
}
-##############################################################################
+################################################################################
# Parse remote SNMP ARP caches.
-##############################################################################
+################################################################################
sub remote_arp($$) {
- my ($self, $device) = @_;
+ my ($self, $device) = @_;
- # Try to learn more MAC addresses from the device's ARP cache.
- my @output = $self->snmp_get($device, $IPNETTOMEDIAPHYSADDRESS);
- foreach my $line (@output) {
- next unless ($line =~ /^$IPNETTOMEDIAPHYSADDRESS\.\d+\.(\S+)\s+=\s+\S+:\s+(.*)$/);
- my ($ip_addr, $mac_addr) = ($1, $2);
+ # Try to learn more MAC addresses from the device's ARP cache.
+ my @output = $self->snmp_get($device, $IPNETTOMEDIAPHYSADDRESS);
+ foreach my $line (@output) {
+ next unless ($line =~ /^$IPNETTOMEDIAPHYSADDRESS\.\d+\.(\S+)\s+=\s+\S+:\s+(.*)$/);
+ my ($ip_addr, $mac_addr) = ($1, $2);
- # Skip broadcast, net and local addresses.
- next if ($ip_addr =~ m/\.255$|\.0$|127\.0\.0\.1$/);
+ # Skip broadcast, net and local addresses.
+ next if ($ip_addr =~ m/\.255$|\.0$|127\.0\.0\.1$/);
- $mac_addr = parse_mac($mac_addr);
- $self->add_mac($mac_addr, $ip_addr);
- $self->call('message', "Found MAC $mac_addr for host $ip_addr in the ARP cache of host $device.", 5);
- }
+ $mac_addr = parse_mac($mac_addr);
+ $self->add_mac($mac_addr, $ip_addr);
+ $self->call('message', "Found MAC $mac_addr for host $ip_addr in the ARP cache of host $device.", 5);
+ }
- # Look in atPhysAddress for MAC addresses too.
- @output = $self->snmp_get($device, $ATPHYSADDRESS);
- foreach my $line (@output) {
- next unless ($line =~ m/^$ATPHYSADDRESS\.\d+\.\d+\.(\S+)\s+=\s+\S+:\s+(.*)$/);
- my ($ip_addr, $mac_addr) = ($1, $2);
+ # Look in atPhysAddress for MAC addresses too.
+ @output = $self->snmp_get($device, $ATPHYSADDRESS);
+ foreach my $line (@output) {
+ next unless ($line =~ m/^$ATPHYSADDRESS\.\d+\.\d+\.(\S+)\s+=\s+\S+:\s+(.*)$/);
+ my ($ip_addr, $mac_addr) = ($1, $2);
- # Skip broadcast, net and local addresses.
- next if ($ip_addr =~ m/\.255$|\.0$|127\.0\.0\.1$/);
+ # Skip broadcast, net and local addresses.
+ next if ($ip_addr =~ m/\.255$|\.0$|127\.0\.0\.1$/);
- $mac_addr = parse_mac($mac_addr);
- $self->add_mac($mac_addr, $ip_addr);
- $self->call('message', "Found MAC $mac_addr for host $ip_addr in the ARP cache (atPhysAddress) of host $device.", 5);
- }
+ $mac_addr = parse_mac($mac_addr);
+ $self->add_mac($mac_addr, $ip_addr);
+ $self->call('message', "Found MAC $mac_addr for host $ip_addr in the ARP cache (atPhysAddress) of host $device.", 5);
+ }
}
-##############################################################################
-# Ping the given host. Returns 1 if the host is alive, 0 otherwise.
-##############################################################################
-sub ping ($$$) {
- my ($self, $host) = @_;
- my ($timeout, $retries, $packets) = ($self->{'icmp_timeout'},$self->{'icmp_checks'},1,);
+################################################################################
+# Add agent to pool (will be registered at the end of the scan).
+################################################################################
+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;
- }
-
- # 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;
+ $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) = @_;
+
+ # Avoid create empty agents.
+ return if is_empty($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, $data) = @_;
+
+ $self->prepare_agent($agent);
+
+ $self->{'agents_found'}->{$agent}->{'modules'} = {}
+ unless ref($self->{'agents_found'}->{$agent}->{'modules'}) eq 'HASH';
+
+ # Test module. Is it well defined?
+ return unless ref($data) eq 'HASH' && defined($data->{'name'})
+ && $data->{'name'} ne '';
+
+ # Test module. Is it success? Some components have MIB name instead OID.
+ $self->{'translate_snmp'} = 1;
+ my $rs = $self->call('test_module', $agent, $data);
+ $self->{'translate_snmp'} = 0;
+
+ return unless is_enabled($rs);
+
+ $self->{'agents_found'}->{$agent}->{'modules'}{$data->{'name'}} = $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);
+ }
+
+ # WMI discovery.
+ if (is_enabled($self->{'wmi_enabled'})) {
+ # Add wmi scan if enabled.
+ $self->wmi_discovery($addr);
+ }
+}
+
+################################################################################
# Scan the given subnet.
-##########################################################################
+################################################################################
sub scan_subnet($) {
- my ($self) = @_;
- my $progress = 1;
+ my ($self) = @_;
+ my $progress = 1;
- my @subnets = @{$self->get_subnets()};
- foreach my $subnet (@subnets) {
- $self->{'c_network_percent'} = 0;
- $self->{'c_network_name'} = $subnet;
+ my @subnets = @{$self->get_subnets()};
+ 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;
+ # Clean blanks.
+ $subnet =~ s/\s+//g;
- my $net_addr = new NetAddr::IP($subnet);
- if (!defined($net_addr)) {
- $self->call('message', "Invalid network: $subnet", 3);
- next;
- }
+ my $net_addr = new NetAddr::IP($subnet);
+ if (!defined($net_addr)) {
+ $self->call('message', "Invalid network: $subnet", 3);
+ next;
+ }
- # Save the network and broadcast addresses.
- my $network = $net_addr->network();
- my $broadcast = $net_addr->broadcast();
+ # Save the network and broadcast addresses.
+ 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);
+ $host_block_size = 50 unless defined($self->{'block_size'});
- 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);
+ # The first 50% of the recon task approx.
+ my $step = 25.0 / scalar(@subnets) / (($total_hosts / $host_block_size)+1);
+ my $subnet_step = 50.0 / (($total_hosts / $host_block_size)+1);
- my @temp = split(/ /, $line);
- if (scalar(@temp) != 1) {
+ 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;
- # Junk is shown for broadcast addresses.
- # Increase summary.not_alive hosts.
- $self->{'summary'}->{'not_alive'} += 1;
- next;
- }
- my $host = $temp[0];
+ my $c_block_size = $to - $block_index;
+ my @block = pandora_block_ping(
+ {
+ 'fping' => $self->{'fping'},
+ 'networktimeout' => 0.5 # use fping defaults
+ },
+ @hosts[$block_index .. $to - 1]
+ );
- # Skip network and broadcast addresses.
- next if ($host eq $network->addr() || $host eq $broadcast->addr());
+ # check alive hosts in current block
+ %hosts_alive = (
+ %hosts_alive,
+ map {chomp; $_ => 1} @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;
+ $self->{'summary'}->{'not_alive'} += $c_block_size - (scalar @block);
+ $self->{'summary'}->{'alive'} += scalar @block;
- $self->snmp_discovery($host);
+ # Update progress.
+ $progress += $step;
+ $self->{'c_network_percent'} += $subnet_step;
- # 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;
+ if ($total_hosts == 0) {
+ # Populate.
+ $self->{'c_network_percent'} += 50;
+ $self->call('update_progress', ceil($progress)+25);
+ next;
+ }
+ $step = 25.0 / scalar(@subnets) / $total_hosts;
+ $subnet_step = 50.0 / $total_hosts;
- $self->call('message', "Scanning host: $host", 5);
- $self->call('update_progress', ceil($progress));
- $progress += $step;
+ $self->{'step'} = STEP_CAPABILITIES;
+ foreach my $addr (keys %hosts_alive) {
+ # Increase self summary.alive hosts.
+ $self->call('message', "Scanning host: $addr", 5);
+ $self->{'c_network_name'} = $addr;
- # Check if the host is up.
- if ($self->ping($host) == 0) {
- $self->{'summary'}->{'not_alive'} += 1;
- next;
- }
+ # Update progress.
+ $progress += $step;
+ $self->{'c_network_percent'} += $subnet_step;
- $self->{'summary'}->{'alive'} += 1;
- $self->{'c_network_percent'} += $subnet_step;
+ # Populate.
+ $self->call('update_progress', ceil($progress));
- $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
-##########################################################################
+################################################################################
sub cloud_scan($) {
- my $self = shift;
- my ($progress, $step);
+ my $self = shift;
+ my ($progress, $step);
- my $type = '';
+ my $type = '';
- if ( $self->{'task_data'}->{'type'} == DISCOVERY_CLOUD_AWS_EC2
- || $self->{'task_data'}->{'type'} == DISCOVERY_CLOUD_AWS_RDS) {
- $type = 'Aws';
- } else {
+ if ( $self->{'task_data'}->{'type'} == DISCOVERY_CLOUD_AWS_EC2
+ || $self->{'task_data'}->{'type'} == DISCOVERY_CLOUD_AWS_RDS) {
+ $type = 'Aws';
+ } else {
- # Unrecognized task type.
- $self->call('message', 'Unrecognized task type', 1);
- $self->call('update_progress', -1);
- return;
- }
+ # Unrecognized task type.
+ $self->call('message', 'Unrecognized task type', 1);
+ $self->call('update_progress', -1);
+ return;
+ }
- # Initialize cloud object.
- my $cloudObj = PandoraFMS::Recon::Util::enterprise_new(
- 'PandoraFMS::Recon::Cloud::'.$type,
- [
- task_data => $self->{'task_data'},
- aws_access_key_id => $self->{'aws_access_key_id'},
- aws_secret_access_key => $self->{'aws_secret_access_key'},
- cloud_util_path => $self->{'cloud_util_path'},
- creds_file => $self->{'creds_file'},
- parent => $self
- ]
+ # Initialize cloud object.
+ my $cloudObj = PandoraFMS::Recon::Util::enterprise_new(
+ 'PandoraFMS::Recon::Cloud::'.$type,
+ [
+ task_data => $self->{'task_data'},
+ aws_access_key_id => $self->{'aws_access_key_id'},
+ aws_secret_access_key => $self->{'aws_secret_access_key'},
+ cloud_util_path => $self->{'cloud_util_path'},
+ creds_file => $self->{'creds_file'},
+ parent => $self
+ ]
- );
+ );
- if (!$cloudObj) {
+ if (!$cloudObj) {
- # Failed to initialize, check Cloud credentials or anything.
- $self->call('message', 'Unable to initialize PandoraFMS::Recon::Cloud::'.$type, 3);
- } else {
+ # Failed to initialize, check Cloud credentials or anything.
+ $self->call('message', 'Unable to initialize PandoraFMS::Recon::Cloud::'.$type, 3);
+ } else {
- # Let Cloud object manage scan.
- $cloudObj->scan();
- }
+ # Let Cloud object manage scan.
+ $cloudObj->scan();
+ }
- # Update progress.
- # Done!
- $self->{'step'} = '';
- $self->call('update_progress', -1);
+ # Update progress.
+ # Done!
+ $self->{'step'} = '';
+ $self->call('update_progress', -1);
}
-##########################################################################
+################################################################################
# Performs a database scan.
-##########################################################################
+################################################################################
sub database_scan($$$) {
- my ($self, $type, $obj, $global_percent, $targets) = @_;
+ my ($self, $type, $obj, $global_percent, $targets) = @_;
- my @data;
- my @modules;
+ my @data;
+ my @modules;
- my $dbObjCfg = $obj->get_config();
+ my $dbObjCfg = $obj->get_config();
- $self->{'summary'}->{'discovered'} += 1;
- $self->{'summary'}->{'alive'} += 1;
+ $self->{'summary'}->{'discovered'} += 1;
+ $self->{'summary'}->{'alive'} += 1;
- push @modules,
- {
- name => $type . ' connection',
- type => 'generic_proc',
- data => 1,
- description => $type . ' availability'
- };
+ push @modules,
+ {
+ name => $type . ' connection',
+ type => 'generic_proc',
+ data => 1,
+ description => $type . ' availability'
+ };
- # Analyze.
- $self->{'step'} = STEP_STATISTICS;
- $self->{'c_network_percent'} = 30;
- $self->call('update_progress', $global_percent + (30 / (scalar @$targets)));
- $self->{'c_network_name'} = $obj->get_host();
+ # Analyze.
+ $self->{'step'} = STEP_STATISTICS;
+ $self->{'c_network_percent'} = 30;
+ $self->call('update_progress', $global_percent + (30 / (scalar @$targets)));
+ $self->{'c_network_name'} = $obj->get_host();
- # Retrieve connection statistics.
- # Retrieve uptime statistics
- # Retrieve query stats
- # Retrieve connections
- # Retrieve innodb
- # Retrieve cache
- $self->{'c_network_percent'} = 50;
- $self->call('update_progress', $global_percent + (50 / (scalar @$targets)));
- push @modules, $obj->get_statistics();
+ # Retrieve connection statistics.
+ # Retrieve uptime statistics
+ # Retrieve query stats
+ # Retrieve connections
+ # Retrieve innodb
+ # Retrieve cache
+ $self->{'c_network_percent'} = 50;
+ $self->call('update_progress', $global_percent + (50 / (scalar @$targets)));
+ push @modules, $obj->get_statistics();
- # Custom queries.
- $self->{'step'} = STEP_CUSTOM_QUERIES;
- $self->{'c_network_percent'} = 80;
- $self->call('update_progress', $global_percent + (80 / (scalar @$targets)));
- push @modules, $obj->execute_custom_queries();
+ # Custom queries.
+ $self->{'step'} = STEP_CUSTOM_QUERIES;
+ $self->{'c_network_percent'} = 80;
+ $self->call('update_progress', $global_percent + (80 / (scalar @$targets)));
+ push @modules, $obj->execute_custom_queries();
- if (defined($dbObjCfg->{'scan_databases'})
- && "$dbObjCfg->{'scan_databases'}" eq "1") {
+ if (defined($dbObjCfg->{'scan_databases'})
+ && "$dbObjCfg->{'scan_databases'}" eq "1") {
- # Skip database scan in Oracle tasks
- next if defined($self->{'type'}) && $self->{'type'} == DISCOVERY_APP_ORACLE;
+ # Skip database scan in Oracle tasks
+ next if defined($self->{'type'}) && $self->{'type'} == DISCOVERY_APP_ORACLE;
- my $__data = $obj->scan_databases();
+ my $__data = $obj->scan_databases();
- if (ref($__data) eq "ARRAY") {
- if (defined($dbObjCfg->{'agent_per_database'})
- && $dbObjCfg->{'agent_per_database'} == 1) {
+ if (ref($__data) eq "ARRAY") {
+ if (defined($dbObjCfg->{'agent_per_database'})
+ && $dbObjCfg->{'agent_per_database'} == 1) {
- # Agent per database detected.
- push @data, @{$__data};
+ # Agent per database detected.
+ push @data, @{$__data};
- } else {
+ } else {
- # Merge modules into engine agent.
- my @_modules = map {
- map { $_ }
- @{$_->{'module_data'}}
- } @{$__data};
+ # Merge modules into engine agent.
+ my @_modules = map {
+ map { $_ }
+ @{$_->{'module_data'}}
+ } @{$__data};
- push @modules, @_modules;
- }
- }
- }
+ push @modules, @_modules;
+ }
+ }
+ }
- return {
- 'modules' => \@modules,
- 'data' => \@data
- };
+ return {
+ 'modules' => \@modules,
+ 'data' => \@data
+ };
}
-##########################################################################
+################################################################################
# Perform an Application scan.
-##########################################################################
+################################################################################
sub app_scan($) {
- my ($self) = @_;
- my ($progress, $step);
+ my ($self) = @_;
+ my ($progress, $step);
- my $type = '';
- my $db_scan = 0;
+ my $type = '';
+ my $db_scan = 0;
- # APP object initialization.
- if ($self->{'task_data'}->{'type'} == DISCOVERY_APP_MYSQL) {
- $type = 'MySQL';
- } elsif ($self->{'task_data'}->{'type'} == DISCOVERY_APP_ORACLE) {
- $type = 'Oracle';
- } elsif ($self->{'task_data'}->{'type'} == DISCOVERY_APP_SAP) {
- $type = 'SAP';
- } else {
- # Unrecognized task type.
- $self->call('message', 'Unrecognized task type', 1);
- $self->call('update_progress', -1);
- return;
- }
+ # APP object initialization.
+ if ($self->{'task_data'}->{'type'} == DISCOVERY_APP_MYSQL) {
+ $type = 'MySQL';
+ } elsif ($self->{'task_data'}->{'type'} == DISCOVERY_APP_ORACLE) {
+ $type = 'Oracle';
+ } elsif ($self->{'task_data'}->{'type'} == DISCOVERY_APP_SAP) {
+ $type = 'SAP';
+ } else {
+ # Unrecognized task type.
+ $self->call('message', 'Unrecognized task type', 1);
+ $self->call('update_progress', -1);
+ return;
+ }
- my @targets = split /,/, $self->{'task_data'}->{'subnet'};
+ my @targets = split /,/, $self->{'task_data'}->{'subnet'};
- my $global_step = 100 / (scalar @targets);
- my $global_percent = 0;
- my $i = 0;
- foreach my $target (@targets) {
- if ( !defined($target)
- || $target eq ''
- || $target =~ /^#/) {
- # Ignore empty target or commented one.
- next;
- }
+ my $global_step = 100 / (scalar @targets);
+ my $global_percent = 0;
+ my $i = 0;
+ foreach my $target (@targets) {
+ if ( !defined($target)
+ || $target eq ''
+ || $target =~ /^#/) {
+ # Ignore empty target or commented one.
+ next;
+ }
- my @data;
- my @modules;
+ my @data;
+ my @modules;
- $self->{'step'} = STEP_APP_SCAN;
- $self->{'c_network_name'} = $target;
- $self->{'c_network_percent'} = 0;
+ $self->{'step'} = STEP_APP_SCAN;
+ $self->{'c_network_name'} = $target;
+ $self->{'c_network_percent'} = 0;
- # Send message
- $self->call('message', 'Checking target ' . $target, 10);
+ # Send message
+ $self->call('message', 'Checking target ' . $target, 10);
- # Force target acquirement.
- $self->{'task_data'}->{'dbhost'} = $target;
- $self->{'task_data'}->{'target_index'} = $i++;
+ # Force target acquirement.
+ $self->{'task_data'}->{'dbhost'} = $target;
+ $self->{'task_data'}->{'target_index'} = $i++;
- # Update progress
- $self->{'c_network_percent'} = 10;
- $self->call('update_progress', $global_percent + (10 / (scalar @targets)));
+ # Update progress
+ $self->{'c_network_percent'} = 10;
+ $self->call('update_progress', $global_percent + (10 / (scalar @targets)));
- # Connect to target.
- my $obj = PandoraFMS::Recon::Util::enterprise_new(
- 'PandoraFMS::Recon::Applications::'.$type,
- {
- %{$self->{'task_data'}},
- 'target' => $target,
- 'pa_config' => $self->{'pa_config'},
- 'parent' => $self
- },
- );
+ # Connect to target.
+ my $obj = PandoraFMS::Recon::Util::enterprise_new(
+ 'PandoraFMS::Recon::Applications::'.$type,
+ {
+ %{$self->{'task_data'}},
+ 'target' => $target,
+ 'pa_config' => $self->{'pa_config'},
+ 'parent' => $self
+ },
+ );
- if (defined($obj)) {
+ if (defined($obj)) {
- # Verify if object is connected. If cannot connect to current target
- # return with module.
- if (!$obj->is_connected()) {
- $self->call('message', 'Cannot connect to target ' . $target, 3);
- $global_percent += $global_step;
- $self->{'c_network_percent'} = 90;
+ # Verify if object is connected. If cannot connect to current target
+ # return with module.
+ if (!$obj->is_connected()) {
+ $self->call('message', 'Cannot connect to target ' . $target, 3);
+ $global_percent += $global_step;
+ $self->{'c_network_percent'} = 90;
- # Update progress
- $self->call('update_progress', $global_percent + (90 / (scalar @targets)));
- $self->{'summary'}->{'not_alive'} += 1;
- push @modules, {
- name => $type . ' connection',
- type => 'generic_proc',
- data => 0,
- description => $type . ' availability'
- };
+ # Update progress
+ $self->call('update_progress', $global_percent + (90 / (scalar @targets)));
+ $self->{'summary'}->{'not_alive'} += 1;
+ push @modules, {
+ name => $type . ' connection',
+ type => 'generic_proc',
+ data => 0,
+ description => $type . ' availability'
+ };
- } else {
- #
- # $results is always a hash with:
- # @modules => 'global' modules.
- # @data => {
- # 'agent_data' => {}
- # 'module_data' => []
- # }
- my $results;
+ } else {
+ #
+ # $results is always a hash with:
+ # @modules => 'global' modules.
+ # @data => {
+ # 'agent_data' => {}
+ # 'module_data' => []
+ # }
+ my $results;
- # Scan connected obj.
- if ( $self->{'task_data'}->{'type'} == DISCOVERY_APP_MYSQL
- || $self->{'task_data'}->{'type'} == DISCOVERY_APP_ORACLE) {
+ # Scan connected obj.
+ if ( $self->{'task_data'}->{'type'} == DISCOVERY_APP_MYSQL
+ || $self->{'task_data'}->{'type'} == DISCOVERY_APP_ORACLE) {
- # Database.
- $results = $self->database_scan($type, $obj, $global_percent, \@targets);
+ # Database.
+ $results = $self->database_scan($type, $obj, $global_percent, \@targets);
- } elsif ($self->{'task_data'}->{'type'} == DISCOVERY_APP_SAP) {
+ } elsif ($self->{'task_data'}->{'type'} == DISCOVERY_APP_SAP) {
- # SAP scan
- $results = $obj->scan();
+ # SAP scan
+ $results = $obj->scan();
- }
+ }
- # Add results.
- if (ref($results) eq 'HASH') {
- if (defined($results->{'modules'})) {
- push @modules, @{$results->{'modules'}};
- }
+ # Add results.
+ if (ref($results) eq 'HASH') {
+ if (defined($results->{'modules'})) {
+ push @modules, @{$results->{'modules'}};
+ }
- if (defined($results->{'data'})) {
- push @data, @{$results->{'data'}};
- }
- }
- }
+ if (defined($results->{'data'})) {
+ push @data, @{$results->{'data'}};
+ }
+ }
+ }
- # Put engine agent at the beginning of the list.
- my $version = $obj->get_version();
- unshift @data, {
- 'agent_data' => {
- 'agent_name' => $obj->get_agent_name(),
- 'os' => $type,
- 'os_version' => (defined($version) ? $version : 'Discovery'),
- 'interval' => $self->{'task_data'}->{'interval_sweep'},
- 'id_group' => $self->{'task_data'}->{'id_group'},
- 'address' => $obj->get_host(),
- 'description' => '',
- },
- 'module_data' => \@modules,
- };
+ # Put engine agent at the beginning of the list.
+ my $version = $obj->get_version();
+ unshift @data, {
+ 'agent_data' => {
+ 'agent_name' => $obj->get_agent_name(),
+ 'os' => $type,
+ 'os_version' => (defined($version) ? $version : 'Discovery'),
+ 'interval' => $self->{'task_data'}->{'interval_sweep'},
+ 'id_group' => $self->{'task_data'}->{'id_group'},
+ 'address' => $obj->get_host(),
+ 'description' => '',
+ },
+ 'module_data' => \@modules,
+ };
- $self->call('create_agents', \@data);
+ $self->call('create_agents', \@data);
- # Destroy item.
- undef($obj);
- }
+ # Destroy item.
+ undef($obj);
+ }
- $global_percent += $global_step;
- $self->{'c_network_percent'} = 100;
- $self->call('update_progress', $global_percent);
- }
+ $global_percent += $global_step;
+ $self->{'c_network_percent'} = 100;
+ $self->call('update_progress', $global_percent);
+ }
- # Update progress.
- # Done!
- $self->{'step'} = '';
- $self->call('update_progress', -1);
+ # Update progress.
+ # Done!
+ $self->{'step'} = '';
+ $self->call('update_progress', -1);
}
-##########################################################################
+################################################################################
# Perform a deployment scan.
-##########################################################################
+################################################################################
sub deploy_scan($) {
- my $self = shift;
- my ($progress, $step);
+ my $self = shift;
+ my ($progress, $step);
- my $type = '';
+ my $type = '';
- # Initialize deployer object.
- my $deployer = PandoraFMS::Recon::Util::enterprise_new(
- 'PandoraFMS::Recon::Deployer',
- [
- task_data => $self->{'task_data'},
- parent => $self
- ]
+ # Initialize deployer object.
+ my $deployer = PandoraFMS::Recon::Util::enterprise_new(
+ 'PandoraFMS::Recon::Deployer',
+ [
+ task_data => $self->{'task_data'},
+ parent => $self
+ ]
- );
+ );
- if (!$deployer) {
+ if (!$deployer) {
- # Failed to initialize, check Cloud credentials or anything.
- $self->call('message', 'Unable to initialize PandoraFMS::Recon::Deployer', 3);
- } else {
+ # Failed to initialize, check Cloud credentials or anything.
+ $self->call('message', 'Unable to initialize PandoraFMS::Recon::Deployer', 3);
+ } else {
- # Let deployer object manage scan.
- $deployer->scan();
- }
+ # Let deployer object manage scan.
+ $deployer->scan();
+ }
- # Update progress.
- # Done!
- $self->{'step'} = '';
- $self->call('update_progress', -1);
+ # Update progress.
+ # Done!
+ $self->{'step'} = '';
+ $self->call('update_progress', -1);
}
-##########################################################################
+################################################################################
# Perform a network scan.
-##########################################################################
+################################################################################
sub scan($) {
- my ($self) = @_;
- my ($progress, $step) = 1, 0;
+ my ($self) = @_;
+ my ($progress, $step) = 1, 0;
- # 1%
- $self->call('update_progress', 1);
+ # 1%
+ $self->call('update_progress', 1);
- if (defined($self->{'task_data'})) {
- if ( $self->{'task_data'}->{'type'} == DISCOVERY_APP_MYSQL
- || $self->{'task_data'}->{'type'} == DISCOVERY_APP_ORACLE
- || $self->{'task_data'}->{'type'} == DISCOVERY_APP_SAP) {
- # Application scan.
- $self->call('message', "Scanning application ...", 6);
- return $self->app_scan();
- }
+ if (defined($self->{'task_data'})) {
+ if ( $self->{'task_data'}->{'type'} == DISCOVERY_APP_MYSQL
+ || $self->{'task_data'}->{'type'} == DISCOVERY_APP_ORACLE
+ || $self->{'task_data'}->{'type'} == DISCOVERY_APP_SAP) {
+ # Application scan.
+ $self->call('message', "Scanning application ...", 6);
+ return $self->app_scan();
+ }
- if ($self->{'task_data'}->{'type'} == DISCOVERY_CLOUD_AWS_RDS) {
+ if ($self->{'task_data'}->{'type'} == DISCOVERY_CLOUD_AWS_RDS) {
- # Cloud scan.
- return $self->cloud_scan();
- }
+ # Cloud scan.
+ return $self->cloud_scan();
+ }
- if($self->{'task_data'}->{'type'} == DISCOVERY_DEPLOY_AGENTS) {
- return $self->deploy_scan();
- }
- }
+ if($self->{'task_data'}->{'type'} == DISCOVERY_DEPLOY_AGENTS) {
+ return $self->deploy_scan();
+ }
+ }
- # Find devices.
- $self->call('message', "[1/4] Scanning the network...", 3);
- $self->{'step'} = STEP_SCANNING;
- $self->call('update_progress', $progress);
- $self->scan_subnet();
+ if(defined($self->{'task_data'}{'review_mode'})
+ && $self->{'task_data'}{'review_mode'} == DISCOVERY_RESULTS
+ ) {
+ # Use Cached results.
+ $self->{'step'} = STEP_PROCESSING;
+ $self->call('report_scanned_agents');
- # Read the local ARP cache.
- $self->local_arp();
+ # Done!
+ $self->{'step'} = '';
+ $self->call('update_progress', -1);
+ return;
+ }
- # Get a list of found hosts.
- my @hosts = @{$self->get_hosts()};
- if (scalar(@hosts) > 0 && $self->{'parent_detection'} == 1) {
+ # Find devices.
+ $self->call('message', "[1/6] Scanning the network...", 3);
+ $self->{'c_network_name'} = '';
+ $self->{'step'} = STEP_SCANNING;
+ $self->call('update_progress', $progress);
- # Delete previous connections.
- $self->call('delete_connections');
+ $self->scan_subnet();
+ # Read the local ARP cache.
+ $self->local_arp();
- # 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%.
- for (my $i = 0; defined($hosts[$i]); $i++) {
- $self->call('update_progress', $progress);
- $progress += $step;
- $self->aft_connectivity($hosts[$i]);
- }
+ # Get a list of found hosts.
+ my @hosts = @{$self->get_hosts()};
+ if (scalar(@hosts) > 0 && $self->{'parent_detection'} == 1) {
- # 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%.
- foreach my $host (@hosts) {
- $self->call('update_progress', $progress);
- $progress += $step;
- next if ($self->has_parent($host) || $self->has_children($host));
- $self->traceroute_connectivity($host);
- }
+ # Delete previous connections.
+ $self->call('delete_connections');
- # 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%.
- $self->get_routes(); # Update the route cache.
- foreach my $host (@hosts) {
- $self->call('update_progress', $progress);
- $progress += $step;
- next if ($self->has_parent($host));
- $self->gateway_connectivity($host);
- }
- }
+ # Connectivity from address forwarding tables.
+ $self->call('message', "[2/6] Finding address forwarding table connectivity...", 3);
+ $self->{'c_network_name'} = '';
+ $self->{'step'} = STEP_AFT;
+ ($progress, $step) = (50, 10.0 / scalar(@hosts)); # From 50% to 60%.
+ for (my $i = 0; defined($hosts[$i]); $i++) {
+ $self->call('update_progress', $progress);
+ $progress += $step;
+ $self->aft_connectivity($hosts[$i]);
+ }
- # Done!
- $self->{'step'} = '';
- $self->call('update_progress', -1);
+ # Connect hosts that are still unconnected using traceroute.
+ $self->call('message', "[3/6] Finding traceroute connectivity.", 3);
+ $self->{'c_network_name'} = '';
+ $self->{'step'} = STEP_TRACEROUTE;
+ ($progress, $step) = (60, 10.0 / scalar(@hosts)); # From 60% to 70%.
+ foreach my $host (@hosts) {
+ $self->call('update_progress', $progress);
+ $progress += $step;
+ next if ($self->has_parent($host) || $self->has_children($host));
+ $self->traceroute_connectivity($host);
+ }
- # Print debug information on found devices.
- $self->call('message', "[Summary]", 3);
- foreach my $host (@hosts) {
- my $device = $self->get_device($host);
- next unless defined($device);
+ # Connect hosts that are still unconnected using known gateways.
+ $self->call('message', "[4/6] Finding host to gateway connectivity.", 3);
+ $self->{'c_network_name'} = '';
+ $self->{'step'} = STEP_GATEWAY;
+ ($progress, $step) = (70, 10.0 / scalar(@hosts)); # From 70% to 80%.
+ $self->get_routes(); # Update the route cache.
+ foreach my $host (@hosts) {
+ $self->call('update_progress', $progress);
+ $progress += $step;
+ next if ($self->has_parent($host));
+ $self->gateway_connectivity($host);
+ }
+ }
+
+ # Apply monitoring templates
+ $self->call('message', "[5/6] Applying monitoring.", 3);
+ $self->{'step'} = STEP_MONITORING;
+ $self->call('apply_monitoring', $self);
+
+ # Print debug information on found devices.
+ $self->call('message', "[Summary]", 3);
+ foreach my $host (@hosts) {
+ my $device = $self->get_device($host);
+ next unless defined($device);
+
+ # Print device information.
+ my $dev_info = "Device: " . $device->{'type'} . " (";
+ foreach my $ip_address ($self->get_addresses($host)) {
+ $dev_info .= "$ip_address,";
+ }
+ chop($dev_info);
+ $dev_info .= ')';
+ $self->call('message', $dev_info, 3);
+ }
+
+ # Apply monitoring templates
+ $self->call('message', "[6/6] Processing results.", 3);
+ $self->{'step'} = STEP_PROCESSING;
+ # Send agent information to Database (Discovery) or XML (satellite.).
+ $self->call('report_scanned_agents');
+
+ if(defined($self->{'task_data'}{'review_mode'})
+ && $self->{'task_data'}{'review_mode'} == DISCOVERY_STANDARD
+ ) {
+ # Send agent information to Database (Discovery) or XML (satellite.).
+ $self->call('report_scanned_agents', 1);
+ }
+
+ # Done!
+ $self->{'step'} = '';
+ $self->call('update_progress', -1);
- # Print device information.
- my $dev_info = "Device: " . $device->{'type'} . " (";
- foreach my $ip_address ($self->get_addresses($host)) {
- $dev_info .= "$ip_address,";
- }
- chop($dev_info);
- $dev_info .= ')';
- $self->call('message', $dev_info, 3);
- }
}
-########################################################################################
+################################################################################
# Set an SNMP community for the given device.
-########################################################################################
+################################################################################
sub set_community($$$) {
- my ($self, $device, $community) = @_;
+ my ($self, $device, $community) = @_;
- $self->{'community_cache'}->{$device} = $community;
+ $self->{'community_cache'}->{$device} = $community;
}
-########################################################################################
+################################################################################
# Set the type of the given device.
-########################################################################################
+################################################################################
sub set_device_type($$$) {
- my ($self, $device, $type) = @_;
+ my ($self, $device, $type) = @_;
- $self->{'visited_devices'}->{$device}->{'type'} = $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_value($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.
-########################################################################################
+################################################################################
sub snmp_get($$$) {
- my ($self, $device, $oid) = @_;
- my @output;
+ my ($self, $device, $oid) = @_;
+ my @output;
- return () unless defined $self->is_snmp_discovered($device);
- my $community = $self->get_community($device);
+ return () unless defined $self->is_snmp_discovered($device);
+ my $community = $self->get_community($device);
- # Check the SNMP query cache first.
- if (defined($self->{'snmp_cache'}->{"${device}_${oid}"})) {
- return @{$self->{'snmp_cache'}->{"${device}_${oid}"}};
- }
+ # Check the SNMP query cache first.
+ if (defined($self->{'snmp_cache'}->{"${device}_${oid}"})) {
+ return @{$self->{'snmp_cache'}->{"${device}_${oid}"}};
+ }
- # Check VLANS.
- my @vlans = $self->get_vlans($device);
- if (scalar(@vlans) == 0) {
- my $command = $self->snmp_get_command($device, $oid, $community);
- @output = `$command`;
- }else {
+ # Check VLANS.
+ my @vlans = $self->get_vlans($device);
+ if (scalar(@vlans) == 0) {
+ my $command = $self->snmp_get_command($device, $oid, $community);
+ @output = `$command`;
+ }else {
- # Handle duplicate lines.
- my %output_hash;
- foreach my $vlan (@vlans) {
- my $command = $self->snmp_get_command($device, $oid, $community, $vlan);
- foreach my $line (`$command`) {
- $output_hash{$line} = 1;
- }
- }
- push(@output, keys(%output_hash));
- }
+ # Handle duplicate lines.
+ my %output_hash;
+ foreach my $vlan (@vlans) {
+ my $command = $self->snmp_get_command($device, $oid, $community, $vlan);
+ foreach my $line (`$command`) {
+ $output_hash{$line} = 1;
+ }
+ }
+ push(@output, keys(%output_hash));
+ }
- # Update the SNMP query cache.
- $self->{'snmp_cache'}->{"${device}_${oid}"} = [@output];
+ # Update the SNMP query cache.
+ $self->{'snmp_cache'}->{"${device}_${oid}"} = [@output];
- return @output;
+ return @output;
}
-########################################################################################
+################################################################################
# Get the snmpwalk command seing version 1, 2, 2c or 3.
-########################################################################################
+################################################################################
sub snmp_get_command {
- my ($self, $device, $oid, $community, $vlan) = @_;
- $vlan = defined($vlan) ? "\@" . $vlan : '';
+ my ($self, $device, $oid, $community, $vlan) = @_;
+ $vlan = defined($vlan) ? "\@" . $vlan : '';
- my $command = "snmpwalk -M$DEVNULL -r$self->{'snmp_checks'} -t$self->{'snmp_timeout'} -v$self->{'snmp_version'} -On -Oe ";
- if ($self->{'snmp_version'} eq "3") {
- if ($self->{'community'}) { # Context
- $command .= " -N $self->{'community'} ";
- }
- $command .= " -l$self->{'snmp_security_level'} ";
- if ($self->{'snmp_security_level'} ne "noAuthNoPriv") {
- $command .= " -u$self->{'snmp_auth_user'} -a$self->{'snmp_auth_method'} -A$self->{'snmp_auth_pass'} ";
- }
- if ($self->{'snmp_security_level'} eq "authPriv") {
- $command .= " -x$self->{'snmp_privacy_method'} -X$self->{'snmp_privacy_pass'} ";
- }
- } else {
- $command .= " -c$community$vlan ";
- }
+ my $command = "snmpwalk -M$DEVNULL -r$self->{'snmp_checks'} -t$self->{'snmp_timeout'} -v$self->{'snmp_version'} -On -Oe ";
+ if ($self->{'snmp_version'} eq "3") {
+ if ($self->{'community'}) { # Context
+ $command .= " -N $self->{'community'} ";
+ }
+ $command .= " -l$self->{'snmp_security_level'} ";
+ if ($self->{'snmp_security_level'} ne "noAuthNoPriv") {
+ $command .= " -u$self->{'snmp_auth_user'} -a$self->{'snmp_auth_method'} -A$self->{'snmp_auth_pass'} ";
+ }
+ if ($self->{'snmp_security_level'} eq "authPriv") {
+ $command .= " -x$self->{'snmp_privacy_method'} -X$self->{'snmp_privacy_pass'} ";
+ }
+ } else {
+ $command .= " -c$community$vlan ";
+ }
- return "$command $device $oid 2>$DEVNULL";
+ return "$command $device $oid 2>$DEVNULL";
}
-########################################################################################
+################################################################################
# Performs an SNMP WALK and returns the value of the given OID. Returns undef
# on error.
-########################################################################################
+################################################################################
sub snmp_get_value($$$) {
- my ($self, $device, $oid) = @_;
+ my ($self, $device, $oid) = @_;
- my @output = $self->snmp_get($device, $oid);
- foreach my $line (@output) {
- chomp($line);
- return $1 if ($line =~ /^$oid\s+=\s+\S+:\s+(.*)$/);
- }
+ my $effective_oid = $oid;
+ if (is_enabled($self->{'translate_snmp'})) {
+ $effective_oid = `snmptranslate $oid -On 2>$DEVNULL`;
+ chomp($effective_oid);
+ }
- return undef;
+ my @output = $self->snmp_get($device, $effective_oid);
+
+ foreach my $line (@output) {
+ chomp($line);
+ return $1 if ($line =~ /^$effective_oid\s+=\s+\S+:\s+(.*)$/);
+ }
+
+ return undef;
}
-########################################################################################
+################################################################################
# Performs an SNMP WALK and returns an array of values.
-########################################################################################
+################################################################################
sub snmp_get_value_array($$$) {
- my ($self, $device, $oid) = @_;
- my @values;
+ my ($self, $device, $oid) = @_;
+ my @values;
- my @output = $self->snmp_get($device, $oid);
- foreach my $line (@output) {
- chomp($line);
- push(@values, $1) if ($line =~ /^$oid\S*\s+=\s+\S+:\s+(.*)$/);
- }
+ my @output = $self->snmp_get($device, $oid);
+ foreach my $line (@output) {
+ chomp($line);
+ push(@values, $1) if ($line =~ /^$oid\S*\s+=\s+\S+:\s+(.*)$/);
+ }
- return @values;
+ return @values;
}
-########################################################################################
+################################################################################
# Performs an SNMP WALK and returns a hash of values.
-########################################################################################
+################################################################################
sub snmp_get_value_hash($$$) {
- my ($self, $device, $oid) = @_;
- my %values;
+ my ($self, $device, $oid) = @_;
+ my %values;
- my @output = $self->snmp_get_value_array($device, $oid);
- foreach my $line (@output) {
- $values{$line} = '';
- }
+ my @output = $self->snmp_get_value_array($device, $oid);
+ foreach my $line (@output) {
+ $values{$line} = '';
+ }
- return %values;
+ return %values;
}
-##########################################################################
+################################################################################
# Connect the given host to its parent using traceroute.
-##########################################################################
+################################################################################
sub traceroute_connectivity($$) {
- my ($self, $host) = @_;
+ my ($self, $host) = @_;
- # Perform a traceroute.
- my $nmap_args = '-nsP -PE --traceroute --max-retries '.$self->{'icmp_checks'}.' --host-timeout '.$self->{'icmp_timeout'}.'s -T'.$self->{'recon_timing_template'};
- my $np = PandoraFMS::Recon::NmapParser->new();
- eval {$np->parsescan($self->{'nmap'}, $nmap_args, ($host));};
- return if ($@);
+ # Perform a traceroute.
+ my $nmap_args = '-nsP -PE --traceroute --max-retries '.$self->{'icmp_checks'}.' --host-timeout '.$self->{'icmp_timeout'}.'s -T'.$self->{'recon_timing_template'};
+ my $np = PandoraFMS::Recon::NmapParser->new();
+ eval {$np->parsescan($self->{'nmap'}, $nmap_args, ($host));};
+ return if ($@);
- # Get hops to the host.
- my ($h) = $np->all_hosts();
- return unless defined($h);
- my @hops = $h->all_trace_hops();
+ # Get hops to the host.
+ my ($h) = $np->all_hosts();
+ return unless defined($h);
+ my @hops = $h->all_trace_hops();
- # Skip the target host.
- pop(@hops);
+ # Skip the target host.
+ pop(@hops);
- # Reverse the host order (closest hosts first).
- @hops = reverse(@hops);
+ # Reverse the host order (closest hosts first).
+ @hops = reverse(@hops);
- # Look for parents.
- my $device = $host;
- for (my $i = 0; $i < $self->{'parent_recursion'}; $i++) {
- next unless defined($hops[$i]);
- my $parent = $hops[$i]->ipaddr();
+ # Look for parents.
+ my $device = $host;
+ for (my $i = 0; $i < $self->{'parent_recursion'}; $i++) {
+ next if is_empty($hops[$i]);
+ my $parent = $hops[$i]->ipaddr();
- # Create an agent for the parent.
- $self->call('create_agent', $parent);
+ # Create an agent for the parent.
+ $self->add_agent($parent);
- $self->call('message', "Host $device is one hop away from host $parent.", 5);
- $self->mark_connected($parent, '', $device, '');
+ $self->call('message', "Host $device is one hop away from host $parent.", 5);
+ $self->mark_connected($parent, '', $device, '');
- # Move on to the next hop.
- $device = $parent;
- }
+ # Move on to the next hop.
+ $device = $parent;
+ }
}
-##########################################################################
+################################################################################
# Returns the credentials with which the host responds to WMI queries or
# undef if it does not respond to WMI.
-##########################################################################
-sub responds_to_wmi {
- my ($self, $target) = @_;
-
- foreach my $auth (@{$self->{'auth_strings_array'}}) {
- my @output;
- if ($auth ne '') {
- @output = `$self->{'timeout_cmd'}$self->{'wmi_client'} -U $auth //$target "SELECT * FROM Win32_ComputerSystem" 2>&1`;
- } else {
- @output = `$self->{'timeout_cmd'}$self->{'wmi_client'} -N //$target "SELECT * FROM Win32_ComputerSystem" 2>&1`;
- }
-
- foreach my $line (@output) {
- chomp($line);
- return $auth if ($line =~ m/^CLASS: Win32_ComputerSystem$/);
- }
- }
-
- return undef;
+################################################################################
+sub wmi_credentials {
+ my ($self, $target) = @_;
+ return $self->{'wmi_auth'}{$target};
}
-##########################################################################
-# Add wmi modules to the given host.
-##########################################################################
-sub wmi_scan {
+################################################################################
+# Returns the credentials KEY with which the host responds to WMI queries or
+# undef if it does not respond to WMI.
+################################################################################
+sub wmi_credentials_key {
my ($self, $target) = @_;
-
- $self->call('message', "[".$target."] Checking WMI.", 5);
-
- my $auth = $self->responds_to_wmi($target);
- return unless defined($auth);
-
- $self->{'summary'}->{'WMI'} += 1;
-
- $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);
-
- # 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'));
- }
-
- # 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'));
- }
-
- # 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'));
- }
+ return $self->{'wmi_auth_key'}{$target};
}
-##########################################################################
+################################################################################
+# Calculate WMI credentials for target, 1 if calculated, undef if cannot
+# connect to target. Credentials could be empty (-N)
+################################################################################
+sub wmi_credentials_calculation {
+ my ($self, $target) = @_;
+
+ # Test empty credentials.
+ my @output = `$self->{'timeout_cmd'}$self->{'wmi_client'} -N //$target "SELECT * FROM Win32_ComputerSystem" 2>$DEVNULL`;
+ my $rs = $self->wmi_output_check($?, @output);
+
+ if ($rs == WMI_OK) {
+ $self->{'wmi_auth'}{$target} = '';
+ $self->{'wmi_auth_key'}{$target} = '';
+ return 1;
+ }
+
+ if ($rs == WMI_UNREACHABLE) {
+ # Target does not respond.
+ $self->{'wmi'}{$target} = 0;
+ return undef;
+ }
+
+ # Test all credentials selected.
+ foreach my $key_index (@{$self->{'auth_strings_array'}}) {
+ my $cred = $self->call('get_credentials', $key_index);
+ next if ref($cred) ne 'HASH';
+
+ my $auth = $cred->{'username'}.'%'.$cred->{'password'};
+ next if $auth eq '%';
+
+ @output = `$self->{'timeout_cmd'}$self->{'wmi_client'} -U $auth //$target "SELECT * FROM Win32_ComputerSystem" 2>$DEVNULL`;
+
+ my $rs = $self->wmi_output_check($?, @output);
+
+ if ($rs == WMI_OK) {
+ $self->{'wmi_auth'}{$target} = $auth;
+ $self->{'wmi_auth_key'}{$target} = $key_index;
+ $self->{'wmi'}{$target} = 1;
+ $self->{'summary'}->{'WMI'} += 1;
+ $self->call('message', "[".$target."] WMI available.", 10);
+ return 1;
+ }
+
+ if ($rs == WMI_UNREACHABLE) {
+ # Target does not respond.
+ $self->call('message', "[".$target."] WMI unreachable.", 10);
+ $self->{'wmi'}{$target} = 0;
+ return undef;
+ }
+ }
+
+ return undef;
+}
+
+################################################################################
+# Tests wmi capability for addr.
+################################################################################
+sub wmi_discovery {
+ my ($self, $addr) = @_;
+
+ # Initialization.
+ $self->{'wmi'} = {} unless ref($self->{'wmi'}) eq 'HASH';
+
+ # Calculate credentials.
+ $self->wmi_credentials_calculation($addr);
+
+}
+
+################################################################################
# Extra: WMI imported methods. DO NOT EXPORT TO AVOID DOUBLE DEF.
-##########################################################################
+################################################################################
-##########################################################################
-# Performs a wmi get requests and returns the response as an array.
-##########################################################################
-sub wmi_get {
- my ($self, $target, $auth, $query) = @_;
+################################################################################
+# Validate wmi output. (err code and messages).
+################################################################################
+sub wmi_output_check {
+ my ($self, $rc, @output) = @_;
+ if ($? != 0) {
+ # Something went wrong.
+ if (defined($output[-1]) && $output[-1] =~ /NTSTATUS: (.*)/) {
+ my $err = $1;
+ $self->{'last_wmi_error'} = $err;
- my @output;
- if (defined($auth) && $auth ne '') {
- @output = `$self->{'timeout_cmd'}"$self->{'wmi_client'}" -U $auth //$target "$query" 2>&1`;
- }else {
- @output = `$self->{'timeout_cmd'}"$self->{'wmi_client'}" -N //$target "$query" 2>&1`;
- }
+ if ($err =~ /NT_STATUS_IO_TIMEOUT/
+ || $err =~ /NT_STATUS_CONNECTION_REFUSED/
+ ) {
+ # Fail.
+ return WMI_UNREACHABLE;
+ }
- # Something went wrong.
- return () if ($? != 0);
+ if ($err =~ /NT_STATUS_ACCESS_DENIED/) {
+ return WMI_BAD_PASSWORD;
+ }
+ }
- return @output;
+ # Fail.
+ return WMI_GENERIC_ERROR;
+ }
+
+ # Ok.
+ return WMI_OK;
}
-##########################################################################
+################################################################################
+# Performs a wmi get requests and returns the response as an array.
+################################################################################
+sub wmi_get {
+ my ($self, $target, $query) = @_;
+
+ return () unless $self->wmi_responds($target);
+
+ return $self->wmi_get_command($target, $self->{'wmi_auth'}{$target}, $query);
+}
+
+################################################################################
+# Performs a wmi get requests and returns the response as an array.
+################################################################################
+sub wmi_get_command {
+ my ($self, $target, $auth, $query) = @_;
+
+ return () if is_empty($target);
+
+ my @output;
+ if (defined($auth) && $auth ne '') {
+ $auth =~ s/'/\'/g;
+ @output = `$self->{'timeout_cmd'}"$self->{'wmi_client'}" -U '$auth' //$target "$query" 2>$DEVNULL`;
+ }else {
+ @output = `$self->{'timeout_cmd'}"$self->{'wmi_client'}" -N //$target "$query" 2>$DEVNULL`;
+ }
+
+ my $rs = $self->wmi_output_check($?, @output);
+
+ if ($rs == WMI_OK) {
+ return @output;
+ }
+
+ my $err = $self->{'last_wmi_error'};
+ $err = 'Not OK, empty error' if is_empty($err);
+
+ $self->call(
+ 'message',
+ "[".$target."] WMI error: ".$err,
+ 10
+ );
+
+ return ();
+}
+
+################################################################################
+# Checks if target is reachable using wmi.
+################################################################################
+sub wmi_responds {
+ my ($self, $target) = @_;
+ return 1 if is_enabled($self->{'wmi'}{$target});
+ return 0;
+}
+
+################################################################################
# Performs a WMI request and returns the requested column of the first row.
# Returns undef on error.
-##########################################################################
+################################################################################
sub wmi_get_value {
- my ($self, $target, $auth, $query, $column) = @_;
- my @result;
+ my ($self, $target, $query, $column) = @_;
+ my @result;
- my @output = $self->wmi_get($target, $auth, $query);
- return undef unless defined($output[2]);
+ my @output = $self->wmi_get($target, $query);
+ return undef unless defined($output[2]);
- my $line = $output[2];
- chomp($line);
- my @columns = split(/\|/, $line);
- return undef unless defined($columns[$column]);
+ my $line = $output[2];
+ chomp($line);
+ my @columns = split(/\|/, $line);
+ return undef unless defined($columns[$column]);
- return $columns[$column];
+ return $columns[$column];
}
-##########################################################################
+################################################################################
# Performs a WMI request and returns row values for the requested column
# in an array.
-##########################################################################
+################################################################################
sub wmi_get_value_array {
- my ($self, $target, $auth, $query, $column) = @_;
- my @result;
+ my ($self, $target, $query, $column) = @_;
+ my @result;
- my @output = $self->wmi_get($target, $auth, $query);
- foreach (my $i = 2; defined($output[$i]); $i++) {
- my $line = $output[$i];
- chomp($line);
- my @columns = split(/\|/, $line);
- next unless defined($columns[$column]);
- push(@result, $columns[$column]);
- }
+ my @output = $self->wmi_get($target, $query);
+ foreach (my $i = 2; defined($output[$i]); $i++) {
+ my $line = $output[$i];
+ chomp($line);
+ my @columns = split(/\|/, $line);
+ next unless defined($columns[$column]);
+ push(@result, $columns[$column]);
+ }
- return @result;
+ return @result;
}
-##########################################################################
+################################################################################
# END: WMI imported methods.
-##########################################################################
+################################################################################
1;
__END__
diff --git a/pandora_server/lib/PandoraFMS/Recon/Util.pm b/pandora_server/lib/PandoraFMS/Recon/Util.pm
index 64cc7b28e6..32bc921806 100644
--- a/pandora_server/lib/PandoraFMS/Recon/Util.pm
+++ b/pandora_server/lib/PandoraFMS/Recon/Util.pm
@@ -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);
diff --git a/pandora_server/pandora_server.redhat.spec b/pandora_server/pandora_server.redhat.spec
index ff6b8f1e84..11ddf8372e 100644
--- a/pandora_server/pandora_server.redhat.spec
+++ b/pandora_server/pandora_server.redhat.spec
@@ -3,7 +3,7 @@
#
%define name pandorafms_server
%define version 7.0NG.744
-%define release 200413
+%define release 200414
Summary: Pandora FMS Server
Name: %{name}
diff --git a/pandora_server/pandora_server.spec b/pandora_server/pandora_server.spec
index 719ff10fdb..cbffcc09bb 100644
--- a/pandora_server/pandora_server.spec
+++ b/pandora_server/pandora_server.spec
@@ -3,7 +3,7 @@
#
%define name pandorafms_server
%define version 7.0NG.744
-%define release 200413
+%define release 200414
Summary: Pandora FMS Server
Name: %{name}
diff --git a/pandora_server/pandora_server_installer b/pandora_server/pandora_server_installer
index 77286d428d..dd6b406114 100755
--- a/pandora_server/pandora_server_installer
+++ b/pandora_server/pandora_server_installer
@@ -9,7 +9,7 @@
# **********************************************************************
PI_VERSION="7.0NG.744"
-PI_BUILD="200413"
+PI_BUILD="200414"
MODE=$1
if [ $# -gt 1 ]; then
diff --git a/pandora_server/util/pandora_db.pl b/pandora_server/util/pandora_db.pl
index a28d5e92b8..0cbbf01fb7 100644
--- a/pandora_server/util/pandora_db.pl
+++ b/pandora_server/util/pandora_db.pl
@@ -35,7 +35,7 @@ use PandoraFMS::Config;
use PandoraFMS::DB;
# version: define current version
-my $version = "7.0NG.744 PS200413";
+my $version = "7.0NG.744 PS200414";
# Pandora server configuration
my %conf;
diff --git a/pandora_server/util/pandora_manage.pl b/pandora_server/util/pandora_manage.pl
index 2552896724..ab784928d4 100755
--- a/pandora_server/util/pandora_manage.pl
+++ b/pandora_server/util/pandora_manage.pl
@@ -36,7 +36,7 @@ use Encode::Locale;
Encode::Locale::decode_argv;
# version: define current version
-my $version = "7.0NG.744 PS200413";
+my $version = "7.0NG.744 PS200414";
# save program name for logging
my $progname = basename($0);
diff --git a/pandora_server/util/plugin/wizard_snmp_module.pl b/pandora_server/util/plugin/wizard_snmp_module.pl
new file mode 100755
index 0000000000..ae1d739864
--- /dev/null
+++ b/pandora_server/util/plugin/wizard_snmp_module.pl
@@ -0,0 +1,308 @@
+#!/usr/bin/perl
+#
+################################################################################
+#
+# SNMP wizard module
+#
+# Requirements:
+# Net::SNMP
+# Crypt::DES
+# Digest::SHA1
+#
+# (c) Enrique Martin Garcia
+#
+# 2020/03/10
+#
+################################################################################
+
+use strict;
+use warnings;
+
+use POSIX qw(strftime);
+
+use Encode;
+use Encode::Locale;
+use Getopt::Long;
+use Net::SNMP;
+
+my $HELP=<" -version "" [SNMP] [SNMPv3] -oidList "," -operation ""
+
+-host Target host
+-version SNMP version (1, 2c, 3)
+
+-oidList Comma separated OIDs used
+-operation Aritmetic operation to get data.
+ Macros _oN_ will be changed by OIDs in list.
+ Example: (_o1_ * 100) / _o2_
+
+[SNMP]
+ -community Community (only version 1 and 2c)
+ -port Target UDP port (Default 161)
+
+[SNMPv3]
+ -user Username
+ -authMethod Authentication method (MD5, SHA)
+ -authPass Authentication password
+ -privMethod Privacy method (DES, AES)
+ -privPass Privacy password
+ -secLevel Security level (noAuthNoPriv, authNoPriv, authPriv)
+
+Example: $0 -host 192.168.80.43 -community public -version 1 -oidlist "1.3.6.1.2.1.2.2.1.10.1,1.3.6.1.2.1.2.2.1.16.1" -operation "_o1_ + _o2_"
+
+EO_HELP
+
+#
+# FUNCTIONS
+##############
+
+sub new_snmp_target {
+ my ($config) = @_;
+ my $target;
+ my $error;
+
+ if ($config->{'version'} ne '3'){
+ ($target, $error) = Net::SNMP->session(
+ -hostname => $config->{'host'},
+ -port => $config->{'port'},
+ -version => $config->{'version'},
+ -timeout => $config->{'timeout'},
+ -translate => 0,
+ -community => $config->{'community'}
+ );
+ }else{
+ if ($config->{'sec_level'} =~ /^noAuthNoPriv$/i){
+ ($target, $error) = Net::SNMP->session(
+ -hostname => $config->{'host'},
+ -port => $config->{'port'},
+ -version => $config->{'version'},
+ -timeout => $config->{'timeout'},
+ -translate => 0,
+ -username => $config->{'user'}
+ );
+ }elsif ($config->{'sec_level'} =~ /^authNoPriv$/i){
+ ($target, $error) = Net::SNMP->session(
+ -hostname => $config->{'host'},
+ -port => $config->{'port'},
+ -version => $config->{'version'},
+ -timeout => $config->{'timeout'},
+ -translate => 0,
+ -username => $config->{'user'},
+ -authpassword => $config->{'auth_pass'},
+ -authprotocol => $config->{'auth_method'}
+ );
+ }elsif ($config->{'sec_level'} =~ /^authPriv$/i){
+ ($target, $error) = Net::SNMP->session(
+ -hostname => $config->{'host'},
+ -port => $config->{'port'},
+ -version => $config->{'version'},
+ -timeout => $config->{'timeout'},
+ -translate => 0,
+ -username => $config->{'user'},
+ -authpassword => $config->{'auth_pass'},
+ -authprotocol => $config->{'auth_method'},
+ -privpassword => $config->{'priv_pass'},
+ -privprotocol => $config->{'priv_method'}
+ );
+ }
+ }
+
+
+ return ($target, $error);
+}
+
+sub snmp_walk {
+ my ($target, $oid) = @_;
+ my $result = {};
+
+ my $walk = $target->get_table(
+ -baseoid => $oid,
+ );
+
+ if (defined($walk)){
+ $result = $walk;
+ }
+
+ return $result;
+}
+
+sub snmp_get {
+ my ($target, $oid) = @_;
+ my $result = '';
+
+ my $get = $target->get_request(
+ -varbindlist => [$oid],
+ );
+
+ if (defined($get)){
+ $result = $get->{$oid};
+ }
+
+ return $result;
+}
+
+#
+# MAIN
+##############
+
+@ARGV = map { decode(locale => $_, 1) } @ARGV if -t STDIN;
+binmode STDOUT, ":encoding(console_out)" if -t STDOUT;
+binmode STDERR, ":encoding(console_out)" if -t STDERR;
+
+my %Param = ();
+GetOptions(
+ \%Param,
+ # General
+ 'community=s',
+ 'version=s',
+ 'host=s',
+ 'port=s',
+ 'timeout=s',
+ # Version 3
+ 'user=s',
+ 'authMethod=s',
+ 'authPass=s',
+ 'privMethod=s',
+ 'privPass=s',
+ 'secLevel=s',
+ # Operation
+ 'oidList=s',
+ 'operation=s',
+ # Help option
+ 'Help',
+);
+
+if ($Param{Help}){
+ print $HELP;
+ exit 0;
+}
+
+my $config;
+
+# General parameters
+$config->{'community'} = $Param{community} || '';
+$config->{'version'} = $Param{version} || '';
+$config->{'host'} = $Param{host} || '';
+$config->{'port'} = $Param{port} || '161';
+$config->{'timeout'} = $Param{timeout} || '2';
+
+# Version 3 parameters
+$config->{'auth_method'} = $Param{authMethod} || '';
+$config->{'user'} = $Param{user} || '';
+$config->{'auth_pass'} = $Param{authPass} || '';
+$config->{'priv_method'} = $Param{privMethod} || '';
+$config->{'priv_pass'} = $Param{privPass} || '';
+$config->{'sec_level'} = $Param{secLevel} || '';
+
+$config->{'auth_method'} = uc($config->{'auth_method'});
+$config->{'priv_method'} = uc($config->{'priv_method'});
+
+# Operation
+my $operation = $Param{operation} || '';
+
+# OIDs
+my @oid_list = split /,/, $Param{oidList} || '';
+
+# Verify parameters
+if (!$config->{'host'} || !$config->{'version'} || !$operation || !@oid_list){
+ print $HELP;
+ print "Host, version, OID list and operation are required.\n";
+ exit 1;
+}
+
+if ($config->{'version'} ne '1' && $config->{'version'} ne '2c' && $config->{'version'} ne '3'){
+ print $HELP;
+ print "Invalid SNMP version provided.\n";
+ exit 1;
+}
+
+if ($config->{'version'} eq '1' || $config->{'version'} eq '2c'){
+ if (!$config->{'community'}){
+ print $HELP;
+ print "SNMP community required for version 1 or 2c.\n";
+ exit 1;
+ }
+}
+
+if ($config->{'version'} eq '3'){
+ if ($config->{'sec_level'} =~ /^noAuthNoPriv$/i){
+ if (!$config->{'user'}){
+ print $HELP;
+ print "Username required for SNMP version 3 and security level 'noAuthNoPriv'.\n";
+ exit 1;
+ }
+ }elsif ($config->{'sec_level'} =~ /^authNoPriv$/i){
+ if (!$config->{'user'} && !$config->{'auth_pass'} && !$config->{'auth_method'}){
+ print $HELP;
+ print "Username, authentication password and authentication method required for SNMP version 3 and security level 'authNoPriv'.\n";
+ exit 1;
+ }
+ }elsif ($config->{'sec_level'} =~ /^authPriv$/i){
+ if (!$config->{'user'} && !$config->{'auth_pass'} && !$config->{'auth_method'} && !$config->{'priv_pass'} && !$config->{'priv_method'}){
+ print $HELP;
+ print "Username, authentication password, authentication method, privacy password and privacy method required for SNMP version 3 and security level 'authPriv'.\n";
+ exit 1;
+ }
+ }else{
+ print $HELP;
+ print "Invalid SNMP security level provided for version 3.\n";
+ exit 1;
+ }
+
+ if ($config->{'auth_method'} && $config->{'auth_method'} ne 'MD5' && $config->{'auth_method'} ne 'SHA'){
+ print $HELP;
+ print "Invalid SNMP authentication method provided for version 3.\n";
+ exit 1;
+ }
+
+ if ($config->{'priv_method'} && $config->{'priv_method'} ne 'DES' && $config->{'priv_method'} ne 'AES'){
+ print $HELP;
+ print "Invalid SNMP privacy method provided for version 3.\n";
+ exit 1;
+ }
+}
+
+# Verify operation (avoid code injection)
+my @operation = split //, lc($operation);
+
+foreach my $op (@operation){
+ if ($op !~ /\d/ && $op ne ' ' && $op ne '(' && $op ne ')' && $op ne '_' && $op ne '-' && $op ne '+' && $op ne '*' && $op ne '/' && $op ne 'o'){
+ print $HELP;
+ print "Specified operation has invalid characters: " . $op . "\n";
+ exit 1;
+ }
+}
+
+# Create SNMP target
+my ($target, $error) = new_snmp_target($config);
+
+if (!$target){
+ print $error . "\n";
+ exit 1;
+}
+
+# Get OIDs values
+my $oid_values = {};
+my $i = 1;
+foreach my $oid (@oid_list){
+ $oid_values->{'_o' . $i . '_'} = snmp_get($target, $oid);
+ $i++;
+}
+
+# Change operation macros with values
+$i = 1;
+foreach my $k (keys %{$oid_values}){
+ my $oid_macro = '_o' . $i . '_';
+ my $value = $oid_values->{$oid_macro};
+ $operation =~ s/$oid_macro/$value/g;
+ $i++;
+}
+
+# Get operation result
+my $result = eval $operation;
+if (defined($result)){
+ print $result . "\n";
+}
\ No newline at end of file
diff --git a/pandora_server/util/plugin/wizard_snmp_process.pl b/pandora_server/util/plugin/wizard_snmp_process.pl
new file mode 100755
index 0000000000..c510de1171
--- /dev/null
+++ b/pandora_server/util/plugin/wizard_snmp_process.pl
@@ -0,0 +1,282 @@
+#!/usr/bin/perl
+#
+################################################################################
+#
+# SNMP wizard process
+#
+# Requirements:
+# Net::SNMP
+# Crypt::DES
+# Digest::SHA1
+#
+# (c) Enrique Martin Garcia
+#
+# 2020/03/10
+#
+################################################################################
+
+use strict;
+use warnings;
+
+use POSIX qw(strftime);
+
+use Encode;
+use Encode::Locale;
+use Getopt::Long;
+use Net::SNMP;
+
+my $HELP=<" -version "" [SNMP] [SNMPv3] -process ""
+
+-host Target host
+-version SNMP version (1, 2c, 3)
+
+-process Process name to check if is running (case sensitive)
+
+[SNMP]
+ -community Community (only version 1 and 2c)
+ -port Target UDP port (Default 161)
+
+[SNMPv3]
+ -user Username
+ -authMethod Authentication method (MD5, SHA)
+ -authPass Authentication password
+ -privMethod Privacy method (DES, AES)
+ -privPass Privacy password
+ -secLevel Security level (noAuthNoPriv, authNoPriv, authPriv)
+
+Example: $0 -host 192.168.80.43 -community public -version 1 -process "httpd"
+
+EO_HELP
+
+#
+# FUNCTIONS
+##############
+
+sub new_snmp_target {
+ my ($config) = @_;
+ my $target;
+ my $error;
+
+ if ($config->{'version'} ne '3'){
+ ($target, $error) = Net::SNMP->session(
+ -hostname => $config->{'host'},
+ -port => $config->{'port'},
+ -version => $config->{'version'},
+ -timeout => $config->{'timeout'},
+ -translate => 0,
+ -community => $config->{'community'}
+ );
+ }else{
+ if ($config->{'sec_level'} =~ /^noAuthNoPriv$/i){
+ ($target, $error) = Net::SNMP->session(
+ -hostname => $config->{'host'},
+ -port => $config->{'port'},
+ -version => $config->{'version'},
+ -timeout => $config->{'timeout'},
+ -translate => 0,
+ -username => $config->{'user'}
+ );
+ }elsif ($config->{'sec_level'} =~ /^authNoPriv$/i){
+ ($target, $error) = Net::SNMP->session(
+ -hostname => $config->{'host'},
+ -port => $config->{'port'},
+ -version => $config->{'version'},
+ -timeout => $config->{'timeout'},
+ -translate => 0,
+ -username => $config->{'user'},
+ -authpassword => $config->{'auth_pass'},
+ -authprotocol => $config->{'auth_method'}
+ );
+ }elsif ($config->{'sec_level'} =~ /^authPriv$/i){
+ ($target, $error) = Net::SNMP->session(
+ -hostname => $config->{'host'},
+ -port => $config->{'port'},
+ -version => $config->{'version'},
+ -timeout => $config->{'timeout'},
+ -translate => 0,
+ -username => $config->{'user'},
+ -authpassword => $config->{'auth_pass'},
+ -authprotocol => $config->{'auth_method'},
+ -privpassword => $config->{'priv_pass'},
+ -privprotocol => $config->{'priv_method'}
+ );
+ }
+ }
+
+
+ return ($target, $error);
+}
+
+sub snmp_walk {
+ my ($target, $oid) = @_;
+ my $result = {};
+
+ my $walk = $target->get_table(
+ -baseoid => $oid,
+ );
+
+ if (defined($walk)){
+ $result = $walk;
+ }
+
+ return $result;
+}
+
+sub snmp_get {
+ my ($target, $oid) = @_;
+ my $result = '';
+
+ my $get = $target->get_request(
+ -varbindlist => [$oid],
+ );
+
+ if (defined($get)){
+ $result = $get->{$oid};
+ }
+
+ return $result;
+}
+
+#
+# MAIN
+##############
+
+@ARGV = map { decode(locale => $_, 1) } @ARGV if -t STDIN;
+binmode STDOUT, ":encoding(console_out)" if -t STDOUT;
+binmode STDERR, ":encoding(console_out)" if -t STDERR;
+
+my %Param = ();
+GetOptions(
+ \%Param,
+ # General
+ 'community=s',
+ 'version=s',
+ 'host=s',
+ 'port=s',
+ 'timeout=s',
+ # Version 3
+ 'user=s',
+ 'authMethod=s',
+ 'authPass=s',
+ 'privMethod=s',
+ 'privPass=s',
+ 'secLevel=s',
+ # Process
+ 'process=s',
+ # Help option
+ 'Help',
+);
+
+if ($Param{Help}){
+ print $HELP;
+ exit 0;
+}
+
+my $config;
+
+# General parameters
+$config->{'community'} = $Param{community} || '';
+$config->{'version'} = $Param{version} || '';
+$config->{'host'} = $Param{host} || '';
+$config->{'port'} = $Param{port} || '161';
+$config->{'timeout'} = $Param{timeout} || '2';
+
+# Version 3 parameters
+$config->{'auth_method'} = $Param{authMethod} || '';
+$config->{'user'} = $Param{user} || '';
+$config->{'auth_pass'} = $Param{authPass} || '';
+$config->{'priv_method'} = $Param{privMethod} || '';
+$config->{'priv_pass'} = $Param{privPass} || '';
+$config->{'sec_level'} = $Param{secLevel} || '';
+
+$config->{'auth_method'} = uc($config->{'auth_method'});
+$config->{'priv_method'} = uc($config->{'priv_method'});
+
+# Operation
+my $process = $Param{process} || '';
+
+# Verify parameters
+if (!$config->{'host'} || !$config->{'version'} || !$process){
+ print $HELP;
+ print "Host, version and process are required.\n";
+ exit 1;
+}
+
+if ($config->{'version'} ne '1' && $config->{'version'} ne '2c' && $config->{'version'} ne '3'){
+ print $HELP;
+ print "Invalid SNMP version provided.\n";
+ exit 1;
+}
+
+if ($config->{'version'} eq '1' || $config->{'version'} eq '2c'){
+ if (!$config->{'community'}){
+ print $HELP;
+ print "SNMP community required for version 1 or 2c.\n";
+ exit 1;
+ }
+}
+
+if ($config->{'version'} eq '3'){
+ if ($config->{'sec_level'} =~ /^noAuthNoPriv$/i){
+ if (!$config->{'user'}){
+ print $HELP;
+ print "Username required for SNMP version 3 and security level 'noAuthNoPriv'.\n";
+ exit 1;
+ }
+ }elsif ($config->{'sec_level'} =~ /^authNoPriv$/i){
+ if (!$config->{'user'} && !$config->{'auth_pass'} && !$config->{'auth_method'}){
+ print $HELP;
+ print "Username, authentication password and authentication method required for SNMP version 3 and security level 'authNoPriv'.\n";
+ exit 1;
+ }
+ }elsif ($config->{'sec_level'} =~ /^authPriv$/i){
+ if (!$config->{'user'} && !$config->{'auth_pass'} && !$config->{'auth_method'} && !$config->{'priv_pass'} && !$config->{'priv_method'}){
+ print $HELP;
+ print "Username, authentication password, authentication method, privacy password and privacy method required for SNMP version 3 and security level 'authPriv'.\n";
+ exit 1;
+ }
+ }else{
+ print $HELP;
+ print "Invalid SNMP security level provided for version 3.\n";
+ exit 1;
+ }
+
+ if ($config->{'auth_method'} && $config->{'auth_method'} ne 'MD5' && $config->{'auth_method'} ne 'SHA'){
+ print $HELP;
+ print "Invalid SNMP authentication method provided for version 3.\n";
+ exit 1;
+ }
+
+ if ($config->{'priv_method'} && $config->{'priv_method'} ne 'DES' && $config->{'priv_method'} ne 'AES'){
+ print $HELP;
+ print "Invalid SNMP privacy method provided for version 3.\n";
+ exit 1;
+ }
+}
+
+# Create SNMP target
+my ($target, $error) = new_snmp_target($config);
+
+if (!$target){
+ print $error . "\n";
+ exit 1;
+}
+
+# Get all running processes
+my $processes = snmp_walk($target, '.1.3.6.1.2.1.25.4.2.1.2');
+
+my $result = 0;
+
+# Search process name
+foreach my $k (keys %{$processes}){
+ if ($processes->{$k} eq $process){
+ $result = 1;
+ last;
+ }
+}
+
+print $result . "\n";
\ No newline at end of file
diff --git a/pandora_server/util/plugin/wizard_wmi_module.pl b/pandora_server/util/plugin/wizard_wmi_module.pl
new file mode 100755
index 0000000000..3cb1661da9
--- /dev/null
+++ b/pandora_server/util/plugin/wizard_wmi_module.pl
@@ -0,0 +1,176 @@
+#!/usr/bin/perl
+#
+################################################################################
+#
+# WMI wizard module
+#
+# Requirements:
+# wmic
+#
+# (c) Enrique Martin Garcia
+#
+# 2020/03/10
+#
+################################################################################
+
+use strict;
+use warnings;
+
+use POSIX qw(strftime);
+
+use Encode;
+use Encode::Locale;
+use Getopt::Long;
+
+use Data::Dumper;
+
+my $HELP=<"] -host "" [-namespace ""] -user "" -pass "" -wmiClass "" -fieldsList "" [-queryFilter ""] -operation ""
+
+-wmicPath Path to wmic command (Default: /usr/bin/wmic)
+
+-host Target host
+-namespace WMI namespace
+-user Windows username ([domain/]username)
+-pass User password
+
+-wmiClass WMI class for query (Example: Win32_OperatingSystem)
+-fieldsList Comma separated class fields list (Example: TotalVisibleMemorySize,FreePhysicalMemory)
+-queryFilter WMI query class filter (Example: DeviceID = 3 AND DeviceType = 1)
+
+-operation Aritmetic operation to get data.
+ Macros _fN_ will be changed by fields in list.
+ Example: ((_f1_ - _f2_) * 100) / _f1_
+
+Example: $0 -host "192.168.80.43" -user "pandora/Administrator" -pass "PandoraFMS1234" -wmiClass "Win32_OperatingSystem" -fieldsList "TotalVisibleMemorySize,FreePhysicalMemory" -operation "((_f1_ - _f2_) * 100) / _f1_"
+
+EO_HELP
+
+#
+# MAIN
+##############
+
+@ARGV = map { decode(locale => $_, 1) } @ARGV if -t STDIN;
+binmode STDOUT, ":encoding(console_out)" if -t STDOUT;
+binmode STDERR, ":encoding(console_out)" if -t STDERR;
+
+my %Param = ();
+GetOptions(
+ \%Param,
+ # General
+ 'wmicPath=s',
+ 'host=s',
+ 'namespace=s',
+ 'user=s',
+ 'pass=s',
+ # Query
+ 'wmiClass=s',
+ 'fieldsList=s',
+ 'queryFilter=s',
+ # Operation
+ 'operation=s',
+ # Help option
+ 'Help',
+);
+
+if ($Param{Help}){
+ print $HELP;
+ exit 0;
+}
+
+my $config;
+
+# General parameters
+$config->{'wmicPath'} = $Param{wmicPath} || '/usr/bin/wmic';
+$config->{'host'} = $Param{host} || '';
+$config->{'namespace'} = $Param{namespace} || '';
+$config->{'user'} = $Param{user} || '';
+$config->{'pass'} = $Param{pass} || '';
+
+# Query parameters
+$config->{'wmiClass'} = $Param{wmiClass} || '';
+$config->{'queryFilter'} = $Param{queryFilter} || '';
+$config->{'fieldsList'} = $Param{fieldsList} || '';
+
+# Operation
+my $operation = $Param{operation} || '';
+
+# Fields
+my @fields_list = split /,/, $config->{'fieldsList'} || '';
+
+# Verify parameters
+if (!$config->{'host'} || !$config->{'user'} || !$config->{'pass'} || !$config->{'wmiClass'} || !@fields_list || !$operation){
+ print $HELP;
+ print "Host, user, password, WMI class, fields list and operation are required.\n";
+ exit 1;
+}
+
+# Verify operation (avoid code injection)
+my @operation = split //, lc($operation);
+
+foreach my $op (@operation){
+ if ($op !~ /\d/ && $op ne ' ' && $op ne '(' && $op ne ')' && $op ne '_' && $op ne '-' && $op ne '+' && $op ne '*' && $op ne '/' && $op ne 'f'){
+ print $HELP;
+ print "Specified operation has invalid characters: " . $op . "\n";
+ exit 1;
+ }
+}
+
+# Build WMI query
+my $wmi_query = 'SELECT ' . $config->{'fieldsList'} . ' FROM ' . $config->{'wmiClass'} . ($config->{'queryFilter'} ? ' WHERE ' . $config->{'queryFilter'} : '');
+
+# Build wmic command
+my $wmi_command = $config->{'wmicPath'} . ' -U ' . $config->{'user'} . '%' . $config->{'pass'} . ($config->{'namespace'} ? ' --namespace="' . $config->{'namespace'} . '"' : '') . ' //' . $config->{'host'} . ' "' . $wmi_query . '"';
+
+# Run wmic and parse output
+my $output = `$wmi_command 2>/dev/null`;
+
+my @data = split("\n", $output);
+
+if ($data[0] ne 'CLASS: ' . $config->{'wmiClass'}){
+ print $output;
+ exit 1;
+}
+
+# Parse fields positions
+my @fields_pos;
+
+my $i = 0;
+foreach my $field (split /\|/, $data[1]){
+ my $x = 1;
+ foreach my $f (@fields_list){
+ $f =~ s/^\s*//;
+ $f =~ s/\s*$//;
+ if (lc($field) eq lc($f)){
+ $fields_pos[$i] = $x;
+ }
+ $x++;
+ }
+ $i++;
+}
+
+# Get fields values
+my $fields_values = {};
+$i = 0;
+foreach my $field_value (split /\|/, $data[2]){
+ $fields_values->{'_f' . $fields_pos[$i] . '_'} = $field_value;
+ $i++;
+}
+
+# Change operation macros with values
+$i = 1;
+foreach my $k (keys %{$fields_values}){
+ my $field_macro = '_f' . $i . '_';
+ my $value = $fields_values->{$field_macro};
+ $operation =~ s/$field_macro/$value/g;
+ $i++;
+}
+
+# Get operation result
+my $result = eval $operation;
+if (defined($result)){
+ print $result . "\n";
+}
\ No newline at end of file