diff --git a/pandora_agents/pc/AIX/pandora_agent.conf b/pandora_agents/pc/AIX/pandora_agent.conf index 07054ee2e1..c5a79a38b5 100644 --- a/pandora_agents/pc/AIX/pandora_agent.conf +++ b/pandora_agents/pc/AIX/pandora_agent.conf @@ -1,5 +1,5 @@ # Base config file for Pandora FMS agents -# Version 7.0NG.732, AIX version +# Version 7.0NG.733, AIX version # Licensed under GPL license v2, # Copyright (c) 2003-2010 Artica Soluciones Tecnologicas # http://www.pandorafms.com diff --git a/pandora_agents/pc/FreeBSD/pandora_agent.conf b/pandora_agents/pc/FreeBSD/pandora_agent.conf index 9d8a49bb99..da15c864ea 100644 --- a/pandora_agents/pc/FreeBSD/pandora_agent.conf +++ b/pandora_agents/pc/FreeBSD/pandora_agent.conf @@ -1,5 +1,5 @@ # Base config file for Pandora FMS agents -# Version 7.0NG.732, FreeBSD Version +# Version 7.0NG.733, FreeBSD Version # Licensed under GPL license v2, # Copyright (c) 2003-2010 Artica Soluciones Tecnologicas # http://www.pandorafms.com diff --git a/pandora_agents/pc/HP-UX/pandora_agent.conf b/pandora_agents/pc/HP-UX/pandora_agent.conf index c02e4647e1..cb8075b7ac 100644 --- a/pandora_agents/pc/HP-UX/pandora_agent.conf +++ b/pandora_agents/pc/HP-UX/pandora_agent.conf @@ -1,5 +1,5 @@ # Base config file for Pandora FMS agents -# Version 7.0NG.732, HP-UX Version +# Version 7.0NG.733, HP-UX Version # Licensed under GPL license v2, # Copyright (c) 2003-2009 Artica Soluciones Tecnologicas # http://www.pandorafms.com diff --git a/pandora_agents/pc/Linux/pandora_agent.conf b/pandora_agents/pc/Linux/pandora_agent.conf index 153113e070..170e9c6ccf 100644 --- a/pandora_agents/pc/Linux/pandora_agent.conf +++ b/pandora_agents/pc/Linux/pandora_agent.conf @@ -1,5 +1,5 @@ # Base config file for Pandora FMS agents -# Version 7.0NG.732, GNU/Linux +# Version 7.0NG.733, GNU/Linux # Licensed under GPL license v2, # Copyright (c) 2003-2009 Artica Soluciones Tecnologicas # http://www.pandorafms.com diff --git a/pandora_agents/pc/NT4/pandora_agent.conf b/pandora_agents/pc/NT4/pandora_agent.conf index 6ddeba7edc..42257021fa 100644 --- a/pandora_agents/pc/NT4/pandora_agent.conf +++ b/pandora_agents/pc/NT4/pandora_agent.conf @@ -1,5 +1,5 @@ # Base config file for Pandora FMS agents -# Version 7.0NG.732, GNU/Linux +# Version 7.0NG.733, GNU/Linux # Licensed under GPL license v2, # Copyright (c) 2003-2009 Artica Soluciones Tecnologicas # http://www.pandorafms.com diff --git a/pandora_agents/pc/SunOS/pandora_agent.conf b/pandora_agents/pc/SunOS/pandora_agent.conf index 502317f893..ebad34a0ab 100644 --- a/pandora_agents/pc/SunOS/pandora_agent.conf +++ b/pandora_agents/pc/SunOS/pandora_agent.conf @@ -1,5 +1,5 @@ # Base config file for Pandora FMS agents -# Version 7.0NG.732, Solaris Version +# Version 7.0NG.733, Solaris Version # Licensed under GPL license v2, # Copyright (c) 2003-2009 Artica Soluciones Tecnologicas # http://www.pandorafms.com diff --git a/pandora_agents/pc/Win32/pandora_agent.conf b/pandora_agents/pc/Win32/pandora_agent.conf index 96b20ea7e3..972f6d8aa1 100644 --- a/pandora_agents/pc/Win32/pandora_agent.conf +++ b/pandora_agents/pc/Win32/pandora_agent.conf @@ -1,6 +1,6 @@ # Base config file for Pandora FMS Windows Agent # (c) 2006-2010 Artica Soluciones Tecnologicas -# Version 7.0NG.732 +# Version 7.0NG.733 # This program is Free Software, you can redistribute it and/or modify it # under the terms of the GNU General Public Licence as published by the Free Software diff --git a/pandora_agents/shellscript/aix/pandora_agent.conf b/pandora_agents/shellscript/aix/pandora_agent.conf index 200ff9db97..6a80829c29 100644 --- a/pandora_agents/shellscript/aix/pandora_agent.conf +++ b/pandora_agents/shellscript/aix/pandora_agent.conf @@ -1,6 +1,6 @@ # Fichero de configuracion base de agentes de Pandora # Base config file for Pandora agents -# Version 7.0NG.732, AIX version +# Version 7.0NG.733, AIX version # General Parameters # ================== diff --git a/pandora_agents/shellscript/bsd-ipso/pandora_agent.conf b/pandora_agents/shellscript/bsd-ipso/pandora_agent.conf index 2002f4db65..6555df787c 100644 --- a/pandora_agents/shellscript/bsd-ipso/pandora_agent.conf +++ b/pandora_agents/shellscript/bsd-ipso/pandora_agent.conf @@ -1,6 +1,6 @@ # Fichero de configuracion base de agentes de Pandora # Base config file for Pandora agents -# Version 7.0NG.732 +# Version 7.0NG.733 # FreeBSD/IPSO version # Licenced under GPL licence, 2003-2007 Sancho Lerena diff --git a/pandora_agents/shellscript/hp-ux/pandora_agent.conf b/pandora_agents/shellscript/hp-ux/pandora_agent.conf index f9c19dbd06..ba29482633 100644 --- a/pandora_agents/shellscript/hp-ux/pandora_agent.conf +++ b/pandora_agents/shellscript/hp-ux/pandora_agent.conf @@ -1,6 +1,6 @@ # Fichero de configuracion base de agentes de Pandora # Base config file for Pandora agents -# Version 7.0NG.732, HPUX Version +# Version 7.0NG.733, HPUX Version # General Parameters # ================== diff --git a/pandora_agents/shellscript/linux/pandora_agent.conf b/pandora_agents/shellscript/linux/pandora_agent.conf index dc272a7a71..7bd41ad039 100644 --- a/pandora_agents/shellscript/linux/pandora_agent.conf +++ b/pandora_agents/shellscript/linux/pandora_agent.conf @@ -1,5 +1,5 @@ # Base config file for Pandora FMS agents -# Version 7.0NG.732 +# Version 7.0NG.733 # Licensed under GPL license v2, # (c) 2003-2010 Artica Soluciones Tecnologicas # please visit http://pandora.sourceforge.net diff --git a/pandora_agents/shellscript/mac_osx/pandora_agent.conf b/pandora_agents/shellscript/mac_osx/pandora_agent.conf index 5a466677d2..525f70c2af 100644 --- a/pandora_agents/shellscript/mac_osx/pandora_agent.conf +++ b/pandora_agents/shellscript/mac_osx/pandora_agent.conf @@ -1,5 +1,5 @@ # Base config file for Pandora FMS agents -# Version 7.0NG.732 +# Version 7.0NG.733 # Licensed under GPL license v2, # (c) 2003-2009 Artica Soluciones Tecnologicas # please visit http://pandora.sourceforge.net diff --git a/pandora_agents/shellscript/openWRT/pandora_agent.conf b/pandora_agents/shellscript/openWRT/pandora_agent.conf index 170188cc6f..d3cf26efa2 100644 --- a/pandora_agents/shellscript/openWRT/pandora_agent.conf +++ b/pandora_agents/shellscript/openWRT/pandora_agent.conf @@ -1,5 +1,5 @@ # Base config file for Pandora FMS agents -# Version 7.0NG.732 +# Version 7.0NG.733 # Licensed under GPL license v2, # please visit http://pandora.sourceforge.net diff --git a/pandora_agents/shellscript/solaris/pandora_agent.conf b/pandora_agents/shellscript/solaris/pandora_agent.conf index aad04ca60d..5a94defce2 100644 --- a/pandora_agents/shellscript/solaris/pandora_agent.conf +++ b/pandora_agents/shellscript/solaris/pandora_agent.conf @@ -1,6 +1,6 @@ # Fichero de configuracion base de agentes de Pandora # Base config file for Pandora agents -# Version 7.0NG.732, Solaris version +# Version 7.0NG.733, Solaris version # General Parameters # ================== diff --git a/pandora_agents/unix/AIX/pandora_agent.conf b/pandora_agents/unix/AIX/pandora_agent.conf index 3ce7da3c7e..ac43dfdabb 100644 --- a/pandora_agents/unix/AIX/pandora_agent.conf +++ b/pandora_agents/unix/AIX/pandora_agent.conf @@ -1,5 +1,5 @@ # Base config file for Pandora FMS agents -# Version 7.0NG.732, AIX version +# Version 7.0NG.733, AIX version # Licensed under GPL license v2, # Copyright (c) 2003-2010 Artica Soluciones Tecnologicas # http://www.pandorafms.com diff --git a/pandora_agents/unix/DEBIAN/control b/pandora_agents/unix/DEBIAN/control index c5593f4d39..00bba31f75 100644 --- a/pandora_agents/unix/DEBIAN/control +++ b/pandora_agents/unix/DEBIAN/control @@ -1,5 +1,5 @@ package: pandorafms-agent-unix -Version: 7.0NG.732-190327 +Version: 7.0NG.733 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 5325602855..53591139bf 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.732-190327" +pandora_version="7.0NG.733" 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/Darwin/pandora_agent.conf b/pandora_agents/unix/Darwin/pandora_agent.conf index 35202fcbe5..3b87b2bdbf 100644 --- a/pandora_agents/unix/Darwin/pandora_agent.conf +++ b/pandora_agents/unix/Darwin/pandora_agent.conf @@ -1,5 +1,5 @@ # Base config file for Pandora FMS agents -# Version 7.0NG.732, GNU/Linux +# Version 7.0NG.733, GNU/Linux # Licensed under GPL license v2, # Copyright (c) 2003-2012 Artica Soluciones Tecnologicas # http://www.pandorafms.com diff --git a/pandora_agents/unix/FreeBSD/pandora_agent.conf b/pandora_agents/unix/FreeBSD/pandora_agent.conf index c505d5f75e..55e5ab3dd0 100644 --- a/pandora_agents/unix/FreeBSD/pandora_agent.conf +++ b/pandora_agents/unix/FreeBSD/pandora_agent.conf @@ -1,5 +1,5 @@ # Base config file for Pandora FMS agents -# Version 7.0NG.732, FreeBSD Version +# Version 7.0NG.733, FreeBSD Version # Licensed under GPL license v2, # Copyright (c) 2003-2016 Artica Soluciones Tecnologicas # http://www.pandorafms.com diff --git a/pandora_agents/unix/HP-UX/pandora_agent.conf b/pandora_agents/unix/HP-UX/pandora_agent.conf index 237bffb291..3c9891fdce 100644 --- a/pandora_agents/unix/HP-UX/pandora_agent.conf +++ b/pandora_agents/unix/HP-UX/pandora_agent.conf @@ -1,5 +1,5 @@ # Base config file for Pandora FMS agents -# Version 7.0NG.732, HP-UX Version +# Version 7.0NG.733, HP-UX Version # Licensed under GPL license v2, # Copyright (c) 2003-2009 Artica Soluciones Tecnologicas # http://www.pandorafms.com diff --git a/pandora_agents/unix/Linux/pandora_agent.conf b/pandora_agents/unix/Linux/pandora_agent.conf index 5a65e0e095..0f6cbfc83a 100644 --- a/pandora_agents/unix/Linux/pandora_agent.conf +++ b/pandora_agents/unix/Linux/pandora_agent.conf @@ -1,5 +1,5 @@ # Base config file for Pandora FMS agents -# Version 7.0NG.732, GNU/Linux +# Version 7.0NG.733, GNU/Linux # Licensed under GPL license v2, # Copyright (c) 2003-2014 Artica Soluciones Tecnologicas # http://www.pandorafms.com diff --git a/pandora_agents/unix/NT4/pandora_agent.conf b/pandora_agents/unix/NT4/pandora_agent.conf index 1394067390..11e8c8e6c0 100644 --- a/pandora_agents/unix/NT4/pandora_agent.conf +++ b/pandora_agents/unix/NT4/pandora_agent.conf @@ -1,5 +1,5 @@ # Base config file for Pandora FMS agents -# Version 7.0NG.732, GNU/Linux +# Version 7.0NG.733, GNU/Linux # Licensed under GPL license v2, # Copyright (c) 2003-2009 Artica Soluciones Tecnologicas # http://www.pandorafms.com diff --git a/pandora_agents/unix/NetBSD/pandora_agent.conf b/pandora_agents/unix/NetBSD/pandora_agent.conf index 677615a47c..d0e7f040e2 100644 --- a/pandora_agents/unix/NetBSD/pandora_agent.conf +++ b/pandora_agents/unix/NetBSD/pandora_agent.conf @@ -1,5 +1,5 @@ # Base config file for Pandora FMS agents -# Version 7.0NG.732, NetBSD Version +# Version 7.0NG.733, NetBSD Version # Licensed under GPL license v2, # Copyright (c) 2003-2010 Artica Soluciones Tecnologicas # http://www.pandorafms.com diff --git a/pandora_agents/unix/SunOS/pandora_agent.conf b/pandora_agents/unix/SunOS/pandora_agent.conf index 89d5b46100..bb270634a5 100644 --- a/pandora_agents/unix/SunOS/pandora_agent.conf +++ b/pandora_agents/unix/SunOS/pandora_agent.conf @@ -1,5 +1,5 @@ # Base config file for Pandora FMS agents -# Version 7.0NG.732, Solaris Version +# Version 7.0NG.733, Solaris Version # Licensed under GPL license v2, # Copyright (c) 2003-2009 Artica Soluciones Tecnologicas # http://www.pandorafms.com diff --git a/pandora_agents/unix/pandora_agent b/pandora_agents/unix/pandora_agent index db68a4c637..6818cc90b7 100755 --- a/pandora_agents/unix/pandora_agent +++ b/pandora_agents/unix/pandora_agent @@ -41,7 +41,7 @@ my $Sem = undef; # Semaphore used to control the number of threads my $ThreadSem = undef; -use constant AGENT_VERSION => '7.0NG.732'; +use constant AGENT_VERSION => '7.0NG.733'; use constant AGENT_BUILD => '190327'; # Agent log default file size maximum and instances diff --git a/pandora_agents/unix/pandora_agent.redhat.spec b/pandora_agents/unix/pandora_agent.redhat.spec index 92a3d10086..0cf4bc8449 100644 --- a/pandora_agents/unix/pandora_agent.redhat.spec +++ b/pandora_agents/unix/pandora_agent.redhat.spec @@ -2,8 +2,8 @@ #Pandora FMS Linux Agent # %define name pandorafms_agent_unix -%define version 7.0NG.732 -%define release 190327 +%define version 7.0NG.733 +%define release 1 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 4ec527ceb8..171b9b5669 100644 --- a/pandora_agents/unix/pandora_agent.spec +++ b/pandora_agents/unix/pandora_agent.spec @@ -2,8 +2,8 @@ #Pandora FMS Linux Agent # %define name pandorafms_agent_unix -%define version 7.0NG.732 -%define release 190327 +%define version 7.0NG.733 +%define release 1 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 5145594c3d..991399fb08 100755 --- a/pandora_agents/unix/pandora_agent_installer +++ b/pandora_agents/unix/pandora_agent_installer @@ -9,7 +9,7 @@ # Please see http://www.pandorafms.org. This code is licensed under GPL 2.0 license. # ********************************************************************** -PI_VERSION="7.0NG.732" +PI_VERSION="7.0NG.733" PI_BUILD="190327" OS_NAME=`uname -s` diff --git a/pandora_agents/win32/bin/pandora_agent.conf b/pandora_agents/win32/bin/pandora_agent.conf index 3d1e208de8..12ccb4e91b 100644 --- a/pandora_agents/win32/bin/pandora_agent.conf +++ b/pandora_agents/win32/bin/pandora_agent.conf @@ -1,6 +1,6 @@ # Base config file for Pandora FMS Windows Agent # (c) 2006-2017 Artica Soluciones Tecnologicas -# Version 7.0NG.732 +# Version 7.0NG.733 # This program is Free Software, you can redistribute it and/or modify it # under the terms of the GNU General Public Licence as published by the Free Software diff --git a/pandora_agents/win32/installer/pandora.mpi b/pandora_agents/win32/installer/pandora.mpi index ed3a26bf93..449c6e9ec4 100644 --- a/pandora_agents/win32/installer/pandora.mpi +++ b/pandora_agents/win32/installer/pandora.mpi @@ -3,7 +3,7 @@ AllowLanguageSelection {Yes} AppName -{Pandora FMS Windows Agent v7.0NG.732} +{Pandora FMS Windows Agent v7.0NG.733} ApplicationID {17E3D2CF-CA02-406B-8A80-9D31C17BD08F} @@ -2387,7 +2387,7 @@ Windows,BuildSeparateArchives {No} Windows,Executable -{<%AppName%>-<%Version%>-Setup<%Ext%>} +{<%AppName%>-Setup<%Ext%>} Windows,FileDescription {<%AppName%> <%Version%> Setup} diff --git a/pandora_agents/win32/pandora.cc b/pandora_agents/win32/pandora.cc index 39bc92b3c3..8e6b33dddd 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.732(Build 190327)") +#define PANDORA_VERSION ("7.0NG.733(Build 190327)") string pandora_path; string pandora_dir; diff --git a/pandora_agents/win32/versioninfo.rc b/pandora_agents/win32/versioninfo.rc index ace464831d..17a14d6942 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.732(Build 190327))" + VALUE "ProductVersion", "(7.0NG.733(Build 190327))" VALUE "FileVersion", "1.0.0.0" END END diff --git a/pandora_console/DEBIAN/control b/pandora_console/DEBIAN/control index 89a8716f46..d7d20f2bd6 100644 --- a/pandora_console/DEBIAN/control +++ b/pandora_console/DEBIAN/control @@ -1,5 +1,5 @@ package: pandorafms-console -Version: 7.0NG.732-190327 +Version: 7.0NG.733 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 176e8bacfb..f23b9b5aa5 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.732-190327" +pandora_version="7.0NG.733" package_pear=0 package_pandora=1 diff --git a/pandora_console/extras/mr/26.sql b/pandora_console/extras/mr/26.sql index d48f722f60..aefaae76ae 100644 --- a/pandora_console/extras/mr/26.sql +++ b/pandora_console/extras/mr/26.sql @@ -1,6 +1,20 @@ START TRANSACTION; -ALTER TABLE tagent_custom_fields ADD COLUMN `combo_values` VARCHAR(255) DEFAULT ''; +CREATE TABLE IF NOT EXISTS `tnetwork_matrix` ( + `id` int(10) unsigned NOT NULL auto_increment, + `source` varchar(60) default '', + `destination` varchar(60) default '', + `utimestamp` bigint(20) default 0, + `bytes` int(18) unsigned default 0, + `pkts` int(18) unsigned default 0, + PRIMARY KEY (`id`), + UNIQUE (`source`, `destination`, `utimestamp`) +) ENGINE = InnoDB DEFAULT CHARSET=utf8 ; + +ALTER TABLE `treport_content` ADD COLUMN `show_extended_events` tinyint(1) default '0'; +UPDATE `treport_content` SET type="netflow_summary" WHERE type="netflow_pie" OR type="netflow_statistics"; + +UPDATE `tnetflow_filter` SET aggregate="dstip" WHERE aggregate NOT IN ("dstip", "srcip", "dstport", "srcport"); ALTER TABLE `treport_content` ADD COLUMN `show_extended_events` tinyint(1) default '0'; 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 ce3c78126f..6e5e2ebcc9 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 @@ -1355,6 +1355,7 @@ ALTER TABLE tgraph ADD COLUMN `fullscale` tinyint(1) UNSIGNED NOT NULL default ' -- Table `tnetflow_filter` -- --------------------------------------------------------------------- ALTER TABLE tnetflow_filter ADD COLUMN `router_ip` TEXT NOT NULL DEFAULT ""; +UPDATE `tnetflow_filter` SET aggregate="dstip" WHERE aggregate NOT IN ("dstip", "srcip", "dstport", "srcport"); -- --------------------------------------------------------------------- -- Table `treport_custom_sql` @@ -1377,6 +1378,7 @@ ALTER TABLE treport_content ADD COLUMN `visual_format` tinyint(1) default '0'; ALTER TABLE treport_content ADD COLUMN `hide_no_data` tinyint(1) default '0'; ALTER TABLE treport_content ADD COLUMN `recursion` tinyint(1) default NULL; ALTER TABLE treport_content ADD COLUMN `show_extended_events` tinyint(1) default '0'; +UPDATE `treport_content` SET type="netflow_summary" WHERE type="netflow_pie" OR type="netflow_statistics"; -- --------------------------------------------------------------------- -- Table `tmodule_relationship` @@ -1914,6 +1916,20 @@ CREATE TABLE `tgis_map_layer_groups` ( CONSTRAINT `tgis_map_layer_groups_ibfk_3` FOREIGN KEY (`agent_id`) REFERENCES `tagente` (`id_agente`) ON DELETE CASCADE ) ENGINE=InnoDB DEFAULT CHARSET=utf8; +-- ----------------------------------------------------- +-- Table `tnetwork_matrix` +-- ----------------------------------------------------- +CREATE TABLE IF NOT EXISTS `tnetwork_matrix` ( + `id` int(10) unsigned NOT NULL auto_increment, + `source` varchar(60) default '', + `destination` varchar(60) default '', + `utimestamp` bigint(20) default 0, + `bytes` int(18) unsigned default 0, + `pkts` int(18) unsigned default 0, + PRIMARY KEY (`id`), + UNIQUE (`source`, `destination`, `utimestamp`) +) ENGINE = InnoDB DEFAULT CHARSET=utf8 ; + -- ----------------------------------------------------- -- Table `tnotification_source` -- ----------------------------------------------------- diff --git a/pandora_console/general/main_menu.php b/pandora_console/general/main_menu.php index 072484ee06..877f171090 100644 --- a/pandora_console/general/main_menu.php +++ b/pandora_console/general/main_menu.php @@ -56,7 +56,7 @@ $custom_logo_collapsed = 'images/custom_logo/'.$config['custom_logo_collapsed']; if (!defined('PANDORA_ENTERPRISE')) { $logo_title = get_product_name().' Opensource'; - $custom_logo = 'images/custom_logo/pandora_logo_head_green.png'; + $custom_logo = 'images/custom_logo/pandora_logo_head_3.png'; $custom_logo_collapsed = 'images/custom_logo/pandora_logo_green_collapsed.png'; } else { if (file_exists(ENTERPRISE_DIR.'/'.$custom_logo)) { diff --git a/pandora_console/godmode/netflow/nf_edit_form.php b/pandora_console/godmode/netflow/nf_edit_form.php index 80f88f709e..60cd41f019 100644 --- a/pandora_console/godmode/netflow/nf_edit_form.php +++ b/pandora_console/godmode/netflow/nf_edit_form.php @@ -85,7 +85,6 @@ if ($id) { $dst_port = $filter['dst_port']; $src_port = $filter['src_port']; $aggregate = $filter['aggregate']; - $output = $filter['output']; $advanced_filter = $filter['advanced_filter']; } else { $name = ''; @@ -94,8 +93,7 @@ if ($id) { $ip_src = ''; $dst_port = ''; $src_port = ''; - $aggregate = 'none'; - $output = 'bytes'; + $aggregate = 'dstip'; $advanced_filter = ''; } @@ -103,7 +101,6 @@ if ($update) { $name = (string) get_parameter('name'); $assign_group = (int) get_parameter('assign_group'); $aggregate = get_parameter('aggregate', ''); - $output = get_parameter('output', 'bytes'); $ip_dst = get_parameter('ip_dst', ''); $ip_src = get_parameter('ip_src', ''); $dst_port = get_parameter('dst_port', ''); @@ -123,7 +120,6 @@ if ($update) { 'dst_port' => $dst_port, 'src_port' => $src_port, 'advanced_filter' => $advanced_filter, - 'output' => $output, ]; // Save filter args @@ -142,8 +138,7 @@ if ($update) { if ($create) { $name = (string) get_parameter('name'); $assign_group = (int) get_parameter('assign_group'); - $aggregate = get_parameter('aggregate', 'none'); - $output = get_parameter('output', 'bytes'); + $aggregate = get_parameter('aggregate', 'dstip'); $ip_dst = get_parameter('ip_dst', ''); $ip_src = get_parameter('ip_src', ''); $dst_port = get_parameter('dst_port', ''); @@ -159,7 +154,6 @@ if ($create) { 'src_port' => $src_port, 'aggregate' => $aggregate, 'advanced_filter' => $advanced_filter, - 'output' => $output, ]; // Save filter args @@ -241,8 +235,6 @@ $table->data[7][1] = html_print_textarea('advanced_filter', 4, 40, $advanced_fil $table->data[8][0] = '<b>'.__('Aggregate by').'</b>'.ui_print_help_icon('aggregate_by', true); $aggregate_list = [ - 'none' => __('None'), - 'proto' => __('Protocol'), 'srcip' => __('Src Ip Address'), 'dstip' => __('Dst Ip Address'), 'srcport' => __('Src Port'), @@ -251,15 +243,6 @@ $aggregate_list = [ $table->data[8][1] = html_print_select($aggregate_list, 'aggregate', $aggregate, '', '', 0, true, false, true, '', false); -$table->data[9][0] = '<b>'.__('Output format').'</b>'; -$show_output = [ - 'kilobytes' => __('Kilobytes'), - 'megabytes' => __('Megabytes'), - 'kilobytespersecond' => __('Kilobytes per second'), - 'megabytespersecond' => __('Megabytes per second'), -]; -$table->data[9][1] = html_print_select($show_output, 'output', $output, '', '', 0, true, false, true, '', false); - echo '<form method="post" action="'.$config['homeurl'].'index.php?sec=netf&sec2=godmode/netflow/nf_edit_form&pure='.$pure.'">'; html_print_table($table); echo '<div class="action-buttons" style="width: '.$table->width.'">'; diff --git a/pandora_console/godmode/reporting/reporting_builder.item_editor.php b/pandora_console/godmode/reporting/reporting_builder.item_editor.php index 46bcdf2280..62d58c9261 100755 --- a/pandora_console/godmode/reporting/reporting_builder.item_editor.php +++ b/pandora_console/godmode/reporting/reporting_builder.item_editor.php @@ -110,7 +110,7 @@ $event_graph_validated_vs_unvalidated = false; $netflow_filter = 0; $max_values = 0; -$resolution = 0; +$resolution = NETFLOW_RES_MEDD; $lapse_calc = 0; $lapse = 300; @@ -600,18 +600,22 @@ switch ($action) { break; case 'netflow_area': - case 'netflow_pie': case 'netflow_data': - case 'netflow_statistics': case 'netflow_summary': $netflow_filter = $item['text']; - // Filter + // Filter. $period = $item['period']; $description = $item['description']; $resolution = $item['top_n']; - // Interval resolution + // Interval resolution. $max_values = $item['top_n_value']; - // Max values + // Max values. + break; + + case 'nt_top_n': + $period = $item['period']; + $description = $item['description']; + $top_n_value = $item['top_n_value']; break; } @@ -638,6 +642,7 @@ switch ($action) { case 'simple_baseline_graph': case 'event_report_log': case 'increment': + case 'nt_top_n': $label = (isset($style['label'])) ? $style['label'] : ''; break; @@ -840,7 +845,11 @@ $class = 'databox filters'; </td> <td style=""> <?php - html_print_extended_select_for_time('resolution', $resolution, '', '', '0', 10); + html_print_select( + netflow_resolution_select_params(), + 'resolution', + $resolution + ); ?> </td> </tr> @@ -3673,16 +3682,6 @@ function chooseType() { $("#row_historical_db_check").hide(); break; - case 'netflow_pie': - $("#row_netflow_filter").show(); - $("#row_description").show(); - $("#row_period").show(); - $("#row_max_values").show(); - $("#row_resolution").show(); - $("#row_servers").show(); - $("#row_historical_db_check").hide(); - break; - case 'netflow_data': $("#row_netflow_filter").show(); $("#row_description").show(); @@ -3694,15 +3693,6 @@ function chooseType() { break; case 'netflow_summary': - $("#row_netflow_filter").show(); - $("#row_description").show(); - $("#row_period").show(); - $("#row_resolution").show(); - $("#row_servers").show(); - $("#row_historical_db_check").hide(); - break; - - case 'netflow_statistics': $("#row_netflow_filter").show(); $("#row_description").show(); $("#row_period").show(); @@ -3711,6 +3701,12 @@ function chooseType() { $("#row_servers").show(); $("#row_historical_db_check").hide(); break; + + case 'nt_top_n': + $("#row_description").show(); + $("#row_period").show(); + $("#row_quantity").show(); + break; } switch (type) { case 'event_report_agent': diff --git a/pandora_console/godmode/reporting/reporting_builder.php b/pandora_console/godmode/reporting/reporting_builder.php index fd64d9ac5e..9e40223340 100755 --- a/pandora_console/godmode/reporting/reporting_builder.php +++ b/pandora_console/godmode/reporting/reporting_builder.php @@ -1209,9 +1209,7 @@ switch ($action) { break; case 'netflow_area': - case 'netflow_pie': case 'netflow_data': - case 'netflow_statistics': case 'netflow_summary': $values['text'] = get_parameter('netflow_filter'); $values['description'] = get_parameter('description'); @@ -1247,6 +1245,12 @@ switch ($action) { $good_format = true; break; + case 'nt_top_n': + $values['period'] = get_parameter('period'); + $values['top_n_value'] = get_parameter('quantity'); + $good_format = true; + break; + default: $values['period'] = get_parameter('period'); $values['top_n'] = get_parameter('radiobutton_max_min_avg', 0); @@ -1437,6 +1441,7 @@ switch ($action) { case 'MTBF': case 'MTTR': case 'simple_baseline_graph': + case 'nt_top_n': if ($label != '') { $style['label'] = $label; } else { @@ -1577,9 +1582,7 @@ switch ($action) { break; case 'netflow_area': - case 'netflow_pie': case 'netflow_data': - case 'netflow_statistics': case 'netflow_summary': $values['text'] = get_parameter('netflow_filter'); $values['description'] = get_parameter('description'); @@ -1615,6 +1618,12 @@ switch ($action) { $good_format = true; break; + case 'nt_top_n': + $values['top_n_value'] = get_parameter('quantity'); + $values['period'] = get_parameter('period'); + $good_format = true; + break; + default: $values['period'] = get_parameter('period'); $values['top_n'] = get_parameter('radiobutton_max_min_avg', 0); @@ -1811,6 +1820,7 @@ switch ($action) { case 'MTBF': case 'MTTR': case 'simple_baseline_graph': + case 'nt_top_n': if ($label != '') { $style['label'] = $label; } else { diff --git a/pandora_console/godmode/servers/discovery.php b/pandora_console/godmode/servers/discovery.php index d617d92fdf..d9e19abdff 100755 --- a/pandora_console/godmode/servers/discovery.php +++ b/pandora_console/godmode/servers/discovery.php @@ -15,6 +15,7 @@ if (! check_acl($config['id_user'], 0, 'AW')) { ui_require_css_file('discovery'); + /** * Mask class names. * diff --git a/pandora_console/godmode/setup/performance.php b/pandora_console/godmode/setup/performance.php index 666dd0b21c..4d4281eec5 100644 --- a/pandora_console/godmode/setup/performance.php +++ b/pandora_console/godmode/setup/performance.php @@ -536,6 +536,19 @@ $table->data[] = [ ), ]; + +$table->data[] = [ + __('Max. days before delete old network matrix data'), + html_print_input_text( + 'delete_old_network_matrix', + $config['delete_old_network_matrix'], + '', + 5, + 5, + true + ), +]; + $table_other = new stdClass(); $table_other->width = '100%'; $table_other->class = 'databox filters'; diff --git a/pandora_console/godmode/setup/setup_general.php b/pandora_console/godmode/setup/setup_general.php index 370df5d808..4f2679fcf9 100644 --- a/pandora_console/godmode/setup/setup_general.php +++ b/pandora_console/godmode/setup/setup_general.php @@ -131,6 +131,14 @@ if (strtoupper(substr(PHP_OS, 0, 3)) == 'WIN') { $table->data[19][1] = html_print_checkbox_switch_extended('activate_netflow', 1, $config['activate_netflow'], $rbt_disabled, '', '', true); +$table->data[21][0] = __('Enable Network Traffic Analyzer'); +$table->data[21][1] = html_print_switch( + [ + 'name' => 'activate_nta', + 'value' => $config['activate_nta'], + ] +); + $zone_name = [ 'Africa' => __('Africa'), diff --git a/pandora_console/godmode/wizards/Wizard.main.php b/pandora_console/godmode/wizards/Wizard.main.php index fde2b411c0..022402a8d1 100644 --- a/pandora_console/godmode/wizards/Wizard.main.php +++ b/pandora_console/godmode/wizards/Wizard.main.php @@ -214,12 +214,16 @@ class Wizard $bc[$i] = ''; - if ($separator_beginning === true) $bc[$i] .= '<span class="breadcrumb_link"> / </span>'; + if ($separator_beginning === true) { + $bc[$i] .= '<span class="breadcrumb_link"> / </span>'; + } $bc[$i] .= '<span><a class="breadcrumb_link '.$class.'" href="'.$url['link'].'">'; $bc[$i] .= $url['label']; $bc[$i] .= '</a>'; - if ($count < $array_size) $bc[$i] .= '<span class="breadcrumb_link"> / </span>'; + if ($count < $array_size) { + $bc[$i] .= '<span class="breadcrumb_link"> / </span>'; + } $bc[$i] .= '</span>'; diff --git a/pandora_console/include/class/ConsoleSupervisor.php b/pandora_console/include/class/ConsoleSupervisor.php index b33a208c5a..7259287d68 100644 --- a/pandora_console/include/class/ConsoleSupervisor.php +++ b/pandora_console/include/class/ConsoleSupervisor.php @@ -710,7 +710,7 @@ class ConsoleSupervisor $this->notify( [ 'type' => 'NOTIF.LICENSE.EXPIRATION', - 'title' => __('License is going to expire.'), + 'title' => __('License is about to expire'), 'message' => __( 'Your license will expire in %d days. Please, contact our sales department.', $days_to_expiry diff --git a/pandora_console/include/class/NetworkMap.class.php b/pandora_console/include/class/NetworkMap.class.php index 1191063bdd..fb019bfa6f 100644 --- a/pandora_console/include/class/NetworkMap.class.php +++ b/pandora_console/include/class/NetworkMap.class.php @@ -289,6 +289,13 @@ class NetworkMap */ private $filter; + /** + * Do not show the popup window. + * + * @var integer + */ + private $noPopUp; + /** * Base constructor. @@ -315,7 +322,7 @@ class NetworkMap $this->mapOptions['width'] = $config['networkmap_max_width']; $this->mapOptions['height'] = $config['networkmap_max_width']; $this->mapOptions['simple'] = 0; - $this->mapOptions['font_size'] = 12; + $this->mapOptions['font_size'] = 20; $this->mapOptions['nooverlap'] = 1; $this->mapOptions['z_dash'] = 0.5; $this->mapOptions['center'] = 0; @@ -376,10 +383,13 @@ class NetworkMap $this->noPandoraNode = $options['no_pandora_node']; } + if (isset($options['no_popup'])) { + $this->noPopUp = $options['no_popup']; + } + // Initialize as widget? if (isset($options['widget'])) { $this->isWidget = (bool) $options['widget']; - } else { $this->isWidget = true; } @@ -3421,13 +3431,17 @@ class NetworkMap $output .= $this->loadMapSkel(); $output .= $this->loadMapData(); $output .= $this->loadController(); - $output .= $this->loadAdvancedInterface(); + if (!$this->noPopUp) { + $output .= $this->loadAdvancedInterface(); + } } else { // Simulated, no tmap entries. $output .= $this->loadMapSkel(); $output .= $this->loadMapData(); $output .= $this->loadController(); - $output .= $this->loadSimpleInterface(); + if (!$this->noPopUp) { + $output .= $this->loadSimpleInterface(); + } } $output .= ' diff --git a/pandora_console/include/config_process.php b/pandora_console/include/config_process.php index 4e913ba3d4..8bdf4572da 100644 --- a/pandora_console/include/config_process.php +++ b/pandora_console/include/config_process.php @@ -21,7 +21,7 @@ * Pandora build version and version */ $build_version = 'PC190327'; -$pandora_version = 'v7.0NG.732'; +$pandora_version = 'v7.0NG.733'; // Do not overwrite default timezone set if defined. $script_tz = @date_default_timezone_get(); diff --git a/pandora_console/include/functions.php b/pandora_console/include/functions.php index 9816e373bb..0b9f71221b 100644 --- a/pandora_console/include/functions.php +++ b/pandora_console/include/functions.php @@ -243,19 +243,25 @@ function format_numeric($number, $decimals=1) /** * Render numeric data for a graph. It adds magnitude suffix to the number - * (M for millions, K for thousands...) base-10 + * (M for millions, K for thousands...). Base can be modified with divider. * - * TODO: base-2 multiplication - * - * @param float $number Number to be rendered - * @param integer $decimals Numbers after comma. Default value: 1 - * @param dec_point Decimal separator character. Default value: . - * @param thousands_sep Thousands separator character. Default value: , + * @param float $number Number to be rendered. + * @param integer $decimals Numbers after comma (default 1). + * @param string $dec_point Decimal separator character (default .). + * @param string $thousands_sep Thousands separator character (default ,). + * @param integer $divider Number to divide the rendered number. + * @param string $sufix Units of the multiple. * * @return string A string with the number and the multiplier */ -function format_for_graph($number, $decimals=1, $dec_point='.', $thousands_sep=',') -{ +function format_for_graph( + $number, + $decimals=1, + $dec_point='.', + $thousands_sep=',', + $divider=1000, + $sufix='' +) { $shorts = [ '', 'K', @@ -268,15 +274,15 @@ function format_for_graph($number, $decimals=1, $dec_point='.', $thousands_sep=' 'Y', ]; $pos = 0; - while ($number >= 1000) { - // as long as the number can be divided by 1000 + while ($number >= $divider) { + // As long as the number can be divided by divider. $pos++; - // Position in array starting with 0 - $number = ($number / 1000); + // Position in array starting with 0. + $number = ($number / $divider); } - return remove_right_zeros(format_numeric($number, $decimals)).$shorts[$pos]; - // This will actually do the rounding and the decimals + // This will actually do the rounding and the decimals. + return remove_right_zeros(format_numeric($number, $decimals)).$shorts[$pos].$sufix; } diff --git a/pandora_console/include/functions_config.php b/pandora_console/include/functions_config.php index 6e6673b917..5435de5b8a 100644 --- a/pandora_console/include/functions_config.php +++ b/pandora_console/include/functions_config.php @@ -224,6 +224,10 @@ function config_update_config() $error_update[] = __('Enable Netflow'); } + if (!config_update_value('activate_nta', (bool) get_parameter_switch('activate_nta'))) { + $error_update[] = __('Enable Network Traffic Analyzer'); + } + $timezone = (string) get_parameter('timezone'); if ($timezone != '') { if (!config_update_value('timezone', $timezone)) { @@ -756,6 +760,10 @@ function config_update_config() $error_update[] = __('Max. days before delete old messages'); } + if (!config_update_value('delete_old_network_matrix', get_parameter('delete_old_network_matrix'))) { + $error_update[] = __('Max. days before delete old network matrix data'); + } + if (!config_update_value('max_graph_container', get_parameter('max_graph_container'))) { $error_update[] = __('Graph container - Max. Items'); } @@ -1555,6 +1563,10 @@ function config_process_config() config_update_value('delete_old_messages', 21); } + if (!isset($config['delete_old_network_matrix'])) { + config_update_value('delete_old_network_matrix', 10); + } + if (!isset($config['max_graph_container'])) { config_update_value('max_graph_container', 10); } @@ -1991,6 +2003,10 @@ function config_process_config() config_update_value('activate_netflow', 0); } + if (!isset($config['activate_nta'])) { + config_update_value('activate_nta', 0); + } + if (!isset($config['netflow_path'])) { if ($is_windows) { $default = 'C:\\PandoraFMS\\Pandora_Server\\data_in\\netflow'; diff --git a/pandora_console/include/functions_graph.php b/pandora_console/include/functions_graph.php index 71049d7804..de0a1bdd6f 100644 --- a/pandora_console/include/functions_graph.php +++ b/pandora_console/include/functions_graph.php @@ -533,7 +533,8 @@ function grafico_modulo_sparse_data( 'image_treshold' => false, 'graph_combined' => false, 'zoom' => 1, - 'server_id' => null + 'server_id' => null, + 'stacked' => 0, ); */ function grafico_modulo_sparse($params) @@ -710,6 +711,10 @@ function grafico_modulo_sparse($params) $agent_module_id = $params['agent_module_id']; } + if (!isset($params['stacked'])) { + $params['stacked'] = 0; + } + // XXXX Configurable $params['grid_color'] = '#C1C1C1'; $params['legend_color'] = '#636363'; @@ -4104,7 +4109,7 @@ function fullscale_data( /** * Print an area graph with netflow aggregated */ -function graph_netflow_aggregate_area($data, $period, $width, $height, $unit='', $ttl=1, $only_image=false) +function graph_netflow_aggregate_area($data, $period, $width, $height, $ttl=1, $only_image=false, $date=null) { global $config; global $graphic_type; @@ -4150,7 +4155,7 @@ function graph_netflow_aggregate_area($data, $period, $width, $height, $unit='', 'period' => $period, 'width' => '90%', 'height' => 450, - 'unit' => $unit, + 'unit' => 'bytes', 'only_image' => $only_image, 'homeurl' => $homeurl, 'menu' => true, @@ -4159,6 +4164,10 @@ function graph_netflow_aggregate_area($data, $period, $width, $height, $unit='', 'font' => $config['fontpath'], 'font_size' => $config['font_size'], 'array_data_create' => $chart, + 'stacked' => 1, + 'date' => $date, + 'show_export_csv' => false, + 'show_overview' => false, ]; return grafico_modulo_sparse($params); @@ -4280,9 +4289,16 @@ function graph_netflow_aggregate_pie($data, $aggregate, $ttl=1, $only_image=fals /** - * Print a circular graph with the data transmitted between IPs + * Print a circular mesh array. + * + * @param array $data Array with properly data structure. Array with two + * elements required: + * 'elements': Non-associative array with all the relationships. + * 'matrix': Array of arrays with value of the relationship. + * + * @return string HTML data. */ -function graph_netflow_circular_mesh($data, $unit, $radius=700) +function graph_netflow_circular_mesh($data) { global $config; @@ -4292,14 +4308,14 @@ function graph_netflow_circular_mesh($data, $unit, $radius=700) include_once $config['homedir'].'/include/graphs/functions_d3.php'; - return d3_relationship_graph($data['elements'], $data['matrix'], $unit, $radius, true); + return d3_relationship_graph($data['elements'], $data['matrix'], 700, true); } /** * Print a rectangular graph with the traffic of the ports for each IP */ -function graph_netflow_host_traffic($data, $unit, $width=700, $height=700) +function graph_netflow_host_traffic($data, $width=700, $height=700) { global $config; diff --git a/pandora_console/include/functions_html.php b/pandora_console/include/functions_html.php index 4cb405d154..4a24d5a964 100644 --- a/pandora_console/include/functions_html.php +++ b/pandora_console/include/functions_html.php @@ -1060,7 +1060,7 @@ function html_print_extended_select_for_time( 'images/pencil.png', true, [ - 'class' => $uniq_name.'_toggler', + 'class' => $uniq_name.'_toggler '.$class, 'alt' => __('Custom'), 'title' => __('Custom'), 'style' => 'width: 18px;'.$style_icon, @@ -2392,12 +2392,21 @@ function html_print_checkbox_switch($name, $value, $checked=false, $return=false /** * Prints an image HTML element. * - * @param string $src Image source filename. - * @param boolean $return Whether to return or print - * @param array $options Array with optional HTML options to set. At this moment, the - * following options are supported: alt, style, title, width, height, class, pos_tree. - * @param boolean $return_src Whether to return src field of image ('images/*.*') or complete html img tag ('<img src="..." alt="...">'). - * @param boolean $relative Whether to use relative path to image or not (i.e. $relative= true : /pandora/<img_src>). + * @param string $src Image source filename. + * @param boolean $return Whether to return or print. + * @param array $options Array with optional HTML options to set. + * At this moment, the following options are supported: + * align, border, hspace, ismap, vspace, style, title, height, + * longdesc, usemap, width, id, class, lang, xml:lang, onclick, + * ondblclick, onmousedown, onmouseup, onmouseover, onmousemove, + * onmouseout, onkeypress, onkeydown, onkeyup, pos_tree, alt. + * @param boolean $return_src Whether to return src field of image + * ('images/*.*') or complete html img tag ('<img src="..." alt="...">'). + * @param boolean $relative Whether to use relative path to image or not + * (i.e. $relative= true : /pandora/<img_src>). + * @param boolean $no_in_meta Do not show on metaconsole folder at first. Go + * directly to the node. + * @param boolean $isExternalLink Do not shearch for images in Pandora. * * @return string HTML code if return parameter is true. */ @@ -2412,9 +2421,9 @@ function html_print_image( ) { global $config; - // If metaconsole is in use then don't use skins + // If metaconsole is in use then don't use skins. if (!is_metaconsole()) { - // Checks if user's skin is available + // Checks if user's skin is available. $isFunctionSkins = enterprise_include_once('include/functions_skins.php'); if ($isFunctionSkins !== ENTERPRISE_NOT_HOOK) { @@ -2426,11 +2435,11 @@ function html_print_image( } } - // If metaconsole is activated and image doesn't exists try to search on normal console + // If metaconsole is activated and image doesn't exists try to search on normal console. if (is_metaconsole()) { if (!$relative) { $working_dir = str_replace('\\', '/', getcwd()); - // Windows compatibility + // Windows compatibility. if ($no_in_meta) { $src = '../../'.$src; } else if (strstr($working_dir, 'enterprise/meta') === false) { @@ -2468,22 +2477,22 @@ function html_print_image( } } - // Only return src field of image + // Only return src field of image. if ($return_src) { if (!$return) { echo io_safe_input($src); - return; + return null; } return io_safe_input($src); } $output = '<img src="'.$src.'" '; - // Dont use safe_input here or the performance will dead + // Dont use safe_input here or the performance will dead. $style = ''; if (!empty($options)) { - // Deprecated or value-less attributes + // Deprecated or value-less attributes. if (isset($options['align'])) { $style .= 'align:'.$options['align'].';'; // Align is deprecated, use styles. @@ -2491,23 +2500,23 @@ function html_print_image( if (isset($options['border'])) { $style .= 'border:'.$options['border'].'px;'; - // Border is deprecated, use styles + // Border is deprecated, use styles. } if (isset($options['hspace'])) { $style .= 'margin-left:'.$options['hspace'].'px;'; - // hspace is deprecated, use styles + // hspace is deprecated, use styles. $style .= 'margin-right:'.$options['hspace'].'px;'; } if (isset($options['ismap'])) { $output .= 'ismap="ismap" '; - // Defines the image as a server-side image map + // Defines the image as a server-side image map. } if (isset($options['vspace'])) { $style .= 'margin-top:'.$options['vspace'].'px;'; - // hspace is deprecated, use styles + // hspace is deprecated, use styles. $style .= 'margin-bottom:'.$options['vspace'].'px;'; } @@ -2515,7 +2524,7 @@ function html_print_image( $style .= $options['style']; } - // If title is provided activate forced title + // If title is provided activate forced title. if (isset($options['title']) && $options['title'] != '') { if (isset($options['class'])) { $options['class'] .= ' forced_title'; @@ -2523,12 +2532,12 @@ function html_print_image( $options['class'] = 'forced_title'; } - // New way to show the force_title (cleaner and better performance) + // New way to show the force_title (cleaner and better performance). $output .= 'data-title="'.io_safe_input_html($options['title']).'" '; $output .= 'data-use_title_for_force_title="1" '; } - // Valid attributes (invalid attributes get skipped) + // Valid attributes (invalid attributes get skipped). $attrs = [ 'height', 'longdesc', @@ -2562,7 +2571,7 @@ function html_print_image( if (!isset($options['alt']) && isset($options['title'])) { $options['alt'] = io_safe_input_html($options['title']); - // Set alt to title if it's not set + // Set alt to title if it's not set. } if (!empty($style)) { @@ -3002,3 +3011,48 @@ function html_print_switch($attributes=[]) <span class='p-slider'></span> </label>"; } + + +/** + * Print a link with post params.The component is really a form with a button + * with some inputs hidden. + * + * @param string $text Text to show. + * @param array $params Params to be written like inputs hidden. + * @param string $text Text of image. + * @param string $style Additional style for the element. + * + * @return string With HTML code. + */ +function html_print_link_with_params($text, $params=[], $type='text', $style='') +{ + $html = '<form method=post>'; + switch ($type) { + case 'image': + $html .= html_print_input_image($text, $text, $text, $style, true); + break; + + case 'text': + default: + if (!empty($style)) { + $style = ' style="'.$style.'"'; + } + + $html .= html_print_submit_button( + $text, + $text, + false, + 'class="button-as-link"'.$style, + true + ); + break; + } + + foreach ($params as $param => $value) { + $html .= html_print_input_hidden($param, $value, true); + } + + $html .= '</form>'; + + return $html; +} \ No newline at end of file diff --git a/pandora_console/include/functions_netflow.php b/pandora_console/include/functions_netflow.php index 84f3c26169..69aa0a1608 100644 --- a/pandora_console/include/functions_netflow.php +++ b/pandora_console/include/functions_netflow.php @@ -1,36 +1,60 @@ <?php -// Pandora FMS - http://pandorafms.com -// ================================================== -// Copyright (c) 2005-2010 Artica Soluciones Tecnologicas -// Please see http://pandorafms.org for full contribution list -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public License -// as published by the Free Software Foundation; version 2 -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. +/** + * Netflow functions + * + * @package Functons. + * @subpackage Netflow functions. + * + * Pandora FMS - http://pandorafms.com + * ================================================== + * Copyright (c) 2005-2019 Artica Soluciones Tecnologicas + * Please see http://pandorafms.org for full contribution list + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; version 2 + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + require_once $config['homedir'].'/include/functions_users.php'; require_once $config['homedir'].'/include/functions_io.php'; require_once $config['homedir'].'/include/functions_io.php'; -enterprise_include_once($config['homedir'].'/enterprise/include/pdf_translator.php'); -enterprise_include_once($config['homedir'].'/enterprise/include/functions_metaconsole.php'); +require_once $config['homedir'].'/include/functions_network.php'; +require_once $config['homedir'].'/include/class/NetworkMap.class.php'; +enterprise_include_once( + $config['homedir'].'/enterprise/include/pdf_translator.php' +); +enterprise_include_once( + $config['homedir'].'/enterprise/include/functions_metaconsole.php' +); -// Date format for nfdump +define('NETFLOW_RES_LOWD', 6); +define('NETFLOW_RES_MEDD', 12); +define('NETFLOW_RES_HID', 24); +define('NETFLOW_RES_ULTRAD', 30); +define('NETFLOW_RES_HOURLY', 'hourly'); +define('NETFLOW_RES_DAILY', 'daily'); + +define('NETFLOW_MAX_DATA_CIRCULAR_MESH', 10000); + +// Date format for nfdump. global $nfdump_date_format; $nfdump_date_format = 'Y/m/d.H:i:s'; -// Array to hold the hostnames +// Array to hold the hostnames. $hostnames = []; /** * Selects all netflow filters (array (id_name => id_name)) or filters filtered * - * @param mixed Array with filter conditions to retrieve filters or false. + * @param mixed $filter Array with filter conditions to retrieve filters or + * false. * - * @return array List of all filters + * @return array List of all filters. */ function netflow_get_filters($filter=false) { @@ -56,9 +80,10 @@ function netflow_get_filters($filter=false) /** * Selects all netflow reports (array (id_name => id_name)) or filters filtered * - * @param mixed Array with filter conditions to retrieve filters or false. + * @param mixed $filter Array with filter conditions to retrieve filters or + * false. * - * @return array List of all filters + * @return array List of all filters. */ function netflow_get_reports($filter=false) { @@ -81,14 +106,20 @@ function netflow_get_reports($filter=false) } -// permite validar si un filtro pertenece a un grupo permitido para el usuario +/** + * Check if a filter owns to a certain group. + * + * @param integer $id_sg Id group to check. + * + * @return boolean True if user manages that group. + */ function netflow_check_filter_group($id_sg) { global $config; $id_group = db_get_value('id_group', 'tnetflow_filter', 'id_sg', $id_sg); $own_info = get_user_info($config['id_user']); - // Get group list that user has access + // Get group list that user has access. $groups_user = users_get_groups($config['id_user'], 'IW', $own_info['is_admin'], true); $groups_id = []; $has_permission = false; @@ -103,44 +134,12 @@ function netflow_check_filter_group($id_sg) } -/* - Permite validar si un informe pertenece a un grupo permitido para el usuario. - * Si mode = false entonces es modo godmode y solo puede ver el grupo All el admin - * Si es modo operation (mode = true) entonces todos pueden ver el grupo All - */ - -function netflow_check_report_group($id_report, $mode=false) -{ - global $config; - - if (!$mode) { - $own_info = get_user_info($config['id_user']); - $mode = $own_info['is_admin']; - } - - $id_group = db_get_value('id_group', 'tnetflow_report', 'id_report', $id_report); - - // Get group list that user has access - $groups_user = users_get_groups($config['id_user'], 'IW', $mode, true); - $groups_id = []; - $has_permission = false; - - foreach ($groups_user as $key => $groups) { - if ($groups['id_grupo'] == $id_group) { - return true; - } - } - - return false; -} - - /** * Get a filter. * - * @param int filter id to be fetched. - * @param array Extra filter. - * @param array Fields to be fetched. + * @param integer $id_sg Filter id to be fetched. + * @param mixed $filter Extra filter. + * @param mixed $fields Fields to be fetched. * * @return array A netflow filter matching id and filter. */ @@ -156,52 +155,11 @@ function netflow_filter_get_filter($id_sg, $filter=false, $fields=false) } -/** - * Get options. - * - * @param int filter id to be fetched. - * @param array Extra filter. - * @param array Fields to be fetched. - * - * @return array A netflow filter matching id and filter. - */ -function netflow_reports_get_reports($id_report, $filter=false, $fields=false) -{ - if (empty($id_report)) { - return false; - } - - if (! is_array($filter)) { - $filter = []; - } - - $filter['id_report'] = (int) $id_report; - - return db_get_row_filter('tnetflow_report', $filter, $fields); -} - - -function netflow_reports_get_content($id_rc, $filter=false, $fields=false) -{ - if (empty($id_rc)) { - return false; - } - - if (! is_array($filter)) { - $filter = []; - } - - $filter['id_rc'] = (int) $id_rc; - - return db_get_row_filter('tnetflow_report_content', $filter, $fields); -} - - /** * Compare two flows according to the 'data' column. * - * @param array a First flow. - * @param array b Second flow. + * @param array $a First flow. + * @param array $b Second flow. * * @return Result of the comparison. */ @@ -214,7 +172,9 @@ function compare_flows($a, $b) /** * Sort netflow data according to the 'data' column. * - * @param array netflow_data Netflow data array. + * @param array $netflow_data Netflow data array. + * + * @return void (Array passed by reference) */ function sort_netflow_data(&$netflow_data) { @@ -225,22 +185,22 @@ function sort_netflow_data(&$netflow_data) /** * Show a table with netflow statistics. * - * @param array data Statistic data. - * @param string start_date Start date. - * @param string end_date End date. - * @param string aggregate Aggregate field. - * @param string unit Unit to show. + * @param array $data Statistic data. + * @param string $start_date Start date. + * @param string $end_date End date. + * @param string $aggregate Aggregate field. * - * @return The statistics table. + * @return string HTML statistics table. */ -function netflow_stat_table($data, $start_date, $end_date, $aggregate, $unit) +function netflow_stat_table($data, $start_date, $end_date, $aggregate) { global $nfdump_date_format; $start_date = date($nfdump_date_format, $start_date); $end_date = date($nfdump_date_format, $end_date); $values = []; - $table->width = '40%'; + $table = new stdClass(); + $table->width = '100%'; $table->cellspacing = 0; $table->class = 'databox'; $table->data = []; @@ -249,7 +209,7 @@ function netflow_stat_table($data, $start_date, $end_date, $aggregate, $unit) $table->head = []; $table->head[0] = '<b>'.netflow_format_aggregate($aggregate).'</b>'; - $table->head[1] = '<b>'.netflow_format_unit($unit).'</b>'; + $table->head[1] = '<b>'.__('Value').'</b>'; $table->style[0] = 'padding: 6px;'; $table->style[1] = 'padding: 6px;'; @@ -257,14 +217,13 @@ function netflow_stat_table($data, $start_date, $end_date, $aggregate, $unit) $agg = $data[$j]['agg']; if (!isset($values[$agg])) { $values[$agg] = $data[$j]['data']; - $table->data[$x][0] = $agg; - $table->data[$x][1] = format_numeric($data[$j]['data']).' '.netflow_format_unit($unit); } else { $values[$agg] += $data[$j]['data']; - $table->data[$x][0] = $agg; - $table->data[$x][1] = format_numeric($data[$j]['data']).' '.netflow_format_unit($unit); } + $table->data[$x][0] = $agg; + $table->data[$x][1] = network_format_bytes($data[$j]['data']); + $j++; $x++; } @@ -276,14 +235,14 @@ function netflow_stat_table($data, $start_date, $end_date, $aggregate, $unit) /** * Show a table with netflow data. * - * @param array data Netflow data. - * @param string start_date Start date. - * @param string end_date End date. - * @param string aggregate Aggregate field. + * @param array $data Netflow data. + * @param string $start_date Start date. + * @param string $end_date End date. + * @param string $aggregate Aggregate field. * - * @return The statistics table. + * @return string HTML data table. */ -function netflow_data_table($data, $start_date, $end_date, $aggregate, $unit) +function netflow_data_table($data, $start_date, $end_date, $aggregate) { global $nfdump_date_format; @@ -291,7 +250,7 @@ function netflow_data_table($data, $start_date, $end_date, $aggregate, $unit) $start_date = date($nfdump_date_format, $start_date); $end_date = date($nfdump_date_format, $end_date); - // Set the format + // Set the format. if ($period <= SECONDS_6HOURS) { $time_format = 'H:i:s'; } else if ($period < SECONDS_1DAY) { @@ -305,6 +264,7 @@ function netflow_data_table($data, $start_date, $end_date, $aggregate, $unit) } $values = []; + $table = new stdClass(); $table->size = ['100%']; $table->class = 'databox'; $table->cellspacing = 0; @@ -332,7 +292,7 @@ function netflow_data_table($data, $start_date, $end_date, $aggregate, $unit) $table->style[1] = 'padding: 4px;'; } - // No aggregates + // No aggregates. if ($source_count == 0) { $table->head[1] = __('Data'); $table->align[1] = 'right'; @@ -340,21 +300,17 @@ function netflow_data_table($data, $start_date, $end_date, $aggregate, $unit) foreach ($data as $timestamp => $value) { $table->data[$i][0] = date($time_format, $timestamp); - $table->data[$i][1] = format_numeric($value['data']).' '.netflow_format_unit($unit); + $table->data[$i][1] = network_format_bytes($value['data']); $i++; } - } - // Aggregates - else { + } else { $i = 0; foreach ($data['data'] as $timestamp => $values) { $table->data[$i][0] = date($time_format, $timestamp); for ($j = 0; $j < $source_count; $j++) { - if (isset($values[$source_index[$j]])) { - $table->data[$i][($j + 1)] = format_numeric($values[$source_index[$j]]).' '.netflow_format_unit($unit); - } else { - $table->data[$i][($j + 1)] = (0).' '.netflow_format_unit($unit); - } + $table->data[$i][($j + 1)] = network_format_bytes( + $values[$source_index[$j]] + ); } $i++; @@ -368,18 +324,19 @@ function netflow_data_table($data, $start_date, $end_date, $aggregate, $unit) /** * Show a table with a traffic summary. * - * @param array data Summary data. + * @param array $data Summary data. * - * @return The statistics table. + * @return string HTML summary table. */ function netflow_summary_table($data) { global $nfdump_date_format; $values = []; - $table->size = ['50%']; + $table = new stdClass(); $table->cellspacing = 0; $table->class = 'databox'; + $table->styleTable = 'width: 100%'; $table->data = []; $table->style[0] = 'font-weight: bold; padding: 6px'; @@ -387,32 +344,32 @@ function netflow_summary_table($data) $row = []; $row[] = __('Total flows'); - $row[] = format_numeric($data['totalflows']); + $row[] = format_for_graph($data['totalflows'], 2); $table->data[] = $row; $row = []; $row[] = __('Total bytes'); - $row[] = format_numeric($data['totalbytes']); + $row[] = network_format_bytes($data['totalbytes']); $table->data[] = $row; $row = []; $row[] = __('Total packets'); - $row[] = format_numeric($data['totalpackets']); + $row[] = format_for_graph($data['totalpackets'], 2); $table->data[] = $row; $row = []; $row[] = __('Average bits per second'); - $row[] = format_numeric($data['avgbps']); + $row[] = network_format_bytes($data['avgbps']); $table->data[] = $row; $row = []; $row[] = __('Average packets per second'); - $row[] = format_numeric($data['avgpps']); + $row[] = format_for_graph($data['avgpps'], 2); $table->data[] = $row; $row = []; $row[] = __('Average bytes per packet'); - $row[] = format_numeric($data['avgbpp']); + $row[] = format_for_graph($data['avgbpp'], 2); $table->data[] = $row; $html = html_print_table($table, true); @@ -424,7 +381,7 @@ function netflow_summary_table($data) /** * Returns 1 if the given address is a network address. * - * @param string address Host or network address. + * @param string $address Host or network address. * * @return 1 if the address is a network address, 0 otherwise. */ @@ -441,225 +398,173 @@ function netflow_is_net($address) /** * Returns netflow data for the given period in an array. * - * @param string start_date Period start date. - * @param string end_date Period end date. - * @param string filter Netflow filter. - * @param string aggregate Aggregate field. - * @param int max Maximum number of aggregates. - * @param string unit Unit to show. + * @param string $start_date Period start date. + * @param string $end_date Period end date. + * @param mixed $interval_length Resolution points or hourly or daily. + * @param string $filter Netflow filter. + * @param string $aggregate Aggregate field. + * @param integer $max Maximum number of aggregates. + * @param boolean $absolute True to give the absolute data and false + * to get troughput. + * @param string $connection_name Node name when data is get in meta. + * @param boolean $address_resolution True to resolve ips to hostnames. * - * @return An array with netflow stats. + * @return array An array with netflow stats. */ -function netflow_get_data($start_date, $end_date, $interval_length, $filter, $aggregate, $max, $unit, $connection_name='', $address_resolution=false) -{ +function netflow_get_data( + $start_date, + $end_date, + $interval_length, + $filter, + $aggregate, + $max, + $absolute, + $connection_name='', + $address_resolution=false +) { global $nfdump_date_format; global $config; - // Requesting remote data + // Requesting remote data. if (defined('METACONSOLE') && $connection_name != '') { - $data = metaconsole_call_remote_api($connection_name, 'netflow_get_data', "$start_date|$end_date|$interval_length|".base64_encode(json_encode($filter))."|$aggregate|$max|$unit".(int) $address_resolution); + $data = metaconsole_call_remote_api( + $connection_name, + 'netflow_get_data', + "$start_date|$end_date|$interval_length|".base64_encode(json_encode($filter))."|$aggregate|$max|1".(int) $address_resolution + ); return json_decode($data, true); } - // Calculate the number of intervals - if ($interval_length <= 0) { - // $num_intervals = $config['graph_res'] * 50; - $num_intervals = 250; - $period = ($end_date - $start_date); - $interval_length = (int) ($period / $num_intervals); - } else { - $period = ($end_date - $start_date); - $num_intervals = (int) ($period / $interval_length); + if ($start_date > $end_date) { + return []; } - // Set a max number of intervals - if ($num_intervals > $config['netflow_max_resolution']) { - $num_intervals = $config['netflow_max_resolution']; - $interval_length = (int) ($period / $num_intervals); + // Calculate the number of intervals. + $multiplier_time = ($end_date - $start_date); + switch ($interval_length) { + case NETFLOW_RES_LOWD: + case NETFLOW_RES_MEDD: + case NETFLOW_RES_HID: + case NETFLOW_RES_ULTRAD: + $multiplier_time = ceil(($end_date - $start_date) / $interval_length); + break; + + case NETFLOW_RES_HOURLY: + $multiplier_time = SECONDS_1HOUR; + break; + + case NETFLOW_RES_DAILY: + $multiplier_time = SECONDS_1DAY; + break; + + default: + $multiplier_time = ($end_date - $start_date); + break; } - // If there is aggregation calculate the top n - if ($aggregate != 'none') { - $values['data'] = []; - $values['sources'] = []; - - // Get the command to call nfdump - $command = netflow_get_command($filter); - - // Suppress the header line and the statistics at the bottom and configure piped output - $command .= ' -q -o csv'; - - // Call nfdump - $agg_command = $command." -n $max -s $aggregate/bytes -t ".date($nfdump_date_format, $start_date).'-'.date($nfdump_date_format, $end_date); - exec($agg_command, $string); - - // Remove the first line - $string[0] = ''; - - // Parse aggregates - foreach ($string as $line) { - if ($line == '') { - continue; - } - - $val = explode(',', $line); - if ($aggregate == 'proto') { - $values['sources'][$val[3]] = 1; - } else { - $values['sources'][$val[4]] = 1; - } - } - - // Update the filter - switch ($aggregate) { - case 'proto': - $extra_filter = 'proto'; - break; - - default: - case 'srcip': - $extra_filter = 'ip_src'; - break; - case 'srcport': - $extra_filter = 'src_port'; - break; - - case 'dstip': - $extra_filter = 'ip_dst'; - break; - - case 'dstport': - $extra_filter = 'dst_port'; - break; - } - - if (isset($filter[$extra_filter]) && $filter[$extra_filter] != '') { - $filter[$extra_filter] .= ','; - } - - $filter[$extra_filter] = implode( - ',', - array_keys($values['sources']) + // Recalculate to not pass of netflow_max_resolution. + if ($config['netflow_max_resolution'] > 0 + && (($end_date - $start_date) / $multiplier_time) > 50 + ) { + $multiplier_time = ceil( + (($end_date - $start_date) / $config['netflow_max_resolution']) ); - } else { - $values = []; } - // Address resolution start - $get_hostnames = false; - if ($address_resolution && ($aggregate == 'srcip' || $aggregate == 'dstip')) { - $get_hostnames = true; - global $hostnames; + // Put all points into an array. + $intervals = [($start_date - $multiplier_time)]; + while ((end($intervals) < $end_date) === true) { + $intervals[] = (end($intervals) + $multiplier_time); + } - $sources = []; - foreach ($values['sources'] as $source => $value) { - if (!isset($hostnames[$source])) { - $hostname = gethostbyaddr($source); - if ($hostname !== false) { - $hostnames[$source] = $hostname; - $source = $hostname; + if (end($intervals) != $end_date) { + $intervals[] = $end_date; + } + + // Calculate the top values. + $values = netflow_get_top_data( + $start_date, + $end_date, + $filter, + $aggregate, + $max + ); + + // Update the filter to get properly next data. + netflow_update_second_level_filter( + $filter, + $aggregate, + array_keys($values['sources']) + ); + + // Resolve addresses if required. + $get_hostnames = false; + if ($address_resolution === true) { + global $hostnames; + netflow_address_resolution($values, $get_hostnames, $aggregate); + } + + foreach ($intervals as $k => $time) { + $interval_start = $time; + if (!isset($intervals[($k + 1)])) { + continue; + } + + $interval_end = $intervals[($k + 1)]; + + // Set default values. + foreach ($values['sources'] as $source => $discard) { + $values['data'][$interval_end][$source] = 0; + } + + $data = netflow_get_stats( + $interval_start, + $interval_end, + $filter, + $aggregate, + $max, + $absolute, + $connection_name + ); + + foreach ($data as $line) { + // Address resolution start. + if ($get_hostnames) { + if (!isset($hostnames[$line['agg']])) { + $hostname = false; + // Trying to get something like an IP from the description. + if (preg_match('/\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}/', $line['agg'], $matches) + || preg_match( + "/(((?=(?>.*?(::))(?!.+\3)))\3?|([\dA-F]{1,4}(\3|:?)|\2))(?4){5}((?4){2}|(25[0-5]| + (2[0-4]|1\d|[1-9])?\d)(\.(?7)){3})/i", + $line['agg'], + $matches + ) + ) { + if ($matches[0]) { + $hostname = gethostbyaddr($line['agg']); + } + } + + if ($hostname !== false) { + $hostnames[$line['agg']] = $hostname; + $line['agg'] = $hostname; + } + } else { + $line['agg'] = $hostnames[$line['agg']]; } - } else { - $source = $hostnames[$source]; } - $sources[$source] = $value; - } - - $values['sources'] = $sources; - } - - // Address resolution end - $interval_start = $start_date; - for ($i = 0; $i < $num_intervals; $i++, $interval_start += ($interval_length + 1)) { - $interval_end = ($interval_start + $interval_length); - if ($interval_end > $end_date) { - $interval_end = $end_date; - } - - if ($aggregate == 'none') { - $data = netflow_get_summary($interval_start, $interval_end, $filter, $connection_name); - if (! isset($data['totalbytes'])) { - $values[$interval_start]['data'] = 0; + // Address resolution end. + if (! isset($values['sources'][$line['agg']])) { continue; } - switch ($unit) { - case 'megabytes': - $values[$interval_start]['data'] = ($data['totalbytes'] / 1048576); - break; - - case 'megabytespersecond': - $values[$interval_start]['data'] = ($data['avgbps'] / 1048576 / 8); - break; - - case 'kilobytes': - $values[$interval_start]['data'] = ($data['totalbytes'] / 1024); - break; - - case 'kilobytespersecond': - $values[$interval_start]['data'] = ($data['avgbps'] / 1024 / 8); - break; - - default: - $values[$interval_start]['data'] = $data['totalbytes']; - break; - } - } else { - // Set default values - foreach ($values['sources'] as $source => $discard) { - $values['data'][$interval_start][$source] = 0; - } - - $data = netflow_get_stats( - $interval_start, - $interval_end, - $filter, - $aggregate, - $max, - $unit, - $connection_name - ); - - foreach ($data as $line) { - // Address resolution start - if ($get_hostnames) { - if (!isset($hostnames[$line['agg']])) { - $hostname = false; - // Trying to get something like an IP from the description - if (preg_match('/\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}/', $line['agg'], $matches) - || preg_match( - "/(((?=(?>.*?(::))(?!.+\3)))\3?|([\dA-F]{1,4}(\3|:?)|\2))(?4){5}((?4){2}|(25[0-5]| - (2[0-4]|1\d|[1-9])?\d)(\.(?7)){3})/i", - $line['agg'], - $matches - ) - ) { - if ($matches[0]) { - $hostname = gethostbyaddr($line['agg']); - } - } - - if ($hostname !== false) { - $hostnames[$line['agg']] = $hostname; - $line['agg'] = $hostname; - } - } else { - $line['agg'] = $hostnames[$line['agg']]; - } - } - - // Address resolution end - if (! isset($values['sources'][$line['agg']])) { - continue; - } - - $values['data'][$interval_start][$line['agg']] = $line['data']; - } + $values['data'][$interval_end][$line['agg']] = $line['data']; } } - if (($aggregate != 'none') && (empty($values['data']))) { + if (empty($values['data'])) { return []; } @@ -670,29 +575,40 @@ function netflow_get_data($start_date, $end_date, $interval_length, $filter, $ag /** * Returns netflow stats for the given period in an array. * - * @param string start_date Period start date. - * @param string end_date Period end date. - * @param string filter Netflow filter. - * @param string aggregate Aggregate field. - * @param int max Maximum number of aggregates. - * @param string unit Unit to show. + * @param string $start_date Period start date. + * @param string $end_date Period end date. + * @param string $filter Netflow filter. + * @param string $aggregate Aggregate field. + * @param integer $max Maximum number of aggregates. + * @param boolean $absolute True to give the absolute data and false + * to get troughput. + * @param string $connection_name Node name when data is get in meta. + * @param boolean $address_resolution True to resolve ips to hostnames. * - * @return An array with netflow stats. + * @return array With netflow stats. */ -function netflow_get_stats($start_date, $end_date, $filter, $aggregate, $max, $unit, $connection_name='', $address_resolution=false) -{ +function netflow_get_stats( + $start_date, + $end_date, + $filter, + $aggregate, + $max, + $absolute=true, + $connection_name='', + $address_resolution=false +) { global $config, $nfdump_date_format; - // Requesting remote data + // Requesting remote data. if (defined('METACONSOLE') && $connection_name != '') { - $data = metaconsole_call_remote_api($connection_name, 'netflow_get_stats', "$start_date|$end_date|".base64_encode(json_encode($filter))."|$aggregate|$max|$unit|".(int) $address_resolution); + $data = metaconsole_call_remote_api($connection_name, 'netflow_get_stats', "$start_date|$end_date|".base64_encode(json_encode($filter))."|$aggregate|$max|$absolute|".(int) $address_resolution); return json_decode($data, true); } - // Get the command to call nfdump + // Get the command to call nfdump. $command = netflow_get_command($filter); - // Execute nfdump + // Execute nfdump. $command .= " -o csv -q -n $max -s $aggregate/bytes -t ".date($nfdump_date_format, $start_date).'-'.date($nfdump_date_format, $end_date); exec($command, $string); @@ -700,7 +616,7 @@ function netflow_get_stats($start_date, $end_date, $filter, $aggregate, $max, $u return []; } - // Remove the first line + // Remove the first line. $string[0] = ''; $i = 0; @@ -716,60 +632,35 @@ function netflow_get_stats($start_date, $end_date, $filter, $aggregate, $max, $u $values[$i]['date'] = $val[0]; $values[$i]['time'] = $val[1]; - // create field to sort array + // Create field to sort array. $datetime = $val[0]; $end_date = strtotime($datetime); $values[$i]['datetime'] = $end_date; - if ($aggregate == 'proto') { - $values[$i]['agg'] = $val[3]; - } else { - // Address resolution start - if ($address_resolution && ($aggregate == 'srcip' || $aggregate == 'dstip')) { - global $hostnames; + // Address resolution start. + if ($address_resolution && ($aggregate == 'srcip' || $aggregate == 'dstip')) { + global $hostnames; - if (!isset($hostnames[$val[4]])) { - $hostname = gethostbyaddr($val[4]); - if ($hostname !== false) { - $hostnames[$val[4]] = $hostname; - $val[4] = $hostname; - } - } else { - $val[4] = $hostnames[$val[4]]; + if (!isset($hostnames[$val[4]])) { + $hostname = gethostbyaddr($val[4]); + if ($hostname !== false) { + $hostnames[$val[4]] = $hostname; + $val[4] = $hostname; } + } else { + $val[4] = $hostnames[$val[4]]; } - - // Address resolution end - $values[$i]['agg'] = $val[4]; } + // Address resolution end. + $values[$i]['agg'] = $val[4]; + if (! isset($val[9])) { return []; } - switch ($unit) { - case 'megabytes': - $values[$i]['data'] = ($val[9] / 1048576); - break; - - case 'megabytespersecond': - $values[$i]['data'] = ($val[9] / 1048576 / $interval_length); - break; - - case 'kilobytes': - $values[$i]['data'] = ($val[9] / 1024); - break; - - case 'kilobytespersecond': - $values[$i]['data'] = ($val[9] / 1024 / $interval_length); - break; - - default: - case 'bytes': - $values[$i]['data'] = $val[9]; - break; - case 'bytespersecond': - $values[$i]['data'] = ($val[9] / $interval_length); - break; + $values[$i]['data'] = $val[9]; + if (!$absolute) { + $values[$i]['data'] = ($values[$i]['data'] / $interval_length); } $i++; @@ -784,27 +675,28 @@ function netflow_get_stats($start_date, $end_date, $filter, $aggregate, $max, $u /** * Returns a traffic summary for the given period in an array. * - * @param string start_date Period start date. - * @param string end_date Period end date. - * @param string filter Netflow filter. + * @param string $start_date Period start date. + * @param string $end_date Period end date. + * @param string $filter Netflow filter. + * @param string $connection_name Node name when data is get in meta. * - * @return An array with netflow stats. + * @return array With netflow summary data. */ function netflow_get_summary($start_date, $end_date, $filter, $connection_name='') { global $nfdump_date_format; global $config; - // Requesting remote data + // Requesting remote data. if (defined('METACONSOLE') && $connection_name != '') { $data = metaconsole_call_remote_api($connection_name, 'netflow_get_summary', "$start_date|$end_date|".base64_encode(json_encode($filter))); return json_decode($data, true); } - // Get the command to call nfdump + // Get the command to call nfdump. $command = netflow_get_command($filter); - // Execute nfdump + // Execute nfdump. $command .= ' -o csv -n 1 -s srcip/bytes -t '.date($nfdump_date_format, $start_date).'-'.date($nfdump_date_format, $end_date); exec($command, $string); @@ -812,7 +704,7 @@ function netflow_get_summary($start_date, $end_date, $filter, $connection_name=' return []; } - // Read the summary + // Read the summary. $summary = explode(',', $string[5]); if (! isset($summary[5])) { return []; @@ -830,137 +722,174 @@ function netflow_get_summary($start_date, $end_date, $filter, $connection_name=' /** - * Returns a traffic record for the given period in an array. + * Returns a relationships data for the given period in an array. * - * @param string start_date Period start date. - * @param string end_date Period end date. - * @param string filter Netflow filter. - * @param int max Maximum number of elements. - * @param string unit to show. + * @param string $start_date Period start date. + * @param string $end_date Period end date. + * @param string $filter Netflow filter. + * @param integer $max Maximum number of elements. + * @param string $aggregate One of srcip, srcport, dstip, dstport. * - * @return An array with netflow stats. + * @return array With raw relationship data. */ -function netflow_get_record($start_date, $end_date, $filter, $max, $unit, $address_resolution=false) -{ +function netflow_get_relationships_raw_data( + $start_date, + $end_date, + $filter, + $max, + $aggregate +) { global $nfdump_date_format; global $config; - // TIME_START = 0; - // TIME_END = 1; - // DURATION = 2; - // SOURCE_ADDRESS = 3; - // DESTINATION_ADDRESS = 4; - // SOURCE_PORT = 5; - // DESTINATION_PORT = 6; - // PROTOCOL = 7; - // INPUT_BYTES = 12; - // Get the command to call nfdump + $max_data = netflow_get_top_data( + $start_date, + $end_date, + $filter, + $aggregate, + $max + ); + + // Update src and dst filter (both). + $sources_array = array_keys($max_data['sources']); + $is_ip = netflow_aggregate_is_ip($aggregate); + netflow_update_second_level_filter( + $filter, + ($is_ip === true) ? 'dstip' : 'dstport', + $sources_array + ); + netflow_update_second_level_filter( + $filter, + ($is_ip === true) ? 'srcip' : 'srcport', + $sources_array + ); + + // Get the command to call nfdump. + $command = sprintf( + '%s -q -o csv -n %s -s %s/bytes -t %s-%s', + netflow_get_command($filter), + NETFLOW_MAX_DATA_CIRCULAR_MESH, + 'record', + date($nfdump_date_format, $start_date), + date($nfdump_date_format, $end_date) + ); + + // Get the command to call nfdump. $command = netflow_get_command($filter); - // Execute nfdump - $command .= " -q -o csv -n $max -s record/bytes -t ".date($nfdump_date_format, $start_date).'-'.date($nfdump_date_format, $end_date); + // Execute nfdump. + $command .= ' -q -o csv -n 10000 -s record/bytes -t '.date($nfdump_date_format, $start_date).'-'.date($nfdump_date_format, $end_date); exec($command, $result); if (! is_array($result)) { + return [ + 'lines' => [], + 'sources' => [], + ]; + } + + return [ + 'lines' => $result, + 'sources' => $sources_array, + ]; +} + + +/** + * Parse the raw relationships data to be painted by circular mesh chart. + * + * @param array $result Lines gotten from nfdump call. + * @param array $sources_array Array with sources involved in the chart. + * @param boolean $is_ip Is ip or port. + * + * @return array With data to be parsed on circular mesh chart. + */ +function netflow_parse_relationships_for_circular_mesh( + $result, + $sources_array, + $is_ip +) { + if (empty($result)) { return []; } - $values = []; - foreach ($result as $key => $line) { - $data = []; + // Initialize some data structures. + $data = [ + 'elements' => [], + 'matrix' => [], + ]; + $initial_data = []; + // This array has the ips or port like keys and the array position as value. + $inverse_sources_array = array_flip($sources_array); + foreach ($sources_array as $sdata) { + $data['elements'][$inverse_sources_array[$sdata]] = $sdata; + $initial_data[$inverse_sources_array[$sdata]] = 0; + } + foreach ($sources_array as $sdata) { + $data['matrix'][$inverse_sources_array[$sdata]] = $initial_data; + } + + // Port are situated in a different places from addreses. + $src_key = ($is_ip === true) ? 3 : 5; + $dst_key = ($is_ip === true) ? 4 : 6; + // Store a footprint of initial data to be compared at the end. + $freeze_data = md5(serialize($data)); + foreach ($result as $line) { + if (empty($line) === true) { + continue; + } + + // Parse the line. $items = explode(',', $line); - $data['time_start'] = $items[0]; - $data['time_end'] = $items[1]; - $data['duration'] = ($items[2] / 1000); - $data['source_address'] = $items[3]; - $data['destination_address'] = $items[4]; - $data['source_port'] = $items[5]; - $data['destination_port'] = $items[6]; - $data['protocol'] = $items[7]; + // Get the required data. + $src_item = $inverse_sources_array[$items[$src_key]]; + $dst_item = $inverse_sources_array[$items[$dst_key]]; + $value = $items[12]; - switch ($unit) { - case 'megabytes': - $data['data'] = ($items[12] / 1048576); - break; - - case 'megabytespersecond': - $data['data'] = ($items[12] / 1048576 / $data['duration']); - break; - - case 'kilobytes': - $data['data'] = ($items[12] / 1024); - break; - - case 'kilobytespersecond': - $data['data'] = ($items[12] / 1024 / $data['duration']); - break; - - default: - case 'bytes': - $data['data'] = $items[12]; - break; - case 'bytespersecond': - $data['data'] = ($items[12] / $data['duration']); - break; + // Check if valid data. + if (!isset($value) + || !isset($data['matrix'][$dst_item][$src_item]) + || !isset($data['matrix'][$src_item][$dst_item]) + ) { + continue; } - $values[] = $data; + // Update the value. + $data['matrix'][$src_item][$dst_item] += (int) $value; } - // Address resolution start - if ($address_resolution) { - global $hostnames; - - for ($i = 0; $i < count($values); $i++) { - if (!isset($hostnames[$values[$i]['source_address']])) { - $hostname = gethostbyaddr($values[$i]['source_address']); - if ($hostname !== false) { - $hostnames[$values[$i]['source_address']] = $hostname; - $values[$i]['source_address'] = $hostname; - } - } else { - $values[$i]['source_address'] = $hostnames[$values[$i]['source_address']]; - } - - if (!isset($hostnames[$values[$i]['destination_address']])) { - $hostname = gethostbyaddr($values[$i]['destination_address']); - if ($hostname !== false) { - $hostnames[$values[$i]['destination_address']] = $hostname; - $values[$i]['destination_address'] = $hostname; - } - } else { - $values[$i]['destination_address'] = $hostnames[$values[$i]['destination_address']]; - } - } + // Comparte footprints. + if ($freeze_data === md5(serialize($data))) { + // Taht means that all relationships are 0. + return []; } - // Address resolution end - return $values; + return $data; } /** * Returns the command needed to run nfdump for the given filter. * - * @param array filter Netflow filter. + * @param array $filter Netflow filter. * - * @return Command to run. + * @return string Command to run. */ function netflow_get_command($filter) { global $config; - // Build command + // Build command. $command = io_safe_output($config['netflow_nfdump']).' -N'; - // Netflow data path + // Netflow data path. if (isset($config['netflow_path']) && $config['netflow_path'] != '') { $command .= ' -R. -M '.$config['netflow_path']; } - // Filter options + // Filter options. $command .= netflow_get_filter_arguments($filter); return $command; @@ -970,13 +899,13 @@ function netflow_get_command($filter) /** * Returns the nfdump command line arguments that match the given filter. * - * @param array filter Netflow filter. + * @param array $filter Netflow filter. * - * @return Command line argument string. + * @return string Command line argument string. */ function netflow_get_filter_arguments($filter) { - // Advanced filter + // Advanced filter. $filter_args = ''; if ($filter['advanced_filter'] != '') { $filter_args = preg_replace('/["\r\n]/', '', io_safe_output($filter['advanced_filter'])); @@ -987,7 +916,7 @@ function netflow_get_filter_arguments($filter) $filter_args .= ' "(router ip '.$filter['router_ip'].')'; } - // Normal filter + // Normal filter. if ($filter['ip_dst'] != '') { $filter_args .= ' "('; $val_ipdst = explode(',', io_safe_output($filter['ip_dst'])); @@ -1102,74 +1031,11 @@ function netflow_get_filter_arguments($filter) function netflow_get_chart_types() { return [ - 'netflow_area' => __('Area graph'), - 'netflow_pie_summatory' => __('Pie graph and Summary table'), - 'netflow_statistics' => __('Statistics table'), - 'netflow_data' => __('Data table'), - 'netflow_mesh' => __('Circular mesh'), - 'netflow_host_treemap' => __('Host detailed traffic'), - ]; -} - - -/** - * Gets valid intervals for a netflow chart in the format: - * - * interval_length => interval_description - * - * @return array of valid intervals. - */ -function netflow_get_valid_intervals() -{ - return [ - (string) SECONDS_10MINUTES => __('10 mins'), - (string) SECONDS_15MINUTES => __('15 mins'), - (string) SECONDS_30MINUTES => __('30 mins'), - (string) SECONDS_1HOUR => __('1 hour'), - (string) SECONDS_2HOUR => __('2 hours'), - (string) SECONDS_5HOUR => __('5 hours'), - (string) SECONDS_12HOURS => __('12 hours'), - (string) SECONDS_1DAY => __('1 day'), - (string) SECONDS_2DAY => __('2 days'), - (string) SECONDS_5DAY => __('5 days'), - (string) SECONDS_15DAYS => __('15 days'), - (string) SECONDS_1WEEK => __('Last week'), - (string) SECONDS_1MONTH => __('Last month'), - (string) SECONDS_2MONTHS => __('2 months'), - (string) SECONDS_3MONTHS => __('3 months'), - (string) SECONDS_6MONTHS => __('6 months'), - (string) SECONDS_1YEAR => __('Last year'), - (string) SECONDS_2YEARS => __('2 years'), - ]; -} - - -/** - * Gets valid intervals for a netflow chart in the format: - * - * interval_length => interval_description - * - * @return array of valid intervals. - */ -function netflow_get_valid_subintervals() -{ - return [ - (string) SECONDS_1MINUTE => __('1 min'), - (string) SECONDS_2MINUTES => __('2 mins'), - (string) SECONDS_5MINUTES => __('5 mins'), - (string) SECONDS_10MINUTES => __('10 mins'), - (string) SECONDS_15MINUTES => __('15 mins'), - (string) SECONDS_30MINUTES => __('30 mins'), - (string) SECONDS_1HOUR => __('1 hour'), - (string) SECONDS_2HOUR => __('2 hours'), - (string) SECONDS_5HOUR => __('5 hours'), - (string) SECONDS_12HOURS => __('12 hours'), - (string) SECONDS_1DAY => __('1 day'), - (string) SECONDS_2DAY => __('2 days'), - (string) SECONDS_5DAY => __('5 days'), - (string) SECONDS_15DAYS => __('15 days'), - (string) SECONDS_1WEEK => __('1 week'), - (string) SECONDS_1MONTH => __('1 month'), + 'netflow_area' => __('Area graph'), + 'netflow_summary' => __('Summary'), + 'netflow_data' => __('Data table'), + 'netflow_mesh' => __('Circular mesh'), + 'netflow_host_treemap' => __('Host detailed traffic'), ]; } @@ -1177,20 +1043,31 @@ function netflow_get_valid_subintervals() /** * Draw a netflow report item. * - * @param string start_date Period start date. - * @param string end_date Period end date. - * @param string interval_length Interval length in seconds (num_intervals * interval_length = start_date - end_date). - * @param string type Chart type. - * @param array filter Netflow filter. - * @param int max_aggregates Maximum number of aggregates. - * @param string output Output format. Only HTML and XML are supported. + * @param string $start_date Period start date. + * @param string $end_date Period end date. + * @param mixed $interval_length Resolution points or hourly or daily. + * @param string $type Chart type. + * @param array $filter Netflow filter. + * @param integer $max_aggregates Maximum number of aggregates. + * @param string $connection_name Node name when data is get in meta. + * @param string $output Output format. Only HTML, PDF and XML + * are supported. + * @param boolean $address_resolution True to resolve ips to hostnames. * - * @return The netflow report in the appropriate format. + * @return string The netflow report in the appropriate format. */ -function netflow_draw_item($start_date, $end_date, $interval_length, $type, $filter, $max_aggregates, $connection_name='', $output='HTML', $address_resolution=false) -{ +function netflow_draw_item( + $start_date, + $end_date, + $interval_length, + $type, + $filter, + $max_aggregates, + $connection_name='', + $output='HTML', + $address_resolution=false +) { $aggregate = $filter['aggregate']; - $unit = $filter['output']; $interval = ($end_date - $start_date); if (defined('METACONSOLE')) { $width = 950; @@ -1200,106 +1077,17 @@ function netflow_draw_item($start_date, $end_date, $interval_length, $type, $fil $height = 320; - // Process item + // Process item. switch ($type) { - case '0': case 'netflow_area': - $data = netflow_get_data($start_date, $end_date, $interval_length, $filter, $aggregate, $max_aggregates, $unit, $connection_name, $address_resolution); - if (empty($data)) { - break; - } - - if ($aggregate != 'none') { - if ($output == 'HTML') { - $html = '<b>'.__('Unit').':</b> '.netflow_format_unit($unit); - $html .= ' <b>'.__('Aggregate').':</b> '.netflow_format_aggregate($aggregate); - if ($interval_length != 0) { - $html .= ' <b>'._('Resolution').":</b> $interval_length ".__('seconds'); - } - - $html .= graph_netflow_aggregate_area($data, $interval, $width, $height, netflow_format_unit($unit)); - return $html; - } else if ($output == 'PDF') { - $html = '<b>'.__('Unit').':</b> '.netflow_format_unit($unit); - $html .= ' <b>'.__('Aggregate').':</b> '.netflow_format_aggregate($aggregate); - if ($interval_length != 0) { - $html .= ' <b>'._('Resolution').":</b> $interval_length ".__('seconds'); - } - - $html .= graph_netflow_aggregate_area($data, $interval, $width, $height, netflow_format_unit($unit), 2, true); - return $html; - } else if ($output == 'XML') { - $xml = "<unit>$unit</unit>\n"; - $xml .= "<aggregate>$aggregate</aggregate>\n"; - $xml .= "<resolution>$interval_length</resolution>\n"; - $xml .= netflow_aggregate_area_xml($data); - return $xml; - } - } else { - if ($output == 'HTML') { - $html = '<b>'.__('Unit').':</b> '.netflow_format_unit($unit); - if ($interval_length != 0) { - $html .= ' <b>'._('Resolution').":</b> $interval_length ".__('seconds'); - } - - $html .= graph_netflow_total_area($data, $interval, 660, 320, netflow_format_unit($unit)); - return $html; - } else if ($output == 'PDF') { - $html = '<b>'.__('Unit').':</b> '.netflow_format_unit($unit); - if ($interval_length != 0) { - $html .= ' <b>'._('Resolution').":</b> $interval_length ".__('seconds'); - } - - $html .= graph_netflow_total_area($data, $interval, 660, 320, netflow_format_unit($unit), 2, true); - return $html; - } else if ($output == 'XML') { - $xml = "<unit>$unit</unit>\n"; - $xml .= "<resolution>$interval_length</resolution>\n"; - $xml .= netflow_total_area_xml($data); - return $xml; - } - } - break; - - case '2': - case 'netflow_data': - $data = netflow_get_data($start_date, $end_date, $interval_length, $filter, $aggregate, $max_aggregates, $unit, $connection_name, $address_resolution); - - if (empty($data)) { - break; - } - - if ($output == 'HTML' || $output == 'PDF') { - $html = '<b>'.__('Unit').':</b> '.netflow_format_unit($unit); - $html .= ' <b>'.__('Aggregate').':</b> '.netflow_format_aggregate($aggregate); - if ($interval_length != 0) { - $html .= ' <b>'._('Resolution').":</b> $interval_length ".__('seconds'); - } - - $html .= "<div style='width: 100%; overflow: auto;'>"; - $html .= netflow_data_table($data, $start_date, $end_date, $aggregate, $unit); - $html .= '</div>'; - - return $html; - } else if ($output == 'XML') { - $xml = "<unit>$unit</unit>\n"; - $xml .= "<aggregate>$aggregate</aggregate>\n"; - $xml .= "<resolution>$interval_length</resolution>\n"; - // Same as netflow_aggregate_area_xml - $xml .= netflow_aggregate_area_xml($data); - return $xml; - } - break; - - case '3': - case 'netflow_statistics': - $data = netflow_get_stats( + $data = netflow_get_data( $start_date, $end_date, + $interval_length, $filter, $aggregate, $max_aggregates, - $unit, + false, $connection_name, $address_resolution ); @@ -1308,14 +1096,55 @@ function netflow_draw_item($start_date, $end_date, $interval_length, $type, $fil } if ($output == 'HTML' || $output == 'PDF') { - $html = netflow_stat_table($data, $start_date, $end_date, $aggregate, $unit); + $html .= graph_netflow_aggregate_area( + $data, + $interval, + $width, + $height, + ($output === 'HTML') ? 1 : 2, + ($output === 'HTML'), + $end_date + ); return $html; } else if ($output == 'XML') { - return netflow_stat_xml($data); + $xml .= '<aggregate>'.$aggregate."</aggregate>\n"; + $xml .= '<resolution>'.$interval_length."</resolution>\n"; + $xml .= netflow_aggregate_area_xml($data); + return $xml; + } + break; + + case 'netflow_data': + $data = netflow_get_data( + $start_date, + $end_date, + $interval_length, + $filter, + $aggregate, + $max_aggregates, + true, + $connection_name, + $address_resolution + ); + if (empty($data)) { + break; + } + + if ($output == 'HTML' || $output == 'PDF') { + $html .= "<div style='width: 100%; overflow: auto;'>"; + $html .= netflow_data_table($data, $start_date, $end_date, $aggregate); + $html .= '</div>'; + + return $html; + } else if ($output == 'XML') { + $xml .= '<aggregate>'.$aggregate."</aggregate>\n"; + $xml .= '<resolution>'.$interval_length."</resolution>\n"; + // Same as netflow_aggregate_area_xml. + $xml .= netflow_aggregate_area_xml($data); + return $xml; } break; - case '4': case 'netflow_summary': $data_summary = netflow_get_summary( $start_date, @@ -1327,22 +1156,13 @@ function netflow_draw_item($start_date, $end_date, $interval_length, $type, $fil break; } - if ($output == 'HTML' || $output == 'PDF') { - return netflow_summary_table($data_summary); - } else if ($output == 'XML') { - return netflow_summary_xml($data_summary); - } - break; - - case '1': - case 'netflow_pie': $data_pie = netflow_get_stats( $start_date, $end_date, $filter, $aggregate, $max_aggregates, - $unit, + true, $connection_name, $address_resolution ); @@ -1350,131 +1170,65 @@ function netflow_draw_item($start_date, $end_date, $interval_length, $type, $fil break; } - if ($output == 'HTML') { - $html = '<b>'.__('Unit').':</b> '.netflow_format_unit($unit); - $html .= ' <b>'.__('Aggregate').':</b> '.netflow_format_aggregate($aggregate); - $html .= graph_netflow_aggregate_pie($data_pie, netflow_format_aggregate($aggregate)); + if ($output === 'HTML' || $output === 'PDF') { + $html = '<table style="width: 100%">'; + $html .= '<tr>'; + $html .= '<td style="width: 50%">'; + $html .= netflow_summary_table($data_summary); + $html .= '</td>'; + $html .= '<td style="width: 50%">'; + $html .= graph_netflow_aggregate_pie( + $data_pie, + netflow_format_aggregate($aggregate), + ($output === 'HTML') ? 1 : 2, + ($output === 'HTML') + ); + $html .= '</td>'; + $html .= '</tr>'; + $html .= '</table>'; + $html .= netflow_stat_table( + $data_pie, + $start_date, + $end_date, + $aggregate + ); return $html; - } else if ($output == 'PDF') { - $html = '<b>'.__('Unit').':</b> '.netflow_format_unit($unit); - $html .= ' <b>'.__('Aggregate').":</b> $aggregate"; - $html .= graph_netflow_aggregate_pie($data_pie, netflow_format_aggregate($aggregate), 2, true); - return $html; - } else if ($output == 'XML') { - $xml = "<unit>$unit</unit>\n"; - $xml .= "<aggregate>$aggregate</aggregate>\n"; - $xml .= netflow_aggregate_pie_xml($data_pie); - return $xml; - } - break; - - case 'netflow_pie_summatory': - $data_summary = netflow_get_summary( - $start_date, - $end_date, - $filter, - $connection_name - ); - if (empty($data_summary)) { - break; - } - - $data_pie = netflow_get_stats( - $start_date, - $end_date, - $filter, - $aggregate, - $max_aggregates, - $unit, - $connection_name, - $address_resolution - ); - if (empty($data_pie)) { - break; - } - - switch ($output) { - case 'HTML': - $html = '<table>'; - $html .= '<tr>'; - $html .= '<td>'; - $html .= netflow_summary_table($data_summary); - $html .= '<b>'.__('Unit').':</b> '.netflow_format_unit($unit); - $html .= ' <b>'.__('Aggregate').':</b> '.netflow_format_aggregate($aggregate); - $html .= '</td>'; - $html .= '<td>'; - $html .= graph_netflow_aggregate_pie($data_pie, netflow_format_aggregate($aggregate)); - $html .= '</td>'; - $html .= '</tr>'; - $html .= '</table>'; - return $html; - - break; - case 'PDF': - break; - - case 'XML': - return netflow_summary_xml($data_summary); - - break; + } else if ($output === 'XML') { + return netflow_summary_xml($data_summary, $data_pie); } break; case 'netflow_mesh': - $netflow_data = netflow_get_record($start_date, $end_date, $filter, $max_aggregates, $unit, $address_resolution); - - switch ($aggregate) { - case 'srcport': - case 'dstport': - $source_type = 'source_port'; - $destination_type = 'destination_port'; - break; - - default: - case 'dstip': - case 'srcip': - $source_type = 'source_address'; - $destination_type = 'destination_address'; - break; - } - - $data = []; - $data['elements'] = []; - $data['matrix'] = []; - foreach ($netflow_data as $record) { - if (!in_array($record[$source_type], $data['elements'])) { - $data['elements'][] = $record[$source_type]; - $data['matrix'][] = []; - } - - if (!in_array($record[$destination_type], $data['elements'])) { - $data['elements'][] = $record[$destination_type]; - $data['matrix'][] = []; - } - } - - for ($i = 0; $i < count($data['matrix']); $i++) { - $data['matrix'][$i] = array_fill(0, count($data['matrix']), 0); - } - - foreach ($netflow_data as $record) { - $source_key = array_search($record[$source_type], $data['elements']); - $destination_key = array_search($record[$destination_type], $data['elements']); - if ($source_key !== false && $destination_key !== false) { - $data['matrix'][$source_key][$destination_key] += $record['data']; - } - } + $data = netflow_get_relationships_raw_data( + $start_date, + $end_date, + $filter, + $max_aggregates, + $aggregate, + $address_resolution + ); + $data_circular = netflow_parse_relationships_for_circular_mesh( + $data['lines'], + $data['sources'], + netflow_aggregate_is_ip($aggregate) + ); $html = '<div style="text-align:center;">'; - $html .= graph_netflow_circular_mesh($data, netflow_format_unit($unit), 700); + $html .= graph_netflow_circular_mesh($data_circular); $html .= '</div>'; - return $html; - break; case 'netflow_host_treemap': - $netflow_data = netflow_get_record($start_date, $end_date, $filter, $max_aggregates, $unit, $address_resolution); - + $data_stats = netflow_get_stats( + $start_date, + $end_date, + $filter, + $aggregate, + $max_aggregates, + true, + $connection_name, + $address_resolution + ); switch ($aggregate) { case 'srcip': case 'srcport': @@ -1492,51 +1246,30 @@ function netflow_draw_item($start_date, $end_date, $interval_length, $type, $fil break; } - $data_aux = []; - foreach ($netflow_data as $record) { - $address = $record[$address_type]; - $port = $record[$port_type]; - - if (!isset($data_aux[$address])) { - $data_aux[$address] = []; - } - - if (!isset($data_aux[$address][$port])) { - $data_aux[$address][$port] = 0; - } - - $data_aux[$address][$port] += $record['data']; - } - + $data_graph = [ + 'name' => __('Host detailed traffic').': '.$type, + 'children' => [], + ]; $id = -1; - $data = []; - - if (! empty($netflow_data)) { - $data['name'] = __('Host detailed traffic').': '.$type; - $data['children'] = []; - - foreach ($data_aux as $address => $ports) { - $children = []; - $children['id'] = $id++; - $children['name'] = $address; - $children['children'] = []; - foreach ($ports as $port => $value) { - $children_data = []; - $children_data['id'] = $id++; - $children_data['name'] = $port; - $children_data['value'] = $value; - $children_data['tooltip_content'] = "$port: <b>".format_numeric($value).' '.netflow_format_unit($unit).'</b>'; - $children['children'][] = $children_data; - } - - $data['children'][] = $children; - } + foreach ($data_stats as $sdata) { + $data_graph['children'][] = [ + 'id' => $i++, + 'name' => $sdata['agg'], + 'children' => [ + [ + 'id' => $i++, + 'name' => $sdata['agg'], + 'value' => $sdata['data'], + 'tooltip_content' => network_format_bytes($sdata['data']), + ], + ], + ]; } - return graph_netflow_host_traffic($data, netflow_format_unit($unit), 'auto', 400); + return graph_netflow_host_traffic($data_graph, 'auto', 400); - break; default: + // Nothing to do. break; } @@ -1546,107 +1279,32 @@ function netflow_draw_item($start_date, $end_date, $interval_length, $type, $fil } -/** - * Render a netflow report as an XML. - * - * @param int ID of the netflow report. - * @param string end_date Period start date. - * @param string end_date Period end date. - * @param string interval_length Interval length in seconds (num_intervals * interval_length = start_date - end_date). - */ -function netflow_xml_report($id, $start_date, $end_date, $interval_length=0) -{ - // Get report data - $report = db_get_row_sql('SELECT * FROM tnetflow_report WHERE id_report ='.(int) $id); - if ($report === false) { - echo '<report>'.__('Error generating report')."</report>\n"; - return; - } - - // Print report header - $time = get_system_time(); - echo '<?xml version="1.0" encoding="UTF-8" ?>'; - echo "<report>\n"; - echo " <generated>\n"; - echo ' <unix>'.$time."</unix>\n"; - echo ' <rfc2822>'.date('r', $time)."</rfc2822>\n"; - echo " </generated>\n"; - echo ' <name>'.io_safe_output($report['id_name'])."</name>\n"; - echo ' <description>'.io_safe_output($report['description'])."</description>\n"; - echo ' <start_date>'.date('r', $start_date)."</start_date>\n"; - echo ' <end_date>'.date('r', $end_date)."</end_date>\n"; - - // Get netflow item types - $item_types = netflow_get_chart_types(); - - // Print report items - $report_contents = db_get_all_rows_sql( - "SELECT * - FROM tnetflow_report_content - WHERE id_report='".$report['id_report']."' - ORDER BY `order`" - ); - foreach ($report_contents as $content) { - // Get item filters - $filter = db_get_row_sql( - "SELECT * - FROM tnetflow_filter - WHERE id_sg = '".io_safe_input($content['id_filter'])."'", - false, - true - ); - if ($filter === false) { - continue; - } - - echo " <report_item>\n"; - echo ' <description>'.io_safe_output($content['description'])."</description>\n"; - echo ' <type>'.io_safe_output($item_types[$content['show_graph']])."</type>\n"; - echo ' <max_aggregates>'.$content['max']."</max_aggregates>\n"; - echo " <filter>\n"; - echo ' <name>'.io_safe_output($filter['id_name'])."</name>\n"; - echo ' <src_ip>'.io_safe_output($filter['ip_src'])."</src_ip>\n"; - echo ' <dst_ip>'.io_safe_output($filter['ip_dst'])."</dst_ip>\n"; - echo ' <src_port>'.io_safe_output($filter['src_port'])."</src_port>\n"; - echo ' <dst_port>'.io_safe_output($filter['src_port'])."</dst_port>\n"; - echo ' <advanced>'.io_safe_output($filter['advanced_filter'])."</advanced>\n"; - echo ' <aggregate>'.io_safe_output($filter['aggregate'])."</aggregate>\n"; - echo ' <unit>'.io_safe_output($filter['output'])."</unit>\n"; - echo " </filter>\n"; - - echo netflow_draw_item($start_date, $end_date, $interval_length, $content['show_graph'], $filter, $content['max'], $report['server_name'], 'XML'); - - echo " </report_item>\n"; - } - - echo "</report>\n"; -} - - /** * Render an aggregated area chart as an XML. * - * @param array Netflow data. + * @param array $data Netflow data. + * + * @return void XML is echoed. */ function netflow_aggregate_area_xml($data) { - // Print source information + // Print source information. if (isset($data['sources'])) { echo "<aggregates>\n"; foreach ($data['sources'] as $source => $discard) { - echo "<aggregate>$source</aggregate>\n"; + echo '<aggregate>'.$source."</aggregate>\n"; } echo "</aggregates>\n"; - // Print flow information + // Print flow information. echo "<flows>\n"; foreach ($data['data'] as $timestamp => $flow) { echo "<flow>\n"; echo ' <timestamp>'.$timestamp."</timestamp>\n"; echo " <aggregates>\n"; foreach ($flow as $source => $data) { - echo " <aggregate>$source</aggregate>\n"; + echo ' <aggregate>'.$source."</aggregate>\n"; echo ' <data>'.$data."</data>\n"; } @@ -1669,133 +1327,49 @@ function netflow_aggregate_area_xml($data) } -/** - * Render an area chart as an XML. - * - * @param array Netflow data. - */ -function netflow_total_area_xml($data) -{ - // Print flow information - $xml = "<flows>\n"; - foreach ($data as $timestamp => $flow) { - $xml .= "<flow>\n"; - $xml .= ' <timestamp>'.$timestamp."</timestamp>\n"; - $xml .= ' <data>'.$flow['data']."</data>\n"; - $xml .= "</flow>\n"; - } - - $xml .= "</flows>\n"; - - return $xml; -} - - -/** - * Render a pie chart as an XML. - * - * @param array Netflow data. - */ -function netflow_aggregate_pie_xml($data) -{ - // Calculate total - $total = 0; - foreach ($data as $flow) { - $total += $flow['data']; - } - - if ($total == 0) { - return; - } - - // Print percentages - echo "<pie>\n"; - foreach ($data as $flow) { - echo '<aggregate>'.$flow['agg']."</aggregate>\n"; - echo '<data>'.format_numeric((100 * $flow['data'] / $total), 2)."%</data>\n"; - } - - echo "</pie>\n"; -} - - -/** - * Render a stats table as an XML. - * - * @param array Netflow data. - */ -function netflow_stat_xml($data) -{ - // Print stats - $xml .= "<stats>\n"; - foreach ($data as $flow) { - $xml .= '<aggregate>'.$flow['agg']."</aggregate>\n"; - $xml .= '<data>'.$flow['data']."</data>\n"; - } - - $xml .= "</stats>\n"; - - return $xml; -} - - /** * Render a summary table as an XML. * - * @param array Netflow data. + * @param array $data Netflow data. + * @param array $rows_data Table info (top N hosts). + * + * @return string Wiht XML data. */ -function netflow_summary_xml($data) +function netflow_summary_xml($data, $rows_data) { - // Print summary + // Print summary. $xml = "<summary>\n"; - $xml .= ' <total_flows>'.$data['totalflows']."</total_flows>\n"; - $xml .= ' <total_bytes>'.$data['totalbytes']."</total_bytes>\n"; - $xml .= ' <total_packets>'.$data['totalbytes']."</total_packets>\n"; - $xml .= ' <average_bps>'.$data['avgbps']."</average_bps>\n"; - $xml .= ' <average_pps>'.$data['avgpps']."</average_pps>\n"; - $xml .= ' <average_bpp>'.$data['avgpps']."</average_bpp>\n"; + $xml = " <totals>\n"; + $xml .= ' <total_flows>'.$data['totalflows']."</total_flows>\n"; + $xml .= ' <total_bytes>'.$data['totalbytes']."</total_bytes>\n"; + $xml .= ' <total_packets>'.$data['totalbytes']."</total_packets>\n"; + $xml .= ' <average_bps>'.$data['avgbps']."</average_bps>\n"; + $xml .= ' <average_pps>'.$data['avgpps']."</average_pps>\n"; + $xml .= ' <average_bpp>'.$data['avgpps']."</average_bpp>\n"; + $xml .= " </totals>\n"; + + // Add the data table. + $xml .= " <hostsdata>\n"; + foreach ($rows_data as $d) { + $xml .= "<data>\n"; + $xml .= '<host>'.$d['agg']."</host>\n"; + $xml .= '<bytes>'.$d['data']."</bytes>\n"; + $xml .= "</data>\n"; + } + + $xml .= " </hostsdata>\n"; $xml .= "</summary>\n"; return $xml; } -/** - * Return a string describing the given unit. - * - * @param string Netflow unit. - */ -function netflow_format_unit($unit) -{ - switch ($unit) { - case 'megabytes': - return __('MB'); - - case 'megabytespersecond': - return __('MB/s'); - - case 'kilobytes': - return __('kB'); - - case 'kilobytespersecond': - return __('kB/s'); - - case 'bytes': - return __('Bytes'); - - case 'bytespersecond': - return __('B/s'); - - default: - return ''; - } -} - - /** * Return a string describing the given aggregate. * - * @param string Netflow aggregate. + * @param string $aggregate Netflow aggregate. + * + * @return string With formatted aggregate. */ function netflow_format_aggregate($aggregate) { @@ -1806,9 +1380,6 @@ function netflow_format_aggregate($aggregate) case 'dstip': return __('Dst IP'); - case 'proto': - return __('Protocol'); - case 'srcip': return __('Src IP'); @@ -1824,20 +1395,20 @@ function netflow_format_aggregate($aggregate) /** * Check the nfdump binary for compatibility. * - * @param string nfdump binary full path. + * @param string $nfdump_binary Nfdump binary full path. * - * @return 1 if the binary does not exist or is not executable, 2 if a + * @return integer 1 if the binary does not exist or is not executable, 2 if a * version older than 1.6.8 is installed or the version cannot be * determined, 0 otherwise. */ function netflow_check_nfdump_binary($nfdump_binary) { - // Check that the binary exists and is executable + // Check that the binary exists and is executable. if (! is_executable($nfdump_binary)) { return 1; } - // Check at least version 1.6.8 + // Check at least version 1.6.8. $output = ''; $rc = -1; exec($nfdump_binary.' -V', $output, $rc); @@ -1866,3 +1437,462 @@ function netflow_check_nfdump_binary($nfdump_binary) return 2; } + + +/** + * Get the netflow datas to build a netflow explorer data structure. + * + * @param integer $max Number of result displayed. + * @param string $top_action Action to do (listeners,talkers,tcp or udp). + * @param integer $start_date In utimestamp. + * @param integer $end_date In utimestamp. + * @param string $filter Ip to filter. + * @param string $order Select one of bytes,pkts,flow. + * + * @return array With data (host, sum_bytes, sum_pkts and sum_flows). + */ +function netflow_get_top_summary( + $max, + $top_action, + $start_date, + $end_date, + $filter='', + $order='bytes' +) { + global $nfdump_date_format; + $netflow_filter = []; + $sort = ''; + switch ($top_action) { + case 'listeners': + if (empty(!$filter)) { + $netflow_filter['ip_src'] = $filter; + } + + $sort = 'dstip'; + break; + + case 'talkers': + if (empty(!$filter)) { + $netflow_filter['ip_dst'] = $filter; + } + + $sort = 'srcip'; + break; + + case 'tcp': + case 'udp': + $netflow_filter['proto'] = $top_action; + $sort = 'port'; + if (empty(!$filter)) { + $netflow_filter['advanced_filter'] = sprintf( + '((dst port %s) or (src port %s)) and (proto %s)', + $filter, + $filter, + $top_action + ); + // Display ips when filter is set in port. + $sort = 'ip'; + } + break; + + default: + return []; + } + + $command = netflow_get_command($netflow_filter); + + // Execute nfdump. + $order_text = ''; + switch ($order) { + case 'flows': + $order_text = 'flows'; + break; + + case 'pkts': + $order_text = 'packets'; + break; + + case 'bytes': + default: + $order_text = 'bytes'; + break; + } + + $command .= " -q -o csv -n $max -s $sort/$order_text -t ".date($nfdump_date_format, $start_date).'-'.date($nfdump_date_format, $end_date); + exec($command, $result); + + if (! is_array($result)) { + return []; + } + + // Remove first line (avoiding slow array_shift). + $result = array_reverse($result); + array_pop($result); + $result = array_reverse($result); + + $top_info = []; + foreach ($result as $line) { + if (empty($line)) { + continue; + } + + $data = explode(',', $line); + if (!isset($data[9])) { + continue; + } + + $top_info[(string) $data[4]] = [ + 'host' => $data[4], + 'sum_bytes' => $data[9], + 'sum_pkts' => $data[7], + 'sum_flows' => $data[5], + 'pct_bytes' => $data[10], + 'pct_pkts' => $data[8], + 'pct_flows' => $data[6], + ]; + } + + return $top_info; +} + + +/** + * Check the netflow version and print an error message if there is not correct. + * + * @return boolean True if version check is correct. + */ +function netflow_print_check_version_error() +{ + global $config; + + switch (netflow_check_nfdump_binary($config['netflow_nfdump'])) { + case 0: + return true; + + case 1: + ui_print_error_message( + __('nfdump binary (%s) not found!', $config['netflow_nfdump']) + ); + return false; + + case 2: + default: + ui_print_error_message( + __('Make sure nfdump version 1.6.8 or newer is installed!') + ); + return false; + } +} + + +/** + * Returns the array for netflow resolution select. + * + * @return array With all values. + */ +function netflow_resolution_select_params() +{ + return [ + NETFLOW_RES_LOWD => __('Low'), + NETFLOW_RES_MEDD => __('Medium'), + NETFLOW_RES_HID => __('High'), + NETFLOW_RES_ULTRAD => __('Ultra High'), + NETFLOW_RES_HOURLY => __('Hourly'), + NETFLOW_RES_DAILY => __('Daily'), + ]; +} + + +/** + * Get the resolution name. + * + * @param mixed $value Type. + * + * @return string Translated name. Unknown for unrecognized resolution names. + */ +function netflow_get_resolution_name($value) +{ + $resolutions = netflow_resolution_select_params(); + return (isset($resolutions[$value])) ? $resolutions[$value] : __('Unknown'); +} + + +/** + * Report formatted subtitle. + * + * @param string $aggregate Aggregate by param. + * @param string $resolution Netfow live view resolution. + * @param string $type Type of view. + * + * @return string HTML with formatted subtitle. + */ +function netflow_generate_subtitle_report($aggregate, $resolution, $type) +{ + $subt = __( + 'Agregate by %s', + netflow_format_aggregate($aggregate) + ); + + // Display the resolution only in required reports. + if (in_array($type, ['netflow_area', 'netflow_data']) === true) { + $subt .= ' - '; + $subt .= __( + 'Resolution %s', + netflow_get_resolution_name($resolution) + ); + } + + return $subt; +} + + +/** + * Returns netflow stats for the given period in an array. + * + * @param string $start_date Period start date. + * @param string $end_date Period end date. + * @param string $filter Netflow filter. + * @param string $aggregate Aggregate field. + * @param integer $max Maximum number of aggregates. + * + * @return array With netflow stats. + */ +function netflow_get_top_data( + $start_date, + $end_date, + $filter, + $aggregate, + $max +) { + global $nfdump_date_format; + + $values = [ + 'data' => [], + 'sources' => [], + ]; + + // Get the command to call nfdump. + $agg_command = sprintf( + '%s -q -o csv -n %s -s %s/bytes -t %s-%s', + netflow_get_command($filter), + $max, + $aggregate, + date($nfdump_date_format, $start_date), + date($nfdump_date_format, $end_date) + ); + + // Call nfdump. + exec($agg_command, $string); + + // Remove the first line. + $string[0] = ''; + + // Parse aggregates. + foreach ($string as $line) { + if (empty($line) === true) { + continue; + } + + $val = explode(',', $line); + $values['sources'][$val[4]] = 1; + } + + return $values; +} + + +/** + * Returns netflow stats for the given period in an array. + * + * @param string $filter Netflow filter (passed by reference). + * @param string $aggregate Aggregate field. + * @param array $sources Sources to aggregate to filter. + * + * @return void $filter is passed by reference. + */ +function netflow_update_second_level_filter(&$filter, $aggregate, $sources) +{ + // Update the filter. + switch ($aggregate) { + default: + case 'srcip': + $extra_filter = 'ip_src'; + break; + case 'srcport': + $extra_filter = 'src_port'; + break; + + case 'dstip': + $extra_filter = 'ip_dst'; + break; + + case 'dstport': + $extra_filter = 'dst_port'; + break; + } + + if (isset($filter[$extra_filter]) && $filter[$extra_filter] != '') { + $filter[$extra_filter] .= ','; + } + + $filter[$extra_filter] = implode(',', $sources); +} + + +/** + * Change some values on address resolve. + * + * @param array $values Where data will be overwritten (ref). + * @param boolean $get_hostnames Change it if address resolution es done (ref). + * @param string $aggregate One of srcip, srcport, dstip, dstport. + * + * @return void Referenced passed params will be changed. + */ +function netflow_address_resolution(&$values, &$get_hostnames, $aggregate) +{ + if ($aggregate !== 'srcip' && $aggregate !== 'dstip') { + return; + } + + $get_hostnames = true; + global $hostnames; + + $sources = []; + foreach ($values['sources'] as $source => $value) { + if (!isset($hostnames[$source])) { + $hostname = gethostbyaddr($source); + if ($hostname !== false) { + $hostnames[$source] = $hostname; + $source = $hostname; + } + } else { + $source = $hostnames[$source]; + } + + $sources[$source] = $value; + } + + $values['sources'] = $sources; +} + + +/** + * Check if is aggregate by IP or by port + * + * @param string $aggregate Aggregate tag. + * + * @return boolean True if is IP. False for port. + */ +function netflow_aggregate_is_ip($aggregate) +{ + return in_array($aggregate, ['dstip', 'srcip']); +} + + +/** + * Build netflow data structure to network map. + * + * @param integer $start_date Time in timestamp format. + * @param integer $end_date Time in timestamp format. + * @param integer $top Max data to show. + * @param integer $aggregate One of dstip or srcip. + * + * @return array With map structure. + */ +function netflow_build_map_data($start_date, $end_date, $top, $aggregate) +{ + // Pass an empty filter data structure. + $data = netflow_get_relationships_raw_data( + $start_date, + $end_date, + [ + 'id_name' => '', + 'id_group' => 0, + 'aggregate' => $aggregate, + 'id_dst' => '', + 'ip_src' => '', + 'dst_port' => '', + 'src_port' => '', + 'advanced_filter' => '', + 'router_ip' => '', + ], + $top, + $aggregate + ); + + $nodes = array_map( + function ($elem) { + return network_init_node_map($elem); + }, + array_merge($data['sources'], [__('Others')]) + ); + + $relations = []; + $inverse_nodes = array_flip($data['sources']); + + // Port are situated in a different places from addreses. + $is_ip = true; + $src_key = ($is_ip === true) ? 3 : 5; + $dst_key = ($is_ip === true) ? 4 : 6; + $retrieved_data = array_fill_keys($inverse_nodes, false); + + foreach ($data['lines'] as $line) { + if (empty($line) === true) { + continue; + } + + // Parse the line. + $items = explode(',', $line); + + // Get the required data. + $src_item = $inverse_nodes[$items[$src_key]]; + $dst_item = $inverse_nodes[$items[$dst_key]]; + $value = $items[12]; + $index_rel = $src_item.'-'.$dst_item; + + // Check if valid data. + if (!isset($value) || (!isset($src_item) && !isset($dst_item))) { + continue; + } + + // Mark as connected source and destination. + $retrieved_data[$src_item] = true; + $retrieved_data[$dst_item] = true; + + if (isset($relations[$index_rel])) { + $relations[$index_rel]['text_start'] += $value; + } else { + // Update the value. + network_init_relation_map($relations, $src_item, $dst_item, $value); + } + } + + // Format the data in edges. + array_walk( + $relations, + function (&$elem) { + $elem['text_start'] = network_format_bytes($elem['text_start']); + } + ); + + // Search for orphan nodes. + $orphan_hosts = []; + $orphan_index = (end($inverse_nodes) + 1); + foreach ($retrieved_data as $position => $rd) { + if ($rd === true) { + continue; + } + + network_init_relation_map($orphan_hosts, $position, $orphan_index); + } + + // If there is not any orphan node, delete it. + if (empty($orphan_hosts)) { + array_pop($nodes); + } + + return network_general_map_configuration( + $nodes, + array_merge($relations, $orphan_hosts) + ); +} diff --git a/pandora_console/include/functions_network.php b/pandora_console/include/functions_network.php new file mode 100644 index 0000000000..9c9e1456b4 --- /dev/null +++ b/pandora_console/include/functions_network.php @@ -0,0 +1,320 @@ +<?php +/** + * Network explorer + * + * @package Include. + * @subpackage Network functions. + * + * Pandora FMS - http://pandorafms.com + * ================================================== + * Copyright (c) 2005-2019 Artica Soluciones Tecnologicas + * Please see http://pandorafms.org for full contribution list + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; version 2 + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +// Write here requires and definitions. + + +/** + * Get the tnetwok_matrix summatory data. + * + * @param integer $top Number of hosts to show. + * @param boolean $talker Talker (true) or listetener (false). + * @param integer $start Utimestamp of start time. + * @param integer $end Utimestamp of end time. + * @param string $ip_filter Ip to filter. + * @param boolean $order_by_bytes True by top by bytes. False by packets. + * @param array $host_filter Host filter array. + * + * @return array With requested data. + */ +function network_matrix_get_top( + $top, + $talker, + $start, + $end, + $ip_filter='', + $order_by_bytes=true, + $host_filter=[] +) { + $field_to_group = ($talker === true) ? 'source' : 'destination'; + $field_to_order = ($order_by_bytes === true) ? 'sum_bytes' : 'sum_pkts'; + $filter_sql = ''; + if (!empty($ip_filter)) { + $filter_field = ($talker === true) ? 'destination' : 'source'; + $filter_sql = sprintf('AND %s="%s"', $filter_field, $ip_filter); + } + + $host_filter_sql = ''; + if (!empty($host_filter)) { + $host_filter_sql = sprintf( + ' AND %s IN ("%s")', + $field_to_group, + implode('","', $host_filter) + ); + } + + $sql = sprintf( + 'SELECT SUM(bytes) sum_bytes, SUM(pkts) sum_pkts, %s host + FROM tnetwork_matrix + WHERE utimestamp > %d AND utimestamp < %d + %s + %s + GROUP BY %s + ORDER BY %s DESC + LIMIT %d', + $field_to_group, + $start, + $end, + $filter_sql, + $host_filter_sql, + $field_to_group, + $field_to_order, + $top + ); + + $data = db_get_all_rows_sql($sql); + + return ($data !== false) ? $data : []; +} + + +/** + * Get the possible actions on networking. + * + * @param boolean $network True if network. False if netflow. + * + * @return array With the actions to print in a select. + */ +function network_get_report_actions($network=true) +{ + $common_actions = [ + 'listeners' => __('Top listeners'), + 'talkers' => __('Top talkers'), + ]; + + if ($network) { + return $common_actions; + } + + return array_merge( + $common_actions, + [ + 'tcp' => __('Top TCP protocols'), + 'udp' => __('Top UDP protocols'), + ] + ); +} + + +/** + * Print the header of the network + * + * @param string $title Title of header. + * @param string $order Current ordering. + * @param string $selected Selected order. + * @param array $hidden_data All the data to hide into the button. + * + * @return string With HTML data. + */ +function network_print_explorer_header( + $title, + $order, + $selected, + $hidden_data +) { + $cell = '<div style="display: flex; align-items: center;">'; + $cell .= $title; + $cell .= html_print_link_with_params( + 'images/arrow-down-white.png', + array_merge($hidden_data, ['order_by' => $order]), + 'image', + ($selected === $order) ? 'opacity: 0.5' : '' + ); + $cell .= '</div>'; + + return $cell; +} + + +/** + * Alias for format_for_graph to print bytes. + * + * @param integer $value Value to parse like bytes. + * + * @return string Number parsed. + */ +function network_format_bytes($value) +{ + if (!isset($value)) { + $value = 0; + } + + $value = (int) $value; + + return format_for_graph( + $value, + 2, + '.', + ',', + 1024, + 'B' + ); +} + + +/** + * Build netflow data structure to network map. + * + * @param integer $start Time in timestamp format. + * @param integer $end Time in timestamp format. + * @param integer $top Max data to show. + * @param boolean $talker True to get top tolkers. False for listeners. + * + * @return array With map structure. + */ +function network_build_map_data($start, $end, $top, $talker) +{ + $data = network_matrix_get_top($top, $talker, $start, $end); + + $hosts = array_map( + function ($elem) { + return $elem['host']; + }, + $data + ); + $inverse_hosts = array_flip($hosts); + + $nodes = array_map( + function ($elem) { + return network_init_node_map($elem); + }, + $hosts + ); + + $relations = []; + $orphan_relations = []; + foreach ($hosts as $host) { + $host_top = network_matrix_get_top( + $top, + !$talker, + $start, + $end, + $host, + true, + $hosts + ); + foreach ($host_top as $sd) { + $src_index = $inverse_hosts[$host]; + $dst_index = $inverse_hosts[$sd['host']]; + if (isset($src_index) === false || isset($dst_index) === false) { + continue; + } + + network_init_relation_map( + $relations, + $src_index, + $dst_index, + network_format_bytes($sd['sum_bytes']) + ); + } + + // Put the orphans on Other node. + if (empty($host_top)) { + $other_id = (end($inverse_hosts) + 1); + // TODOS: Add the data. + network_init_relation_map( + $orphan_relations, + $other_id, + $inverse_hosts[$host] + ); + } + } + + // Put the Others node and their relations. + if (empty($orphan_relations) === false) { + $nodes[] = network_init_node_map(__('Others')); + $relations = array_merge($relations, $orphan_relations); + } + + return network_general_map_configuration($nodes, $relations); +} + + +/** + * Return the array to pass to constructor to NetworkMap. + * + * @param array $nodes Nodes data structure. + * @param array $relations Relations data structure. + * + * @return array To be passed to NetworMap class. + */ +function network_general_map_configuration($nodes, $relations) +{ + return [ + 'nodes' => $nodes, + 'relations' => $relations, + 'pure' => 1, + 'no_pandora_node' => 1, + 'no_popup' => 1, + 'map_options' => [ + 'generation_method' => LAYOUT_SPRING1, + 'map_filter' => [ + 'node_radius' => 40, + 'node_sep' => 7, + ], + ], + ]; +} + + +/** + * Added a relation to relations array + * + * @param array $relations Relations array (passed by reference). + * @param integer $parent Parent id (numeric). + * @param integer $child Child id (numeric). + * @param string $text Text to show at the end of edge (optional). + * + * @return void Relations will be modified (passed by reference). + */ +function network_init_relation_map(&$relations, $parent, $child, $text='') +{ + $index = $parent.'-'.$child; + $relations[$index] = [ + 'id_parent' => $parent, + 'parent_type' => NODE_GENERIC, + 'child_type' => NODE_GENERIC, + 'id_child' => $child, + 'link_color' => '#82B92E', + ]; + + if (empty($text) === false) { + $relations[$index]['text_start'] = $text; + } +} + + +/** + * Initialize a node structure to NetworkMap class. + * + * @param string $name Node name. + * + * @return array Node data structure. + */ +function network_init_node_map($name) +{ + return [ + 'name' => $name, + 'type' => NODE_GENERIC, + 'width' => 20, + 'height' => 20, + 'status' => '#82B92E', + ]; +} diff --git a/pandora_console/include/functions_reporting.php b/pandora_console/include/functions_reporting.php index f65849bb54..3761c0f904 100755 --- a/pandora_console/include/functions_reporting.php +++ b/pandora_console/include/functions_reporting.php @@ -36,6 +36,7 @@ require_once $config['homedir'].'/include/functions_forecast.php'; require_once $config['homedir'].'/include/functions_ui.php'; require_once $config['homedir'].'/include/functions_netflow.php'; require_once $config['homedir'].'/include/functions_os.php'; +require_once $config['homedir'].'/include/functions_network.php'; // // CONSTANTS DEFINITIONS // @@ -516,16 +517,6 @@ function reporting_make_reporting_data( ); break; - case 'netflow_pie': - $report['contents'][] = reporting_netflow( - $report, - $content, - $type, - $force_width_chart, - $force_height_chart, - 'netflow_pie', - $pdf - ); break; case 'netflow_data': @@ -540,18 +531,6 @@ function reporting_make_reporting_data( ); break; - case 'netflow_statistics': - $report['contents'][] = reporting_netflow( - $report, - $content, - $type, - $force_width_chart, - $force_height_chart, - 'netflow_statistics', - $pdf - ); - break; - case 'netflow_summary': $report['contents'][] = reporting_netflow( $report, @@ -794,6 +773,14 @@ function reporting_make_reporting_data( $pdf ); break; + + case 'nt_top_n': + $report['contents'][] = reporting_nt_top_n_report( + $report, + $content, + $pdf + ); + break; } $index_content++; @@ -3958,6 +3945,20 @@ function reporting_monitor_report($report, $content) } +/** + * Generates the data structure to build a netflow report. + * + * @param array $report Global report info. + * @param array $content Report item info. + * @param string $type Report type (static, dynamic, data). + * @param integer $force_width_chart Fixed width chart. + * @param integer $force_height_chart Fixed height chart. + * @param string $type_netflow One of netflow_area, netflow_data, + * netflow_summary. + * @param boolean $pdf True if a pdf report is generating. + * + * @return array Report item structure. + */ function reporting_netflow( $report, $content, @@ -3974,21 +3975,17 @@ function reporting_netflow( $return['type'] = 'netflow_area'; break; - case 'netflow_pie': - $return['type'] = 'netflow_pie'; - break; - case 'netflow_data': $return['type'] = 'netflow_data'; break; - case 'netflow_statistics': - $return['type'] = 'netflow_statistics'; - break; - case 'netflow_summary': $return['type'] = 'netflow_summary'; break; + + default: + $return['type'] = 'unknown'; + break; } if (empty($content['name'])) { @@ -3997,20 +3994,16 @@ function reporting_netflow( $content['name'] = __('Netflow Area'); break; - case 'netflow_pie': - $content['name'] = __('Netflow Pie'); + case 'netflow_summary': + $content['name'] = __('Netflow Summary'); break; case 'netflow_data': $content['name'] = __('Netflow Data'); break; - case 'netflow_statistics': - $content['name'] = __('Netflow Statistics'); - break; - - case 'netflow_summary': - $content['name'] = __('Netflow Summary'); + default: + $content['name'] = __('Unknown report'); break; } } @@ -4019,7 +4012,7 @@ function reporting_netflow( $return['description'] = $content['description']; $return['date'] = reporting_get_date_text($report, $content); - // Get chart + // Get chart. reporting_set_conf_charts( $width, $height, @@ -4037,7 +4030,7 @@ function reporting_netflow( $height = $force_height_chart; } - // Get item filters + // Get item filters. $filter = db_get_row_sql( "SELECT * FROM tnetflow_filter @@ -4062,9 +4055,17 @@ function reporting_netflow( break; case 'data': + default: + // Nothing to do. break; } + $return['subtitle'] = netflow_generate_subtitle_report( + $filter['aggregate'], + $content['top_n'], + $type_netflow + ); + return reporting_check_structure_content($return); } @@ -11517,3 +11518,38 @@ function reporting_header_table_for_pdf(string $title='', string $description='' return $result_pdf; } + + +/** + * Build the required data to build network traffic top N report + * + * @param int Period (time window). + * @param array Information about the item of report. + * @param bool Pdf or not + * + * @return array With report presentation info and report data. + */ +function reporting_nt_top_n_report($period, $content, $pdf) +{ + $return = []; + $return['type'] = 'nt_top_n'; + $return['title'] = $content['name']; + $return['description'] = $content['description']; + + // Get the data sent and received + $return['data'] = []; + $start_time = ($period['datetime'] - (int) $content['period']); + $return['data']['send'] = network_matrix_get_top( + $content['top_n_value'], + true, + $start_time, + $period['datetime'] + ); + $return['data']['recv'] = network_matrix_get_top( + $content['top_n_value'], + false, + $start_time, + $period['datetime'] + ); + return $return; +} diff --git a/pandora_console/include/functions_reporting_html.php b/pandora_console/include/functions_reporting_html.php index fab9c0d055..7265c721ec 100644 --- a/pandora_console/include/functions_reporting_html.php +++ b/pandora_console/include/functions_reporting_html.php @@ -271,21 +271,7 @@ function reporting_html_print_report($report, $mini=false, $report_info=1) break; case 'netflow_area': - reporting_html_graph($table, $item); - break; - - case 'netflow_pie': - reporting_html_graph($table, $item); - break; - case 'netflow_data': - reporting_html_graph($table, $item); - break; - - case 'netflow_statistics': - reporting_html_graph($table, $item); - break; - case 'netflow_summary': reporting_html_graph($table, $item); break; @@ -367,6 +353,10 @@ function reporting_html_print_report($report, $mini=false, $report_info=1) reporting_enterprise_html_SLA_monthly($table, $item, $mini); break; + case 'nt_top_n': + reporting_html_nt_top_n($table, $item, $mini); + break; + case 'SLA_weekly': reporting_enterprise_html_SLA_weekly($table, $item, $mini); break; @@ -4769,6 +4759,65 @@ function reporting_get_event_histogram_meta($width) } +/** + * Print network traffic data into top n tables + * (one for received data and another for sent) + * + * @param stdClass Table class to paint the report + * @param array Associative array with info about + * @param bool Unused + */ +function reporting_html_nt_top_n($table, $item, $mini) +{ + // Prepare the table + $table_top = new stdClass(); + $table_top->cellpadding = 0; + $table_top->cellspacing = 0; + $table_top->width = '100%'; + $table_top->class = 'databox data'; + $table_top->cellpadding = 0; + $table_top->cellspacing = 0; + $table_top->width = '100%'; + $table_top->class = 'databox data'; + $table_top->head['host'] = __('Agent'); + $table_top->head['bytes'] = __('Kilobytes'); + $table_top->head['pkts'] = __('Packages'); + + // Build the table for sent packages + if (empty($item['data']['send'])) { + $table->data['send_title'] = '<h3>'.__('No network traffic sent data').'</h3>'; + } else { + foreach ($item['data']['send'] as $s_item) { + $table_top->data[] = [ + 'host' => $s_item['host'], + 'bytes' => remove_right_zeros(number_format(($s_item['sum_bytes'] / 1024), $config['graph_precision'])), + 'pkts' => remove_right_zeros(number_format($s_item['sum_pkts'], $config['graph_precision'])), + ]; + } + + $table->data['send_title'] = '<h3>'.__('Network traffic sent').'</h3>'; + $table->data['send'] = html_print_table($table_top, true); + } + + // Reset the table and build the table for received packages + $table_top->data = []; + if (empty($item['data']['send'])) { + $table->data['recv_title'] = '<h3>'.__('No network traffic received data').'</h3>'; + } else { + foreach ($item['data']['recv'] as $s_item) { + $table_top->data[] = [ + 'host' => $s_item['host'], + 'bytes' => remove_right_zeros(number_format(($s_item['sum_bytes'] / 1024), $config['graph_precision'])), + 'pkts' => remove_right_zeros(number_format($s_item['sum_pkts'], $config['graph_precision'])), + ]; + } + + $table->data['recv_title'] = '<h3>'.__('Network traffic received').'</h3>'; + $table->data['recv'] = html_print_table($table_top, true); + } +} + + function reporting_html_planned_downtimes_table($planned_downtimes) { global $config; diff --git a/pandora_console/include/functions_reports.php b/pandora_console/include/functions_reports.php index fd68aa0da2..0bf1f8fe70 100755 --- a/pandora_console/include/functions_reports.php +++ b/pandora_console/include/functions_reports.php @@ -867,18 +867,10 @@ function reports_get_report_types($template=false, $not_editor=false) 'optgroup' => __('Netflow'), 'name' => __('Netflow area chart'), ]; - $types['netflow_pie'] = [ - 'optgroup' => __('Netflow'), - 'name' => __('Netflow pie chart'), - ]; $types['netflow_data'] = [ 'optgroup' => __('Netflow'), 'name' => __('Netflow data table'), ]; - $types['netflow_statistics'] = [ - 'optgroup' => __('Netflow'), - 'name' => __('Netflow statistics table'), - ]; $types['netflow_summary'] = [ 'optgroup' => __('Netflow'), 'name' => __('Netflow summary table'), @@ -892,5 +884,10 @@ function reports_get_report_types($template=false, $not_editor=false) ]; } + $types['nt_top_n'] = [ + 'optgroup' => __('Network traffic'), + 'name' => __('Network Traffic Top N'), + ]; + return $types; } diff --git a/pandora_console/include/functions_ui.php b/pandora_console/include/functions_ui.php index ad16bfc7d5..7865a1c78a 100755 --- a/pandora_console/include/functions_ui.php +++ b/pandora_console/include/functions_ui.php @@ -2792,8 +2792,9 @@ function ui_print_page_header( $buffer = '<div id="'.$type2.'" style="">'; - if (!empty($breadcrumbs)) + if (!empty($breadcrumbs)) { $buffer .= '<div class="breadcrumbs_container">'.$breadcrumbs.'</div>'; + } $buffer .= '<div id="menu_tab_left">'; diff --git a/pandora_console/include/graphs/functions_d3.php b/pandora_console/include/graphs/functions_d3.php index 5ce06e982f..83e622e171 100644 --- a/pandora_console/include/graphs/functions_d3.php +++ b/pandora_console/include/graphs/functions_d3.php @@ -38,7 +38,7 @@ function include_javascript_d3($return=false) } -function d3_relationship_graph($elements, $matrix, $unit, $width=700, $return=false) +function d3_relationship_graph($elements, $matrix, $width=700, $return=false) { global $config; @@ -53,7 +53,7 @@ function d3_relationship_graph($elements, $matrix, $unit, $width=700, $return=fa $output = '<div id="chord_diagram"></div>'; $output .= include_javascript_d3(true); $output .= "<script language=\"javascript\" type=\"text/javascript\"> - chordDiagram('#chord_diagram', $elements, $matrix, '$unit', $width); + chordDiagram('#chord_diagram', $elements, $matrix, $width); </script>"; if (!$return) { diff --git a/pandora_console/include/graphs/pandora.d3.js b/pandora_console/include/graphs/pandora.d3.js index 51dae061ec..d34f9b41cd 100644 --- a/pandora_console/include/graphs/pandora.d3.js +++ b/pandora_console/include/graphs/pandora.d3.js @@ -20,7 +20,7 @@ // matrix = [[0, 0, 2], // a[a => a, a => b, a => c] // [5, 0, 1], // b[b => a, b => b, b => c] // [2, 3, 0]]; // c[c => a, c => b, c => c] -function chordDiagram(recipient, elements, matrix, unit, width) { +function chordDiagram(recipient, elements, matrix, width) { d3.chart = d3.chart || {}; d3.chart.chordWheel = function(options) { // Default values @@ -206,18 +206,14 @@ function chordDiagram(recipient, elements, matrix, unit, width) { " → " + elements[d.target.index] + ": <b>" + - d.source.value.toFixed(2) + - " " + - unit + + valueToBytes(d.source.value) + "</b>" + "<br>" + elements[d.target.index] + " → " + elements[d.source.index] + ": <b>" + - d.target.value.toFixed(2) + - " " + - unit + + valueToBytes(d.target.value) + "</b>" ) ); @@ -227,18 +223,14 @@ function chordDiagram(recipient, elements, matrix, unit, width) { " → " + elements[d.target.index] + ": <b>" + - d.source.value.toFixed(2) + - " " + - unit + + valueToBytes(d.source.value) + "</b>" + "<br>" + elements[d.target.index] + " → " + elements[d.source.index] + ": <b>" + - d.target.value.toFixed(2) + - " " + - unit + + valueToBytes(d.target.value) + "</b>" ); } @@ -2751,3 +2743,17 @@ function printClockDigital1( setTimeout(tick, 1000 - (now % 1000)); })(); } + +function valueToBytes(value) { + var shorts = ["", "K", "M", "G", "T", "P", "E", "Z", "Y"]; + var pos = 0; + while (value >= 1024) { + // As long as the number can be divided by divider. + pos++; + // Position in array starting with 0. + value = value / 1024; + } + + // This will actually do the rounding and the decimals. + return value.toFixed(2) + shorts[pos] + "B"; +} diff --git a/pandora_console/include/styles/pandora.css b/pandora_console/include/styles/pandora.css index bc9e4c6357..3b7bcf9101 100644 --- a/pandora_console/include/styles/pandora.css +++ b/pandora_console/include/styles/pandora.css @@ -4322,6 +4322,18 @@ form ul.form_flex li ul li { text-align: center; } +.div-v-centered { + display: flex; + align-items: center; +} + +.div-v-centered > form > input[type="image"] { + margin: 0; + padding: 0; + width: 14px; + padding-left: 5px; +} + .pandora_upper { text-transform: uppercase; } @@ -4392,6 +4404,13 @@ tr:first-child > td > a.up_arrow { margin-right: 5px; } +.button-as-link { + text-decoration: underline; + background: none !important; + border: none; + padding: 0 !important; +} + /* * --------------------------------------------------------------------- * - MESSAGE LIST POPUP - diff --git a/pandora_console/install.php b/pandora_console/install.php index 58597ed800..9ce9c8fc8f 100644 --- a/pandora_console/install.php +++ b/pandora_console/install.php @@ -128,7 +128,7 @@ </div> <div style='height: 10px'> <?php - $version = '7.0NG.732'; + $version = '7.0NG.733'; $build = '190327'; $banner = "v$version Build $build"; diff --git a/pandora_console/operation/menu.php b/pandora_console/operation/menu.php index 997bfed3cb..e22769cd8a 100644 --- a/pandora_console/operation/menu.php +++ b/pandora_console/operation/menu.php @@ -23,7 +23,7 @@ enterprise_include('operation/menu.php'); $menu_operation = []; $menu_operation['class'] = 'operation'; -// Agent read, Server read +// Agent read, Server read. if (check_acl($config['id_user'], 0, 'AR')) { // View agents $menu_operation['estado']['text'] = __('Monitoring'); @@ -65,20 +65,69 @@ if (check_acl($config['id_user'], 0, 'AR')) { enterprise_hook('inventory_menu'); - if ($config['activate_netflow']) { - $sub['operation/netflow/nf_live_view']['text'] = __('Netflow Live View'); - $sub['operation/netflow/nf_live_view']['id'] = 'Netflow Live View'; - $sub['operation/netflow/nf_live_view']['refr'] = 0; + if ($config['activate_netflow'] || $config['activate_nta']) { + $sub['network'] = [ + 'text' => __('Network'), + 'id' => 'Network', + 'type' => 'direct', + 'subtype' => 'nolink', + 'refr' => 0, + ]; + + // Initialize the submenu. + $netflow_sub = []; + + if ($config['activate_netflow']) { + $netflow_sub = array_merge( + $netflow_sub, + [ + 'operation/netflow/netflow_explorer' => [ + 'text' => __('Netflow explorer'), + 'id' => 'Netflow explorer', + ], + 'operation/netflow/nf_live_view' => [ + 'text' => __('Netflow Live View'), + 'id' => 'Netflow Live View', + ], + ] + ); + } + + if ($config['activate_nta']) { + $netflow_sub = array_merge( + $netflow_sub, + [ + 'operation/network/network_explorer' => [ + 'text' => __('Network explorer'), + 'id' => 'Network explorer', + ], + ] + ); + } + + if ($config['activate_nta'] || $config['activate_netflow']) { + $netflow_sub = array_merge( + $netflow_sub, + [ + 'operation/network/network_usage_map' => [ + 'text' => __('Network usage map'), + 'id' => 'Network usage map', + ], + ] + ); + } + + $sub['network']['sub2'] = $netflow_sub; } if ($config['log_collector'] == 1) { enterprise_hook('log_collector_menu'); } - // End of view agents + // End of view agents. } -// SNMP Console +// SNMP Console. $sub2 = []; if (check_acl($config['id_user'], 0, 'AR') || check_acl($config['id_user'], 0, 'AW')) { $sub2['operation/snmpconsole/snmp_view']['text'] = __('SNMP console'); @@ -115,10 +164,10 @@ if (!empty($sub)) { $menu_operation['estado']['sub'] = $sub; } -// Start network view +// Start network view. $sub = []; if (check_acl($config['id_user'], 0, 'MR') || check_acl($config['id_user'], 0, 'MW') || check_acl($config['id_user'], 0, 'MM')) { - // Network enterprise + // Network enterprise. $sub['operation/agentes/pandora_networkmap']['text'] = __('Network map'); $sub['operation/agentes/pandora_networkmap']['id'] = 'Network map'; $sub['operation/agentes/pandora_networkmap']['refr'] = 0; @@ -130,17 +179,17 @@ enterprise_hook('services_menu'); if (check_acl($config['id_user'], 0, 'VR') || check_acl($config['id_user'], 0, 'VW') || check_acl($config['id_user'], 0, 'VM')) { if (!isset($config['vc_favourite_view']) || $config['vc_favourite_view'] == 0) { - // Visual console + // Visual console. $sub['godmode/reporting/map_builder']['text'] = __('Visual console'); $sub['godmode/reporting/map_builder']['id'] = 'Visual console'; } else { - // Visual console favorite + // Visual console favorite. $sub['godmode/reporting/visual_console_favorite']['text'] = __('Visual console'); $sub['godmode/reporting/visual_console_favorite']['id'] = 'Visual console'; } if ($config['vc_menu_items'] != 0) { - // Set godomode path + // Set godomode path. if (!isset($config['vc_favourite_view']) || $config['vc_favourite_view'] == 0) { $sub['godmode/reporting/map_builder']['subsecs'] = [ 'godmode/reporting/map_builder', @@ -212,7 +261,7 @@ if (check_acl($config['id_user'], 0, 'VR') || check_acl($config['id_user'], 0, ' if (check_acl($config['id_user'], 0, 'MR') || check_acl($config['id_user'], 0, 'MW') || check_acl($config['id_user'], 0, 'MM')) { - // INI GIS Maps + // INI GIS Maps. if ($config['activate_gis']) { $sub['gismaps']['text'] = __('GIS Maps'); $sub['gismaps']['id'] = 'GIS Maps'; @@ -254,7 +303,7 @@ if (check_acl($config['id_user'], 0, 'MR') || check_acl($config['id_user'], 0, ' $sub['gismaps']['sub2'] = $sub2; } - // END GIS Maps + // END GIS Maps. } if (!empty($sub)) { @@ -265,10 +314,10 @@ if (!empty($sub)) { $menu_operation['network']['sub'] = $sub; } -// End networkview -// Reports read +// End networkview. +// Reports read. if (check_acl($config['id_user'], 0, 'RR') || check_acl($config['id_user'], 0, 'RW') || check_acl($config['id_user'], 0, 'RM')) { - // Reporting + // Reporting. $menu_operation['reporting']['text'] = __('Reporting'); $menu_operation['reporting']['sec2'] = 'godmode/reporting/reporting_builder'; $menu_operation['reporting']['id'] = 'oper-reporting'; @@ -278,7 +327,7 @@ if (check_acl($config['id_user'], 0, 'RR') || check_acl($config['id_user'], 0, ' $sub['godmode/reporting/reporting_builder']['text'] = __('Custom reporting'); $sub['godmode/reporting/reporting_builder']['id'] = 'Custom reporting'; - // Set godomode path + // Set godomode path. $sub['godmode/reporting/reporting_builder']['subsecs'] = [ 'godmode/reporting/reporting_builder', 'operation/reporting/reporting_viewer', @@ -287,7 +336,7 @@ if (check_acl($config['id_user'], 0, 'RR') || check_acl($config['id_user'], 0, ' $sub['godmode/reporting/graphs']['text'] = __('Custom graphs'); $sub['godmode/reporting/graphs']['id'] = 'Custom graphs'; - // Set godomode path + // Set godomode path. $sub['godmode/reporting/graphs']['subsecs'] = [ 'operation/reporting/graph_viewer', 'godmode/reporting/graph_builder', @@ -297,15 +346,15 @@ if (check_acl($config['id_user'], 0, 'RR') || check_acl($config['id_user'], 0, ' enterprise_hook('reporting_godmenu'); $menu_operation['reporting']['sub'] = $sub; - // End reporting + // End reporting. } -// Events reading +// Events reading. if (check_acl($config['id_user'], 0, 'ER') || check_acl($config['id_user'], 0, 'EW') || check_acl($config['id_user'], 0, 'EM') ) { - // Events + // Events. $menu_operation['eventos']['text'] = __('Events'); $menu_operation['eventos']['refr'] = 0; $menu_operation['eventos']['sec2'] = 'operation/events/events'; @@ -318,24 +367,24 @@ if (check_acl($config['id_user'], 0, 'ER') $sub['operation/events/event_statistics']['text'] = __('Statistics'); $sub['operation/events/event_statistics']['id'] = 'Statistics'; - // If ip doesn't is in list of allowed IP, isn't show this options + // If ip doesn't is in list of allowed IP, isn't show this options. include_once 'include/functions_api.php'; if (isInACL($_SERVER['REMOTE_ADDR'])) { $pss = get_user_info($config['id_user']); $hashup = md5($config['id_user'].$pss['password']); - // RSS + // RSS. $sub['operation/events/events_rss.php?user='.$config['id_user'].'&hashup='.$hashup.'&search=&event_type=&severity=-1&status=3&id_group=0&refr=0&id_agent=0&pagination=20&group_rep=1&event_view_hr=8&id_user_ack=0&tag_with=&tag_without=&filter_only_alert-1&offset=0&toogle_filter=no&filter_id=0&id_name=&id_group=0&history=0§ion=list&open_filter=0&pure=']['text'] = __('RSS'); $sub['operation/events/events_rss.php?user='.$config['id_user'].'&hashup='.$hashup.'&search=&event_type=&severity=-1&status=3&id_group=0&refr=0&id_agent=0&pagination=20&group_rep=1&event_view_hr=8&id_user_ack=0&tag_with=&tag_without=&filter_only_alert-1&offset=0&toogle_filter=no&filter_id=0&id_name=&id_group=0&history=0§ion=list&open_filter=0&pure=']['id'] = 'RSS'; $sub['operation/events/events_rss.php?user='.$config['id_user'].'&hashup='.$hashup.'&search=&event_type=&severity=-1&status=3&id_group=0&refr=0&id_agent=0&pagination=20&group_rep=1&event_view_hr=8&id_user_ack=0&tag_with=&tag_without=&filter_only_alert-1&offset=0&toogle_filter=no&filter_id=0&id_name=&id_group=0&history=0§ion=list&open_filter=0&pure=']['type'] = 'direct'; - // Marquee + // Marquee. $sub['operation/events/events_marquee.php']['text'] = __('Marquee'); $sub['operation/events/events_marquee.php']['id'] = 'Marquee'; $sub['operation/events/events_marquee.php']['type'] = 'direct'; } - // Sound Events + // Sound Events. $javascript = "javascript: window.open('operation/events/sound_events.php');"; $javascript = 'javascript: alert(111);'; $javascript = 'javascript: openSoundEventWindow();'; @@ -359,31 +408,31 @@ if (check_acl($config['id_user'], 0, 'ER') $menu_operation['eventos']['sub'] = $sub; } -// Workspace +// Workspace. $menu_operation['workspace']['text'] = __('Workspace'); $menu_operation['workspace']['sec2'] = 'operation/users/user_edit'; $menu_operation['workspace']['id'] = 'oper-users'; // ANY user can view him/herself ! -// Users +// Users. $sub = []; $sub['operation/users/user_edit']['text'] = __('Edit my user'); $sub['operation/users/user_edit']['id'] = 'Edit my user'; $sub['operation/users/user_edit']['refr'] = 0; -// Users +// Users. $sub['operation/users/user_edit_notifications']['text'] = __('Configure user notifications'); $sub['operation/users/user_edit_notifications']['id'] = 'Configure user notifications'; $sub['operation/users/user_edit_notifications']['refr'] = 0; // ANY user can chat with other user and dogs. -// Users +// Users. $sub['operation/users/webchat']['text'] = __('WebChat'); $sub['operation/users/webchat']['id'] = 'WebChat'; $sub['operation/users/webchat']['refr'] = 0; -// Incidents +// Incidents. if (check_acl($config['id_user'], 0, 'IR') || check_acl($config['id_user'], 0, 'IW') || check_acl($config['id_user'], 0, 'IM') @@ -410,7 +459,7 @@ if (check_acl($config['id_user'], 0, 'IR') } -// Messages +// Messages. $sub['message_list']['text'] = __('Messages'); $sub['message_list']['id'] = 'Messages'; $sub['message_list']['refr'] = 0; @@ -427,7 +476,7 @@ $menu_operation['workspace']['sub'] = $sub; // End Workspace // Rest of options, all with AR privilege (or should events be with incidents?) // ~ if (check_acl ($config['id_user'], 0, "AR")) { -// Extensions menu additions +// Extensions menu additions. if (is_array($config['extensions'])) { $sub = []; $sub2 = []; @@ -450,12 +499,12 @@ if (is_array($config['extensions'])) { } foreach ($config['extensions'] as $extension) { - // If no operation_menu is a godmode extension + // If no operation_menu is a godmode extension. if ($extension['operation_menu'] == '') { continue; } - // Check the ACL for this user + // Check the ACL for this user. if (! check_acl($config['id_user'], 0, $extension['operation_menu']['acl'])) { continue; } @@ -469,7 +518,7 @@ if (is_array($config['extensions'])) { continue; } - // Check if was displayed inside other menu + // Check if was displayed inside other menu. if ($extension['operation_menu']['fatherId'] == '') { if ($extension_menu['name'] == 'Update manager') { continue; @@ -480,7 +529,7 @@ if (is_array($config['extensions'])) { $sub[$extension_menu['sec2']]['refr'] = 0; } else { if (array_key_exists('fatherId', $extension_menu)) { - // Check that extension father ID exists previously on the menu + // Check that extension father ID exists previously on the menu. if ((strlen($extension_menu['fatherId']) > 0)) { if (array_key_exists('subfatherId', $extension_menu)) { if ((strlen($extension_menu['subfatherId']) > 0)) { diff --git a/pandora_console/operation/netflow/netflow_explorer.php b/pandora_console/operation/netflow/netflow_explorer.php new file mode 100644 index 0000000000..318b6dd5f1 --- /dev/null +++ b/pandora_console/operation/netflow/netflow_explorer.php @@ -0,0 +1,42 @@ +<?php +/** + * Network explorer + * + * @package Operations. + * @subpackage Netflow explorer view. + * + * Pandora FMS - http://pandorafms.com + * ================================================== + * Copyright (c) 2005-2019 Artica Soluciones Tecnologicas + * Please see http://pandorafms.org for full contribution list + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; version 2 + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +global $config; + +check_login(); + +// ACL Check. +if (! check_acl($config['id_user'], 0, 'AR')) { + db_pandora_audit( + 'ACL Violation', + 'Trying to access Netflow explorer' + ); + include 'general/noaccess.php'; + exit; +} + +$action = get_parameter('action', 'listeners'); +$is_network = false; + +ui_print_page_header(__('Netflow explorer')); + +if (netflow_print_check_version_error()) { + include $config['homedir'].'/operation/network/network_report.php'; +} diff --git a/pandora_console/operation/netflow/nf_live_view.php b/pandora_console/operation/netflow/nf_live_view.php index 62a52d3e77..a9f742d779 100644 --- a/pandora_console/operation/netflow/nf_live_view.php +++ b/pandora_console/operation/netflow/nf_live_view.php @@ -1,16 +1,23 @@ <?php +/** + * Netflow live view + * + * @package Pandora FMS open. + * @subpackage UI file. + * + * Pandora FMS - http://pandorafms.com + * ================================================== + * Copyright (c) 2005-2019 Artica Soluciones Tecnologicas + * Please see http://pandorafms.org for full contribution list + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; version 2 + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ -// Pandora FMS - http://pandorafms.com -// ================================================== -// Copyright (c) 2005-2011 Artica Soluciones Tecnologicas -// Please see http://pandorafms.org for full contribution list -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; version 2 -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. global $config; require_once $config['homedir'].'/include/functions_graph.php'; @@ -19,7 +26,7 @@ require_once $config['homedir'].'/include/functions_netflow.php'; ui_require_javascript_file('calendar'); -// ACL +// ACL. check_login(); if (! check_acl($config['id_user'], 0, 'AR') && ! check_acl($config['id_user'], 0, 'AW')) { db_pandora_audit( @@ -32,12 +39,12 @@ if (! check_acl($config['id_user'], 0, 'AR') && ! check_acl($config['id_user'], $pure = get_parameter('pure', 0); -// Ajax callbacks +// Ajax callbacks. if (is_ajax()) { $get_filter_type = get_parameter('get_filter_type', 0); $get_filter_values = get_parameter('get_filter_values', 0); - // Get filter of the current netflow filter + // Get filter of the current netflow filter. if ($get_filter_type) { $id = get_parameter('id'); @@ -52,13 +59,13 @@ if (is_ajax()) { echo $type; } - // Get values of the current netflow filter + // Get values of the current netflow filter. if ($get_filter_values) { $id = get_parameter('id'); $filter_values = db_get_row_filter('tnetflow_filter', ['id_sg' => $id]); - // Decode HTML entities + // Decode HTML entities. $filter_values['advanced_filter'] = io_safe_output($filter_values['advanced_filter']); @@ -68,12 +75,11 @@ if (is_ajax()) { return; } -// Read filter configuration +// Read filter configuration. $filter_id = (int) get_parameter('filter_id', 0); $filter['id_name'] = get_parameter('name', ''); $filter['id_group'] = (int) get_parameter('assign_group', 0); $filter['aggregate'] = get_parameter('aggregate', ''); -$filter['output'] = get_parameter('output', 'bytes'); $filter['ip_dst'] = get_parameter('ip_dst', ''); $filter['ip_src'] = get_parameter('ip_src', ''); $filter['dst_port'] = get_parameter('dst_port', ''); @@ -81,30 +87,38 @@ $filter['src_port'] = get_parameter('src_port', ''); $filter['advanced_filter'] = get_parameter('advanced_filter', ''); $filter['router_ip'] = get_parameter('router_ip'); -// Read chart configuration +// Read chart configuration. $chart_type = get_parameter('chart_type', 'netflow_area'); -$max_aggregates = (int) get_parameter('max_aggregates', 1); -$period = (int) get_parameter('period', SECONDS_1DAY); +$max_aggregates = (int) get_parameter('max_aggregates', 10); $update_date = (int) get_parameter('update_date', 0); -$date = get_parameter_post('date', date(DATE_FORMAT, get_system_time())); -$time = get_parameter_post('time', date(TIME_FORMAT, get_system_time())); $connection_name = get_parameter('connection_name', ''); -$interval_length = (int) get_parameter('interval_length', 300); +$interval_length = get_parameter('interval_length', NETFLOW_RES_MEDD); $address_resolution = (int) get_parameter('address_resolution', $config['netflow_get_ip_hostname']); $filter_selected = (int) get_parameter('filter_selected', 0); -// Read buttons +// Read time values. +$date = get_parameter_post('date', date(DATE_FORMAT, get_system_time())); +$time = get_parameter_post('time', date(TIME_FORMAT, get_system_time())); +$end_date = strtotime($date.' '.$time); +$is_period = (bool) get_parameter('is_period', false); +$period = (int) get_parameter('period', SECONDS_1DAY); +$time_lower = get_parameter('time_lower', date(TIME_FORMAT, ($end_date - $period))); +$date_lower = get_parameter('date_lower', date(DATE_FORMAT, ($end_date - $period))); +$start_date = ($is_period) ? ($end_date - $period) : strtotime($date_lower.' '.$time_lower); +if (!$is_period) { + $period = ($end_date - $start_date); +} else { + $time_lower = date(TIME_FORMAT, $start_date); + $date_lower = date(DATE_FORMAT, $start_date); +} + +// Read buttons. $draw = get_parameter('draw_button', ''); $save = get_parameter('save_button', ''); $update = get_parameter('update_button', ''); - -// Calculate start and end dates -$end_date = strtotime($date.' '.$time); -$start_date = ($end_date - $period); - if (!is_metaconsole()) { - // Header + // Header. ui_print_page_header( __('Netflow live view'), 'images/op_netflow.png', @@ -118,22 +132,7 @@ if (!is_metaconsole()) { if ($is_windows) { ui_print_error_message(__('Not supported in Windows systems')); } else { - // Check the nfdump binary - $check_result = netflow_check_nfdump_binary($config['netflow_nfdump']); - - // Not found or not executable - if ($check_result == 1) { - ui_print_error_message( - sprintf( - __('nfdump binary (%s) not found!'), - $config['netflow_nfdump'] - ) - ); - } - // Wrong version - else if ($check_result == 2) { - ui_print_error_message(sprintf(__('Make sure nfdump version 1.6.8 or newer is installed!'))); - } + netflow_print_check_version_error(); } } else { $nav_bar = [ @@ -152,9 +151,9 @@ if (!is_metaconsole()) { ui_meta_print_header(__('Netflow live view')); } -// Save user defined filter +// Save user defined filter. if ($save != '' && check_acl($config['id_user'], 0, 'AW')) { - // Save filter args + // Save filter args. $filter['filter_args'] = netflow_get_filter_arguments($filter); $filter_id = db_process_sql_insert('tnetflow_filter', $filter); @@ -164,15 +163,14 @@ if ($save != '' && check_acl($config['id_user'], 0, 'AW')) { } else { ui_print_success_message(__('Filter created successfully')); } -} -// Update current filter -else if ($update != '' && check_acl($config['id_user'], 0, 'AW')) { - // Do not update the filter name and group +} else if ($update != '' && check_acl($config['id_user'], 0, 'AW')) { + // Update current filter. + // Do not update the filter name and group. $filter_copy = $filter; unset($filter_copy['id_name']); unset($filter_copy['id_group']); - // Save filter args + // Save filter args. $filter_copy['filter_args'] = netflow_get_filter_arguments($filter_copy); $result = db_process_sql_update( @@ -188,7 +186,7 @@ else if ($update != '' && check_acl($config['id_user'], 0, 'AW')) { } -// The filter name will not be needed anymore +// The filter name will not be needed anymore. $filter['id_name'] = ''; $netflow_disable_custom_lvfilters = false; @@ -223,7 +221,7 @@ if (is_metaconsole()) { } foreach ($servers as $server) { - // If connection was good then retrieve all data server + // If connection was good then retrieve all data server. if (metaconsole_load_external_db($server)) { $connection = true; } else { @@ -241,7 +239,7 @@ if (is_metaconsole()) { } echo '<tr>'; - echo '<td>'.'<b>'.__('Connection').'</b>'.'</td>'; + echo '<td><b>'.__('Connection').'</b></td>'; echo '<td>'.html_print_select( $list_servers, 'connection_name', @@ -258,23 +256,59 @@ if (is_metaconsole()) { echo '<tr>'; - echo '<td>'.'<b>'.__('Date').'</b>'.'</td>'; + $class_not_period = ($is_period) ? 'nf_hidden' : 'nf_display'; + $class_period = ($is_period) ? 'nf_display' : 'nf_hidden'; + echo '<td>'; + echo '<b class="'.$class_period.'">'.__('Interval').'</b>'; + echo '<b class="'.$class_not_period.'">'.__('Start date').'</b>'; + echo '</td>'; + echo '<td>'; + echo html_print_extended_select_for_time('period', $period, '', '', 0, false, true, false, true, $class_period); + echo html_print_input_text('date_lower', $date_lower, false, 13, 10, true, false, false, '', $class_not_period); + echo html_print_image( + 'images/calendar_view_day.png', + true, + [ + 'alt' => 'calendar', + 'class' => $class_not_period, + ] + ).html_print_input_text('time_lower', $time_lower, false, 10, 8, true, false, false, '', $class_not_period); + echo html_print_checkbox( + 'is_period', + 1, + ($is_period === true) ? 1 : 0, + true, + false, + 'nf_view_click_period(event)' + ); + echo ui_print_help_tip(__('Select this checkbox to write interval instead a date.'), true); + echo '</td>'; + + echo '<td><b>'.__('End date').'</b></td>'; echo '<td>'.html_print_input_text('date', $date, false, 13, 10, true).html_print_image( 'images/calendar_view_day.png', true, ['alt' => 'calendar'] - ).ui_print_help_tip(__('Date format is YY/MM/DD'), true).html_print_input_text('time', $time, false, 10, 8, true).ui_print_help_tip(__('Watch format is hours (24h):minutes:seconds'), true).'</td>'; + ).ui_print_help_tip(__('Date format is YY/MM/DD'), true).html_print_input_text('time', $time, false, 10, 8, true).ui_print_help_tip(__('Watch format is hours (24h):minutes:seconds'), true); + echo '</td>'; - echo '<td>'.'<b>'.__('Interval').'</b>'.'</td>'; - echo '<td>'.html_print_select(netflow_get_valid_intervals(), 'period', $period, '', '', 0, true, false, false).'</td>'; - - echo '<td>'.'<b>'.__('Resolution').ui_print_help_tip(__('The interval will be divided in chunks the length of the resolution.'), true).'</b>'.'</td>'; - echo '<td>'.html_print_select(netflow_get_valid_subintervals(), 'interval_length', $interval_length, '', '', 0, true, false, false).'</td>'; + echo '<td><b>'.__('Resolution').ui_print_help_tip(__('The interval will be divided in chunks the length of the resolution.'), true).'</b></td>'; + echo '<td>'.html_print_select( + netflow_resolution_select_params(), + 'interval_length', + $interval_length, + '', + '', + 0, + true, + false, + false + ).'</td>'; echo '</tr>'; echo '<tr>'; - echo '<td>'.'<b>'.__('Type').'</b>'.'</td>'; + echo '<td><b>'.__('Type').'</b></td>'; echo '<td>'.html_print_select( netflow_get_chart_types(), 'chart_type', @@ -285,7 +319,7 @@ if (is_metaconsole()) { true ).'</td>'; - echo '<td>'.'<b>'.__('Max. values').'</b>'.'</td>'; + echo '<td><b>'.__('Max. values').'</b></td>'; $max_values = [ '2' => '2', '5' => '5', @@ -299,6 +333,134 @@ if (is_metaconsole()) { echo '<td>'.html_print_select($max_values, 'max_aggregates', $max_aggregates, '', '', 0, true).'<a id="max_values" href="#" onclick="javascript: edit_max_value();">'.html_print_image('images/pencil.png', true, ['id' => 'pencil']).'</a>'; echo '</td>'; + echo '<td><b>'.__('Aggregate by').'</b>'.ui_print_help_icon('aggregate_by', true).'</td>'; + $aggregate_list = []; + $aggregate_list = [ + 'srcip' => __('Src Ip Address'), + 'dstip' => __('Dst Ip Address'), + 'srcport' => __('Src Port'), + 'dstport' => __('Dst Port'), + ]; + echo '<td>'.html_print_select($aggregate_list, 'aggregate', $filter['aggregate'], '', '', 0, true, false, true, '', false).'</td>'; + + echo '</tr>'; + + // Read filter type. + if ($filter['advanced_filter'] != '') { + $filter_type = 1; + } else { + $filter_type = 0; + } + + echo "<tr class='filter_save' style='display: none;'>"; + + echo "<td colspan='6'>".ui_print_error_message('Define a name for the filter and click on Save as new filter again', '', true).'</td>'; + + echo '</tr>'; + echo "<tr class='filter_save' style='display: none;'>"; + + echo '<td><span id="filter_name_color"><b>'.__('Name').'</b></span></td>'; + echo "<td colspan='2'>".html_print_input_text( + 'name', + $filter['id_name'], + false, + 20, + 80, + true + ).'</td>'; + $own_info = get_user_info($config['id_user']); + echo '<td><span id="filter_group_color"><b>'.__('Group').'</b></span></td>'; + echo "<td colspan='2'>".html_print_select_groups($config['id_user'], 'IW', $own_info['is_admin'], 'assign_group', $filter['id_group'], '', '', -1, true, false, false).'</td>'; + echo '</tr>'; + + echo '<tr id="filter_toggle">'; + echo '<td colspan="5">'; + html_print_image( + 'images/darrowdown.png', + false, + [ + 'onclick' => 'toggleFilters(event)', + 'style' => 'cursor: pointer;', + 'id' => 'nf-toggle-button', + ] + ); + echo __('Advanced'); + echo '</td>'; + echo '</tr>'; + + echo '<tr class="nf_filter">'; + if ($netflow_disable_custom_lvfilters) { + echo '<td></td>'; + echo '<td></td>'; + } else { + echo '<td><b>'.__('Filter').'</b></td>'; + echo '<td colspan="2">'.__('Normal').' '.html_print_radio_button_extended('filter_type', 0, '', $filter_type, false, 'displayNormalFilter();', 'style="margin-right: 40px;"', true).__('Custom').' '.html_print_radio_button_extended('filter_type', 1, '', $filter_type, false, 'displayAdvancedFilter();', 'style="margin-right: 40px;"', true).'</td>'; + } + + + + echo '<td><b>'.__('Load filter').'</b></td>'; + $user_groups = users_get_groups($config['id_user'], 'AR', $own_info['is_admin'], true); + $user_groups[0] = 0; + // Add all groups. + $sql = 'SELECT * + FROM tnetflow_filter + WHERE id_group IN ('.implode(',', array_keys($user_groups)).')'; + echo "<td colspan='3'>".html_print_select_from_sql($sql, 'filter_id', $filter_id, '', __('Select a filter'), 0, true); + html_print_input_hidden('filter_selected', $filter_selected, false); + echo '</td>'; + echo '</tr>'; + + echo "<tr class='filter_normal nf_filter'>"; + if ($netflow_disable_custom_lvfilters) { + echo '<td></td>'; + echo '<td></td>'; + } else { + echo "<td style='font-weight:bold;'>".__('Dst Ip').ui_print_help_tip(__('Destination IP. A comma separated list of destination ip. If we leave the field blank, will show all ip. Example filter by ip:<br>25.46.157.214,160.253.135.249'), true).'</td>'; + echo '<td colspan="2">'.html_print_input_text('ip_dst', $filter['ip_dst'], false, 40, 80, true).'</td>'; + } + + if ($netflow_disable_custom_lvfilters) { + echo '<td></td>'; + echo '<td></td>'; + } else { + echo "<td style='font-weight:bold;'>".__('Src Ip').ui_print_help_tip(__('Source IP. A comma separated list of source ip. If we leave the field blank, will show all ip. Example filter by ip:<br>25.46.157.214,160.253.135.249'), true).'</td>'; + echo '<td colspan="2">'.html_print_input_text('ip_src', $filter['ip_src'], false, 40, 80, true).'</td>'; + } + + echo '</tr>'; + + echo "<tr class='filter_normal nf_filter'>"; + if ($netflow_disable_custom_lvfilters) { + echo '<td></td>'; + echo '<td></td>'; + } else { + echo "<td style='font-weight:bold;'>".__('Dst Port').ui_print_help_tip(__('Destination port. A comma separated list of destination ports. If we leave the field blank, will show all ports. Example filter by ports 80 and 22:<br>80,22'), true).'</td>'; + echo '<td colspan="2">'.html_print_input_text('dst_port', $filter['dst_port'], false, 40, 80, true).'</td>'; + } + + if ($netflow_disable_custom_lvfilters) { + echo '<td></td>'; + echo '<td></td>'; + } else { + echo "<td style='font-weight:bold;'>".__('Src Port').ui_print_help_tip(__('Source port. A comma separated list of source ports. If we leave the field blank, will show all ports. Example filter by ports 80 and 22:<br>80,22'), true).'</td>'; + echo '<td colspan="2">'.html_print_input_text('src_port', $filter['src_port'], false, 40, 80, true).'</td>'; + } + + echo '</tr>'; + + echo "<tr class='filter_advance nf_filter' style='display: none;'>"; + if ($netflow_disable_custom_lvfilters) { + echo '<td></td>'; + echo '<td></td>'; + } else { + echo '<td>'.ui_print_help_icon('pcap_filter', true).'</td>'; + echo "<td colspan='5'>".html_print_textarea('advanced_filter', 4, 40, $filter['advanced_filter'], "style='min-height: 0px; width: 90%;'", true).'</td>'; + } + + echo '</tr>'; + echo '<tr class="nf_filter">'; + $onclick = "if (!confirm('".__('Warning').'. '.__('IP address resolution can take a lot of time')."')) return false;"; $radio_buttons = __('Yes').' '.html_print_radio_button_extended( 'address_resolution', @@ -317,141 +479,11 @@ if (is_metaconsole()) { $address_resolution, true ); - echo '<td>'.'<b>'.__('IP address resolution').'</b>'.ui_print_help_tip(__('Resolve the IP addresses to get their hostnames.'), true).'</td>'; - echo "<td>$radio_buttons</td>"; + echo '<td><b>'.__('IP address resolution').'</b>'.ui_print_help_tip(__('Resolve the IP addresses to get their hostnames.'), true).'</td>'; + echo '<td colspan="2">'.$radio_buttons.'</td>'; - echo '</tr>'; - - // Read filter type - if ($filter['advanced_filter'] != '') { - $filter_type = 1; - } else { - $filter_type = 0; - } - - echo "<tr class='filter_save' style='display: none;'>"; - - echo "<td colspan='6'>".ui_print_error_message('Define a name for the filter and click on Save as new filter again', '', true).'</td>'; - - echo '</tr>'; - echo "<tr class='filter_save' style='display: none;'>"; - - echo '<td>'.'<span id="filter_name_color"><b>'.__('Name').'</b></span>'.'</td>'; - echo "<td colspan='2'>".html_print_input_text( - 'name', - $filter['id_name'], - false, - 20, - 80, - true - ).'</td>'; - $own_info = get_user_info($config['id_user']); - echo '<td>'.'<span id="filter_group_color"><b>'.__('Group').'</b></span>'.'</td>'; - echo "<td colspan='2'>".html_print_select_groups($config['id_user'], 'IW', $own_info['is_admin'], 'assign_group', $filter['id_group'], '', '', -1, true, false, false).'</td>'; - - echo '</tr>'; - echo '<tr>'; - - if ($netflow_disable_custom_lvfilters) { - echo '<td></td>'; - echo '<td></td>'; - } else { - echo '<td>'.'<b>'.__('Filter').'</b>'.'</td>'; - echo '<td>'.__('Normal').' '.html_print_radio_button_extended('filter_type', 0, '', $filter_type, false, 'displayNormalFilter();', 'style="margin-right: 40px;"', true).__('Advanced').' '.html_print_radio_button_extended('filter_type', 1, '', $filter_type, false, 'displayAdvancedFilter();', 'style="margin-right: 40px;"', true).'</td>'; - } - - - - echo '<td>'.'<b>'.__('Load filter').'</b>'.'</td>'; - $user_groups = users_get_groups($config['id_user'], 'AR', $own_info['is_admin'], true); - $user_groups[0] = 0; - // Add all groups. - $sql = 'SELECT * - FROM tnetflow_filter - WHERE id_group IN ('.implode(',', array_keys($user_groups)).')'; - echo "<td colspan='3'>".html_print_select_from_sql($sql, 'filter_id', $filter_id, '', __('Select a filter'), 0, true); - html_print_input_hidden('filter_selected', $filter_selected, false); - echo '</td>'; - echo '</tr>'; - - - - echo "<tr class='filter_normal'>"; - - if ($netflow_disable_custom_lvfilters) { - echo '<td></td>'; - echo '<td></td>'; - } else { - echo "<td style='font-weight:bold;'>".__('Dst Ip').ui_print_help_tip(__('Destination IP. A comma separated list of destination ip. If we leave the field blank, will show all ip. Example filter by ip:<br>25.46.157.214,160.253.135.249'), true).'</td>'; - echo '<td>'.html_print_input_text('ip_dst', $filter['ip_dst'], false, 30, 80, true).'</td>'; - } - - if ($netflow_disable_custom_lvfilters) { - echo '<td></td>'; - echo '<td></td>'; - } else { - echo "<td style='font-weight:bold;'>".__('Src Ip').ui_print_help_tip(__('Source IP. A comma separated list of source ip. If we leave the field blank, will show all ip. Example filter by ip:<br>25.46.157.214,160.253.135.249'), true).'</td>'; - echo '<td>'.html_print_input_text('ip_src', $filter['ip_src'], false, 30, 80, true).'</td>'; - } - - echo '</tr>'; - echo "<tr class='filter_normal'>"; - - if ($netflow_disable_custom_lvfilters) { - echo '<td></td>'; - echo '<td></td>'; - } else { - echo "<td style='font-weight:bold;'>".__('Dst Port').ui_print_help_tip(__('Destination port. A comma separated list of destination ports. If we leave the field blank, will show all ports. Example filter by ports 80 and 22:<br>80,22'), true).'</td>'; - echo '<td>'.html_print_input_text('dst_port', $filter['dst_port'], false, 30, 80, true).'</td>'; - } - - if ($netflow_disable_custom_lvfilters) { - echo '<td></td>'; - echo '<td></td>'; - } else { - echo "<td style='font-weight:bold;'>".__('Src Port').ui_print_help_tip(__('Source port. A comma separated list of source ports. If we leave the field blank, will show all ports. Example filter by ports 80 and 22:<br>80,22'), true).'</td>'; - echo '<td>'.html_print_input_text('src_port', $filter['src_port'], false, 30, 80, true).'</td>'; - } - - echo '</tr>'; - echo "<tr class='filter_advance' style='display: none;'>"; - - if ($netflow_disable_custom_lvfilters) { - echo '<td></td>'; - echo '<td></td>'; - } else { - echo '<td>'.ui_print_help_icon('pcap_filter', true).'</td>'; - echo "<td colspan='5'>".html_print_textarea('advanced_filter', 4, 40, $filter['advanced_filter'], "style='min-height: 0px; width: 90%;'", true).'</td>'; - } - - echo '</tr>'; - echo '<tr>'; - - echo '<td>'.'<b>'.__('Aggregate by').'</b>'.ui_print_help_icon('aggregate_by', true).'</td>'; - $aggregate_list = []; - $aggregate_list = [ - 'none' => __('None'), - 'proto' => __('Protocol'), - 'srcip' => __('Src Ip Address'), - 'dstip' => __('Dst Ip Address'), - 'srcport' => __('Src Port'), - 'dstport' => __('Dst Port'), - ]; - echo '<td>'.html_print_select($aggregate_list, 'aggregate', $filter['aggregate'], '', '', 0, true, false, true, '', false).'</td>'; - - echo '<td>'.'<b>'.__('Router ip').'</b>'.'</td>'; - echo '<td>'.html_print_input_text('router_ip', $filter['router_ip'], false, 30, 80, true).'</td>'; - - echo '<td>'.'<b>'.__('Output format').'</b>'.'</td>'; - $show_output = [ - 'bytes' => __('Bytes'), - 'bytespersecond' => __('Bytes per second'), - 'kilobytes' => __('Kilobytes'), - 'megabytes' => __('Megabytes'), - 'kilobytespersecond' => __('Kilobytes per second'), - 'megabytespersecond' => __('Megabytes per second'), - ]; - echo '<td>'.html_print_select($show_output, 'output', $filter['output'], '', '', 0, true, false, true, '', false).'</td>'; + echo '<td><b>'.__('Source ip').'</b></td>'; + echo '<td colspan="2">'.html_print_input_text('router_ip', $filter['router_ip'], false, 40, 80, true).'</td>'; echo '</tr>'; @@ -473,15 +505,14 @@ if (is_metaconsole()) { echo '</form>'; if ($draw != '') { - // Draw + // Draw. echo '<br/>'; - // No filter selected + // No filter selected. if ($netflow_disable_custom_lvfilters && $filter_selected == 0) { ui_print_error_message(__('No filter selected')); - } - // Draw the netflow chart - else { + } else { + // Draw the netflow chart. echo netflow_draw_item( $start_date, $end_date, @@ -569,7 +600,22 @@ if (is_metaconsole()) { return true; }; - + + function toggleFilters (event) { + // Display or show the items. + var is_advanced = $("#radiobtn0001").is(':checked'); + var class_name = is_advanced ? ".filter_advance" : ".filter_normal"; + $(".nf_filter").not(class_name).toggle(); + + // Change the image. + $('#' + event.target.id).attr( + 'src', + $(".nf_filter").not(class_name).first().is(':visible') + ? 'images/darrowup.png' + : 'images/darrowdown.png' + ); + } + // Display the appropriate filter var filter_type = <?php echo $filter_type; ?>; if (filter_type == 0) { @@ -600,7 +646,6 @@ if (is_metaconsole()) { $("#text-router_ip").val(''); $("#textarea_advanced_filter").val(''); $("#aggregate").val(''); - $("#output").val(''); // Hide update filter button $("#submit-update_button").hide(); @@ -669,8 +714,6 @@ if (is_metaconsole()) { $("#textarea_advanced_filter").val(val); if (i == 'aggregate') $("#aggregate").val(val); - if (i == 'output') - $("#output").val(val); }); }, "json"); @@ -704,7 +747,7 @@ if (is_metaconsole()) { }); }); - $("#text-time").timepicker({ + $("#text-time, #text-time_lower").timepicker({ showSecond: true, timeFormat: '<?php echo TIME_FORMAT_JS; ?>', timeOnlyTitle: '<?php echo __('Choose time'); ?>', @@ -715,7 +758,17 @@ if (is_metaconsole()) { currentText: '<?php echo __('Now'); ?>', closeText: '<?php echo __('Close'); ?>'}); - $("#text-date").datepicker({dateFormat: "<?php echo DATE_FORMAT_JS; ?>"}); + $("#text-date, #text-date_lower").datepicker({dateFormat: "<?php echo DATE_FORMAT_JS; ?>"}); $.datepicker.regional["<?php echo get_user_language(); ?>"]; + + function nf_view_click_period(event) { + $(".nf_display").toggle(); + $(".nf_hidden").toggle(); + } </script> +<style type="text/css"> +.nf_filter, .nf_hidden { + display: none; +} +</style> \ No newline at end of file diff --git a/pandora_console/operation/network/network_explorer.php b/pandora_console/operation/network/network_explorer.php new file mode 100644 index 0000000000..ced3706172 --- /dev/null +++ b/pandora_console/operation/network/network_explorer.php @@ -0,0 +1,40 @@ +<?php +/** + * Network explorer + * + * @package Operations. + * @subpackage Network explorer view. + * + * Pandora FMS - http://pandorafms.com + * ================================================== + * Copyright (c) 2005-2019 Artica Soluciones Tecnologicas + * Please see http://pandorafms.org for full contribution list + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; version 2 + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +global $config; + +check_login(); + +// ACL Check. +if (! check_acl($config['id_user'], 0, 'AR')) { + db_pandora_audit( + 'ACL Violation', + 'Trying to access Network explorer' + ); + include 'general/noaccess.php'; + exit; +} + +$action = get_parameter('action', 'listeners'); +$is_network = true; + +ui_print_page_header(__('Network explorer')); + +require $config['homedir'].'/operation/network/network_report.php'; diff --git a/pandora_console/operation/network/network_report.php b/pandora_console/operation/network/network_report.php new file mode 100644 index 0000000000..c9f3edf408 --- /dev/null +++ b/pandora_console/operation/network/network_report.php @@ -0,0 +1,374 @@ +<?php +/** + * Network explorer + * + * @package Operations. + * @subpackage Network explorer view. + * + * Pandora FMS - http://pandorafms.com + * ================================================== + * Copyright (c) 2005-2019 Artica Soluciones Tecnologicas + * Please see http://pandorafms.org for full contribution list + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; version 2 + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +check_login(); + +// ACL Check. +if (! check_acl($config['id_user'], 0, 'AR')) { + db_pandora_audit( + 'ACL Violation', + 'Trying to access Network report.' + ); + include 'general/noaccess.php'; + exit; +} + +// Include JS timepicker. +ui_include_time_picker(); + +// Query params and other initializations. +$time_greater = get_parameter('time_greater', date(TIME_FORMAT)); +$date_greater = get_parameter('date_greater', date(DATE_FORMAT)); +$utimestamp_greater = strtotime($date_greater.' '.$time_greater); +$is_period = (bool) get_parameter('is_period', false); +$period = (int) get_parameter('period', SECONDS_1HOUR); +$time_lower = get_parameter('time_lower', date(TIME_FORMAT, ($utimestamp_greater - $period))); +$date_lower = get_parameter('date_lower', date(DATE_FORMAT, ($utimestamp_greater - $period))); +$utimestamp_lower = ($is_period) ? ($utimestamp_greater - $period) : strtotime($date_lower.' '.$time_lower); +if (!$is_period) { + $period = ($utimestamp_greater - $utimestamp_lower); +} + +$top = (int) get_parameter('top', 10); +$main_value = ((bool) get_parameter('remove_filter', 0)) ? '' : get_parameter('main_value', ''); +if (is_numeric($main_value) && !in_array($action, ['udp', 'tcp'])) { + $main_value = ''; +} + +$order_by = get_parameter('order_by', 'bytes'); +if (!in_array($order_by, ['bytes', 'pkts', 'flows'])) { + $order_by = 'bytes'; +} + +$style_end = ($is_period) ? 'display: none;' : ''; +$style_period = ($is_period) ? '' : 'display: none;'; + +// Build the table. +$table = new stdClass(); +$table->class = 'databox'; +$table->styleTable = 'width: 100%'; +$table->data['0']['0'] = __('Data to show').' '; +$table->data['0']['0'] .= html_print_select( + network_get_report_actions($is_network), + 'action', + $action, + '', + '', + 0, + true +); + +$table->data['0']['1'] = __('Number of result to show').' '; +$table->data['0']['1'] .= html_print_select( + [ + '5' => 5, + '10' => 10, + '15' => 15, + '20' => 20, + '25' => 25, + '50' => 50, + '100' => 100, + '250' => 250, + ], + 'top', + $top, + '', + '', + 0, + true +); + +$table->data['0']['2'] = ''; + +$table->data['1']['0'] = '<div style="display: flex;">'; +$table->data['1']['0'] .= '<div id="end_date_container" style="'.$style_end.'">'; +$table->data['1']['0'] .= __('Start date').' '; +$table->data['1']['0'] .= html_print_input_text('date_lower', $date_lower, '', 10, 7, true); +$table->data['1']['0'] .= ' '; +$table->data['1']['0'] .= html_print_input_text('time_lower', $time_lower, '', 7, 8, true); +$table->data['1']['0'] .= '</div>'; + +$table->data['1']['0'] .= '<div id="period_container" style="'.$style_period.'">'; +$table->data['1']['0'] .= __('Time Period').' '; +$table->data['1']['0'] .= html_print_extended_select_for_time('period', $period, '', '', 0, false, true); +$table->data['1']['0'] .= '</div>'; +$table->data['1']['0'] .= html_print_checkbox( + 'is_period', + 1, + ($is_period === true) ? 1 : 0, + true, + false, + 'network_report_click_period(event)' +); +$table->data['1']['0'] .= ui_print_help_tip( + __('Select this checkbox to write interval instead a date.'), + true +); +$table->data['1']['0'] .= '</div>'; + +$table->data['1']['1'] = __('End date').' '; +$table->data['1']['1'] .= html_print_input_text('date_greater', $date_greater, '', 10, 7, true); +$table->data['1']['1'] .= ' '; +$table->data['1']['1'] .= html_print_input_text('time_greater', $time_greater, '', 7, 8, true); + +$table->data['1']['2'] = html_print_submit_button( + __('Update'), + 'update', + false, + 'class="sub upd"', + true +); +$table->data['1']['2'] .= ' '; +$table->data['1']['2'] .= html_print_submit_button( + __('Export to CSV'), + 'export_csv', + false, + 'class="sub next"', + true +); + +echo '<form method="post">'; +html_print_input_hidden('order_by', $order_by); +if (!empty($main_value)) { + html_print_input_hidden('main_value', $main_value); +} + +html_print_table($table); +echo '</form>'; + +// Print the data. +$data = []; +if ($is_network) { + $data = network_matrix_get_top( + $top, + $action === 'talkers', + $utimestamp_lower, + $utimestamp_greater, + $main_value, + $order_by !== 'pkts' + ); +} else { + $data = netflow_get_top_summary( + $top, + $action, + $utimestamp_lower, + $utimestamp_greater, + $main_value, + $order_by + ); +} + +// Get the params to return the builder. +$hidden_main_link = [ + 'time_greater' => $time_greater, + 'date_greater' => $date_greater, + 'is_period' => $is_period, + 'period' => $period, + 'time_lower' => $time_lower, + 'date_lower' => $date_lower, + 'top' => $top, + 'action' => $action, +]; + +unset($table); +$table = new stdClass(); +$table->styleTable = 'width: 60%'; +// Print the header. +$table->head = []; +$table->head['main'] = __('IP'); +if (!$is_network) { + $table->head['flows'] = network_print_explorer_header( + __('Flows'), + 'flows', + $order_by, + array_merge( + $hidden_main_link, + ['main_value' => $main_value] + ) + ); +} + +$table->head['pkts'] = network_print_explorer_header( + __('Packets'), + 'pkts', + $order_by, + array_merge( + $hidden_main_link, + ['main_value' => $main_value] + ) +); +$table->head['bytes'] = network_print_explorer_header( + __('Bytes'), + 'bytes', + $order_by, + array_merge( + $hidden_main_link, + ['main_value' => $main_value] + ) +); + +// Add the order. +$hidden_main_link['order_by'] = $order_by; + +if (get_parameter('export_csv')) { + // Clean the buffer. + while (ob_get_level()) { + ob_end_clean(); + } + + // Write metadata. + header('Content-type: text/csv;'); + header('Content-Disposition: attachment; filename="network_data.csv"'); + + $div = $config['csv_divider']; + $nl = "\n"; + + // Print the header. + echo reset($table->head).$div; + if (!$is_network) { + echo __('Flows').$div; + } + + echo __('Packets').$div; + echo __('Bytes').$div; + echo $nl; + + // Print the data. + foreach ($data as $row) { + echo $row['host'].$div; + if (isset($row['sum_flows'])) { + echo $row['sum_flows'].$div; + } + + echo $row['sum_pkts'].$div; + echo $row['sum_bytes'].$nl; + } + + exit; +} + +// Print the filter remove link. +if (!empty($main_value)) { + echo html_print_link_with_params( + in_array($action, ['udp', 'tcp']) ? __('Filtered by port %s. Click here to remove the filter.', $main_value) : __('Filtered by IP %s. Click here to remove the filter.', $main_value), + array_merge( + $hidden_main_link, + [ + 'main_value' => $main_value, + 'remove_filter' => 1, + ] + ) + ); +} + +// Print the data and build the chart. +$table->data = []; +$chart_data = []; +$hide_filter = !empty($main_value) && ($action === 'udp' || $action === 'tcp'); +foreach ($data as $item) { + $row = []; + $row['main'] = '<div class="div-v-centered">'; + $row['main'] .= $item['host']; + if (!$hide_filter) { + $row['main'] .= html_print_link_with_params( + 'images/filter.png', + array_merge($hidden_main_link, ['main_value' => $item['host']]), + 'image' + ); + } + + $row['main'] .= '</div>'; + if (!$is_network) { + $row['flows'] = format_for_graph($item['sum_flows'], 2); + $row['flows'] .= ' ('.$item['pct_flows'].'%)'; + } + + $row['pkts'] = format_for_graph($item['sum_pkts'], 2); + if (!$is_network) { + $row['pkts'] .= ' ('.$item['pct_pkts'].'%)'; + } + + $row['bytes'] = network_format_bytes($item['sum_bytes']); + if (!$is_network) { + $row['bytes'] .= ' ('.$item['pct_bytes'].'%)'; + } + + $table->data[] = $row; + + // Build the pie graph data structure. + switch ($order_by) { + case 'pkts': + $chart_data[$item['host']] = $item['sum_bytes']; + break; + + case 'flows': + $chart_data[$item['host']] = $item['sum_flows']; + break; + + case 'bytes': + default: + $chart_data[$item['host']] = $item['sum_bytes']; + break; + } +} + +if (empty($data)) { + ui_print_info_message(__('No data found')); +} else { + echo '<div style="display: flex; margin-top: 10px;">'; + html_print_table($table); + + // Print the graph. + echo '<div style="margin-top: 50px; width: 40%;">'; + echo pie_graph( + $chart_data, + 320, + 200, + __('Others') + ); + echo '</div>'; + echo '</div>'; +} + +?> +<script> +// Configure jQuery timepickers. +$("#text-time_lower, #text-time_greater").timepicker({ + showSecond: true, + timeFormat: '<?php echo TIME_FORMAT_JS; ?>', + timeOnlyTitle: '<?php echo __('Choose time'); ?>', + timeText: '<?php echo __('Time'); ?>', + hourText: '<?php echo __('Hour'); ?>', + minuteText: '<?php echo __('Minute'); ?>', + secondText: '<?php echo __('Second'); ?>', + currentText: '<?php echo __('Now'); ?>', + closeText: '<?php echo __('Close'); ?>' +}); + +$("#text-date_lower, #text-date_greater").datepicker({dateFormat: "<?php echo DATE_FORMAT_JS; ?>"}); +$.datepicker.setDefaults($.datepicker.regional[ "<?php echo get_user_language(); ?>"]); + +function network_report_click_period(event) { + var is_period = document.getElementById(event.target.id).checked; + + document.getElementById('period_container').style.display = !is_period ? 'none' : 'block'; + document.getElementById('end_date_container').style.display = is_period ? 'none' : 'block'; +} +</script> diff --git a/pandora_console/operation/network/network_usage_map.php b/pandora_console/operation/network/network_usage_map.php new file mode 100644 index 0000000000..046cc1fcc4 --- /dev/null +++ b/pandora_console/operation/network/network_usage_map.php @@ -0,0 +1,236 @@ +<?php + +/** + * Netflow functions + * + * @package Netflow usage map. + * @subpackage UI. + * + * Pandora FMS - http://pandorafms.com + * ================================================== + * Copyright (c) 2005-2019 Artica Soluciones Tecnologicas + * Please see http://pandorafms.org for full contribution list + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; version 2 + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +require_once $config['homedir'].'/include/functions_network.php'; +require_once $config['homedir'].'/include/class/NetworkMap.class.php'; + +global $config; + +check_login(); + +ui_print_page_header(__('Network usage map')); + +// ACL Check. +if (! check_acl($config['id_user'], 0, 'AR')) { + db_pandora_audit( + 'ACL Violation', + 'Trying to access Network usage map.' + ); + include 'general/noaccess.php'; + exit; +} + +// Include JS timepicker. +ui_include_time_picker(); + +// Query params and other initializations. +$action = get_parameter('action', 'talkers'); +$time_greater = get_parameter('time_greater', date(TIME_FORMAT)); +$date_greater = get_parameter('date_greater', date(DATE_FORMAT)); +$utimestamp_greater = strtotime($date_greater.' '.$time_greater); +$is_period = (bool) get_parameter('is_period', false); +$period = (int) get_parameter('period', SECONDS_1HOUR); +$time_lower = get_parameter('time_lower', date(TIME_FORMAT, ($utimestamp_greater - $period))); +$date_lower = get_parameter('date_lower', date(DATE_FORMAT, ($utimestamp_greater - $period))); +$utimestamp_lower = ($is_period) ? ($utimestamp_greater - $period) : strtotime($date_lower.' '.$time_lower); +if (!$is_period) { + $period = ($utimestamp_greater - $utimestamp_lower); +} + +$top = (int) get_parameter('top', 10); + +$order_by = get_parameter('order_by', 'bytes'); +if (!in_array($order_by, ['bytes', 'pkts', 'flows'])) { + $order_by = 'bytes'; +} + +$style_end = ($is_period) ? 'display: none;' : ''; +$style_period = ($is_period) ? '' : 'display: none;'; + +// Build the table. +$table = new stdClass(); +$table->class = 'databox'; +$table->styleTable = 'width: 100%'; + +$table->data['0']['0'] = '<div style="display: flex;">'; +$table->data['0']['0'] .= '<div id="end_date_container" style="'.$style_end.'">'; +$table->data['0']['0'] .= __('Start date').' '; +$table->data['0']['0'] .= html_print_input_text('date_lower', $date_lower, '', 10, 7, true); +$table->data['0']['0'] .= ' '; +$table->data['0']['0'] .= html_print_input_text('time_lower', $time_lower, '', 7, 8, true); +$table->data['0']['0'] .= '</div>'; + +$table->data['0']['0'] .= '<div id="period_container" style="'.$style_period.'">'; +$table->data['0']['0'] .= __('Time Period').' '; +$table->data['0']['0'] .= html_print_extended_select_for_time('period', $period, '', '', 0, false, true); +$table->data['0']['0'] .= '</div>'; +$table->data['0']['0'] .= html_print_checkbox( + 'is_period', + 1, + ($is_period === true) ? 1 : 0, + true, + false, + 'network_report_click_period(event)' +); +$table->data['0']['0'] .= ui_print_help_tip( + __('Select this checkbox to write interval instead a date.'), + true +); +$table->data['0']['0'] .= '</div>'; + +$table->data['0']['1'] = __('End date').' '; +$table->data['0']['1'] .= html_print_input_text('date_greater', $date_greater, '', 10, 7, true); +$table->data['0']['1'] .= ' '; +$table->data['0']['1'] .= html_print_input_text('time_greater', $time_greater, '', 7, 8, true); + +$table->data['0']['2'] = __('Number of result to show').' '; +$table->data['0']['2'] .= html_print_select( + [ + '5' => 5, + '10' => 10, + '15' => 15, + '20' => 20, + '25' => 25, + '50' => 50, + '100' => 100, + '250' => 250, + ], + 'top', + $top, + '', + '', + 0, + true +); + + +$table->data['1']['0'] = __('Data to show').' '; +$table->data['1']['0'] .= html_print_select( + network_get_report_actions(), + 'action', + $action, + '', + '', + 0, + true +); +$table->data['1']['1'] = ''; + +$netflow_button = ''; +if ((bool) $config['activate_netflow'] === true) { + $netflow_button = html_print_submit_button( + __('Show netflow map'), + 'update_netflow', + false, + 'class="sub upd"', + true + ); +} + +$nta_button = ''; +if ((bool) $config['activate_nta'] === true) { + $nta_button = html_print_submit_button( + __('Show NTA map'), + 'update_nta', + false, + 'class="sub upd"', + true + ); +} + +$table->data['1']['2'] .= implode( + ' ', + [ + $netflow_button, + $nta_button, + ] +); + +echo '<form method="post">'; +html_print_input_hidden('order_by', $order_by); + +html_print_table($table); +echo '</form>'; + +$has_data = false; +$first_load = true; +if ((bool) get_parameter('update_netflow') === true) { + $map_data = netflow_build_map_data( + $utimestamp_lower, + $utimestamp_greater, + $top, + ($action === 'talkers') ? 'srcip' : 'dstip' + ); + $has_data = !empty($map_data['nodes']); + $first_load = false; +} else if ((bool) get_parameter('update_nta') === true) { + $map_data = network_build_map_data( + $utimestamp_lower, + $utimestamp_greater, + $top, + $action === 'talkers' + ); + $has_data = !empty($map_data['nodes']); + $first_load = false; +} + +if ($has_data === true) { + $map_manager = new NetworkMap($map_data); + $map_manager->printMap(); +} else if (!$first_load) { + ui_print_info_message(__('No data retrieved')); +} + +?> +<script> +// Configure jQuery timepickers. +$("#text-time_lower, #text-time_greater").timepicker({ + showSecond: true, + timeFormat: '<?php echo TIME_FORMAT_JS; ?>', + timeOnlyTitle: '<?php echo __('Choose time'); ?>', + timeText: '<?php echo __('Time'); ?>', + hourText: '<?php echo __('Hour'); ?>', + minuteText: '<?php echo __('Minute'); ?>', + secondText: '<?php echo __('Second'); ?>', + currentText: '<?php echo __('Now'); ?>', + closeText: '<?php echo __('Close'); ?>' +}); + +$("#text-date_lower, #text-date_greater").datepicker({dateFormat: "<?php echo DATE_FORMAT_JS; ?>"}); +$.datepicker.setDefaults($.datepicker.regional[ "<?php echo get_user_language(); ?>"]); + +function network_report_click_period(event) { + var is_period = document.getElementById(event.target.id).checked; + + document.getElementById('period_container').style.display = !is_period + ? 'none' + : 'block'; + document.getElementById('end_date_container').style.display = is_period + ? 'none' + : 'block'; +} +</script> +<style type="text/css"> + tspan { + font-size: 14px !important; + } +</style> + diff --git a/pandora_console/pandora_console.redhat.spec b/pandora_console/pandora_console.redhat.spec index 332eb72629..8eafad0535 100644 --- a/pandora_console/pandora_console.redhat.spec +++ b/pandora_console/pandora_console.redhat.spec @@ -2,8 +2,8 @@ # Pandora FMS Console # %define name pandorafms_console -%define version 7.0NG.732 -%define release 190327 +%define version 7.0NG.733 +%define release 1 # 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 ba7fe5cea9..dd16641878 100644 --- a/pandora_console/pandora_console.spec +++ b/pandora_console/pandora_console.spec @@ -2,8 +2,8 @@ # Pandora FMS Console # %define name pandorafms_console -%define version 7.0NG.732 -%define release 190327 +%define version 7.0NG.733 +%define release 1 %define httpd_name httpd # User and Group under which Apache is running %define httpd_name apache2 diff --git a/pandora_console/pandora_console_install b/pandora_console/pandora_console_install index 1e11c575bf..d81843bc2f 100644 --- a/pandora_console/pandora_console_install +++ b/pandora_console/pandora_console_install @@ -9,7 +9,7 @@ # This code is licensed under GPL 2.0 license. # ********************************************************************** -PI_VERSION="7.0NG.732" +PI_VERSION="7.0NG.733" FORCE=0 DESTDIR="" LOG_TIMESTAMP=`date +"%Y/%m/%d %H:%M:%S"` diff --git a/pandora_console/pandoradb.sql b/pandora_console/pandoradb.sql index 87a502753b..0ecc9b8f5d 100644 --- a/pandora_console/pandoradb.sql +++ b/pandora_console/pandoradb.sql @@ -3491,6 +3491,20 @@ CREATE TABLE IF NOT EXISTS `tagent_custom_fields_filter` ( PRIMARY KEY(`id`) ) ENGINE = InnoDB DEFAULT CHARSET=utf8; +-- ----------------------------------------------------- +-- Table `tnetwork_matrix` +-- ----------------------------------------------------- +CREATE TABLE IF NOT EXISTS `tnetwork_matrix` ( + `id` int(10) unsigned NOT NULL auto_increment, + `source` varchar(60) default '', + `destination` varchar(60) default '', + `utimestamp` bigint(20) default 0, + `bytes` int(18) unsigned default 0, + `pkts` int(18) unsigned default 0, + PRIMARY KEY (`id`), + UNIQUE (`source`, `destination`, `utimestamp`) +) ENGINE = InnoDB DEFAULT CHARSET=utf8 ; + -- --------------------------------------------------------------------- -- Table `user_task` -- --------------------------------------------------------------------- diff --git a/pandora_server/DEBIAN/control b/pandora_server/DEBIAN/control index 50ea9711ab..1f6a7162fa 100644 --- a/pandora_server/DEBIAN/control +++ b/pandora_server/DEBIAN/control @@ -1,5 +1,5 @@ package: pandorafms-server -Version: 7.0NG.732-190327 +Version: 7.0NG.733 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 469e967975..6ac168b436 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.732-190327" +pandora_version="7.0NG.733" package_cpan=0 package_pandora=1 diff --git a/pandora_server/conf/pandora_server.conf.new b/pandora_server/conf/pandora_server.conf.new index 933613ef82..3dad8a139f 100644 --- a/pandora_server/conf/pandora_server.conf.new +++ b/pandora_server/conf/pandora_server.conf.new @@ -1,7 +1,7 @@ ############################################################################# # Pandora FMS Server Parameters # Pandora FMS, the Flexible Monitoring System. -# Version 7.0NG.732 +# Version 7.0NG.733 # Licensed under GPL license v2, # (c) 2003-2017 Artica Soluciones Tecnologicas # http://www.pandorafms.com diff --git a/pandora_server/lib/PandoraFMS/Config.pm b/pandora_server/lib/PandoraFMS/Config.pm index 2ebdc9068d..fa3e51af4a 100644 --- a/pandora_server/lib/PandoraFMS/Config.pm +++ b/pandora_server/lib/PandoraFMS/Config.pm @@ -44,7 +44,7 @@ our @EXPORT = qw( ); # version: Defines actual version of Pandora Server for this module only -my $pandora_version = "7.0NG.732"; +my $pandora_version = "7.0NG.733"; my $pandora_build = "190327"; our $VERSION = $pandora_version." ".$pandora_build; diff --git a/pandora_server/lib/PandoraFMS/DataServer.pm b/pandora_server/lib/PandoraFMS/DataServer.pm index 43092c0f40..bc66eb2d72 100644 --- a/pandora_server/lib/PandoraFMS/DataServer.pm +++ b/pandora_server/lib/PandoraFMS/DataServer.pm @@ -29,6 +29,8 @@ use XML::Parser::Expat; use XML::Simple; use POSIX qw(setsid strftime); use IO::Uncompress::Unzip; +use JSON qw(decode_json); +use MIME::Base64; # Required for file names with accents use Encode qw(decode); @@ -222,6 +224,10 @@ sub data_consumer ($$) { process_xml_server ($self->getConfig (), $file_name, $xml_data, $self->getDBH ()); } elsif (defined($xml_data->{'connection_source'})) { enterprise_hook('process_xml_connections', [$self->getConfig (), $file_name, $xml_data, $self->getDBH ()]); + } elsif (defined($xml_data->{'network_matrix'})){ + process_xml_matrix_network( + $self->getConfig(), $xml_data, $self->getDBH() + ); } else { process_xml_data ($self->getConfig (), $file_name, $xml_data, $self->getServerID (), $self->getDBH ()); } @@ -326,6 +332,7 @@ sub process_xml_data ($$$$$) { # Get agent id my $agent_id = get_agent_id ($dbh, $agent_name); + my $group_id = 0; if ($agent_id < 1) { if ($pa_config->{'autocreate'} == 0) { logger($pa_config, "ERROR: There is no agent defined with name $agent_name", 3); @@ -334,7 +341,7 @@ sub process_xml_data ($$$$$) { # Get OS, group and description my $os = pandora_get_os ($dbh, $data->{'os_name'}); - my $group_id = $pa_config->{'autocreate_group'}; + $group_id = $pa_config->{'autocreate_group'}; if (! defined (get_group_name ($dbh, $group_id))) { if (defined ($data->{'group_id'}) && $data->{'group_id'} ne '') { $group_id = $data->{'group_id'}; @@ -600,6 +607,9 @@ sub process_xml_data ($$$$$) { # Process snmptrapd modules enterprise_hook('process_snmptrap_data', [$pa_config, $data, $server_id, $dbh]); + # Process events + process_events_dataserver($pa_config, $data, $agent_id, $group_id, $dbh); + # Process disovery modules enterprise_hook('process_discovery_data', [$pa_config, $data, $server_id, $dbh]); } @@ -970,5 +980,84 @@ sub unlink_modules { db_do($dbh, "UPDATE tagente_modulo SET parent_module_id = 0 WHERE id_agente_modulo = ?", $child_id); } +########################################################################## +# Process events in the XML. +########################################################################## +sub process_events_dataserver { + my ($pa_config, $data, $agent_id, $group_id, $dbh) = @_; + + return unless defined($data->{'events'}->[0]->{'event'}); + + foreach my $event (@{$data->{'events'}->[0]->{'event'}}) { + next unless defined($event); + + # Try to decode the base64 inside + my $event_info; + eval { + $event_info = decode_json(decode_base64($event)); + }; + + if ($@) { + logger($pa_config, "Error processing base64 event data '$event'.", 5); + next; + } + next unless defined($event_info->{'data'}); + + pandora_event( + $pa_config, + $event_info->{'data'}, + $group_id, + $agent_id, + defined($event_info->{'severity'}) ? $event_info->{'severity'} : 0, + 0, + 0, + 'system', + 0, + $dbh + ); + } + + return; +} + + +########################################################################## +# Process events in the XML. +########################################################################## +sub process_xml_matrix_network { + my ($pa_config, $data, $dbh) = @_; + + my $utimestamp = $data->{'network_matrix'}->[0]->{'utimestamp'}; + my $content = $data->{'network_matrix'}->[0]->{'content'}; + return unless defined($utimestamp) && defined($content); + + # Try to decode the base64 inside + my $matrix_info; + eval { + $matrix_info = decode_json(decode_base64($content)); + }; + + if ($@) { + logger($pa_config, "Error processing base64 matrix data '$content'.", 5); + return; + } + foreach my $source (keys %$matrix_info) { + foreach my $destination (keys %{$matrix_info->{$source}}) { + my $matrix_single_data = $matrix_info->{$source}->{$destination}; + $matrix_single_data->{'source'} = $source; + $matrix_single_data->{'destination'} = $destination; + $matrix_single_data->{'utimestamp'} = $utimestamp; + eval { + db_process_insert($dbh, 'id', 'tnetwork_matrix', $matrix_single_data); + }; + if ($@) { + logger($pa_config, "Error inserted matrix data. Source: $source, destination: $destination, utimestamp: $utimestamp.", 5); + } + } + } + + return; +} + 1; __END__ diff --git a/pandora_server/lib/PandoraFMS/PluginTools.pm b/pandora_server/lib/PandoraFMS/PluginTools.pm index 2101c3e895..f7c883ad75 100644 --- a/pandora_server/lib/PandoraFMS/PluginTools.pm +++ b/pandora_server/lib/PandoraFMS/PluginTools.pm @@ -31,7 +31,7 @@ use base 'Exporter'; our @ISA = qw(Exporter); # version: Defines actual version of Pandora Server for this module only -my $pandora_version = "7.0NG.732"; +my $pandora_version = "7.0NG.733"; my $pandora_build = "190327"; our $VERSION = $pandora_version." ".$pandora_build; diff --git a/pandora_server/pandora_server.redhat.spec b/pandora_server/pandora_server.redhat.spec index ac50fb7e4e..a99d2963a4 100644 --- a/pandora_server/pandora_server.redhat.spec +++ b/pandora_server/pandora_server.redhat.spec @@ -2,8 +2,8 @@ # Pandora FMS Server # %define name pandorafms_server -%define version 7.0NG.732 -%define release 190327 +%define version 7.0NG.733 +%define release 1 Summary: Pandora FMS Server Name: %{name} diff --git a/pandora_server/pandora_server.spec b/pandora_server/pandora_server.spec index ebe2f3afb5..ae7863c306 100644 --- a/pandora_server/pandora_server.spec +++ b/pandora_server/pandora_server.spec @@ -2,8 +2,8 @@ # Pandora FMS Server # %define name pandorafms_server -%define version 7.0NG.732 -%define release 190327 +%define version 7.0NG.733 +%define release 1 Summary: Pandora FMS Server Name: %{name} diff --git a/pandora_server/pandora_server_installer b/pandora_server/pandora_server_installer index e38650eeb3..151f0da31c 100755 --- a/pandora_server/pandora_server_installer +++ b/pandora_server/pandora_server_installer @@ -8,7 +8,7 @@ # This code is licensed under GPL 2.0 license. # ********************************************************************** -PI_VERSION="7.0NG.732" +PI_VERSION="7.0NG.733" PI_BUILD="190327" MODE=$1 diff --git a/pandora_server/util/pandora_db.pl b/pandora_server/util/pandora_db.pl index 9a1058b755..c08dd06bab 100644 --- a/pandora_server/util/pandora_db.pl +++ b/pandora_server/util/pandora_db.pl @@ -34,7 +34,7 @@ use PandoraFMS::Config; use PandoraFMS::DB; # version: define current version -my $version = "7.0NG.732 PS190327"; +my $version = "7.0NG.733 PS190327"; # Pandora server configuration my %conf; @@ -340,7 +340,7 @@ sub pandora_purgedb ($$) { } else { my @blacklist_types = ("'SLA_services'", "'custom_graph'", "'sql_graph_vbar'", "'sql_graph_hbar'", "'sql_graph_pie'", "'database_serialized'", "'sql'", "'inventory'", "'inventory_changes'", - "'netflow_area'", "'netflow_pie'", "'netflow_data'", "'netflow_statistics'", "'netflow_summary'"); + "'netflow_area'", "'netflow_data'", "'netflow_summary'"); my $blacklist_types_str = join(',', @blacklist_types); # Deleted modules @@ -429,10 +429,17 @@ sub pandora_purgedb ($$) { WHERE date < CURDATE() - $conf->{'_num_past_special_days'} AND date > '0001-01-01'"); } } - + # Delete old tgraph_source data db_do ($dbh,"DELETE FROM tgraph_source WHERE id_graph NOT IN (SELECT id_graph FROM tgraph)"); + # Delete network traffic old data. + log_message ('PURGE', 'Deleting old network matrix data.'); + if ($conf->{'_delete_old_network_matrix'} > 0) { + my $matrix_limit = time() - 86400 * $conf->{'_delete_old_network_matrix'}; + db_do ($dbh, "DELETE FROM tnetwork_matrix WHERE utimestamp < ?", $matrix_limit); + } + # Delete old messages log_message ('PURGE', "Deleting old messages."); if ($conf->{'_delete_old_messages'} > 0) { @@ -659,6 +666,7 @@ sub pandora_load_config_pdb ($) { $conf->{'_days_delete_unknown'} = get_db_value ($dbh, "SELECT value FROM tconfig WHERE token = 'days_delete_unknown'"); $conf->{'_inventory_purge'} = get_db_value ($dbh, "SELECT value FROM tconfig WHERE token = 'inventory_purge'"); $conf->{'_delete_old_messages'} = get_db_value ($dbh, "SELECT value FROM tconfig WHERE token = 'delete_old_messages'"); + $conf->{'_delete_old_network_matrix'} = get_db_value ($dbh, "SELECT value FROM tconfig WHERE token = 'delete_old_network_matrix'"); $conf->{'_enterprise_installed'} = get_db_value ($dbh, "SELECT value FROM tconfig WHERE token = 'enterprise_installed'"); $conf->{'_metaconsole'} = get_db_value ($dbh, "SELECT value FROM tconfig WHERE token = 'metaconsole'"); $conf->{'_metaconsole_events_history'} = get_db_value ($dbh, "SELECT value FROM tconfig WHERE token = 'metaconsole_events_history'"); diff --git a/pandora_server/util/pandora_manage.pl b/pandora_server/util/pandora_manage.pl index 59ea5d85b0..5a2154aed2 100644 --- 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.732 PS190327"; +my $version = "7.0NG.733 PS190327"; # save program name for logging my $progname = basename($0);