diff --git a/include/NetworkInterface.h b/include/NetworkInterface.h index 5fab612b03..8b8ad39e66 100644 --- a/include/NetworkInterface.h +++ b/include/NetworkInterface.h @@ -699,9 +699,9 @@ class NetworkInterface : public AlertableEntity { void checkReloadHostsBroadcastDomain(); inline bool reloadHostsBroadcastDomain() { return reload_hosts_bcast_domain; } void reloadHostsBlacklist(); - void checkHostsAlerts(ScriptPeriodicity p, lua_State* vm); - void checkNetworksAlerts(ScriptPeriodicity p, lua_State* vm); - void checkInterfaceAlerts(ScriptPeriodicity p, lua_State* vm); + void checkHostsAlerts(vector *p, lua_State* vm); + void checkNetworksAlerts(vector *p, lua_State* vm); + void checkInterfaceAlerts(vector *p, lua_State* vm); bool isHiddenFromTop(Host *host); virtual bool areTrafficDirectionsSupported() { return(false); }; diff --git a/include/PeriodicActivities.h b/include/PeriodicActivities.h index c0f45f9d69..58c104bb41 100644 --- a/include/PeriodicActivities.h +++ b/include/PeriodicActivities.h @@ -28,7 +28,7 @@ class PeriodicActivities { private: ThreadedActivity *activities[CONST_MAX_NUM_THREADED_ACTIVITIES]; u_int16_t num_activities; - ThreadPool *high_priority_pool, *standard_priority_pool, *timeseries_pool, + ThreadPool *high_priority_pool, *standard_priority_pool, *timeseries_pool, *periodic_user_scripts_pool, *no_priority_pool, *longrun_priority_pool, *discover_pool, *housekeeping_pool; public: diff --git a/include/ntop_defines.h b/include/ntop_defines.h index b7afad0b49..af406016e7 100644 --- a/include/ntop_defines.h +++ b/include/ntop_defines.h @@ -882,6 +882,7 @@ #define MINUTE_SCRIPT_PATH "minute.lua" #define HT_STATE_UPDATE_SCRIPT_PATH "ht_state_update.lua" #define STATS_UPDATE_SCRIPT_PATH "stats_update.lua" +#define PERIODIC_USER_SCRIPTS_PATH "periodic_user_scripts.lua" #define THIRTY_SECONDS_SCRIPT_PATH "30sec.lua" #define FIVE_MINUTES_SCRIPT_PATH "5min.lua" #define HOURLY_SCRIPT_PATH "hourly.lua" diff --git a/scripts/lua/modules/user_scripts.lua b/scripts/lua/modules/user_scripts.lua index f0a7d64421..6de23dc202 100644 --- a/scripts/lua/modules/user_scripts.lua +++ b/scripts/lua/modules/user_scripts.lua @@ -9,9 +9,11 @@ local dirs = ntop.getDirs() package.path = dirs.installdir .. "/scripts/lua/modules/pools/?.lua;" .. package.path +require "lua_utils" local os_utils = require("os_utils") local json = require("dkjson") local plugins_utils = require("plugins_utils") +local alert_consts = require "alert_consts" local info = ntop.getInfo() @@ -32,6 +34,7 @@ user_scripts.field_units = { syn_min = "field_units.syn_min", } +local REQUEST_PERIODIC_USER_SCRIPTS_RUN_KEY = "ntopng.cache.ifid_%i.user_scripts.request.granularity_%s" local NON_TRAFFIC_ELEMENT_CONF_KEY = "all" local NON_TRAFFIC_ELEMENT_ENTITY = "no_entity" local ALL_HOOKS_CONFIG_KEY = "all" @@ -682,25 +685,30 @@ end -- ############################################## +function user_scripts.runScripts() + local requested = {} + for granularity, _ in pairs(alert_consts.alerts_granularities) do + local k = string.format(REQUEST_PERIODIC_USER_SCRIPTS_RUN_KEY, interface.getId(), granularity) + + if ntop.getCache(k) == "1" then + requested[granularity] = true + ntop.delCache(k) + end + end + + if table.len(requested) > 0 then + interface.checkInterfaceAlerts(requested["min"], requested["5mins"], requested["hour"], requested["day"]) + interface.checkNetworksAlerts(requested["min"], requested["5mins"], requested["hour"], requested["day"]) + interface.checkHostsAlerts(requested["min"], requested["5mins"], requested["hour"], requested["day"]) + end +end + +-- ############################################## + function user_scripts.runPeriodicScripts(granularity) - if(granularity == "min") then - interface.checkInterfaceAlertsMin() - interface.checkHostsAlertsMin() - interface.checkNetworksAlertsMin() - elseif(granularity == "5mins") then - interface.checkInterfaceAlerts5Min() - interface.checkHostsAlerts5Min() - interface.checkNetworksAlerts5Min() - elseif(granularity == "hour") then - interface.checkInterfaceAlertsHour() - interface.checkHostsAlertsHour() - interface.checkNetworksAlertsHour() - elseif(granularity == "day") then - interface.checkInterfaceAlertsDay() - interface.checkHostsAlertsDay() - interface.checkNetworksAlertsDay() - else - traceError(TRACE_ERROR, TRACE_CONSOLE, "Unknown granularity " .. granularity) + if alert_consts.alerts_granularities[granularity] then + local k = string.format(REQUEST_PERIODIC_USER_SCRIPTS_RUN_KEY, interface.getId(), granularity) + ntop.setCache(k, "1") end end diff --git a/src/LuaEngineInterface.cpp.inc b/src/LuaEngineInterface.cpp.inc index 7ca3007dc4..66df64c613 100644 --- a/src/LuaEngineInterface.cpp.inc +++ b/src/LuaEngineInterface.cpp.inc @@ -2271,61 +2271,70 @@ static int ntop_zmq_receive(lua_State* vm) { /* ****************************************** */ -static int ntop_check_hosts_alerts(lua_State* vm, ScriptPeriodicity p) { +static int ntop_check_hosts_alerts(lua_State* vm) { NetworkInterface *ntop_interface = getCurrentInterface(vm); + std::vector periodicities; - if(!ntop_interface) + if(!ntop_interface) { + lua_pushnil(vm); return(CONST_LUA_ERROR); - else - ntop_interface->checkHostsAlerts(p, vm); + } + + if(lua_type(vm, 1) == LUA_TBOOLEAN && lua_toboolean(vm, 1) == true) periodicities.push_back(minute_script); + if(lua_type(vm, 2) == LUA_TBOOLEAN && lua_toboolean(vm, 2) == true) periodicities.push_back(five_minute_script); + if(lua_type(vm, 3) == LUA_TBOOLEAN && lua_toboolean(vm, 3) == true) periodicities.push_back(hour_script); + if(lua_type(vm, 4) == LUA_TBOOLEAN && lua_toboolean(vm, 4) == true) periodicities.push_back(day_script); + + ntop_interface->checkHostsAlerts(&periodicities, vm); lua_pushnil(vm); return(CONST_LUA_OK); } -static int ntop_check_hosts_alerts_min(lua_State* vm) { return(ntop_check_hosts_alerts(vm, minute_script)); } -static int ntop_check_hosts_alerts_5min(lua_State* vm) { return(ntop_check_hosts_alerts(vm, five_minute_script)); } -static int ntop_check_hosts_alerts_hour(lua_State* vm) { return(ntop_check_hosts_alerts(vm, hour_script)); } -static int ntop_check_hosts_alerts_day(lua_State* vm) { return(ntop_check_hosts_alerts(vm, day_script)); } - /* ****************************************** */ -static int ntop_check_networks_alerts(lua_State* vm, ScriptPeriodicity p) { +static int ntop_check_networks_alerts(lua_State* vm) { NetworkInterface *ntop_interface = getCurrentInterface(vm); + std::vector periodicities; - if(!ntop_interface) + if(!ntop_interface) { + lua_pushnil(vm); return(CONST_LUA_ERROR); - else - ntop_interface->checkNetworksAlerts(p, vm); + } + + if(lua_type(vm, 1) == LUA_TBOOLEAN && lua_toboolean(vm, 1) == true) periodicities.push_back(minute_script); + if(lua_type(vm, 2) == LUA_TBOOLEAN && lua_toboolean(vm, 2) == true) periodicities.push_back(five_minute_script); + if(lua_type(vm, 3) == LUA_TBOOLEAN && lua_toboolean(vm, 3) == true) periodicities.push_back(hour_script); + if(lua_type(vm, 4) == LUA_TBOOLEAN && lua_toboolean(vm, 4) == true) periodicities.push_back(day_script); + + ntop_interface->checkNetworksAlerts(&periodicities, vm); lua_pushnil(vm); return(CONST_LUA_OK); } -static int ntop_check_networks_alerts_min(lua_State* vm) { return(ntop_check_networks_alerts(vm, minute_script)); } -static int ntop_check_networks_alerts_5min(lua_State* vm) { return(ntop_check_networks_alerts(vm, five_minute_script)); } -static int ntop_check_networks_alerts_hour(lua_State* vm) { return(ntop_check_networks_alerts(vm, hour_script)); } -static int ntop_check_networks_alerts_day(lua_State* vm) { return(ntop_check_networks_alerts(vm, day_script)); } - /* ****************************************** */ -static int ntop_check_interface_alerts(lua_State* vm, ScriptPeriodicity p) { +static int ntop_check_interface_alerts(lua_State* vm) { NetworkInterface *ntop_interface = getCurrentInterface(vm); + std::vector periodicities; - if(!ntop_interface) + if(!ntop_interface) { + lua_pushnil(vm); return(CONST_LUA_ERROR); - else - ntop_interface->checkInterfaceAlerts(p, vm); + } + + if(lua_type(vm, 1) == LUA_TBOOLEAN && lua_toboolean(vm, 1) == true) periodicities.push_back(minute_script); + if(lua_type(vm, 2) == LUA_TBOOLEAN && lua_toboolean(vm, 2) == true) periodicities.push_back(five_minute_script); + if(lua_type(vm, 3) == LUA_TBOOLEAN && lua_toboolean(vm, 3) == true) periodicities.push_back(hour_script); + if(lua_type(vm, 4) == LUA_TBOOLEAN && lua_toboolean(vm, 4) == true) periodicities.push_back(day_script); + + ntop_interface->checkInterfaceAlerts(&periodicities, vm); lua_pushnil(vm); return(CONST_LUA_OK); } -static int ntop_check_interface_alerts_min(lua_State* vm) { return(ntop_check_interface_alerts(vm, minute_script)); } -static int ntop_check_interface_alerts_5min(lua_State* vm) { return(ntop_check_interface_alerts(vm, five_minute_script)); } -static int ntop_check_interface_alerts_hour(lua_State* vm) { return(ntop_check_interface_alerts(vm, hour_script)); } -static int ntop_check_interface_alerts_day(lua_State* vm) { return(ntop_check_interface_alerts(vm, day_script)); } - /* ****************************************** */ static int ntop_get_interface_flows_info(lua_State* vm) { @@ -4638,22 +4647,13 @@ static const luaL_Reg ntop_interface_reg[] = { { "incTotalHostAlerts", ntop_interface_inc_total_host_alerts }, /* Interface Alerts */ - { "checkInterfaceAlertsMin", ntop_check_interface_alerts_min }, - { "checkInterfaceAlerts5Min", ntop_check_interface_alerts_5min }, - { "checkInterfaceAlertsHour", ntop_check_interface_alerts_hour }, - { "checkInterfaceAlertsDay", ntop_check_interface_alerts_day }, + { "checkInterfaceAlerts", ntop_check_interface_alerts }, /* Host Alerts */ - { "checkHostsAlertsMin", ntop_check_hosts_alerts_min }, - { "checkHostsAlerts5Min", ntop_check_hosts_alerts_5min }, - { "checkHostsAlertsHour", ntop_check_hosts_alerts_hour }, - { "checkHostsAlertsDay", ntop_check_hosts_alerts_day }, + { "checkHostsAlerts", ntop_check_hosts_alerts }, /* Network Alerts */ - { "checkNetworksAlertsMin", ntop_check_networks_alerts_min }, - { "checkNetworksAlerts5Min", ntop_check_networks_alerts_5min }, - { "checkNetworksAlertsHour", ntop_check_networks_alerts_hour }, - { "checkNetworksAlertsDay", ntop_check_networks_alerts_day }, + { "checkNetworksAlerts", ntop_check_networks_alerts }, /* eBPF, Containers and Companion Interfaces */ { "getPodsStats", ntop_interface_get_pods_stats }, diff --git a/src/NetworkInterface.cpp b/src/NetworkInterface.cpp index 1f40b432f8..22c7ca1da1 100644 --- a/src/NetworkInterface.cpp +++ b/src/NetworkInterface.cpp @@ -7158,13 +7158,15 @@ static void handle_entity_alerts(AlertCheckLuaEngine *acle, AlertableEntity *ent /* *************************************** */ static bool host_alert_check(GenericHashEntry *h, void *user_data, bool *matched) { - AlertCheckLuaEngine *acle = (AlertCheckLuaEngine*)user_data; + vector *acles = static_cast*>(user_data); Host *host = (Host*)h; - acle->setHost(host); - handle_entity_alerts(acle, host); + for(vector::const_iterator acle = acles->begin(); acle != acles->end(); ++acle) { + (*acle)->setHost(host); + handle_entity_alerts(*acle, host); - host->housekeepAlerts(acle->getPeriodicity() /* periodicity */); + host->housekeepAlerts((*acle)->getPeriodicity() /* periodicity */); + } /* Stop as soon as a shutdown is in progress or the process could hang for too long. */ @@ -7173,38 +7175,68 @@ static bool host_alert_check(GenericHashEntry *h, void *user_data, bool *matched /* *************************************** */ -void NetworkInterface::checkHostsAlerts(ScriptPeriodicity p, lua_State* vm) { +void NetworkInterface::checkHostsAlerts(vector *p, lua_State* vm) { u_int32_t begin_slot = 0; - AlertCheckLuaEngine acle(alert_entity_host, p, this, vm); + vectoracles; + + if(!p || p->size() == 0) + return; + + for(vector::const_iterator it = p->begin(); it != p->end(); ++it) { + AlertCheckLuaEngine *acle = new (nothrow) AlertCheckLuaEngine(alert_entity_host, *it, this, vm); + + if(acle) + acles.push_back(acle); + } /* ... then iterate all hosts */ - walker(&begin_slot, true /* walk_all */, walker_hosts, host_alert_check, &acle); + walker(&begin_slot, true /* walk_all */, walker_hosts, host_alert_check, &acles); + + for(vector::const_iterator it = acles.begin(); it != acles.end(); ++it) + delete *it; } /* *************************************** */ -void NetworkInterface::checkNetworksAlerts(ScriptPeriodicity p, lua_State* vm) { - AlertCheckLuaEngine acle(alert_entity_network, p, this, vm); - - /* ... then iterate all networks */ +void NetworkInterface::checkNetworksAlerts(vector *p, lua_State* vm) { u_int8_t num_local_networks = ntop->getNumLocalNetworks(); - for(u_int8_t network_id = 0; network_id < num_local_networks; network_id++) { - NetworkStats *netstats = getNetworkStats(network_id); + if(!p || p->size() == 0) + return; - acle.setNetwork(netstats); - handle_entity_alerts(&acle, netstats); + for(vector::const_iterator it = p->begin(); it != p->end(); ++it) { + AlertCheckLuaEngine *acle = new (nothrow) AlertCheckLuaEngine(alert_entity_network, *it, this, vm); - netstats->housekeepAlerts(p); + if(acle) { + /* ... then iterate all networks */ + for(u_int8_t network_id = 0; network_id < num_local_networks; network_id++) { + NetworkStats *netstats = getNetworkStats(network_id); + + acle->setNetwork(netstats); + handle_entity_alerts(acle, netstats); + + netstats->housekeepAlerts(acle->getPeriodicity()); + } + + delete acle; + } } } /* *************************************** */ -void NetworkInterface::checkInterfaceAlerts(ScriptPeriodicity p, lua_State* vm) { - AlertCheckLuaEngine acle(alert_entity_interface, p, this, vm); +void NetworkInterface::checkInterfaceAlerts(vector *p, lua_State* vm) { + if(!p || p->size() == 0) + return; - handle_entity_alerts(&acle, this); + for(vector::const_iterator it = p->begin(); it != p->end(); ++it) { + AlertCheckLuaEngine *acle = new (nothrow) AlertCheckLuaEngine(alert_entity_interface, *it, this, vm); + + if(acle) { + handle_entity_alerts(acle, this); + delete acle; + } + } } /* *************************************** */ diff --git a/src/PeriodicActivities.cpp b/src/PeriodicActivities.cpp index 6b05a1a850..e2c5dc9ae9 100644 --- a/src/PeriodicActivities.cpp +++ b/src/PeriodicActivities.cpp @@ -39,7 +39,7 @@ PeriodicActivities::PeriodicActivities() { activities[i] = NULL; high_priority_pool = standard_priority_pool = no_priority_pool = longrun_priority_pool - = timeseries_pool = discover_pool = housekeeping_pool = NULL; + = timeseries_pool = periodic_user_scripts_pool = discover_pool = housekeeping_pool = NULL; num_activities = 0; } @@ -57,13 +57,14 @@ PeriodicActivities::~PeriodicActivities() { } /* This will terminate any possibly running activities into the ThreadPool::run */ - if(high_priority_pool) delete high_priority_pool; - if(standard_priority_pool) delete standard_priority_pool; - if(longrun_priority_pool) delete longrun_priority_pool; - if(timeseries_pool) delete timeseries_pool; - if(discover_pool) delete discover_pool; - if(housekeeping_pool) delete housekeeping_pool; - if(no_priority_pool) delete no_priority_pool; + if(high_priority_pool) delete high_priority_pool; + if(standard_priority_pool) delete standard_priority_pool; + if(longrun_priority_pool) delete longrun_priority_pool; + if(timeseries_pool) delete timeseries_pool; + if(periodic_user_scripts_pool) delete periodic_user_scripts_pool; + if(discover_pool) delete discover_pool; + if(housekeeping_pool) delete housekeeping_pool; + if(no_priority_pool) delete no_priority_pool; /* Now it's safe to delete the activities as no other thread is executing * their code. */ @@ -129,37 +130,39 @@ void PeriodicActivities::startPeriodicActivitiesLoop() { if(num_threads_no_priority > MAX_THREAD_POOL_SIZE) num_threads_no_priority = MAX_THREAD_POOL_SIZE; - high_priority_pool = new ThreadPool(true, num_threads); - standard_priority_pool = new ThreadPool(false, num_threads); - longrun_priority_pool = new ThreadPool(false, num_threads); - timeseries_pool = new ThreadPool(false, 1); - discover_pool = new ThreadPool(false, 1); - housekeeping_pool = new ThreadPool(false, 1); - no_priority_pool = new ThreadPool(false, num_threads_no_priority); + high_priority_pool = new ThreadPool(true, num_threads); + standard_priority_pool = new ThreadPool(false, num_threads); + longrun_priority_pool = new ThreadPool(false, num_threads); + timeseries_pool = new ThreadPool(false, 1); + periodic_user_scripts_pool = new ThreadPool(false, 2); + discover_pool = new ThreadPool(false, 1); + housekeeping_pool = new ThreadPool(false, 1); + no_priority_pool = new ThreadPool(false, num_threads_no_priority); static activity_descr ad[] = { - // Script Periodicity (s) Max (s) Pool Align !View !PCAP Reuse - { HT_STATE_UPDATE_SCRIPT_PATH, 5, 10, high_priority_pool, false, true, false, true }, + // Script Periodicity (s) Max (s) Pool Align !View !PCAP Reuse + { HT_STATE_UPDATE_SCRIPT_PATH, 5, 10, high_priority_pool, false, true, false, true }, - { SECOND_SCRIPT_PATH, 1, 2, standard_priority_pool, false, false, true, true }, - { STATS_UPDATE_SCRIPT_PATH, 5, 10, standard_priority_pool, false, false, true, true }, + { SECOND_SCRIPT_PATH, 1, 2, standard_priority_pool, false, false, true, true }, + { STATS_UPDATE_SCRIPT_PATH, 5, 10, standard_priority_pool, false, false, true, true }, + { PERIODIC_USER_SCRIPTS_PATH, 5, 60, periodic_user_scripts_pool, false, false, true, true }, - { HOUSEKEEPING_SCRIPT_PATH, 3, 6, housekeeping_pool, false, false, false, true }, + { HOUSEKEEPING_SCRIPT_PATH, 3, 6, housekeeping_pool, false, false, false, true }, - { MINUTE_SCRIPT_PATH, 60, 60, no_priority_pool, false, false, true, false }, - { DAILY_SCRIPT_PATH, 86400, 3600, no_priority_pool, true, false, true, false }, + { MINUTE_SCRIPT_PATH, 60, 60, no_priority_pool, false, false, true, false }, + { DAILY_SCRIPT_PATH, 86400, 3600, no_priority_pool, true, false, true, false }, #ifdef HAVE_NEDGE - { PINGER_SCRIPT_PATH, 5, 5, no_priority_pool, false, false, true, false }, + { PINGER_SCRIPT_PATH, 5, 5, no_priority_pool, false, false, true, false }, #endif - { TIMESERIES_SCRIPT_PATH, 1, 3600, timeseries_pool, false, false, true, true }, + { TIMESERIES_SCRIPT_PATH, 1, 3600, timeseries_pool, false, false, true, true }, - { FIVE_MINUTES_SCRIPT_PATH, 300, 300, longrun_priority_pool, false, false, true, false }, - { HOURLY_SCRIPT_PATH, 3600, 600, longrun_priority_pool, false, false, true, false }, + { FIVE_MINUTES_SCRIPT_PATH, 300, 300, longrun_priority_pool, false, false, true, false }, + { HOURLY_SCRIPT_PATH, 3600, 600, longrun_priority_pool, false, false, true, false }, - { DISCOVER_SCRIPT_PATH, 5, 3600, discover_pool, false, false, true, true }, + { DISCOVER_SCRIPT_PATH, 5, 3600, discover_pool, false, false, true, true }, - { NULL, 0, 0, NULL, false, false, false, false } + { NULL, 0, 0, NULL, false, false, false, false } }; ntop->getTrace()->traceEvent(TRACE_NORMAL, "Each periodic activity script will use %u threads", num_threads);