/* * * (C) 2019 - ntop.org * * * 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; either version 3 of the License, or * (at your option) any later version. * * 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. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software Foundation, * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * */ #include "ntop_includes.h" /* ****************************************** */ AlertCheckLuaEngine::AlertCheckLuaEngine(AlertEntity alert_entity, ScriptPeriodicity script_periodicity, NetworkInterface *_iface, lua_State *vm) : LuaEngine(vm) { const char *lua_file = NULL; iface = _iface; tps = Utils::gettickspersec(); script_ok = false; reset_stats(); p = script_periodicity; switch(alert_entity) { case alert_entity_network: lua_file = "network.lua"; break; case alert_entity_interface: lua_file = "interface.lua"; break; case alert_entity_snmp_device: lua_file = "snmp_device.lua"; break; case alert_entity_system: lua_file = "system.lua"; break; case alert_entity_flow: ntop->getTrace()->traceEvent(TRACE_ERROR, "Unexpected entity 'flow'"); break; case alert_entity_host: ntop->getTrace()->traceEvent(TRACE_ERROR, "Unexpected entity 'host'"); break; default: /* Example: lua_file = "generic.lua" to handle a generic entity */ break; } if(lua_file) { snprintf(script_path, sizeof(script_path), "%s/callbacks/%s/%s", ntop->getPrefs()->get_scripts_dir(), iface ? "interface" : "system", lua_file); ntop->fixPath(script_path); if(load_script(script_path, iface) < 0) return; /* Execute the script so that the "setup" function will be exposed */ if(lua_pcall(L, 0, 0, 0)) { ntop->getTrace()->traceEvent(TRACE_WARNING, "Script failure[%s] [%s]", script_path, lua_tostring(L, -1)); return; } lua_getglobal(L, "setup"); /* Called function */ lua_pushstring(L, Utils::periodicityToScriptName(p)); /* push 1st argument */ if(lua_pcall(L, 1 /* 1 argument */, 0, 0)) { ntop->getTrace()->traceEvent(TRACE_WARNING, "Script failure[%s] [%s]", script_path, lua_tostring(L, -1)); return; } script_ok = true; } else { /* Possibly handle a generic entity */ script_path[0] = '\0'; } } /* ****************************************** */ AlertCheckLuaEngine::~AlertCheckLuaEngine() { #if 0 float elapsed_time = (float)total_ticks / tps; ntop->getTrace()->traceEvent(TRACE_WARNING, "[elapsed time: %.4f sec][num calls: %u][calls/sec: %.4f][%s][clocks/sec: %llu]", elapsed_time, num_calls, num_calls / elapsed_time, script_path, tps); #endif if(script_ok) { lua_getglobal(L, "teardown"); /* Called function */ if(lua_isfunction(L, -1)) { lua_pushstring(L, Utils::periodicityToScriptName(p)); /* push 1st argument */ pcall(1 /* 1 argument */, 0); } } } /* ****************************************** */ void AlertCheckLuaEngine::reset_stats() { num_calls = 0; total_ticks = 0; } /* ****************************************** */ void AlertCheckLuaEngine::lua_stats(const char *key, lua_State *vm) { if(vm) { lua_newtable(vm); lua_newtable(vm); float elapsed_time = (float)total_ticks / tps; lua_push_uint64_table_entry(vm, "num_calls", (u_int64_t)num_calls); lua_push_float_table_entry(vm, "tot_duration_ms", elapsed_time * 1000); lua_stats_detail(vm); lua_pushstring(vm, "stats"); lua_insert(vm, -2); lua_settable(vm, -3); lua_pushstring(vm, key); lua_insert(vm, -2); lua_settable(vm, -3); } } /* ****************************************** */ ScriptPeriodicity AlertCheckLuaEngine::getPeriodicity() const { return p; } /* ****************************************** */ const char * AlertCheckLuaEngine::getGranularity() const { return Utils::periodicityToScriptName(p); } /* ****************************************** */ bool AlertCheckLuaEngine::pcall(int num_args, int num_results) { ticks t_begin; if(!script_ok) { /* Remove possibly pushed values on the lua stack to avoid overflow */ lua_settop(L, 0); return(false); } t_begin = Utils::getticks(); if(lua_pcall(L, num_args, num_results, 0)) { ntop->getTrace()->traceEvent(TRACE_WARNING, "Script failure[%s] [%s]", script_path, lua_tostring(L, -1)); return(false); } num_calls++; total_ticks += Utils::getticks() - t_begin; return(true); } /* ****************************************** */ #ifdef TEST_CHECK_ENGINE AfterShutdownAction afterShutdownAction = after_shutdown_nop; int main() { const int num_runs = 1000; ntop = new (std::nothrow) Ntop((char*)"test"); Prefs *prefs = new (std::nothrow) Prefs(ntop); ntop->registerPrefs(prefs, false); NetworkInterface *iface = new (std::nothrow) PcapInterface("lo"); ntop->registerInterface(iface); /* Calls interface.lua for interface lo */ AlertCheckLuaEngine *engine = new (std::nothrow) AlertCheckLuaEngine(alert_entity_interface, minute_script, iface); lua_State *L = engine->getState(); /* Tip: try with a mix of lua compilation/runtime errors in interface.lua/required modules * to ensure that no crash occurs in any situation. */ for(int i=0; ireset_stats(); lua_getglobal(L, USER_SCRIPTS_RUN_CALLBACK); lua_pushstring(L, engine->getGranularity()); engine->pcall(1 /* num args */, 0); } delete engine; delete ntop; } #endif