ntopng/src/LuaEngine.cpp
2019-12-17 14:27:35 +01:00

12076 lines
362 KiB
C++

/*
*
* (C) 2013-19 - 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"
#ifndef _GETOPT_H
#define _GETOPT_H
#endif
#ifndef LIB_VERSION
#define LIB_VERSION "1.4.7"
#endif
extern "C" {
#include "rrd.h"
};
struct keyval string_to_replace[MAX_NUM_HTTP_REPLACEMENTS] = { { NULL, NULL } }; /* TODO remove */
static int live_extraction_num = 0;
static Mutex live_extraction_num_lock;
/* ******************************* */
struct ntopngLuaContext* getUserdata(struct lua_State *vm) {
if(vm) {
struct ntopngLuaContext *userdata;
lua_getglobal(vm, "userdata");
userdata = (struct ntopngLuaContext*) lua_touserdata(vm, lua_gettop(vm));
lua_pop(vm, 1); // undo the push done by lua_getglobal
return(userdata);
} else
return(NULL);
}
/* ******************************* */
#ifdef DUMP_STACK
static void stackDump(lua_State *L) {
int i;
int top = lua_gettop(L);
for(i = 1; i <= top; i++) { /* repeat for each level */
int t = lua_type(L, i);
switch(t) {
case LUA_TSTRING: /* strings */
ntop->getTrace()->traceEvent(TRACE_NORMAL, "%u) %s", i, lua_tostring(L, i));
break;
case LUA_TBOOLEAN: /* booleans */
ntop->getTrace()->traceEvent(TRACE_NORMAL, "%u) %s", i, lua_toboolean(L, i) ? "true" : "false");
break;
case LUA_TNUMBER: /* numbers */
ntop->getTrace()->traceEvent(TRACE_NORMAL, "%u) %g", i, lua_tonumber(L, i));
break;
default: /* other values */
ntop->getTrace()->traceEvent(TRACE_NORMAL, "%u) %s", i, lua_typename(L, t));
break;
}
}
}
#endif
/* ******************************* */
LuaEngine::LuaEngine() {
std::bad_alloc bax;
void *ctx;
#ifdef HAVE_NEDGE
if(!ntop->getPro()->has_valid_license()) {
ntop->getGlobals()->shutdown();
ntop->shutdown();
exit(0);
}
#endif
L = luaL_newstate();
if(!L) {
ntop->getTrace()->traceEvent(TRACE_ERROR, "Unable to create a new Lua state.");
throw bax;
}
ctx = (void*)calloc(1, sizeof(struct ntopngLuaContext));
if(!ctx) {
ntop->getTrace()->traceEvent(TRACE_ERROR,
"Unable to create a context for the new Lua state.");
lua_close(L);
throw bax;
}
lua_pushlightuserdata(L, ctx);
lua_setglobal(L, "userdata");
}
/* ******************************* */
LuaEngine::~LuaEngine() {
if(L) {
struct ntopngLuaContext *ctx;
#ifdef DUMP_STACK
stackDump(L);
#endif
ctx = getLuaVMContext(L);
if(ctx) {
#ifndef HAVE_NEDGE
SNMP *snmp = ctx->snmp;
if(snmp) delete snmp;
#endif
if(ctx->pkt_capture.end_capture > 0) {
ctx->pkt_capture.end_capture = 0; /* Force stop */
pthread_join(ctx->pkt_capture.captureThreadLoop, NULL);
}
if((ctx->iface != NULL) && ctx->live_capture.pcaphdr_sent)
ctx->iface->deregisterLiveCapture(ctx);
#ifndef WIN32
if(ctx->ping != NULL)
delete ctx->ping;
#endif
free(ctx);
}
lua_close(L);
}
}
/* ******************************* */
/**
* @brief Check the expected type of lua function.
* @details Find in the lua stack the function and check the function parameters types.
*
* @param vm The lua state.
* @param func The function name.
* @param pos Index of lua stack.
* @param expected_type Index of expected type.
* @return @ref CONST_LUA_ERROR if the expected type is equal to function type, @ref CONST_LUA_PARAM_ERROR otherwise.
*/
int ntop_lua_check(lua_State* vm, const char* func, int pos, int expected_type) {
if(lua_type(vm, pos) != expected_type) {
ntop->getTrace()->traceEvent(TRACE_ERROR,
"%s : expected %s[@pos %d], got %s", func,
lua_typename(vm, expected_type), pos,
lua_typename(vm, lua_type(vm,pos)));
return(CONST_LUA_PARAM_ERROR);
}
return(CONST_LUA_OK);
}
/* ****************************************** */
void get_host_vlan_info(char* lua_ip, char** host_ip,
u_int16_t* vlan_id,
char *buf, u_int buf_len) {
char *where, *vlan = NULL;
snprintf(buf, buf_len, "%s", lua_ip);
if(((*host_ip) = strtok_r(buf, "@", &where)) != NULL)
vlan = strtok_r(NULL, "@", &where);
if(*host_ip == NULL)
*host_ip = lua_ip;
if(vlan)
(*vlan_id) = (u_int16_t)atoi(vlan);
}
/* ****************************************** */
static NetworkInterface* handle_null_interface(lua_State* vm) {
char allowed_ifname[MAX_INTERFACE_NAME_LEN];
// this is normal, no need to generate a trace
//ntop->getTrace()->traceEvent(TRACE_INFO, "NULL interface: did you restart ntopng in the meantime?");
if(ntop->getInterfaceAllowed(vm, allowed_ifname))
return ntop->getNetworkInterface(allowed_ifname);
return(ntop->getFirstInterface());
}
/* ****************************************** */
static int ntop_dump_file(lua_State* vm) {
char *fname;
FILE *fd;
struct mg_connection *conn;
conn = getLuaVMUserdata(vm, conn);
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
if(ntop_lua_check(vm, __FUNCTION__, 1, LUA_TSTRING) != CONST_LUA_OK) return(CONST_LUA_ERROR);
if((fname = (char*)lua_tostring(vm, 1)) == NULL) return(CONST_LUA_PARAM_ERROR);
ntop->fixPath(fname);
if((fd = fopen(fname, "r")) != NULL) {
char tmp[1024];
ntop->getTrace()->traceEvent(TRACE_INFO, "[HTTP] Serving file %s", fname);
while((fgets(tmp, sizeof(tmp)-256 /* To make sure we have room for replacements */, fd)) != NULL) {
for(int i=0; string_to_replace[i].key != NULL; i++)
Utils::replacestr(tmp, string_to_replace[i].key, string_to_replace[i].val);
mg_printf(conn, "%s", tmp);
}
fclose(fd);
lua_pushnil(vm);
return(CONST_LUA_OK);
} else {
ntop->getTrace()->traceEvent(TRACE_INFO, "Unable to read file %s", fname);
return(CONST_LUA_ERROR);
}
}
/* ****************************************** */
static int ntop_dump_binary_file(lua_State* vm) {
char *fname;
FILE *fd;
struct mg_connection *conn;
conn = getLuaVMUserdata(vm, conn);
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
if(ntop_lua_check(vm, __FUNCTION__, 1, LUA_TSTRING) != CONST_LUA_OK) return(CONST_LUA_ERROR);
if((fname = (char*)lua_tostring(vm, 1)) == NULL) return(CONST_LUA_PARAM_ERROR);
ntop->fixPath(fname);
if((fd = fopen(fname, "rb")) != NULL) {
char tmp[1024];
size_t n;
while((n = fread(tmp, 1, sizeof(tmp), fd)) > 0) {
if(mg_write(conn, tmp, n) < (int) n) break;
}
fclose(fd);
lua_pushnil(vm);
return(CONST_LUA_OK);
} else {
ntop->getTrace()->traceEvent(TRACE_INFO, "Unable to read file %s", fname);
return(CONST_LUA_ERROR);
}
}
/* ****************************************** */
// ***API***
static int ntop_set_active_interface_id(lua_State* vm) {
NetworkInterface *iface;
int id;
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
if(ntop_lua_check(vm, __FUNCTION__, 1, LUA_TNUMBER) != CONST_LUA_OK) return(CONST_LUA_ERROR);
id = lua_tonumber(vm, 1);
iface = ntop->getNetworkInterface(vm, id);
ntop->getTrace()->traceEvent(TRACE_INFO, "Index: %d, Name: %s", id, iface ? iface->get_name() : "<unknown>");
if(iface != NULL)
lua_pushstring(vm, iface->get_name());
else
lua_pushnil(vm);
return(CONST_LUA_OK);
}
/* ****************************************** */
static inline bool matches_allowed_ifname(char *allowed_ifname, char *iface) {
return (((allowed_ifname == NULL) || (allowed_ifname[0] == '\0')) /* Periodic script / unrestricted user */
|| (!strncmp(allowed_ifname, iface, strlen(allowed_ifname))));
}
/* ****************************************** */
// ***API***
static int ntop_get_interface_names(lua_State* vm) {
char *allowed_ifname = getLuaVMUserdata(vm, allowed_ifname);
lua_newtable(vm);
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
for(int i=0; i<ntop->get_num_interfaces(); i++) {
NetworkInterface *iface;
/*
We should not call ntop->getInterfaceAtId() as it
manipulates the vm that has been already modified with
lua_newtable(vm) a few lines above.
*/
if((iface = ntop->getInterface(i)) != NULL) {
char num[8], *ifname = iface->get_name();
if(matches_allowed_ifname(allowed_ifname, ifname)) {
ntop->getTrace()->traceEvent(TRACE_DEBUG, "Returning name [%d][%s]", i, ifname);
snprintf(num, sizeof(num), "%d", iface->get_id());
lua_push_str_table_entry(vm, num, ifname);
}
}
}
return(CONST_LUA_OK);
}
/* ****************************************** */
static int ntop_get_first_interface_id(lua_State* vm) {
NetworkInterface *iface;
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
iface = ntop->getFirstInterface();
if(iface) {
lua_pushinteger(vm, iface->get_id());
return(CONST_LUA_OK);
}
return(CONST_LUA_ERROR);
}
/* ****************************************** */
static AddressTree* get_allowed_nets(lua_State* vm) {
AddressTree *ptree;
ptree = getLuaVMUserdata(vm, allowedNets);
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
return(ptree);
}
/* ****************************************** */
static NetworkInterface* getCurrentInterface(lua_State* vm) {
NetworkInterface *ntop_interface;
ntop_interface = getLuaVMUserdata(vm, iface);
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
return(ntop_interface ? ntop_interface : handle_null_interface(vm));
}
/* ****************************************** */
// ***API***
static int ntop_select_interface(lua_State* vm) {
char *ifname;
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
if(lua_type(vm, 1) == LUA_TNIL)
ifname = (char*)"any";
else {
if(ntop_lua_check(vm, __FUNCTION__, 1, LUA_TSTRING) != CONST_LUA_OK) return(CONST_LUA_ERROR);
ifname = (char*)lua_tostring(vm, 1);
}
getLuaVMUservalue(vm, iface) = ntop->getNetworkInterface(ifname, vm);
// lua_pop(vm, 1); /* Cleanup the Lua stack */
lua_pushnil(vm);
return(CONST_LUA_OK);
}
/* ****************************************** */
static int ntop_get_interface_id(lua_State* vm) {
NetworkInterface *iface;
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
if((iface = getCurrentInterface(vm)) == NULL)
return(CONST_LUA_ERROR);
lua_pushinteger(vm, iface->get_id());
return(CONST_LUA_OK);
}
/* ****************************************** */
// ***API***
static int ntop_get_max_if_speed(lua_State* vm) {
char *ifname = NULL;
int ifid;
NetworkInterface *iface;
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
if(lua_type(vm, 1) == LUA_TSTRING) {
ifname = (char*)lua_tostring(vm, 1);
lua_pushinteger(vm, Utils::getMaxIfSpeed(ifname));
} else if(lua_type(vm, 1) == LUA_TNUMBER) {
ifid = lua_tointeger(vm, 1);
if((iface = ntop->getInterfaceById(ifid)) != NULL) {
lua_pushinteger(vm, iface->getMaxSpeed());
} else {
lua_pushnil(vm);
}
} else
lua_pushnil(vm);
return(CONST_LUA_OK);
}
/* ****************************************** */
#ifndef HAVE_NEDGE
// ***API***
static int ntop_process_flow(lua_State* vm) {
NetworkInterface *ntop_interface = getCurrentInterface(vm);
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
if(!ntop_interface)
return(CONST_LUA_ERROR);
if(lua_type(vm, 1) != LUA_TTABLE)
return(CONST_LUA_ERROR);
if(!dynamic_cast<ParserInterface*>(ntop_interface))
return(CONST_LUA_ERROR);
if(lua_type(vm, 1) == LUA_TTABLE) {
ParserInterface *ntop_parser_interface = dynamic_cast<ParserInterface*>(ntop_interface);
ParsedFlow flow;
flow.fromLua(vm, 1);
ntop_parser_interface->processFlow(&flow);
}
return(CONST_LUA_OK);
}
#endif
/* ****************************************** */
// ***API***
static int ntop_get_active_flows_stats(lua_State* vm) {
NetworkInterface *ntop_interface = getCurrentInterface(vm);
nDPIStats ndpi_stats;
FlowStats stats;
char *host_ip = NULL;
u_int16_t vlan_id = 0;
char buf[64];
Host *host = NULL;
Paginator *p = NULL;
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
if((p = new(std::nothrow) Paginator()) == NULL)
return(CONST_LUA_ERROR);
/* Optional host */
if(lua_type(vm, 1) == LUA_TSTRING) {
get_host_vlan_info((char*)lua_tostring(vm, 1), &host_ip, &vlan_id, buf, sizeof(buf));
host = ntop_interface->getHost(host_ip, vlan_id, false /* Not an inline call */);
}
if(lua_type(vm, 2) == LUA_TTABLE)
p->readOptions(vm, 2);
if(ntop_interface) {
ntop_interface->getActiveFlowsStats(&ndpi_stats, &stats, get_allowed_nets(vm), host, p);
lua_newtable(vm);
ndpi_stats.lua(ntop_interface, vm);
stats.lua(vm);
} else
lua_pushnil(vm);
if(p) delete p;
return(CONST_LUA_OK);
}
/* ****************************************** */
// ***API***
static int ntop_get_host_pools_info(lua_State* vm) {
NetworkInterface *ntop_interface = getCurrentInterface(vm);
if(ntop_interface && ntop_interface->getHostPools()) {
lua_newtable(vm);
ntop_interface->getHostPools()->lua(vm);
return(CONST_LUA_OK);
} else
return(CONST_LUA_ERROR);
}
/* ****************************************** */
/**
* @brief Get the Host Pool statistics of interface.
*
* @param vm The lua state.
* @return @ref CONST_LUA_OK
*/
static int ntop_get_host_pools_interface_stats(lua_State* vm) {
NetworkInterface *ntop_interface = getCurrentInterface(vm);
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
if(ntop_interface && ntop_interface->getHostPools()) {
ntop_interface->luaHostPoolsStats(vm);
return(CONST_LUA_OK);
} else
return(CONST_LUA_ERROR);
}
/* ****************************************** */
/**
* @brief Get the Host Pool statistics for a pool of interface.
*
* @param vm The lua state.
* @return @ref CONST_LUA_OK
*/
static int ntop_get_host_pool_interface_stats(lua_State* vm) {
NetworkInterface *ntop_interface = getCurrentInterface(vm);
HostPools *hp;
u_int64_t pool_id;
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
if(ntop_lua_check(vm, __FUNCTION__, 1, LUA_TNUMBER) != CONST_LUA_OK) return(CONST_LUA_ERROR);
pool_id = (u_int16_t)lua_tonumber(vm, 1);
if(ntop_interface && (hp = ntop_interface->getHostPools())) {
lua_newtable(vm);
hp->luaStats(vm, pool_id);
return(CONST_LUA_OK);
} else
return(CONST_LUA_ERROR);
}
/* ****************************************** */
#ifdef NTOPNG_PRO
/**
* @brief Get the Host Pool volatile members
*
* @param vm The lua state.
* @return @ref CONST_LUA_OK
*/
static int ntop_get_host_pool_volatile_members(lua_State* vm) {
NetworkInterface *ntop_interface = getCurrentInterface(vm);
nDPIStats stats;
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
if(ntop_interface && ntop_interface->getHostPools()) {
ntop_interface->luaHostPoolsVolatileMembers(vm);
return(CONST_LUA_OK);
} else
return(CONST_LUA_ERROR);
}
/* ****************************************** */
/**
* @brief Get the SNMP statistics of interface.
*
* @param vm The lua state.
* @return @ref CONST_LUA_OK
*/
static int ntop_interface_get_snmp_stats(lua_State* vm) {
NetworkInterface *ntop_interface = getCurrentInterface(vm);
nDPIStats stats;
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
if(ntop_interface && ntop_interface->getFlowInterfacesStats()) {
ntop_interface->getFlowInterfacesStats()->lua(vm);
return(CONST_LUA_OK);
} else
return(CONST_LUA_ERROR);
}
/* ****************************************** */
/**
* @brief Get the Host statistics corresponding to the amount of host quotas used
*
* @param vm The lua state.
* @return @ref CONST_LUA_OK
*/
static int ntop_get_host_used_quotas_stats(lua_State* vm) {
NetworkInterface *ntop_interface = getCurrentInterface(vm);
Host *h;
char *host_ip;
u_int16_t vlan_id = 0;
char buf[128];
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
if((!ntop_interface))
return(CONST_LUA_ERROR);
if(ntop_lua_check(vm, __FUNCTION__, 1, LUA_TSTRING) != CONST_LUA_OK) return(CONST_LUA_ERROR);
get_host_vlan_info((char*)lua_tostring(vm, 1), &host_ip, &vlan_id, buf, sizeof(buf));
/* Optional VLAN id */
if(lua_type(vm, 2) == LUA_TNUMBER) vlan_id = (u_int16_t)lua_tonumber(vm, 2);
if((h = ntop_interface->getHost(host_ip, vlan_id, false /* Not an inline call */)))
h->luaUsedQuotas(vm);
else
lua_newtable(vm);
return(CONST_LUA_OK);
}
#endif
/* ****************************************** */
// ***API***
static int ntop_get_ndpi_interface_flows_count(lua_State* vm) {
NetworkInterface *ntop_interface = getCurrentInterface(vm);
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
if(ntop_interface) {
lua_newtable(vm);
ntop_interface->getnDPIFlowsCount(vm);
} else
lua_pushnil(vm);
return(CONST_LUA_OK);
}
/* ****************************************** */
// ***API***
static int ntop_get_ndpi_interface_flows_status(lua_State* vm) {
NetworkInterface *ntop_interface = getCurrentInterface(vm);
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
if(ntop_interface) {
lua_newtable(vm);
ntop_interface->getFlowsStatus(vm);
} else
lua_pushnil(vm);
return(CONST_LUA_OK);
}
/* ****************************************** */
// ***API***
static int ntop_get_ndpi_protocol_name(lua_State* vm) {
NetworkInterface *ntop_interface = getCurrentInterface(vm);
nDPIStats stats;
int proto;
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
if(ntop_lua_check(vm, __FUNCTION__, 1, LUA_TNUMBER) != CONST_LUA_OK) return(CONST_LUA_ERROR);
proto = (u_int32_t)lua_tonumber(vm, 1);
if(proto == HOST_FAMILY_ID)
lua_pushstring(vm, "Host-to-Host Contact");
else {
if(ntop_interface)
lua_pushstring(vm, ntop_interface->get_ndpi_proto_name(proto));
else
lua_pushnil(vm);
}
return(CONST_LUA_OK);
}
/* ****************************************** */
// ***API***
static int ntop_get_ndpi_protocol_id(lua_State* vm) {
NetworkInterface *ntop_interface = getCurrentInterface(vm);
nDPIStats stats;
char *proto;
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
if(ntop_lua_check(vm, __FUNCTION__, 1, LUA_TSTRING) != CONST_LUA_OK) return(CONST_LUA_ERROR);
proto = (char*)lua_tostring(vm, 1);
if(ntop_interface && proto)
lua_pushinteger(vm, ntop_interface->get_ndpi_proto_id(proto));
else
lua_pushnil(vm);
return(CONST_LUA_OK);
}
/* ****************************************** */
// ***API***
static int ntop_get_ndpi_category_id(lua_State* vm) {
NetworkInterface *ntop_interface = getCurrentInterface(vm);
nDPIStats stats;
char *category;
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
if(ntop_lua_check(vm, __FUNCTION__, 1, LUA_TSTRING) != CONST_LUA_OK) return(CONST_LUA_ERROR);
category = (char*)lua_tostring(vm, 1);
if(ntop_interface && category)
lua_pushinteger(vm, ntop_interface->get_ndpi_category_id(category));
else
lua_pushnil(vm);
return(CONST_LUA_OK);
}
/* ****************************************** */
// ***API***
static int ntop_get_ndpi_category_name(lua_State* vm) {
NetworkInterface *ntop_interface = getCurrentInterface(vm);
nDPIStats stats;
ndpi_protocol_category_t category;
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
if(ntop_lua_check(vm, __FUNCTION__, 1, LUA_TNUMBER) != CONST_LUA_OK) return(CONST_LUA_ERROR);
category = (ndpi_protocol_category_t)((int)lua_tonumber(vm, 1));
if(ntop_interface)
lua_pushstring(vm, ntop_interface->get_ndpi_category_name(category));
else
lua_pushnil(vm);
return(CONST_LUA_OK);
}
/* ****************************************** */
// ***API***
static int ntop_get_ndpi_protocol_category(lua_State* vm) {
NetworkInterface *ntop_interface = getCurrentInterface(vm);
u_int proto;
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
if(ntop_lua_check(vm, __FUNCTION__, 1, LUA_TNUMBER) != CONST_LUA_OK) return(CONST_LUA_ERROR);
proto = (u_int)lua_tonumber(vm, 1);
if(ntop_interface) { /* FIX */
ndpi_protocol_category_t category = ntop_interface->get_ndpi_proto_category(proto);
lua_newtable(vm);
lua_push_int32_table_entry(vm, "id", category);
lua_push_str_table_entry(vm, "name", (char*)ntop_interface->get_ndpi_category_name(category));
} else
lua_pushnil(vm);
return(CONST_LUA_OK);
}
/* ****************************************** */
// ***API***
static int ntop_set_ndpi_protocol_category(lua_State* vm) {
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
NetworkInterface *ntop_interface = getCurrentInterface(vm);
u_int16_t proto;
ndpi_protocol_category_t category;
if(ntop_lua_check(vm, __FUNCTION__, 1, LUA_TNUMBER) != CONST_LUA_OK) return(CONST_LUA_ERROR);
proto = (u_int16_t)lua_tonumber(vm, 1);
if(ntop_lua_check(vm, __FUNCTION__, 2, LUA_TNUMBER) != CONST_LUA_OK) return(CONST_LUA_ERROR);
category = (ndpi_protocol_category_t)lua_tointeger(vm, 2);
/* FIX */
if(ntop_interface)
ntop_interface->setnDPIProtocolCategory(proto, category);
lua_pushnil(vm);
return(CONST_LUA_OK);
}
/* ****************************************** */
/**
* @brief Same as ntop_get_ndpi_protocol_name() with the exception that the protocol breed is returned
*
* @param vm The lua state.
* @return CONST_LUA_ERROR if ntop_interface is null, CONST_LUA_OK otherwise.
*/
static int ntop_get_ndpi_protocol_breed(lua_State* vm) {
NetworkInterface *ntop_interface = getCurrentInterface(vm);
nDPIStats stats;
int proto;
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
if(ntop_lua_check(vm, __FUNCTION__, 1, LUA_TNUMBER) != CONST_LUA_OK) return(CONST_LUA_ERROR);
proto = (u_int32_t)lua_tonumber(vm, 1);
if(proto == HOST_FAMILY_ID)
lua_pushstring(vm, "Unrated-to-Host Contact");
else {
if(ntop_interface)
lua_pushstring(vm, ntop_interface->get_ndpi_proto_breed_name(proto));
else
lua_pushnil(vm);
}
return(CONST_LUA_OK);
}
/* ****************************************** */
static int ntop_get_batched_interface_hosts(lua_State* vm, LocationPolicy location, bool tsLua=false) {
NetworkInterface *ntop_interface = getCurrentInterface(vm);
bool show_details = true, filtered_hosts = false, blacklisted_hosts = false, hide_top_hidden = false;
char *sortColumn = (char*)"column_ip", *country = NULL, *mac_filter = NULL;
OperatingSystem os_filter = ((OperatingSystem)-1);
bool a2zSortOrder = true;
u_int16_t vlan_filter = (u_int16_t)-1;
u_int32_t asn_filter = (u_int32_t)-1;
int16_t network_filter = -2;
u_int16_t pool_filter = (u_int16_t)-1;
u_int8_t ipver_filter = 0;
int proto_filter = -1;
TrafficType traffic_type_filter = traffic_type_all;
u_int32_t toSkip = 0, maxHits = CONST_MAX_NUM_HITS;
u_int32_t begin_slot = 0;
bool walk_all = false;
bool anomalousOnly = false;
bool dhcpOnly = false;
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
if(lua_type(vm, 1) == LUA_TNUMBER) begin_slot = (u_int32_t)lua_tonumber(vm, 1);
if(lua_type(vm, 2) == LUA_TBOOLEAN) show_details = lua_toboolean(vm, 2) ? true : false;
if(lua_type(vm, 3) == LUA_TNUMBER) maxHits = (u_int32_t)lua_tonumber(vm, 3);
if(lua_type(vm, 4) == LUA_TBOOLEAN) anomalousOnly = lua_toboolean(vm, 4);
/* If parameter 5 is true, the caller wants to iterate all hosts, including those with unidirectional traffic.
If parameter 5 is false, then the caller only wants host withs bidirectional traffic */
if(lua_type(vm, 5) == LUA_TBOOLEAN) traffic_type_filter = lua_toboolean(vm, 5) ? traffic_type_all : traffic_type_bidirectional;
if((!ntop_interface)
|| ntop_interface->getActiveHostsList(vm,
&begin_slot, walk_all,
0, /* bridge InterfaceId - TODO pass Id 0,1 for bridge devices*/
get_allowed_nets(vm),
show_details, location,
country, mac_filter,
vlan_filter, os_filter, asn_filter,
network_filter, pool_filter, filtered_hosts, blacklisted_hosts, hide_top_hidden,
ipver_filter, proto_filter,
traffic_type_filter, tsLua /* host->tsLua | host->lua */,
anomalousOnly, dhcpOnly,
NULL /* cidr filter */,
sortColumn, maxHits,
toSkip, a2zSortOrder) < 0)
return(CONST_LUA_ERROR);
return(CONST_LUA_OK);
}
/* ****************************************** */
static int ntop_get_interface_hosts(lua_State* vm, LocationPolicy location) {
NetworkInterface *ntop_interface = getCurrentInterface(vm);
bool show_details = true, filtered_hosts = false, blacklisted_hosts = false;
char *sortColumn = (char*)"column_ip", *country = NULL, *mac_filter = NULL;
bool a2zSortOrder = true;
OperatingSystem os_filter = ((OperatingSystem)-1);
u_int16_t vlan_filter = (u_int16_t)-1;
u_int32_t asn_filter = (u_int32_t)-1;
int16_t network_filter = -2;
u_int16_t pool_filter = (u_int16_t)-1;
u_int8_t ipver_filter = 0;
TrafficType traffic_type_filter = traffic_type_all;
int proto_filter = -1;
u_int32_t toSkip = 0, maxHits = CONST_MAX_NUM_HITS;
u_int32_t begin_slot = 0;
bool walk_all = true;
bool hide_top_hidden = false;
bool anomalousOnly = false;
bool dhcpOnly = false, cidr_filter_enabled = false;
AddressTree cidr_filter;
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
if(lua_type(vm, 1) == LUA_TBOOLEAN) show_details = lua_toboolean(vm, 1) ? true : false;
if(lua_type(vm, 2) == LUA_TSTRING) sortColumn = (char*)lua_tostring(vm, 2);
if(lua_type(vm, 3) == LUA_TNUMBER) maxHits = (u_int16_t)lua_tonumber(vm, 3);
if(lua_type(vm, 4) == LUA_TNUMBER) toSkip = (u_int16_t)lua_tonumber(vm, 4);
if(lua_type(vm, 5) == LUA_TBOOLEAN) a2zSortOrder = lua_toboolean(vm, 5) ? true : false;
if(lua_type(vm, 6) == LUA_TSTRING) country = (char*)lua_tostring(vm, 6);
if(lua_type(vm, 7) == LUA_TNUMBER) os_filter = (OperatingSystem)lua_tointeger(vm, 7);
if(lua_type(vm, 8) == LUA_TNUMBER) vlan_filter = (u_int16_t)lua_tonumber(vm, 8);
if(lua_type(vm, 9) == LUA_TNUMBER) asn_filter = (u_int32_t)lua_tonumber(vm, 9);
if(lua_type(vm,10) == LUA_TNUMBER) network_filter = (int16_t)lua_tonumber(vm, 10);
if(lua_type(vm,11) == LUA_TSTRING) mac_filter = (char*)lua_tostring(vm, 11);
if(lua_type(vm,12) == LUA_TNUMBER) pool_filter = (u_int16_t)lua_tonumber(vm, 12);
if(lua_type(vm,13) == LUA_TNUMBER) ipver_filter = (u_int8_t)lua_tonumber(vm, 13);
if(lua_type(vm,14) == LUA_TNUMBER) proto_filter = (int)lua_tonumber(vm, 14);
if(lua_type(vm,15) == LUA_TNUMBER) traffic_type_filter = (TrafficType)lua_tonumber(vm, 15);
if(lua_type(vm,16) == LUA_TBOOLEAN) filtered_hosts = lua_toboolean(vm, 16);
if(lua_type(vm,17) == LUA_TBOOLEAN) blacklisted_hosts = lua_toboolean(vm, 17);
if(lua_type(vm,18) == LUA_TBOOLEAN) hide_top_hidden = lua_toboolean(vm, 18);
if(lua_type(vm,19) == LUA_TBOOLEAN) anomalousOnly = lua_toboolean(vm, 19);
if(lua_type(vm,20) == LUA_TBOOLEAN) dhcpOnly = lua_toboolean(vm, 20);
if(lua_type(vm,21) == LUA_TSTRING) cidr_filter.addAddress(lua_tostring(vm, 21)), cidr_filter_enabled = true;
if((!ntop_interface)
|| ntop_interface->getActiveHostsList(vm,
&begin_slot, walk_all,
0, /* bridge InterfaceId - TODO pass Id 0,1 for bridge devices*/
get_allowed_nets(vm),
show_details, location,
country, mac_filter,
vlan_filter, os_filter, asn_filter,
network_filter, pool_filter, filtered_hosts, blacklisted_hosts, hide_top_hidden,
ipver_filter, proto_filter,
traffic_type_filter, false /* host->lua */,
anomalousOnly, dhcpOnly,
cidr_filter_enabled ? &cidr_filter : NULL,
sortColumn, maxHits,
toSkip, a2zSortOrder) < 0)
return(CONST_LUA_ERROR);
return(CONST_LUA_OK);
}
/* ****************************************** */
/* Receives in input a Lua table, having mac address as keys and tables as values. Every IP address found for a mac is inserted into the table as an 'ip' field. */
static int ntop_add_macs_ip_addresses(lua_State* vm) {
NetworkInterface *ntop_interface = getCurrentInterface(vm);
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
if(ntop_lua_check(vm, __FUNCTION__, 1, LUA_TTABLE) != CONST_LUA_OK) return(CONST_LUA_ERROR);
if((!ntop_interface) || ntop_interface->getMacsIpAddresses(vm, 1) < 0)
return(CONST_LUA_ERROR);
lua_pushnil(vm);
return(CONST_LUA_OK);
}
/* ****************************************** */
// ***API***
static int ntop_get_grouped_interface_hosts(lua_State* vm) {
NetworkInterface *ntop_interface = getCurrentInterface(vm);
bool show_details = true;
char *country = NULL;
OperatingSystem os_filter = ((OperatingSystem)-1);
char *groupBy = (char*)"column_ip";
bool filtered_hosts = false;
u_int16_t vlan_filter = (u_int16_t)-1;
u_int32_t asn_filter = (u_int32_t)-1;
u_int16_t pool_filter = (u_int16_t)-1;
u_int8_t ipver_filter = (u_int8_t)-1;
int16_t network_filter = -2;
u_int32_t begin_slot = 0;
bool walk_all = true;
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
if(lua_type(vm, 1) == LUA_TBOOLEAN) show_details = lua_toboolean(vm, 1) ? true : false;
if(lua_type(vm, 2) == LUA_TSTRING) groupBy = (char*)lua_tostring(vm, 2);
if(lua_type(vm, 3) == LUA_TSTRING) country = (char*)lua_tostring(vm, 3);
if(lua_type(vm, 4) == LUA_TNUMBER) os_filter = (OperatingSystem)lua_tointeger(vm, 4);
if(lua_type(vm, 5) == LUA_TNUMBER) vlan_filter = (u_int16_t)lua_tonumber(vm, 5);
if(lua_type(vm, 6) == LUA_TNUMBER) asn_filter = (u_int32_t)lua_tonumber(vm, 6);
if(lua_type(vm, 7) == LUA_TNUMBER) network_filter = (int16_t)lua_tonumber(vm, 7);
if(lua_type(vm, 8) == LUA_TNUMBER) pool_filter = (u_int16_t)lua_tonumber(vm, 8);
if(lua_type(vm, 9) == LUA_TNUMBER) ipver_filter = (u_int8_t)lua_tonumber(vm, 9);
if((!ntop_interface)
|| ntop_interface->getActiveHostsGroup(vm,
&begin_slot, walk_all,
get_allowed_nets(vm),
show_details, location_all,
country,
vlan_filter, os_filter,
asn_filter, network_filter,
pool_filter, filtered_hosts, ipver_filter, groupBy) < 0)
return(CONST_LUA_ERROR);
return(CONST_LUA_OK);
}
/* ****************************************** */
static u_int8_t str_2_location(const char *s) {
if(! strcmp(s, "lan")) return located_on_lan_interface;
else if(! strcmp(s, "wan")) return located_on_wan_interface;
else if(! strcmp(s, "unknown")) return located_on_unknown_interface;
return (u_int8_t)-1;
}
/* ****************************************** */
// ***API***
static int ntop_get_interface_macs_info(lua_State* vm) {
NetworkInterface *ntop_interface = getCurrentInterface(vm);
char *sortColumn = (char*)"column_mac";
const char* manufacturer = NULL;
u_int32_t toSkip = 0, maxHits = CONST_MAX_NUM_HITS;
u_int16_t pool_filter = (u_int16_t)-1;
u_int8_t devtype_filter = (u_int8_t)-1;
bool a2zSortOrder = true, sourceMacsOnly = false;
u_int8_t location_filter = (u_int8_t)-1;
u_int32_t begin_slot = 0;
bool walk_all = true;
if(lua_type(vm, 1) == LUA_TSTRING) sortColumn = (char*)lua_tostring(vm, 1);
if(lua_type(vm, 2) == LUA_TNUMBER) maxHits = (u_int16_t)lua_tonumber(vm, 2);
if(lua_type(vm, 3) == LUA_TNUMBER) toSkip = (u_int16_t)lua_tonumber(vm, 3);
if(lua_type(vm, 4) == LUA_TBOOLEAN) a2zSortOrder = lua_toboolean(vm, 4);
if(lua_type(vm, 5) == LUA_TBOOLEAN) sourceMacsOnly = lua_toboolean(vm, 5);
if(lua_type(vm, 6) == LUA_TSTRING) manufacturer = lua_tostring(vm, 6);
if(lua_type(vm, 7) == LUA_TNUMBER) pool_filter = (u_int16_t)lua_tonumber(vm, 7);
if(lua_type(vm, 8) == LUA_TNUMBER) devtype_filter = (u_int8_t)lua_tonumber(vm, 8);
if(lua_type(vm, 9) == LUA_TSTRING) location_filter = str_2_location(lua_tostring(vm, 9));
if(!ntop_interface ||
ntop_interface->getActiveMacList(vm,
&begin_slot, walk_all,
0, /* bridge InterfaceId - TODO pass Id 0,1 for bridge devices*/
sourceMacsOnly, manufacturer,
sortColumn, maxHits,
toSkip, a2zSortOrder, pool_filter, devtype_filter, location_filter) < 0)
return(CONST_LUA_ERROR);
return(CONST_LUA_OK);
}
/* ****************************************** */
static int ntop_get_batched_interface_macs_info(lua_State* vm) {
NetworkInterface *ntop_interface = getCurrentInterface(vm);
char *sortColumn = (char*)"column_mac";
const char* manufacturer = NULL;
u_int32_t toSkip = 0, maxHits = CONST_MAX_NUM_HITS;
u_int16_t pool_filter = (u_int16_t)-1;
u_int8_t devtype_filter = (u_int8_t)-1;
bool a2zSortOrder = true, sourceMacsOnly = false;
u_int8_t location_filter = (u_int8_t)-1;
u_int32_t begin_slot = 0;
bool walk_all = false;
if(lua_type(vm, 1) == LUA_TNUMBER) begin_slot = (u_int16_t)lua_tonumber(vm, 1);
if(!ntop_interface ||
ntop_interface->getActiveMacList(vm,
&begin_slot, walk_all,
0, /* bridge InterfaceId - TODO pass Id 0,1 for bridge devices*/
sourceMacsOnly, manufacturer,
sortColumn, maxHits,
toSkip, a2zSortOrder, pool_filter, devtype_filter, location_filter) < 0)
return(CONST_LUA_ERROR);
return(CONST_LUA_OK);
}
/* ****************************************** */
// ***API***
static int ntop_get_interface_mac_info(lua_State* vm) {
NetworkInterface *ntop_interface = getCurrentInterface(vm);
char *mac = NULL;
if(lua_type(vm, 1) == LUA_TSTRING)
mac = (char*)lua_tostring(vm, 1);
if((!ntop_interface)
|| (!mac)
|| (!ntop_interface->getMacInfo(vm, mac)))
return(CONST_LUA_ERROR);
return(CONST_LUA_OK);
}
/* ****************************************** */
// ***API***
static int ntop_get_interface_mac_hosts(lua_State* vm) {
NetworkInterface *ntop_interface = getCurrentInterface(vm);
char *mac = NULL;
if(lua_type(vm, 1) == LUA_TSTRING)
mac = (char*)lua_tostring(vm, 1);
lua_newtable(vm);
if(ntop_interface)
ntop_interface->getActiveMacHosts(vm, mac);
return(CONST_LUA_OK);
}
/* ****************************************** */
// ***API***
static int ntop_set_host_operating_system(lua_State* vm) {
NetworkInterface *ntop_interface = getCurrentInterface(vm);
char *host_ip = NULL, buf[64];
u_int16_t vlan_id;
OperatingSystem os = os_unknown;
Host *host;
if(!ntop_interface)
return(CONST_LUA_ERROR);
if(ntop_lua_check(vm, __FUNCTION__, 1, LUA_TSTRING) != CONST_LUA_OK) return(CONST_LUA_ERROR);
get_host_vlan_info((char*)lua_tostring(vm, 1), &host_ip, &vlan_id, buf, sizeof(buf));
if(ntop_lua_check(vm, __FUNCTION__, 2, LUA_TNUMBER) != CONST_LUA_OK) return(CONST_LUA_ERROR);
os = (OperatingSystem)lua_tonumber(vm, 2);
if(os >= os_max_os) return(CONST_LUA_ERROR);
host = ntop_interface->findHostByIP(get_allowed_nets(vm), host_ip, vlan_id);
if(!host)
return(CONST_LUA_ERROR);
if(os != os_unknown)
host->setOS(os);
lua_pushnil(vm);
return(CONST_LUA_OK);
}
/* ****************************************** */
// ***API***
static int ntop_set_mac_device_type(lua_State* vm) {
NetworkInterface *ntop_interface = getCurrentInterface(vm);
char *mac = NULL;
DeviceType dtype = device_unknown;
bool overwriteType;
int i;
if(ntop_lua_check(vm, __FUNCTION__, 1, LUA_TSTRING) != CONST_LUA_OK) return(CONST_LUA_ERROR);
mac = (char*)lua_tostring(vm, 1);
if(ntop_lua_check(vm, __FUNCTION__, 2, LUA_TNUMBER) != CONST_LUA_OK) return(CONST_LUA_ERROR);
i = lua_tonumber(vm, 2);
dtype = (DeviceType)i;
if(dtype > device_max_type) dtype = device_unknown;
if(ntop_lua_check(vm, __FUNCTION__, 3, LUA_TBOOLEAN) != CONST_LUA_OK) return(CONST_LUA_ERROR);
overwriteType = (bool)lua_toboolean(vm, 3);
if((!ntop_interface)
|| (!mac)
|| (!ntop_interface->setMacDeviceType(mac, dtype, overwriteType)))
return(CONST_LUA_ERROR);
return(CONST_LUA_OK);
}
/* ****************************************** */
// ***API***
static int ntop_get_mac_device_types(lua_State* vm) {
NetworkInterface *ntop_interface = getCurrentInterface(vm);
u_int16_t maxHits = CONST_MAX_NUM_HITS;
bool sourceMacsOnly = false;
char *manufacturer = NULL;
u_int8_t location_filter = (u_int8_t)-1;
if(lua_type(vm, 1) == LUA_TNUMBER)
maxHits = (u_int16_t)lua_tonumber(vm, 1);
if(lua_type(vm, 2) == LUA_TBOOLEAN)
sourceMacsOnly = lua_toboolean(vm, 2) ? true : false;
if(lua_type(vm, 3) == LUA_TSTRING)
manufacturer = (char*)lua_tostring(vm, 3);
if(lua_type(vm, 4) == LUA_TSTRING) location_filter = str_2_location(lua_tostring(vm, 4));
if((!ntop_interface)
|| (ntop_interface->getActiveDeviceTypes(vm, sourceMacsOnly,
0 /* bridge_iface_idx - TODO */,
maxHits, manufacturer, location_filter) < 0))
return(CONST_LUA_ERROR);
return(CONST_LUA_OK);
}
/* ****************************************** */
// ***API***
static int ntop_get_interface_ases_info(lua_State* vm) {
NetworkInterface *ntop_interface = getCurrentInterface(vm);
Paginator *p = NULL;
if(!ntop_interface)
return(CONST_LUA_ERROR);
if((p = new(std::nothrow) Paginator()) == NULL)
return(CONST_LUA_ERROR);
if(lua_type(vm, 1) == LUA_TTABLE)
p->readOptions(vm, 1);
if(ntop_interface->getActiveASList(vm, p) < 0) {
if(p) delete(p);
return(CONST_LUA_ERROR);
}
if(p) delete(p);
return(CONST_LUA_OK);
}
/* ****************************************** */
// ***API***
static int ntop_get_interface_countries_info(lua_State* vm) {
NetworkInterface *ntop_interface = getCurrentInterface(vm);
Paginator *p = NULL;
if(!ntop_interface)
return(CONST_LUA_ERROR);
if((p = new(std::nothrow) Paginator()) == NULL)
return(CONST_LUA_ERROR);
if(lua_type(vm, 1) == LUA_TTABLE)
p->readOptions(vm, 1);
if(ntop_interface->getActiveCountriesList(vm, p) < 0) {
if(p) delete(p);
return(CONST_LUA_ERROR);
}
if(p) delete(p);
return(CONST_LUA_OK);
}
/* ****************************************** */
static int ntop_get_interface_country_info(lua_State* vm) {
NetworkInterface *ntop_interface = getCurrentInterface(vm);
const char* country;
if(ntop_lua_check(vm, __FUNCTION__, 1, LUA_TSTRING) != CONST_LUA_OK) return(CONST_LUA_ERROR);
country = lua_tostring(vm, 1);
if((!ntop_interface)
|| (!ntop_interface->getCountryInfo(vm, country)))
return(CONST_LUA_ERROR);
return(CONST_LUA_OK);
}
/* ****************************************** */
// ***API***
static int ntop_get_interface_vlans_list(lua_State* vm) {
NetworkInterface *ntop_interface = getCurrentInterface(vm);
if((!ntop_interface)
|| ntop_interface->getActiveVLANList(vm,
(char*)"column_vlan", CONST_MAX_NUM_HITS,
0, true, details_normal /* Minimum details */) < 0)
return(CONST_LUA_ERROR);
return(CONST_LUA_OK);
}
/* ****************************************** */
static int ntop_get_interface_vlans_info(lua_State* vm) {
NetworkInterface *ntop_interface = getCurrentInterface(vm);
char *sortColumn = (char*)"column_vlan";
u_int32_t toSkip = 0, maxHits = CONST_MAX_NUM_HITS;
bool a2zSortOrder = true;
DetailsLevel details_level = details_higher;
if(lua_type(vm, 1) == LUA_TSTRING) {
sortColumn = (char*)lua_tostring(vm, 1);
if(lua_type(vm, 2) == LUA_TNUMBER) {
maxHits = (u_int16_t)lua_tonumber(vm, 2);
if(lua_type(vm, 3) == LUA_TNUMBER) {
toSkip = (u_int16_t)lua_tonumber(vm, 3);
if(lua_type(vm, 4) == LUA_TBOOLEAN) {
a2zSortOrder = lua_toboolean(vm, 4) ? true : false;
if(lua_type(vm, 5) == LUA_TBOOLEAN) {
details_level = lua_toboolean(vm, 4) ? details_higher : details_high;
}
}
}
}
}
if(!ntop_interface ||
ntop_interface->getActiveVLANList(vm,
sortColumn, maxHits,
toSkip, a2zSortOrder, details_level) < 0)
return(CONST_LUA_ERROR);
return(CONST_LUA_OK);
}
/* ****************************************** */
// ***API***
static int ntop_get_interface_as_info(lua_State* vm) {
NetworkInterface *ntop_interface = getCurrentInterface(vm);
u_int32_t asn;
if(ntop_lua_check(vm, __FUNCTION__, 1, LUA_TNUMBER) != CONST_LUA_OK) return(CONST_LUA_ERROR);
asn = (u_int32_t)lua_tonumber(vm, 1);
if((!ntop_interface)
|| (!ntop_interface->getASInfo(vm, asn)))
return(CONST_LUA_ERROR);
return(CONST_LUA_OK);
}
/* ****************************************** */
// ***API***
static int ntop_get_interface_vlan_info(lua_State* vm) {
NetworkInterface *ntop_interface = getCurrentInterface(vm);
u_int16_t vlan_id;
if(ntop_lua_check(vm, __FUNCTION__, 1, LUA_TNUMBER) != CONST_LUA_OK) return(CONST_LUA_ERROR);
vlan_id = (u_int16_t)lua_tonumber(vm, 1);
if((!ntop_interface)
|| (!ntop_interface->getVLANInfo(vm, vlan_id)))
return(CONST_LUA_ERROR);
return(CONST_LUA_OK);
}
/* ****************************************** */
// ***API***
static int ntop_get_interface_macs_manufacturers(lua_State* vm) {
NetworkInterface *ntop_interface = getCurrentInterface(vm);
u_int32_t maxHits = CONST_MAX_NUM_HITS;
u_int8_t devtype_filter = (u_int8_t)-1;
bool sourceMacsOnly = false;
u_int8_t location_filter = (u_int8_t)-1;
if(lua_type(vm, 1) == LUA_TNUMBER)
maxHits = (u_int16_t)lua_tonumber(vm, 1);
if(lua_type(vm, 2) == LUA_TBOOLEAN)
sourceMacsOnly = lua_toboolean(vm, 2) ? true : false;
if(lua_type(vm, 3) == LUA_TNUMBER)
devtype_filter = (u_int8_t)lua_tonumber(vm, 3);
if(lua_type(vm, 4) == LUA_TSTRING) location_filter = str_2_location(lua_tostring(vm, 4));
if(!ntop_interface ||
ntop_interface->getActiveMacManufacturers(vm,
0, /* bridge_iface_idx - TODO */
sourceMacsOnly, maxHits,
devtype_filter, location_filter) < 0)
return(CONST_LUA_ERROR);
return(CONST_LUA_OK);
}
/* ****************************************** */
// ***API***
static int ntop_get_mac_manufacturer(lua_State* vm) {
const char *mac = NULL;
if(ntop_lua_check(vm, __FUNCTION__, 1, LUA_TSTRING) != CONST_LUA_OK) return(CONST_LUA_ERROR);
mac = (char*)lua_tostring(vm, 1);
ntop->getMacManufacturer(mac, vm);
return(CONST_LUA_OK);
}
/* ****************************************** */
// ***API***
static int ntop_get_host_information(lua_State* vm) {
struct in_addr management_addr;
management_addr.s_addr = Utils::getHostManagementIPv4Address();
lua_newtable(vm);
lua_push_str_table_entry(vm, "ip", inet_ntoa(management_addr));
lua_push_str_table_entry(vm, "instance_name", ntop->getPrefs()->get_instance_name());
return(CONST_LUA_OK);
}
/* ****************************************** */
#ifdef HAVE_NEDGE
static int ntop_set_bind_addr(lua_State* vm, bool http) {
char *addr, *addr2 = (char *) CONST_LOOPBACK_ADDRESS;
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
if(!ntop->isUserAdministrator(vm))
return(CONST_LUA_ERROR);
if(ntop_lua_check(vm, __FUNCTION__, 1, LUA_TSTRING) != CONST_LUA_OK) return(CONST_LUA_ERROR);
addr = (char*)lua_tostring(vm, 1);
if(lua_type(vm, 2) == LUA_TSTRING)
addr2 = (char*)lua_tostring(vm, 2);
if(http)
ntop->getPrefs()->bind_http_to_address(addr, addr2);
else /* https */
ntop->getPrefs()->bind_https_to_address(addr, addr2);
lua_pushnil(vm);
return(CONST_LUA_OK);
}
static int ntop_set_http_bind_addr(lua_State* vm) {
return ntop_set_bind_addr(vm, true /* http */);
}
static int ntop_set_https_bind_addr(lua_State* vm) {
return ntop_set_bind_addr(vm, false /* https */);
}
#endif
/* ****************************************** */
#ifdef HAVE_NEDGE
static int ntop_shutdown(lua_State* vm) {
char *action;
extern AfterShutdownAction afterShutdownAction;
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
if(!ntop->isUserAdministrator(vm))
return(CONST_LUA_ERROR);
if(lua_type(vm, 1) == LUA_TSTRING) {
action = (char*)lua_tostring(vm, 1);
if(!strcmp(action, "poweroff"))
afterShutdownAction = after_shutdown_poweroff;
else if(!strcmp(action, "reboot"))
afterShutdownAction = after_shutdown_reboot;
else if(!strcmp(action, "restart_self"))
afterShutdownAction = after_shutdown_restart_self;
}
ntop->getGlobals()->requestShutdown();
lua_pushnil(vm);
return(CONST_LUA_OK);
}
#endif
/* ****************************************** */
// ***API***
static int ntop_is_shutdown(lua_State* vm) {
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
lua_pushboolean(vm, ntop->getGlobals()->isShutdownRequested());
return(CONST_LUA_OK);
}
/* ****************************************** */
// ***API***
static int ntop_list_interfaces(lua_State* vm) {
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
lua_newtable(vm);
Utils::listInterfaces(vm);
return(CONST_LUA_OK);
}
/* ****************************************** */
static int ntop_ip_cmp(lua_State* vm) {
IpAddress a, b;
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
if(ntop_lua_check(vm, __FUNCTION__, 1, LUA_TSTRING) != CONST_LUA_OK) return(CONST_LUA_ERROR);
if(ntop_lua_check(vm, __FUNCTION__, 2, LUA_TSTRING) != CONST_LUA_OK) return(CONST_LUA_ERROR);
a.set((char*)lua_tostring(vm, 1));
b.set((char*)lua_tostring(vm, 2));
lua_pushinteger(vm, a.compare(&b));
return(CONST_LUA_OK);
}
/* ****************************************** */
static int ntop_load_malicious_ja3_hash(lua_State* vm) {
const char *ja3_hash;
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
if(ntop_lua_check(vm, __FUNCTION__, 1, LUA_TSTRING) != CONST_LUA_OK) return(CONST_LUA_ERROR);
ja3_hash = lua_tostring(vm, 1);
ntop->loadMaliciousJA3Hash(ja3_hash);
lua_pushnil(vm);
return(CONST_LUA_OK);
}
/* ****************************************** */
static int ntop_reload_ja3_hashes(lua_State* vm) {
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
ntop->reloadJA3Hashes();
lua_pushnil(vm);
return(CONST_LUA_OK);
}
/* ****************************************** */
#ifdef HAVE_NEDGE
static int ntop_set_routing_mode(lua_State* vm) {
bool routing_enabled;
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
if(ntop_lua_check(vm, __FUNCTION__, 1, LUA_TBOOLEAN) != CONST_LUA_OK) return(CONST_LUA_ERROR);
routing_enabled = lua_toboolean(vm, 1);
ntop->getPrefs()->set_routing_mode(routing_enabled);
lua_pushnil(vm);
return(CONST_LUA_OK);
}
#endif
/* ****************************************** */
#ifdef HAVE_NEDGE
static int ntop_is_routing_mode(lua_State* vm) {
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
lua_pushboolean(vm, ntop->getPrefs()->is_routing_mode());
return(CONST_LUA_OK);
}
#endif
/* ****************************************** */
// ***API***
static int ntop_get_interface_hosts_info(lua_State* vm) {
return(ntop_get_interface_hosts(vm, location_all));
}
// ***API***
static int ntop_get_interface_local_hosts_info(lua_State* vm) {
return(ntop_get_interface_hosts(vm, location_local_only));
}
// ***API***
static int ntop_get_interface_remote_hosts_info(lua_State* vm) {
return(ntop_get_interface_hosts(vm, location_remote_only));
}
// ***API***
static int ntop_get_interface_broadcast_domain_hosts_info(lua_State* vm) {
return(ntop_get_interface_hosts(vm, location_broadcast_domain_only));
}
/* ****************************************** */
static int ntop_get_batched_interface_hosts_info(lua_State* vm) {
return(ntop_get_batched_interface_hosts(vm, location_all));
}
static int ntop_get_batched_interface_local_hosts_info(lua_State* vm) {
return(ntop_get_batched_interface_hosts(vm, location_local_only));
}
static int ntop_get_batched_interface_remote_hosts_info(lua_State* vm) {
return(ntop_get_batched_interface_hosts(vm, location_remote_only));
}
static int ntop_get_batched_interface_local_hosts_ts(lua_State* vm) {
return(ntop_get_batched_interface_hosts(vm, location_local_only, true /* timeseries */));
}
/* ****************************************** */
// ***API***
static int ntop_is_dir(lua_State* vm) {
char *path;
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
if(ntop_lua_check(vm, __FUNCTION__, 1, LUA_TSTRING) != CONST_LUA_OK) return(CONST_LUA_ERROR);
path = (char*)lua_tostring(vm, 1);
lua_pushboolean(vm, Utils::dir_exists(path));
return(CONST_LUA_OK);
}
/* ****************************************** */
// ***API***
static int ntop_is_not_empty_file(lua_State* vm) {
char *path;
#ifdef WIN32
struct _stat64 buf;
#else
struct stat buf;
#endif
int rc;
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
if(ntop_lua_check(vm, __FUNCTION__, 1, LUA_TSTRING) != CONST_LUA_OK) return(CONST_LUA_ERROR);
path = (char*)lua_tostring(vm, 1);
rc = (stat(path, &buf) != 0) ? 0 : 1;
if(rc && (buf.st_size == 0)) rc = 0;
lua_pushboolean(vm, rc);
return(CONST_LUA_OK);
}
/* ****************************************** */
// ***API***
static int ntop_get_file_dir_exists(lua_State* vm) {
char *path;
#ifdef WIN32
struct _stat64 buf;
#else
struct stat buf;
#endif
int rc;
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
if(ntop_lua_check(vm, __FUNCTION__, 1, LUA_TSTRING) != CONST_LUA_OK) return(CONST_LUA_ERROR);
path = (char*)lua_tostring(vm, 1);
rc = (stat(path, &buf) != 0) ? 0 : 1;
// ntop->getTrace()->traceEvent(TRACE_ERROR, "%s: %d", path, rc);
lua_pushboolean(vm, rc);
return(CONST_LUA_OK);
}
/* ****************************************** */
// ***API***
static int ntop_get_file_last_change(lua_State* vm) {
char *path;
#ifdef WIN32
struct _stat64 buf;
#else
struct stat buf;
#endif
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
if(ntop_lua_check(vm, __FUNCTION__, 1, LUA_TSTRING) != CONST_LUA_OK) return(CONST_LUA_ERROR);
path = (char*)lua_tostring(vm, 1);
if(stat(path, &buf) == 0)
lua_pushinteger(vm, (lua_Integer)buf.st_mtime);
else
lua_pushinteger(vm, -1); /* not found */
return(CONST_LUA_OK);
}
/* ****************************************** */
// ***API***
static int ntop_interface_has_vlans(lua_State* vm) {
NetworkInterface *ntop_interface = getCurrentInterface(vm);
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
if(ntop_interface)
lua_pushboolean(vm, ntop_interface->hasSeenVlanTaggedPackets());
else
lua_pushboolean(vm, 0);
return(CONST_LUA_OK);
}
/* ****************************************** */
// ***API***
static int ntop_interface_has_ebpf(lua_State* vm) {
NetworkInterface *ntop_interface = getCurrentInterface(vm);
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
if(ntop_interface)
lua_pushboolean(vm, ntop_interface->hasSeenEBPFEvents());
else
lua_pushboolean(vm, 0);
return(CONST_LUA_OK);
}
/* ****************************************** */
// ***API***
static int ntop_interface_has_high_res_ts(lua_State* vm) {
NetworkInterface *ntop_interface = getCurrentInterface(vm);
bool rv = false;
if(ntop_interface && ntop_interface != ntop->getSystemInterface())
rv = TimeseriesRing::isRingEnabled(ntop_interface);
lua_pushboolean(vm, rv);
return(CONST_LUA_OK);
}
/* ****************************************** */
// ***API***
static int ntop_has_geoip(lua_State* vm) {
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
lua_pushboolean(vm, ntop->getGeolocation() ? 1 : 0);
return(CONST_LUA_OK);
}
/* ****************************************** */
// ***API***
static int ntop_is_windows(lua_State* vm) {
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
lua_pushboolean(vm,
#ifdef WIN32
1
#else
0
#endif
);
return(CONST_LUA_OK);
}
/* ****************************************** */
static int ntop_startCustomCategoriesReload(lua_State* vm) {
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
if(ntop->isnDPIReloadInProgress() || (!ntop->startCustomCategoriesReload())) {
/* startCustomCategoriesReload, abort */
lua_pushboolean(vm, false);
return(CONST_LUA_OK);
}
lua_pushboolean(vm, true /* can now start reloading */);
return(CONST_LUA_OK);
}
/* ****************************************** */
static int ntop_loadCustomCategoryIp(lua_State* vm) {
char *net;
ndpi_protocol_category_t catid;
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
if(ntop_lua_check(vm, __FUNCTION__, 1, LUA_TSTRING) != CONST_LUA_OK) return(CONST_LUA_ERROR);
net = (char*)lua_tostring(vm, 1);
if(ntop_lua_check(vm, __FUNCTION__, 2, LUA_TNUMBER) != CONST_LUA_OK) return(CONST_LUA_ERROR);
catid = (ndpi_protocol_category_t)lua_tointeger(vm, 2);
ntop->nDPILoadIPCategory(net, catid);
lua_pushnil(vm);
return(CONST_LUA_OK);
}
/* ****************************************** */
static int ntop_loadCustomCategoryHost(lua_State* vm) {
char *host;
ndpi_protocol_category_t catid;
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
if(ntop_lua_check(vm, __FUNCTION__, 1, LUA_TSTRING) != CONST_LUA_OK) return(CONST_LUA_ERROR);
host = (char*)lua_tostring(vm, 1);
if(ntop_lua_check(vm, __FUNCTION__, 2, LUA_TNUMBER) != CONST_LUA_OK) return(CONST_LUA_ERROR);
catid = (ndpi_protocol_category_t)lua_tointeger(vm, 2);
ntop->nDPILoadHostnameCategory(host, catid);
lua_pushnil(vm);
return(CONST_LUA_OK);
}
/* ****************************************** */
/* NOTE: ntop.startCustomCategoriesReload() must be called before this */
static int ntop_reloadCustomCategories(lua_State* vm) {
ntop->getTrace()->traceEvent(TRACE_DEBUG, "Starting category lists reload");
ntop->reloadCustomCategories();
ntop->getTrace()->traceEvent(TRACE_DEBUG, "Category lists reload done");
ntop->setLastInterfacenDPIReload(time(NULL));
ntop->setnDPICleanupNeeded(true);
lua_pushboolean(vm, true /* reload performed */);
return(CONST_LUA_OK);
}
/* ****************************************** */
static int ntop_match_custom_category(lua_State* vm) {
char *host_to_match;
NetworkInterface *iface;
unsigned long match;
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
iface = ntop->getFirstInterface();
if(ntop_lua_check(vm, __FUNCTION__, 1, LUA_TSTRING) != CONST_LUA_OK) return(CONST_LUA_ERROR);
host_to_match = (char*)lua_tostring(vm, 1);
if((!iface) || (ndpi_get_custom_category_match(iface->get_ndpi_struct(), host_to_match, strlen(host_to_match), &match) != 0))
lua_pushnil(vm);
else
lua_pushinteger(vm, (int)match);
return(CONST_LUA_OK);
}
/* ****************************************** */
static int ntop_gainWriteCapabilities(lua_State* vm) {
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
lua_pushnil(vm);
return(Utils::gainWriteCapabilities() == 0 ? CONST_LUA_OK : CONST_LUA_ERROR);
}
/* ****************************************** */
static int ntop_dropWriteCapabilities(lua_State* vm) {
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
lua_pushnil(vm);
return(Utils::dropWriteCapabilities() == 0 ? CONST_LUA_OK : CONST_LUA_ERROR);
}
/* ****************************************** */
// ***API***
static int ntop_getservbyport(lua_State* vm) {
int port;
char *proto;
struct servent *s = NULL;
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
if(ntop_lua_check(vm, __FUNCTION__, 1, LUA_TNUMBER) != CONST_LUA_OK) return(CONST_LUA_ERROR);
port = (int)lua_tonumber(vm, 1);
if(ntop_lua_check(vm, __FUNCTION__, 2, LUA_TSTRING) != CONST_LUA_OK) return(CONST_LUA_ERROR);
proto = (char*)lua_tostring(vm, 2);
if((port > 0) && (proto != NULL))
s = getservbyport(htons(port), proto);
if(s && s->s_name)
lua_pushstring(vm, s->s_name);
else {
char buf[32];
snprintf(buf, sizeof(buf), "%d", port);
lua_pushstring(vm, buf);
}
return(CONST_LUA_OK);
}
/* ****************************************** */
// ***API***
static int ntop_msleep(lua_State* vm) {
u_int duration, max_duration = 60000 /* 1 min */;
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
if(ntop_lua_check(vm, __FUNCTION__, 1, LUA_TNUMBER) != CONST_LUA_OK) return(CONST_LUA_ERROR);
duration = (u_int)lua_tonumber(vm, 1);
if(duration > max_duration) duration = max_duration;
_usleep(duration*1000);
lua_pushnil(vm);
return(CONST_LUA_OK);
}
/* ****************************************** */
/* https://www.linuxquestions.org/questions/programming-9/connect-timeout-change-145433/ */
static int non_blocking_connect(int sock, struct sockaddr_in *sa, int timeout) {
int flags = 0, error = 0, ret = 0;
fd_set rset, wset;
socklen_t len = sizeof(error);
struct timeval ts;
ts.tv_sec = timeout, ts.tv_usec = 0;
//clear out descriptor sets for select
//add socket to the descriptor sets
FD_ZERO(&rset);
FD_SET(sock, &rset);
wset = rset; //structure assignment ok
#ifdef WIN32
// Wndows sockets are created in blocking mode by default
// currently on windows, there is no easy way to obtain the socket's current blocking mode since WSAIsBlocking was deprecated
u_long f = 1;
if(ioctlsocket(sock, FIONBIO, &f) != NO_ERROR)
return -1;
#else
//set socket nonblocking flag
if((flags = fcntl(sock, F_GETFL, 0)) < 0)
return -1;
if(fcntl(sock, F_SETFL, flags | O_NONBLOCK) < 0)
return -1;
#endif
//initiate non-blocking connect
if( (ret = connect(sock, (struct sockaddr *)sa, sizeof(struct sockaddr_in))) < 0 )
if(errno != EINPROGRESS)
return -1;
if(ret == 0) // then connect succeeded right away
goto done;
//we are waiting for connect to complete now
if( (ret = select(sock + 1, &rset, &wset, NULL, (timeout) ? &ts : NULL)) < 0)
return -1;
if(ret == 0) {
// we had a timeout
errno = ETIMEDOUT;
return -1;
}
// we had a positivite return so a descriptor is ready
if(FD_ISSET(sock, &rset) || FD_ISSET(sock, &wset)){
if(getsockopt(sock, SOL_SOCKET, SO_ERROR,
#ifdef WIN32
(char*)
#endif
&error, &len) < 0)
return -1;
}else
return -1;
if(error){ //check if we had a socket error
errno = error;
return -1;
}
done:
#ifdef WIN32
f = 0;
if(ioctlsocket(sock, FIONBIO, &f) != NO_ERROR)
return -1;
#else
//put socket back in blocking mode
if(fcntl(sock, F_SETFL, flags) < 0)
return -1;
#endif
return 0;
}
/* ****************************************** */
/* Millisecond sleep */
static int ntop_tcp_probe(lua_State* vm) {
char *server_ip;
u_int server_port, timeout = 3;
int sockfd;
struct sockaddr_in serv_addr;
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
if(ntop_lua_check(vm, __FUNCTION__, 1, LUA_TSTRING) != CONST_LUA_OK) return(CONST_LUA_ERROR);
server_ip = (char*)lua_tostring(vm, 1);
if(ntop_lua_check(vm, __FUNCTION__, 2, LUA_TNUMBER) != CONST_LUA_OK) return(CONST_LUA_ERROR);
server_port = (u_int)lua_tonumber(vm, 2);
if(lua_type(vm, 3) == LUA_TNUMBER) timeout = (u_int16_t)lua_tonumber(vm, 3);
if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
return(CONST_LUA_ERROR);
memset(&serv_addr, '0', sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(server_port);
serv_addr.sin_addr.s_addr = inet_addr(server_ip);
if(non_blocking_connect(sockfd, &serv_addr, timeout) < 0)
lua_pushnil(vm);
else {
u_int timeout = 1, offset = 0;
char buf[512];
while(true) {
fd_set rset;
struct timeval tv;
int rc;
FD_ZERO(&rset);
FD_SET(sockfd, &rset);
tv.tv_sec = timeout, tv.tv_usec = 0;
rc = select(sockfd + 1, &rset, NULL, NULL, &tv);
timeout = 0;
if(rc <= 0)
break;
else {
int l = read(sockfd, &buf[offset], sizeof(buf)-offset-1);
if(l <= 0)
break;
else
offset += l;
}
}
buf[offset] = 0;
lua_pushstring(vm, buf);
}
closesocket(sockfd);
return(CONST_LUA_OK);
}
/* ****************************************** */
// ***API***
static int ntop_list_dir_files(lua_State* vm) {
char *path;
DIR *dirp;
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
if(ntop_lua_check(vm, __FUNCTION__, 1, LUA_TSTRING) != CONST_LUA_OK) return(CONST_LUA_ERROR);
path = (char*)lua_tostring(vm, 1);
ntop->fixPath(path);
lua_newtable(vm);
if((dirp = opendir(path)) != NULL) {
struct dirent *dp;
while ((dp = readdir(dirp)) != NULL)
if((dp->d_name[0] != '\0')
&& (dp->d_name[0] != '.')) {
lua_push_str_table_entry(vm, dp->d_name, dp->d_name);
}
(void)closedir(dirp);
}
return(CONST_LUA_OK);
}
/* ****************************************** */
// ***API***
static int ntop_remove_dir_recursively(lua_State* vm) {
char *path = NULL;
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
if(lua_type(vm, 1) == LUA_TSTRING)
path = (char*)lua_tostring(vm, 1);
if(path)
ntop->fixPath(path);
lua_pushboolean(vm, path && !Utils::remove_recursively(path) ? true /* OK */ : false /* Errors */);
return(CONST_LUA_OK);
}
/* ****************************************** */
// ***API***
static int ntop_gettimemsec(lua_State* vm) {
struct timeval tp;
double ret;
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
gettimeofday(&tp, NULL);
ret = (((double)tp.tv_usec) / (double)1000000) + tp.tv_sec;
lua_pushnumber(vm, ret);
return(CONST_LUA_OK);
}
/* ****************************************** */
// ***API***
static int ntop_getticks(lua_State* vm) {
lua_pushnumber(vm, Utils::getticks());
return(CONST_LUA_OK);
}
/* ****************************************** */
// ***API***
static int ntop_gettickspersec(lua_State* vm) {
lua_pushnumber(vm, Utils::gettickspersec());
return(CONST_LUA_OK);
}
/**
* @brief Refreshes the timezone after a change
*
* @param vm The lua state.
* @return CONST_LUA_OK.
*/
static int ntop_tzset(lua_State* vm) {
#ifndef WIN32
tzset();
#endif
lua_pushnil(vm);
return(CONST_LUA_OK);
}
/* ****************************************** */
static int ntop_round_time(lua_State* vm) {
time_t now;
u_int32_t rounder;
bool align_to_localtime;
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
if(ntop_lua_check(vm, __FUNCTION__, 1, LUA_TNUMBER) != CONST_LUA_OK) return(CONST_LUA_PARAM_ERROR);
now = lua_tonumber(vm, 1);
if(ntop_lua_check(vm, __FUNCTION__, 2, LUA_TNUMBER) != CONST_LUA_OK) return(CONST_LUA_PARAM_ERROR);
rounder = lua_tonumber(vm, 2);
if(ntop_lua_check(vm, __FUNCTION__, 3, LUA_TBOOLEAN) != CONST_LUA_OK) return(CONST_LUA_PARAM_ERROR);
align_to_localtime = lua_toboolean(vm, 3);
lua_pushinteger(vm, Utils::roundTime(now, rounder, align_to_localtime ? ntop->get_time_offset() : 0));
return(CONST_LUA_OK);
}
/* ****************************************** */
// ***API***
static int ntop_inet_ntoa(lua_State* vm) {
u_int32_t ip;
struct in_addr in;
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
if(lua_type(vm, 1) == LUA_TSTRING)
ip = atol((char*)lua_tostring(vm, 1));
else if(lua_type(vm, 1) == LUA_TNUMBER)
ip = (u_int32_t)lua_tonumber(vm, 1);
else
return(CONST_LUA_ERROR);
in.s_addr = htonl(ip);
lua_pushstring(vm, inet_ntoa(in));
return(CONST_LUA_OK);
}
/* ****************************************** */
// ***API***
static int ntop_network_prefix(lua_State* vm) {
char *address;
char buf[64];
u_int8_t mask;
IpAddress ip;
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
if(ntop_lua_check(vm, __FUNCTION__, 1, LUA_TSTRING) != CONST_LUA_OK) return(CONST_LUA_PARAM_ERROR);
if((address = (char*)lua_tostring(vm, 1)) == NULL) return(CONST_LUA_PARAM_ERROR);
if(ntop_lua_check(vm, __FUNCTION__, 2, LUA_TNUMBER) != CONST_LUA_OK) return(CONST_LUA_PARAM_ERROR);
mask = (int)lua_tonumber(vm, 2);
ip.set(address);
lua_pushstring(vm, ip.print(buf, sizeof(buf), mask));
return(CONST_LUA_OK);
}
/* ****************************************** */
#ifndef HAVE_NEDGE
static int ntop_zmq_connect(lua_State* vm) {
char *endpoint, *topic;
void *context, *subscriber;
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
if(ntop_lua_check(vm, __FUNCTION__, 1, LUA_TSTRING) != CONST_LUA_OK) return(CONST_LUA_PARAM_ERROR);
if((endpoint = (char*)lua_tostring(vm, 1)) == NULL) return(CONST_LUA_PARAM_ERROR);
if(ntop_lua_check(vm, __FUNCTION__, 2, LUA_TSTRING) != CONST_LUA_OK) return(CONST_LUA_PARAM_ERROR);
if((topic = (char*)lua_tostring(vm, 2)) == NULL) return(CONST_LUA_PARAM_ERROR);
context = zmq_ctx_new(), subscriber = zmq_socket(context, ZMQ_SUB);
if(zmq_connect(subscriber, endpoint) != 0) {
zmq_close(subscriber);
zmq_ctx_destroy(context);
return(CONST_LUA_PARAM_ERROR);
}
if(zmq_setsockopt(subscriber, ZMQ_SUBSCRIBE, topic, strlen(topic)) != 0) {
zmq_close(subscriber);
zmq_ctx_destroy(context);
return -1;
}
getLuaVMUservalue(vm, zmq_context) = context;
getLuaVMUservalue(vm, zmq_subscriber) = subscriber;
lua_pushnil(vm);
return(CONST_LUA_OK);
}
#endif
/* ****************************************** */
// ***API***
static int ntop_get_redis_stats(lua_State* vm) {
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
ntop->getRedis()->lua(vm);
return(CONST_LUA_OK);
}
/* ****************************************** */
static int ntop_delete_redis_key(lua_State* vm) {
char *key;
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
if(ntop_lua_check(vm, __FUNCTION__, 1, LUA_TSTRING) != CONST_LUA_OK) return(CONST_LUA_PARAM_ERROR);
if((key = (char*)lua_tostring(vm, 1)) == NULL) return(CONST_LUA_PARAM_ERROR);
ntop->getRedis()->del(key);
lua_pushnil(vm);
return(CONST_LUA_OK);
}
/* ****************************************** */
// ***API***
static int ntop_flush_redis(lua_State* vm) {
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
if(!ntop->isUserAdministrator(vm))
return(CONST_LUA_ERROR);
lua_pushboolean(vm, (ntop->getRedis()->flushDb() == 0) ? true : false);
return(CONST_LUA_OK);
}
/* ****************************************** */
// ***API***
static int ntop_add_set_member_redis(lua_State* vm) {
char *key, *value;
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
if(ntop_lua_check(vm, __FUNCTION__, 1, LUA_TSTRING) != CONST_LUA_OK) return(CONST_LUA_PARAM_ERROR);
if((key = (char*)lua_tostring(vm, 1)) == NULL) return(CONST_LUA_PARAM_ERROR);
if(ntop_lua_check(vm, __FUNCTION__, 2, LUA_TSTRING) != CONST_LUA_OK) return(CONST_LUA_PARAM_ERROR);
if((value = (char*)lua_tostring(vm, 2)) == NULL) return(CONST_LUA_PARAM_ERROR);
if(ntop->getRedis()->sadd(key, value) == 0) {
lua_pushnil(vm);
return(CONST_LUA_OK);
} else
return(CONST_LUA_ERROR);
}
/* ****************************************** */
// ***API***
static int ntop_del_set_member_redis(lua_State* vm) {
char *key, *value;
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
if(ntop_lua_check(vm, __FUNCTION__, 1, LUA_TSTRING) != CONST_LUA_OK) return(CONST_LUA_PARAM_ERROR);
if((key = (char*)lua_tostring(vm, 1)) == NULL) return(CONST_LUA_PARAM_ERROR);
if(ntop_lua_check(vm, __FUNCTION__, 2, LUA_TSTRING) != CONST_LUA_OK) return(CONST_LUA_PARAM_ERROR);
if((value = (char*)lua_tostring(vm, 2)) == NULL) return(CONST_LUA_PARAM_ERROR);
if(ntop->getRedis()->srem(key, value) == 0) {
lua_pushnil(vm);
return(CONST_LUA_OK);
} else
return(CONST_LUA_ERROR);
}
/* ****************************************** */
// ***API***
static int ntop_get_set_members_redis(lua_State* vm) {
char *key;
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
if(ntop_lua_check(vm, __FUNCTION__, 1, LUA_TSTRING) != CONST_LUA_OK) return(CONST_LUA_PARAM_ERROR);
if((key = (char*)lua_tostring(vm, 1)) == NULL) return(CONST_LUA_PARAM_ERROR);
ntop->getRedis()->smembers(vm, key);
return(CONST_LUA_OK);
}
/* ****************************************** */
#ifndef HAVE_NEDGE
static int ntop_zmq_disconnect(lua_State* vm) {
void *context;
void *subscriber;
context = getLuaVMUserdata(vm, zmq_context);
subscriber = getLuaVMUserdata(vm, zmq_subscriber);
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
zmq_close(subscriber);
zmq_ctx_destroy(context);
lua_pushnil(vm);
return(CONST_LUA_OK);
}
#endif
/* ****************************************** */
#ifndef HAVE_NEDGE
static int ntop_zmq_receive(lua_State* vm) {
NetworkInterface *ntop_interface = getCurrentInterface(vm);
void *subscriber;
int size;
struct zmq_msg_hdr h;
char *payload;
int payload_len;
zmq_pollitem_t item;
int rc;
subscriber = getLuaVMUserdata(vm, zmq_subscriber);
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
item.socket = subscriber;
item.events = ZMQ_POLLIN;
do {
rc = zmq_poll(&item, 1, 1000);
if(rc < 0 || !ntop_interface->isRunning()) /* CHECK */
return(CONST_LUA_PARAM_ERROR);
} while (rc == 0);
size = zmq_recv(subscriber, &h, sizeof(h), 0);
if(size != sizeof(h) || h.version != ZMQ_MSG_VERSION) {
ntop->getTrace()->traceEvent(TRACE_WARNING, "Unsupported publisher version [%d]", h.version);
return -1;
}
payload_len = h.size + 1;
if((payload = (char*)malloc(payload_len)) != NULL) {
size = zmq_recv(subscriber, payload, payload_len, 0);
payload[h.size] = '\0';
if(size > 0) {
enum json_tokener_error jerr = json_tokener_success;
json_object *o = json_tokener_parse_verbose(payload, &jerr);
if(o != NULL) {
struct json_object_iterator it = json_object_iter_begin(o);
struct json_object_iterator itEnd = json_object_iter_end(o);
while (!json_object_iter_equal(&it, &itEnd)) {
char *key = (char*)json_object_iter_peek_name(&it);
const char *value = json_object_get_string(json_object_iter_peek_value(&it));
ntop->getTrace()->traceEvent(TRACE_NORMAL, "[%s]=[%s]", key, value);
json_object_iter_next(&it);
}
json_object_put(o);
} else
ntop->getTrace()->traceEvent(TRACE_WARNING, "JSON Parse error [%s]: %s",
json_tokener_error_desc(jerr),
payload);
lua_pushfstring(vm, "%s", payload);
ntop->getTrace()->traceEvent(TRACE_INFO, "[%u] %s", h.size, payload);
free(payload);
return(CONST_LUA_OK);
} else {
free(payload);
return(CONST_LUA_PARAM_ERROR);
}
} else
return(CONST_LUA_PARAM_ERROR);
}
#endif
/* ****************************************** */
// ***API***
static int ntop_reload_preferences(lua_State* vm) {
lua_newtable(vm);
ntop->getPrefs()->reloadPrefsFromRedis();
return(CONST_LUA_OK);
}
/* ****************************************** */
static int ntop_check_hosts_alerts(lua_State* vm, ScriptPeriodicity p) {
NetworkInterface *ntop_interface = getCurrentInterface(vm);
if(!ntop_interface)
return(CONST_LUA_ERROR);
else
ntop_interface->checkHostsAlerts(p);
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) {
NetworkInterface *ntop_interface = getCurrentInterface(vm);
if(!ntop_interface)
return(CONST_LUA_ERROR);
else
ntop_interface->checkNetworksAlerts(p);
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) {
NetworkInterface *ntop_interface = getCurrentInterface(vm);
if(!ntop_interface)
return(CONST_LUA_ERROR);
else
ntop_interface->checkInterfaceAlerts(p);
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_check_system_scripts(lua_State* vm, ScriptPeriodicity p) {
ntop->checkSystemScripts(p);
lua_pushnil(vm);
return(CONST_LUA_OK);
}
static int ntop_check_system_scripts_min(lua_State* vm) { return(ntop_check_system_scripts(vm, minute_script)); }
static int ntop_check_system_scripts_5min(lua_State* vm) { return(ntop_check_system_scripts(vm, five_minute_script)); }
static int ntop_check_system_scripts_hour(lua_State* vm) { return(ntop_check_system_scripts(vm, hour_script)); }
static int ntop_check_system_scripts_day(lua_State* vm) { return(ntop_check_system_scripts(vm, day_script)); }
/* ****************************************** */
static int ntop_check_snmp_device_alerts(lua_State* vm, ScriptPeriodicity p) {
ntop->checkSNMPDeviceAlerts(p);
lua_pushnil(vm);
return(CONST_LUA_OK);
}
static int ntop_check_snmp_device_alerts_5min(lua_State* vm) { return(ntop_check_snmp_device_alerts(vm, five_minute_script)); }
/* ****************************************** */
static int ntop_temporary_disable_alerts(lua_State* vm) {
bool to_disable;
if(!ntop->isUserAdministrator(vm)) return(CONST_LUA_ERROR);
if(ntop_lua_check(vm, __FUNCTION__, 1, LUA_TBOOLEAN) != CONST_LUA_OK) return(CONST_LUA_PARAM_ERROR);
to_disable = lua_toboolean(vm, 1);
ntop->getPrefs()->set_alerts_status(!to_disable);
lua_pushnil(vm);
return(CONST_LUA_OK);
}
/* ****************************************** */
static int ntop_set_default_file_permissions(lua_State* vm) {
char *fpath;
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
if(ntop_lua_check(vm, __FUNCTION__, 1, LUA_TSTRING) != CONST_LUA_OK) return(CONST_LUA_ERROR);
fpath = (char*)lua_tostring(vm, 1);
if(!fpath)
return(CONST_LUA_ERROR);
#ifndef WIN32
chmod(fpath, CONST_DEFAULT_FILE_MODE);
#endif
lua_pushnil(vm);
return(CONST_LUA_OK);
}
/* ****************************************** */
// ***API***
static int ntop_verbose_trace(lua_State* vm) {
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
lua_pushboolean(vm, (ntop->getTrace()->get_trace_level() == MAX_TRACE_LEVEL) ? true : false);
return(CONST_LUA_OK);
}
/* ****************************************** */
// ***API***
static int ntop_send_udp_data(lua_State* vm) {
int rc, port, sockfd = ntop->getUdpSock();
char *host, *data;
if(sockfd == -1)
return(CONST_LUA_ERROR);
if(ntop_lua_check(vm, __FUNCTION__, 1, LUA_TSTRING) != CONST_LUA_OK) return(CONST_LUA_ERROR);
host = (char*)lua_tostring(vm, 1);
if(ntop_lua_check(vm, __FUNCTION__, 2, LUA_TNUMBER) != CONST_LUA_OK) return(CONST_LUA_ERROR);
port = (u_int16_t)lua_tonumber(vm, 2);
if(ntop_lua_check(vm, __FUNCTION__, 3, LUA_TSTRING) != CONST_LUA_OK) return(CONST_LUA_ERROR);
data = (char*)lua_tostring(vm, 3);
if(strchr(host, ':') != NULL) {
struct sockaddr_in6 server_addr;
memset(&server_addr, 0, sizeof(server_addr));
server_addr.sin6_family = AF_INET6;
inet_pton(AF_INET6, host, &server_addr.sin6_addr);
server_addr.sin6_port = htons(port);
rc = sendto(sockfd, data, strlen(data),0,
(struct sockaddr *)&server_addr,
sizeof(server_addr));
} else {
struct sockaddr_in server_addr;
memset(&server_addr, 0, sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = inet_addr(host); /* FIX: add IPv6 support */
server_addr.sin_port = htons(port);
rc = sendto(sockfd, data, strlen(data),0,
(struct sockaddr *)&server_addr,
sizeof(server_addr));
}
if(rc == -1)
return(CONST_LUA_ERROR);
else {
lua_pushnil(vm);
return(CONST_LUA_OK);
}
}
/* ****************************************** */
static bool is_table_empty(lua_State *L, int index) {
lua_pushnil(L);
if(lua_next(L, index)) {
lua_pop(L, 1);
return(false);
}
return(true);
}
/* ****************************************** */
/* NOTE: outbuf and orig buffers must not overlap */
static inline void influx_escape_char(char *outbuf, int outlen, const char *orig, char to_escape) {
const char *pos;
while((pos = strchr(orig, to_escape)) != NULL) {
int to_copy = (pos - orig);
if((to_copy+3) > outlen) // +3: escape, to_replace, NULL
break;
memcpy(outbuf, orig, to_copy);
outbuf[to_copy] = '\\';
outbuf[to_copy+1] = to_escape;
outbuf += to_copy+2;
outlen -= to_copy+2;
orig = pos+1;
}
if(outlen > 0)
strncpy(outbuf, orig, outlen);
outbuf[outlen-1] = '\0';
}
static inline int influx_concat_table_fields(lua_State *L, int index, char *buf, int size) {
bool first = true;
char val_buf[128];
// table traversal from https://www.lua.org/ftp/refman-5.0.pdf
lua_pushnil(L);
while(lua_next(L, index) != 0) {
influx_escape_char(val_buf, sizeof(val_buf), lua_tostring(L, -1), ' ');
int l = snprintf(buf, size, "%s%s=%s", first ? "" : ",",
lua_tostring(L, -2), val_buf);
buf += l;
size -= l;
first = false;
lua_pop(L, 1);
}
return size;
}
/* ****************************************** */
/* curl -i -XPOST "http://localhost:8086/write?precision=s&db=ntopng" --data-binary 'profile:traffic,ifid=0,profile=a profile bytes=2506351 1559634840' */
static int ntop_append_influx_db(lua_State* vm) {
char data[512], *schema;
int buflen = sizeof(data);
bool rv = false;
time_t tstamp;
NetworkInterface *ntop_interface = getCurrentInterface(vm);
if(!ntop_interface)
return(CONST_LUA_ERROR);
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
if(ntop_lua_check(vm, __FUNCTION__, 1, LUA_TSTRING) != CONST_LUA_OK) return(CONST_LUA_ERROR);
schema = (char*)lua_tostring(vm, 1);
if(ntop_lua_check(vm, __FUNCTION__, 2, LUA_TNUMBER) != CONST_LUA_OK) return(CONST_LUA_ERROR);
tstamp = (time_t)lua_tonumber(vm, 2);
if(ntop_lua_check(vm, __FUNCTION__, 3, LUA_TTABLE) != CONST_LUA_OK) return(CONST_LUA_ERROR);
if(ntop_lua_check(vm, __FUNCTION__, 4, LUA_TTABLE) != CONST_LUA_OK) return(CONST_LUA_ERROR);
// "iface:traffic,ifid=0 bytes=0 1539358699\n"
buflen -= snprintf(data, buflen, is_table_empty(vm, 3) ? "%s" : "%s,", schema);
buflen = influx_concat_table_fields(vm, 3, data + sizeof(data) - buflen, buflen); // tags
buflen -= snprintf(data + sizeof(data) - buflen, buflen, " ");
buflen = influx_concat_table_fields(vm, 4, data + sizeof(data) - buflen, buflen); // metrics
buflen -= snprintf(data + sizeof(data) - buflen, buflen, " %lu\n", tstamp);
if(ntop_interface && ntop_interface->getTSExporter()) {
ntop_interface->getTSExporter()->exportData(data);
rv = true;
}
lua_pushboolean(vm, rv);
return(CONST_LUA_OK);
}
/* ****************************************** */
// ***API***
static int ntop_get_interface_flows_info(lua_State* vm) {
NetworkInterface *ntop_interface = getCurrentInterface(vm);
char buf[64];
char *host_ip = NULL;
u_int16_t vlan_id = 0;
Host *host = NULL;
Paginator *p = NULL;
int numFlows = -1;
u_int32_t begin_slot = 0;
bool walk_all = true;
if(!ntop_interface)
return(CONST_LUA_ERROR);
if((p = new(std::nothrow) Paginator()) == NULL)
return(CONST_LUA_ERROR);
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
if(lua_type(vm, 1) == LUA_TSTRING) {
get_host_vlan_info((char*)lua_tostring(vm, 1), &host_ip, &vlan_id, buf, sizeof(buf));
host = ntop_interface->getHost(host_ip, vlan_id, false /* Not an inline call */);
}
if(lua_type(vm, 2) == LUA_TTABLE)
p->readOptions(vm, 2);
if(ntop_interface
&& (!host_ip || host))
numFlows = ntop_interface->getFlows(vm, &begin_slot, walk_all, get_allowed_nets(vm), host, p);
else
lua_pushnil(vm);
if(p) delete p;
return numFlows < 0 ? CONST_LUA_ERROR : CONST_LUA_OK;
}
/* ****************************************** */
// ***API***
static int ntop_get_batched_interface_flows_info(lua_State* vm) {
NetworkInterface *ntop_interface = getCurrentInterface(vm);
char buf[64];
char *host_ip = NULL;
u_int16_t vlan_id = 0;
Host *host = NULL;
Paginator *p = NULL;
int numFlows = -1;
u_int32_t begin_slot = 0;
bool walk_all = false;
if(!ntop_interface)
return(CONST_LUA_ERROR);
if((p = new(std::nothrow) Paginator()) == NULL)
return(CONST_LUA_ERROR);
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
if(lua_type(vm, 1) == LUA_TNUMBER)
begin_slot = (u_int32_t)lua_tonumber(vm, 1);
if(lua_type(vm, 2) == LUA_TSTRING) {
get_host_vlan_info((char*)lua_tostring(vm, 2), &host_ip, &vlan_id, buf, sizeof(buf));
host = ntop_interface->getHost(host_ip, vlan_id, false /* Not an inline call */);
}
if(lua_type(vm, 3) == LUA_TTABLE)
p->readOptions(vm, 3);
if(ntop_interface
&& (!host_ip || host))
numFlows = ntop_interface->getFlows(vm, &begin_slot, walk_all, get_allowed_nets(vm), host, p);
else
lua_pushnil(vm);
if(p) delete p;
return numFlows < 0 ? CONST_LUA_ERROR : CONST_LUA_OK;
}
/* ****************************************** */
// ***API***
static int ntop_get_interface_get_grouped_flows(lua_State* vm) {
NetworkInterface *ntop_interface = getCurrentInterface(vm);
Paginator *p = NULL;
int numGroups = -1;
const char *group_col;
if(!ntop_interface)
return(CONST_LUA_ERROR);
if(ntop_lua_check(vm, __FUNCTION__, 1, LUA_TSTRING) != CONST_LUA_OK
|| (p = new(std::nothrow) Paginator()) == NULL)
return(CONST_LUA_ERROR);
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
group_col = lua_tostring(vm, 1);
if(lua_type(vm, 2) == LUA_TTABLE)
p->readOptions(vm, 2);
if(ntop_interface)
numGroups = ntop_interface->getFlowsGroup(vm, get_allowed_nets(vm), p, group_col);
else
lua_pushnil(vm);
delete p;
return numGroups < 0 ? CONST_LUA_ERROR : CONST_LUA_OK;
}
/* ****************************************** */
// ***API***
static int ntop_get_interface_flows_stats(lua_State* vm) {
NetworkInterface *ntop_interface = getCurrentInterface(vm);
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
if(ntop_interface) ntop_interface->getFlowsStats(vm);
return(CONST_LUA_OK);
}
/* ****************************************** */
// ***API***
static int ntop_network_get_network_stats(lua_State* vm) {
struct ntopngLuaContext *c = getLuaVMContext(vm);
NetworkStats *ns = c ? c->network : NULL;
if(ns) {
lua_newtable(vm);
ns->lua(vm);
} else
lua_pushnil(vm);
return(CONST_LUA_OK);
}
/* ****************************************** */
// ***API***
static int ntop_get_interface_networks_stats(lua_State* vm) {
NetworkInterface *ntop_interface = getCurrentInterface(vm);
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
if(ntop_interface)
ntop_interface->getNetworksStats(vm);
else
lua_pushnil(vm);
return(CONST_LUA_OK);
}
/* ****************************************** */
// ***API***
static int ntop_get_interface_network_stats(lua_State* vm) {
NetworkInterface *ntop_interface = getCurrentInterface(vm);
u_int8_t network_id;
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
if(ntop_lua_check(vm, __FUNCTION__, 1, LUA_TNUMBER) != CONST_LUA_OK) return(CONST_LUA_ERROR);
network_id = (u_int8_t)lua_tointeger(vm, 1);
if(ntop_interface) {
lua_newtable(vm);
ntop_interface->getNetworkStats(vm, network_id);
} else
lua_pushnil(vm);
return(CONST_LUA_OK);
}
/* ****************************************** */
// ***API***
static int ntop_checkpoint_host_talker(lua_State* vm) {
int ifid;
NetworkInterface *iface = NULL;
char *host_ip;
u_int16_t vlan_id = 0;
char buf[64];
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
if(ntop_lua_check(vm, __FUNCTION__, 1, LUA_TNUMBER) != CONST_LUA_OK) return(CONST_LUA_ERROR);
if(ntop_lua_check(vm, __FUNCTION__, 2, LUA_TSTRING) != CONST_LUA_OK) return(CONST_LUA_ERROR);
ifid = (int)lua_tointeger(vm, 1);
iface = ntop->getInterfaceById(ifid);
get_host_vlan_info((char*)lua_tostring(vm, 2), &host_ip, &vlan_id, buf, sizeof(buf));
if(iface && !iface->isView())
iface->checkPointHostTalker(vm, host_ip, vlan_id);
else
lua_pushnil(vm);
return(CONST_LUA_OK);
}
/* ****************************************** */
// ***API***
static int ntop_get_interface_host_info(lua_State* vm) {
NetworkInterface *ntop_interface = getCurrentInterface(vm);
char *host_ip;
u_int16_t vlan_id = 0;
char buf[64];
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
if(ntop_lua_check(vm, __FUNCTION__, 1, LUA_TSTRING) != CONST_LUA_OK) return(CONST_LUA_ERROR);
get_host_vlan_info((char*)lua_tostring(vm, 1), &host_ip, &vlan_id, buf, sizeof(buf));
/* Optional VLAN id */
if(lua_type(vm, 2) == LUA_TNUMBER) vlan_id = (u_int16_t)lua_tonumber(vm, 2);
if((!ntop_interface) || !ntop_interface->getHostInfo(vm, get_allowed_nets(vm), host_ip, vlan_id))
return(CONST_LUA_ERROR);
else
return(CONST_LUA_OK);
}
/* ****************************************** */
static int ntop_get_interface_host_used_ports(lua_State* vm) {
NetworkInterface *ntop_interface = getCurrentInterface(vm);
char *host_ip;
u_int16_t vlan_id = 0;
char buf[64];
Host *h;
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
if(ntop_lua_check(vm, __FUNCTION__, 1, LUA_TSTRING) != CONST_LUA_OK) return(CONST_LUA_ERROR);
get_host_vlan_info((char*)lua_tostring(vm, 1), &host_ip, &vlan_id, buf, sizeof(buf));
/* Optional VLAN id */
if(lua_type(vm, 2) == LUA_TNUMBER) vlan_id = (u_int16_t)lua_tonumber(vm, 2);
if(!ntop_interface) return(CONST_LUA_ERROR);
h = ntop_interface->findHostByIP(get_allowed_nets(vm), host_ip, vlan_id);
if(!h)
return(CONST_LUA_ERROR);
else {
h->luaPortsDump(vm);
return(CONST_LUA_OK);
}
}
/* ****************************************** */
static int ntop_get_interface_host_timeseries(lua_State* vm) {
NetworkInterface *ntop_interface = getCurrentInterface(vm);
char *host_ip;
u_int16_t vlan_id = 0;
char buf[64];
Host *h;
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
if(ntop_lua_check(vm, __FUNCTION__, 1, LUA_TSTRING) != CONST_LUA_OK) return(CONST_LUA_ERROR);
get_host_vlan_info((char*)lua_tostring(vm, 1), &host_ip, &vlan_id, buf, sizeof(buf));
/* Optional VLAN id */
if(lua_type(vm, 2) == LUA_TNUMBER) vlan_id = (u_int16_t)lua_tonumber(vm, 2);
if((!ntop_interface) || !(h = ntop_interface->getHost(host_ip, vlan_id, false /* Not an inline call */)))
return(CONST_LUA_ERROR);
else {
h->tsLua(vm);
return(CONST_LUA_OK);
}
}
/* ****************************************** */
static int ntop_get_interface_timeseries(lua_State* vm) {
NetworkInterface *ntop_interface = getCurrentInterface(vm);
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
if(!ntop_interface)
return(CONST_LUA_ERROR);
else {
ntop_interface->tsLua(vm);
return(CONST_LUA_OK);
}
}
/* ****************************************** */
// ***API***
static int ntop_get_interface_host_country(lua_State* vm) {
NetworkInterface *ntop_interface = getCurrentInterface(vm);
char *host_ip;
u_int16_t vlan_id = 0;
char buf[64];
Host* h = NULL;
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
if(ntop_lua_check(vm, __FUNCTION__, 1, LUA_TSTRING) != CONST_LUA_OK) return(CONST_LUA_ERROR);
get_host_vlan_info((char*)lua_tostring(vm, 1), &host_ip, &vlan_id, buf, sizeof(buf));
if((!ntop_interface) || ((h = ntop_interface->findHostByIP(get_allowed_nets(vm), host_ip, vlan_id)) == NULL))
return(CONST_LUA_ERROR);
else {
lua_pushstring(vm, h->get_country(buf, sizeof(buf)));
return(CONST_LUA_OK);
}
}
/* ****************************************** */
#ifdef NOTUSED
static int ntop_get_grouped_interface_host(lua_State* vm) {
NetworkInterface *ntop_interface = getCurrentInterface(vm);
char *country_s = NULL, *os_s = NULL;
u_int16_t vlan_n, *vlan_ptr = NULL;
u_int32_t as_n, *as_ptr = NULL;
int16_t network_n, *network_ptr = NULL;
u_int32_t begin_slot = 0;
bool walk_all = true;
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
if(lua_type(vm, 1) == LUA_TNUMBER) vlan_n = (u_int16_t)lua_tonumber(vm, 1), vlan_ptr = &vlan_n;
if(lua_type(vm, 2) == LUA_TNUMBER) as_n = (u_int32_t)lua_tonumber(vm, 2), as_ptr = &as_n;
if(lua_type(vm, 3) == LUA_TNUMBER) network_n = (int16_t)lua_tonumber(vm, 3), network_ptr = &network_n;
if(lua_type(vm, 4) == LUA_TSTRING) country_s = (char*)lua_tostring(vm, 4);
if(lua_type(vm, 5) == LUA_TSTRING) os_s = (char*)lua_tostring(vm, 5);
if(!ntop_interface
|| ntop_interface->getActiveHostsGroup(vm,
&begin_slot, walk_all,
get_allowed_nets(vm), false, false,
country_s, vlan_ptr, os_s, as_ptr,
network_ptr, (char*)"column_ip", (char*)"country",
CONST_MAX_NUM_HITS, 0 /* toSkip */, true /* a2zSortOrder */) < 0)
return(CONST_LUA_ERROR);
return(CONST_LUA_OK);
}
#endif
/* ****************************************** */
#ifdef NTOPNG_PRO
static int ntop_get_flow_devices(lua_State* vm) {
NetworkInterface *ntop_interface = getCurrentInterface(vm);
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
if(!ntop_interface)
return(CONST_LUA_ERROR);
else {
ntop_interface->getFlowDevices(vm);
return(CONST_LUA_OK);
}
}
/* ****************************************** */
static int ntop_get_flow_device_info(lua_State* vm) {
NetworkInterface *ntop_interface = getCurrentInterface(vm);
char *device_ip;
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
if(ntop_lua_check(vm, __FUNCTION__, 1, LUA_TSTRING) != CONST_LUA_OK) return(CONST_LUA_ERROR);
device_ip = (char*)lua_tostring(vm, 1);
if(!ntop_interface)
return(CONST_LUA_ERROR);
else {
in_addr_t addr = inet_addr(device_ip);
ntop_interface->getFlowDeviceInfo(vm, ntohl(addr));
return(CONST_LUA_OK);
}
}
#endif
/* ****************************************** */
static int ntop_discover_iface_hosts(lua_State* vm) {
NetworkInterface *ntop_interface = getCurrentInterface(vm);
u_int timeout = 3; /* sec */
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
if(!ntop_interface)
return(CONST_LUA_ERROR);
if(lua_type(vm, 1) == LUA_TNUMBER) timeout = (u_int)lua_tonumber(vm, 1);
if(ntop_interface->getNetworkDiscovery()) {
/* TODO: do it periodically and not inline */
try {
ntop_interface->getNetworkDiscovery()->discover(vm, timeout);
} catch(...) {
ntop->getTrace()->traceEvent(TRACE_WARNING, "Unable to perform network discovery");
}
return(CONST_LUA_OK);
} else
return(CONST_LUA_ERROR);
}
/* ****************************************** */
static int ntop_arpscan_iface_hosts(lua_State* vm) {
NetworkInterface *ntop_interface = getCurrentInterface(vm);
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
if(!ntop_interface)
return(CONST_LUA_ERROR);
if(ntop_interface->getMDNS()) {
/* This is a device we can use for network discovery */
try {
NetworkDiscovery *d;
#if !defined(__APPLE__) && !defined(WIN32) && !defined(HAVE_NEDGE)
if(Utils::gainWriteCapabilities() == -1)
ntop->getTrace()->traceEvent(TRACE_ERROR, "Unable to enable capabilities");
#endif
d = ntop_interface->getNetworkDiscovery();
#if !defined(__APPLE__) && !defined(WIN32) && !defined(HAVE_NEDGE)
Utils::dropWriteCapabilities();
#endif
if(d)
d->arpScan(vm);
} catch(...) {
ntop->getTrace()->traceEvent(TRACE_WARNING, "Unable to perform network scan");
#if !defined(__APPLE__) && !defined(WIN32) && !defined(HAVE_NEDGE)
Utils::dropWriteCapabilities();
#endif
}
return(CONST_LUA_OK);
} else
return(CONST_LUA_ERROR);
}
/* ****************************************** */
static int ntop_mdns_resolve_name(lua_State* vm) {
char *numIP, symIP[64];
NetworkInterface *ntop_interface = getCurrentInterface(vm);
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
if(ntop_lua_check(vm, __FUNCTION__, 1, LUA_TSTRING) != CONST_LUA_OK) return(CONST_LUA_PARAM_ERROR);
if((numIP = (char*)lua_tostring(vm, 1)) == NULL) return(CONST_LUA_PARAM_ERROR);
if(!ntop_interface)
return(CONST_LUA_ERROR);
lua_pushstring(vm, ntop_interface->mdnsResolveIPv4(inet_addr(numIP),
symIP, sizeof(symIP),
1 /* timeout */));
return(CONST_LUA_OK);
}
/* ****************************************** */
static int ntop_mdns_batch_any_query(lua_State* vm) {
char *query, *target;
NetworkInterface *ntop_interface = getCurrentInterface(vm);
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
if(ntop_lua_check(vm, __FUNCTION__, 1, LUA_TSTRING) != CONST_LUA_OK) return(CONST_LUA_PARAM_ERROR);
if((target = (char*)lua_tostring(vm, 1)) == NULL) return(CONST_LUA_PARAM_ERROR);
if(ntop_lua_check(vm, __FUNCTION__, 2, LUA_TSTRING) != CONST_LUA_OK) return(CONST_LUA_PARAM_ERROR);
if((query = (char*)lua_tostring(vm, 2)) == NULL) return(CONST_LUA_PARAM_ERROR);
if(!ntop_interface)
return(CONST_LUA_ERROR);
ntop_interface->mdnsSendAnyQuery(target, query);
lua_pushnil(vm);
return(CONST_LUA_OK);
}
/* ****************************************** */
#ifndef HAVE_NEDGE
static int ntop_snmp_batch_get(lua_State* vm) {
NetworkInterface *ntop_interface = getCurrentInterface(vm);
char *oid[SNMP_MAX_NUM_OIDS] = { NULL };
SNMP *snmp;
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
if(!ntop_interface)
return(CONST_LUA_ERROR);
if(ntop_lua_check(vm, __FUNCTION__, 1, LUA_TSTRING) != CONST_LUA_OK) return(CONST_LUA_PARAM_ERROR);
if(ntop_lua_check(vm, __FUNCTION__, 2, LUA_TSTRING) != CONST_LUA_OK) return(CONST_LUA_PARAM_ERROR);
if(ntop_lua_check(vm, __FUNCTION__, 3, LUA_TSTRING) != CONST_LUA_OK) return(CONST_LUA_PARAM_ERROR);
if(ntop_lua_check(vm, __FUNCTION__, 4, LUA_TNUMBER) != CONST_LUA_OK) return(CONST_LUA_ERROR);
oid[0] = (char*)lua_tostring(vm, 3);
snmp = getLuaVMUserdata(vm, snmp);
if(snmp == NULL) {
snmp = new SNMP();
if(!snmp) return(CONST_LUA_ERROR);
getLuaVMUservalue(vm, snmp) = snmp;
}
snmp->send_snmp_request((char*)lua_tostring(vm, 1),
(char*)lua_tostring(vm, 2),
false /* SNMP GET */, oid,
(u_int)lua_tonumber(vm, 4));
return(CONST_LUA_OK);
}
#endif
/* ****************************************** */
#ifndef HAVE_NEDGE
static int ntop_snmp_read_responses(lua_State* vm) {
NetworkInterface *ntop_interface = getCurrentInterface(vm);
SNMP *snmp;
snmp = getLuaVMUserdata(vm, snmp);
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
if((!ntop_interface) || (!snmp))
return(CONST_LUA_ERROR);
snmp->snmp_fetch_responses(vm);
return(CONST_LUA_OK);
}
#endif
/* ****************************************** */
static int ntop_mdns_queue_name_to_resolve(lua_State* vm) {
char *numIP;
NetworkInterface *ntop_interface = getCurrentInterface(vm);
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
if(ntop_lua_check(vm, __FUNCTION__, 1, LUA_TSTRING) != CONST_LUA_OK) return(CONST_LUA_PARAM_ERROR);
if((numIP = (char*)lua_tostring(vm, 1)) == NULL) return(CONST_LUA_PARAM_ERROR);
if(!ntop_interface)
return(CONST_LUA_ERROR);
ntop_interface->mdnsQueueResolveIPv4(inet_addr(numIP), true);
lua_pushnil(vm);
return(CONST_LUA_OK);
}
/* ****************************************** */
static int ntop_mdns_read_queued_responses(lua_State* vm) {
NetworkInterface *ntop_interface = getCurrentInterface(vm);
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
if(!ntop_interface)
return(CONST_LUA_ERROR);
ntop_interface->mdnsFetchResolveResponses(vm, 2);
return(CONST_LUA_OK);
}
/* ****************************************** */
// ***API***
static int ntop_getsflowdevices(lua_State* vm) {
NetworkInterface *ntop_interface = getCurrentInterface(vm);
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
if(!ntop_interface)
return(CONST_LUA_ERROR);
else {
ntop_interface->getSFlowDevices(vm);
return(CONST_LUA_OK);
}
}
/* ****************************************** */
// ***API***
static int ntop_getsflowdeviceinfo(lua_State* vm) {
NetworkInterface *ntop_interface = getCurrentInterface(vm);
char *device_ip;
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
if(ntop_lua_check(vm, __FUNCTION__, 1, LUA_TSTRING) != CONST_LUA_OK) return(CONST_LUA_ERROR);
device_ip = (char*)lua_tostring(vm, 1);
if(!ntop_interface)
return(CONST_LUA_ERROR);
else {
in_addr_t addr = inet_addr(device_ip);
ntop_interface->getSFlowDeviceInfo(vm, ntohl(addr));
return(CONST_LUA_OK);
}
}
/* ****************************************** */
static int ntop_restore_interface_host(lua_State* vm) {
NetworkInterface *ntop_interface = getCurrentInterface(vm);
char *host_ip;
u_int16_t vlan_id = 0;
bool skip_privileges_check = false;
char buf[64];
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
if(ntop_lua_check(vm, __FUNCTION__, 1, LUA_TSTRING) != CONST_LUA_OK) return(CONST_LUA_ERROR);
get_host_vlan_info((char*)lua_tostring(vm, 1), &host_ip, &vlan_id, buf, sizeof(buf));
/* make sure skip privileges check cannot be set from the web interface */
if(lua_type(vm, 2) == LUA_TBOOLEAN) skip_privileges_check = lua_toboolean(vm, 2);
if(!skip_privileges_check && !ntop->isUserAdministrator(vm)) return(CONST_LUA_ERROR);
if((!ntop_interface) || !ntop_interface->restoreHost(host_ip, vlan_id))
return(CONST_LUA_ERROR);
else {
lua_pushnil(vm);
return(CONST_LUA_OK);
}
}
/* ****************************************** */
// ***API***
static int ntop_get_interface_flow_key(lua_State* vm) {
NetworkInterface *ntop_interface = getCurrentInterface(vm);
Host *cli, *srv;
char *cli_name = NULL; u_int16_t cli_vlan = 0; u_int16_t cli_port = 0;
char *srv_name = NULL; u_int16_t srv_vlan = 0; u_int16_t srv_port = 0;
u_int16_t protocol;
char cli_buf[256], srv_buf[256];
if(!ntop_interface)
return(CONST_LUA_ERROR);
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
if((ntop_lua_check(vm, __FUNCTION__, 1, LUA_TSTRING) != CONST_LUA_OK) /* cli_host@cli_vlan */
|| (ntop_lua_check(vm, __FUNCTION__, 2, LUA_TNUMBER) != CONST_LUA_OK) /* cli port */
|| (ntop_lua_check(vm, __FUNCTION__, 3, LUA_TSTRING) != CONST_LUA_OK) /* srv_host@srv_vlan */
|| (ntop_lua_check(vm, __FUNCTION__, 4, LUA_TNUMBER) != CONST_LUA_OK) /* srv port */
|| (ntop_lua_check(vm, __FUNCTION__, 5, LUA_TNUMBER) != CONST_LUA_OK) /* protocol */
) return(CONST_LUA_ERROR);
get_host_vlan_info((char*)lua_tostring(vm, 1), &cli_name, &cli_vlan, cli_buf, sizeof(cli_buf));
cli_port = htons((u_int16_t)lua_tonumber(vm, 2));
get_host_vlan_info((char*)lua_tostring(vm, 3), &srv_name, &srv_vlan, srv_buf, sizeof(srv_buf));
srv_port = htons((u_int16_t)lua_tonumber(vm, 4));
protocol = (u_int16_t)lua_tonumber(vm, 5);
if(cli_vlan != srv_vlan) {
ntop->getTrace()->traceEvent(TRACE_ERROR, "Client and Server vlans don't match.");
return(CONST_LUA_ERROR);
}
if(cli_name == NULL || srv_name == NULL
||(cli = ntop_interface->getHost(cli_name, cli_vlan, false /* Not an inline call */)) == NULL
||(srv = ntop_interface->getHost(srv_name, srv_vlan, false /* Not an inline call */)) == NULL) {
lua_pushnil(vm);
} else
lua_pushinteger(vm, Flow::key(cli, cli_port, srv, srv_port, cli_vlan, protocol));
return(CONST_LUA_OK);
}
/* ****************************************** */
// ***API***
static int ntop_get_interface_find_flow_by_key_and_hash_id(lua_State* vm) {
NetworkInterface *ntop_interface = getCurrentInterface(vm);
u_int32_t key;
u_int hash_id;
Flow *f;
AddressTree *ptree = get_allowed_nets(vm);
if(ntop_lua_check(vm, __FUNCTION__, 1, LUA_TNUMBER) != CONST_LUA_OK) return(CONST_LUA_ERROR);
if(ntop_lua_check(vm, __FUNCTION__, 2, LUA_TNUMBER) != CONST_LUA_OK) return(CONST_LUA_ERROR);
key = (u_int32_t)lua_tonumber(vm, 1);
hash_id = (u_int)lua_tonumber(vm, 2);
if(!ntop_interface) return(false);
f = ntop_interface->findFlowByKeyAndHashId(key, hash_id, ptree);
if(f == NULL)
return(CONST_LUA_ERROR);
else {
f->lua(vm, ptree, details_high, false);
return(CONST_LUA_OK);
}
}
/* ****************************************** */
// ***API***
static int ntop_get_interface_find_flow_by_tuple(lua_State* vm) {
NetworkInterface *ntop_interface = getCurrentInterface(vm);
IpAddress src_ip_addr, dst_ip_addr;
u_int16_t vlan_id, src_port, dst_port;
u_int8_t l4_proto;
char *src_ip, *dst_ip;
Flow *f;
AddressTree *ptree = get_allowed_nets(vm);
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
if(!ntop_interface) return(false);
if(ntop_lua_check(vm, __FUNCTION__, 1, LUA_TSTRING) != CONST_LUA_OK) return(CONST_LUA_ERROR);
src_ip = (char*)lua_tostring(vm, 1);
if(ntop_lua_check(vm, __FUNCTION__, 2, LUA_TSTRING) != CONST_LUA_OK) return(CONST_LUA_ERROR);
dst_ip = (char*)lua_tostring(vm, 2);
if(ntop_lua_check(vm, __FUNCTION__, 3, LUA_TNUMBER) != CONST_LUA_OK) return(CONST_LUA_ERROR);
vlan_id = (u_int16_t)lua_tonumber(vm, 3);
if(ntop_lua_check(vm, __FUNCTION__, 4, LUA_TNUMBER) != CONST_LUA_OK) return(CONST_LUA_ERROR);
src_port = (u_int16_t)lua_tonumber(vm, 4);
if(ntop_lua_check(vm, __FUNCTION__, 5, LUA_TNUMBER) != CONST_LUA_OK) return(CONST_LUA_ERROR);
dst_port = (u_int16_t)lua_tonumber(vm, 5);
if(ntop_lua_check(vm, __FUNCTION__, 6, LUA_TNUMBER) != CONST_LUA_OK) return(CONST_LUA_ERROR);
l4_proto = (u_int8_t)lua_tonumber(vm, 6);
src_ip_addr.set(src_ip), dst_ip_addr.set(dst_ip);
f = ntop_interface->findFlowByTuple(vlan_id, &src_ip_addr, &dst_ip_addr, htons(src_port), htons(dst_port), l4_proto, ptree);
if(f == NULL)
return(CONST_LUA_ERROR);
else {
f->lua(vm, ptree, details_high, false);
return(CONST_LUA_OK);
}
}
/* ****************************************** */
// ***API***
static int ntop_drop_flow_traffic(lua_State* vm) {
NetworkInterface *ntop_interface = getCurrentInterface(vm);
u_int32_t key;
u_int hash_id;
Flow *f;
AddressTree *ptree = get_allowed_nets(vm);
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
if(ntop_lua_check(vm, __FUNCTION__, 1, LUA_TNUMBER) != CONST_LUA_OK) return(CONST_LUA_ERROR);
if(ntop_lua_check(vm, __FUNCTION__, 2, LUA_TNUMBER) != CONST_LUA_OK) return(CONST_LUA_ERROR);
key = (u_int32_t)lua_tonumber(vm, 1);
hash_id = (u_int)lua_tonumber(vm, 2);
if(!ntop_interface) return(CONST_LUA_ERROR);
if(!ntop->isUserAdministrator(vm)) return(CONST_LUA_ERROR);
f = ntop_interface->findFlowByKeyAndHashId(key, hash_id, ptree);
if(f == NULL)
return(CONST_LUA_ERROR);
else {
f->setDropVerdict();
lua_pushnil(vm);
return(CONST_LUA_OK);
}
}
/* ****************************************** */
static int ntop_drop_multiple_flows_traffic(lua_State* vm) {
NetworkInterface *ntop_interface = getCurrentInterface(vm);
Paginator *p = NULL;
AddressTree *ptree = get_allowed_nets(vm);
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
if(!ntop_interface) return(CONST_LUA_ERROR);
if(!ntop->isUserAdministrator(vm)) return(CONST_LUA_ERROR);
if(ntop_lua_check(vm, __FUNCTION__, 1, LUA_TTABLE)) return(CONST_LUA_ERROR);
if((p = new(std::nothrow) Paginator()) == NULL) return(CONST_LUA_ERROR);
p->readOptions(vm, 1);
if(ntop_interface->dropFlowsTraffic(ptree, p) < 0)
lua_pushboolean(vm, false);
else
lua_pushboolean(vm, true);
if(p) delete p;
return(CONST_LUA_OK);
}
/* ****************************************** */
static int ntop_dump_local_hosts_2_redis(lua_State* vm) {
NetworkInterface *ntop_interface = getCurrentInterface(vm);
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
if(!ntop_interface)
return(CONST_LUA_ERROR);
lua_pushnil(vm);
ntop_interface->dumpLocalHosts2redis(true /* must disable purge as we are called from lua */);
return(CONST_LUA_OK);
}
/* ****************************************** */
static int ntop_get_interface_find_pid_flows(lua_State* vm) {
NetworkInterface *ntop_interface = getCurrentInterface(vm);
u_int32_t pid;
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
if(!ntop->isUserAdministrator(vm)) return(CONST_LUA_ERROR);
if(ntop_lua_check(vm, __FUNCTION__, 1, LUA_TNUMBER) != CONST_LUA_OK) return(CONST_LUA_ERROR);
pid = (u_int32_t)lua_tonumber(vm, 1);
if(!ntop_interface) return(CONST_LUA_ERROR);
ntop_interface->findPidFlows(vm, pid);
/* TODO check if we need lua_pushnil(vm); in case of no match */
return(CONST_LUA_OK);
}
/* ****************************************** */
static int ntop_get_interface_find_proc_name_flows(lua_State* vm) {
NetworkInterface *ntop_interface = getCurrentInterface(vm);
char *proc_name;
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
if(!ntop->isUserAdministrator(vm)) return(CONST_LUA_ERROR);
if(ntop_lua_check(vm, __FUNCTION__, 1, LUA_TSTRING) != CONST_LUA_OK) return(CONST_LUA_ERROR);
proc_name = (char*)lua_tostring(vm, 1);
if(!ntop_interface) return(CONST_LUA_ERROR);
ntop_interface->findProcNameFlows(vm, proc_name);
/* TODO check if we need lua_pushnil(vm); in case of no match */
return(CONST_LUA_OK);
}
/* ****************************************** */
static int ntop_list_http_hosts(lua_State* vm) {
NetworkInterface *ntop_interface = getCurrentInterface(vm);
char *key;
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
if(!ntop_interface) return(CONST_LUA_ERROR);
if(lua_type(vm, 1) != LUA_TSTRING) /* Optional */
key = NULL;
else
key = (char*)lua_tostring(vm, 1);
ntop_interface->listHTTPHosts(vm, key);
/* TODO check if we need lua_pushnil(vm); in case of no match */
return(CONST_LUA_OK);
}
/* ****************************************** */
// ***API***
static int ntop_get_interface_find_host(lua_State* vm) {
NetworkInterface *ntop_interface = getCurrentInterface(vm);
char *key;
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
if(ntop_lua_check(vm, __FUNCTION__, 1, LUA_TSTRING) != CONST_LUA_OK) return(CONST_LUA_ERROR);
key = (char*)lua_tostring(vm, 1);
if(!ntop_interface) return(CONST_LUA_ERROR);
ntop_interface->findHostsByName(vm, get_allowed_nets(vm), key);
/* TODO check if we need lua_pushnil(vm); in case of no match */
return(CONST_LUA_OK);
}
/* ****************************************** */
// ***API***
static int ntop_get_interface_find_host_by_mac(lua_State* vm) {
NetworkInterface *ntop_interface = getCurrentInterface(vm);
char *mac;
u_int8_t _mac[6];
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
if(ntop_lua_check(vm, __FUNCTION__, 1, LUA_TSTRING) != CONST_LUA_OK) return(CONST_LUA_ERROR);
mac = (char*)lua_tostring(vm, 1);
if(!ntop_interface) return(CONST_LUA_ERROR);
Utils::parseMac(_mac, mac);
ntop_interface->findHostsByMac(vm, _mac);
/* TODO check if we need lua_pushnil(vm); in case of no match */
return(CONST_LUA_OK);
}
/* ****************************************** */
static int ntop_update_traffic_mirrored(lua_State* vm) {
NetworkInterface *ntop_interface = getCurrentInterface(vm);
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
if(ntop_interface)
ntop_interface->updateTrafficMirrored();
lua_pushnil(vm);
return CONST_LUA_OK;
}
/* ****************************************** */
static int ntop_update_dynamic_interface_traffic_policy(lua_State* vm) {
NetworkInterface *ntop_interface = getCurrentInterface(vm);
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
if(ntop_interface)
ntop_interface->updateDynIfaceTrafficPolicy();
lua_pushnil(vm);
return CONST_LUA_OK;
}
/* ****************************************** */
static int ntop_update_lbd_identifier(lua_State* vm) {
NetworkInterface *ntop_interface = getCurrentInterface(vm);
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
if(ntop_interface)
ntop_interface->updateLbdIdentifier();
lua_pushnil(vm);
return CONST_LUA_OK;
}
/* ****************************************** */
static int ntop_update_host_traffic_policy(lua_State* vm) {
NetworkInterface *ntop_interface = getCurrentInterface(vm);
char *host_ip;
u_int16_t vlan_id = 0;
char buf[64];
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
if(ntop_lua_check(vm, __FUNCTION__, 1, LUA_TSTRING) != CONST_LUA_OK) return(CONST_LUA_ERROR);
get_host_vlan_info((char*)lua_tostring(vm, 1), &host_ip, &vlan_id, buf, sizeof(buf));
/* Optional VLAN id */
if(lua_type(vm, 2) == LUA_TNUMBER) vlan_id = (u_int16_t)lua_tonumber(vm, 2);
if(!ntop_interface)
return CONST_LUA_ERROR;
lua_pushboolean(vm, ntop_interface->updateHostTrafficPolicy(get_allowed_nets(vm), host_ip, vlan_id));
return CONST_LUA_OK;
}
/* ****************************************** */
// *** API ***
static int ntop_get_interface_endpoint(lua_State* vm) {
NetworkInterface *ntop_interface = getCurrentInterface(vm);
u_int8_t id;
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
if(lua_type(vm, 1) != LUA_TNUMBER) /* Optional */
id = 0;
else
id = (u_int8_t)lua_tonumber(vm, 1);
if(ntop_interface) {
char *endpoint = ntop_interface->getEndpoint(id); /* CHECK */
lua_pushfstring(vm, "%s", endpoint ? endpoint : "");
} else
lua_pushnil(vm);
return(CONST_LUA_OK);
}
/* ****************************************** */
// *** API ***
static int ntop_interface_is_packet_interface(lua_State* vm) {
NetworkInterface *ntop_interface = getCurrentInterface(vm);
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
if(!ntop_interface) return(CONST_LUA_ERROR);
lua_pushboolean(vm, ntop_interface->isPacketInterface());
return(CONST_LUA_OK);
}
/* ****************************************** */
// *** API ***
static int ntop_interface_is_discoverable_interface(lua_State* vm) {
NetworkInterface *ntop_interface = getCurrentInterface(vm);
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
if(!ntop_interface) return(CONST_LUA_ERROR);
lua_pushboolean(vm, ntop_interface->isDiscoverableInterface());
return(CONST_LUA_OK);
}
/* ****************************************** */
static int ntop_interface_is_bridge_interface(lua_State* vm) {
int ifid;
NetworkInterface *iface = getCurrentInterface(vm);
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
if((lua_type(vm, 1) == LUA_TNUMBER)) {
ifid = lua_tointeger(vm, 1);
if(ifid < 0 || !(iface = ntop->getInterfaceById(ifid)))
return(CONST_LUA_ERROR);
}
lua_pushboolean(vm, iface->is_bridge_interface());
return(CONST_LUA_OK);
}
/* ****************************************** */
// ***API***
static int ntop_interface_is_pcap_dump_interface(lua_State* vm) {
NetworkInterface *ntop_interface = getCurrentInterface(vm);
bool rv = false;
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
if(ntop_interface && ntop_interface->getIfType() == interface_type_PCAP_DUMP)
rv = true;
lua_pushboolean(vm, rv);
return(CONST_LUA_OK);
}
/* ****************************************** */
// ***API***
static int ntop_interface_is_view(lua_State* vm) {
NetworkInterface *ntop_interface = getCurrentInterface(vm);
bool rv = false;
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
if(ntop_interface) rv = ntop_interface->isView();
lua_pushboolean(vm, rv);
return(CONST_LUA_OK);
}
/* ****************************************** */
// ***API***
static int ntop_interface_is_loopback(lua_State* vm) {
NetworkInterface *ntop_interface = getCurrentInterface(vm);
bool rv = false;
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
if(ntop_interface) rv = ntop_interface->isLoopback();
lua_pushboolean(vm, rv);
return(CONST_LUA_OK);
}
/* ****************************************** */
// ***API***
static int ntop_interface_is_running(lua_State* vm) {
NetworkInterface *ntop_interface = getCurrentInterface(vm);
bool rv = false;
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
if(ntop_interface) rv = ntop_interface->isRunning();
lua_pushboolean(vm, rv);
return(CONST_LUA_OK);
}
/* ****************************************** */
// ***API***
static int ntop_interface_is_idle(lua_State* vm) {
NetworkInterface *ntop_interface = getCurrentInterface(vm);
bool rv = false;
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
if(ntop_interface) rv = ntop_interface->idle();
lua_pushboolean(vm, rv);
return(CONST_LUA_OK);
}
/* ****************************************** */
// ***API***
static int ntop_interface_set_idle(lua_State* vm) {
NetworkInterface *ntop_interface = getCurrentInterface(vm);
bool state;
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
if(!ntop_interface) return(CONST_LUA_ERROR);
if(ntop_lua_check(vm, __FUNCTION__, 1, LUA_TBOOLEAN) != CONST_LUA_OK) return(CONST_LUA_ERROR);
state = lua_toboolean(vm, 1) ? true : false;
ntop_interface->setIdleState(state);
lua_pushnil(vm);
return(CONST_LUA_OK);
}
/* ****************************************** */
// ***API***
static int ntop_interface_dump_live_captures(lua_State* vm) {
NetworkInterface *iface = getCurrentInterface(vm);
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
if(!ntop->isUserAdministrator(vm))
return(CONST_LUA_ERROR);
if(!iface)
return(CONST_LUA_ERROR);
iface->dumpLiveCaptures(vm);
return(CONST_LUA_OK);
}
/* ****************************************** */
// ***API***
static int ntop_interface_live_capture(lua_State* vm) {
NetworkInterface *ntop_interface = getCurrentInterface(vm);
struct ntopngLuaContext *c;
int capture_id, duration;
char *bpf = NULL;
NetworkInterface *iface = getCurrentInterface(vm);
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
if(!ntop->isUserAdministrator(vm)) return(CONST_LUA_ERROR);
if(!iface) return(CONST_LUA_ERROR);
c = getLuaVMContext(vm);
if((!ntop_interface) || (!c))
return(CONST_LUA_ERROR);
if(lua_type(vm, 1) == LUA_TSTRING) /* Host */ {
Host *h;
char host_ip[64];
char *key;
u_int16_t vlan_id = 0;
get_host_vlan_info((char*)lua_tostring(vm, 1), &key, &vlan_id, host_ip, sizeof(host_ip));
if((!ntop_interface) || ((h = ntop_interface->findHostByIP(get_allowed_nets(vm), host_ip, vlan_id)) == NULL))
ntop->getTrace()->traceEvent(TRACE_WARNING, "Unable to locate host %s", host_ip);
else
c->live_capture.matching_host = h;
}
if(ntop_lua_check(vm, __FUNCTION__, 2, LUA_TNUMBER) != CONST_LUA_OK) return(CONST_LUA_ERROR);
duration = (u_int32_t)lua_tonumber(vm, 2);
if(ntop_lua_check(vm, __FUNCTION__, 3, LUA_TSTRING) != CONST_LUA_OK) return(CONST_LUA_ERROR);
bpf = (char*)lua_tostring(vm, 3);
c->live_capture.capture_until = time(NULL)+duration;
c->live_capture.capture_max_pkts = CONST_MAX_NUM_PACKETS_PER_LIVE;
c->live_capture.num_captured_packets = 0;
c->live_capture.stopped = c->live_capture.pcaphdr_sent = false;
c->live_capture.bpfFilterSet = false;
if(bpf && (bpf[0] != '\0')) {
if(pcap_compile_nopcap(65535, /* snaplen */
iface->get_datalink(), /* linktype */
&c->live_capture.fcode, /* program */
bpf, /* const char *buf */
0, /* optimize */
PCAP_NETMASK_UNKNOWN) == -1)
ntop->getTrace()->traceEvent(TRACE_WARNING,
"Unable to set capturefilter %s. Filter ignored.", bpf);
else
c->live_capture.bpfFilterSet = true;
}
if(ntop_interface->registerLiveCapture(c, &capture_id)) {
ntop->getTrace()->traceEvent(TRACE_INFO,
"Starting live capture id %d",
capture_id);
while(!c->live_capture.stopped) {
ntop->getTrace()->traceEvent(TRACE_INFO, "Capturing....");
sleep(1);
}
ntop->getTrace()->traceEvent(TRACE_INFO, "Capture completed");
}
lua_pushnil(vm);
return(CONST_LUA_OK);
}
/* ****************************************** */
// ***API***
static int ntop_interface_stop_live_capture(lua_State* vm) {
NetworkInterface *ntop_interface = getCurrentInterface(vm);
int capture_id;
bool rc;
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
if(!ntop->isUserAdministrator(vm))
return(CONST_LUA_ERROR);
if(!ntop_interface)
return(CONST_LUA_ERROR);
if(ntop_lua_check(vm, __FUNCTION__, 1, LUA_TNUMBER) != CONST_LUA_OK) return(CONST_LUA_ERROR);
capture_id = (int)lua_tointeger(vm, 1);
rc = ntop_interface->stopLiveCapture(capture_id);
ntop->getTrace()->traceEvent(TRACE_INFO,
"Stopping live capture %d: %s",
capture_id,
rc ? "stopped" : "error");
lua_pushnil(vm);
return(CONST_LUA_OK);
}
/* ****************************************** */
static int ntop_interface_name2id(lua_State* vm) {
char *if_name;
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
if(lua_type(vm, 1) == LUA_TNIL)
if_name = NULL;
else {
if(ntop_lua_check(vm, __FUNCTION__, 1, LUA_TSTRING) != CONST_LUA_OK) return(CONST_LUA_ERROR);
if_name = (char*)lua_tostring(vm, 1);
}
lua_pushinteger(vm, ntop->getInterfaceIdByName(vm, if_name));
return(CONST_LUA_OK);
}
/* ****************************************** */
// ***API***
static int ntop_get_ndpi_protocols(lua_State* vm) {
NetworkInterface *ntop_interface = getCurrentInterface(vm);
ndpi_protocol_category_t category_filter = (ndpi_protocol_category_t)((u_int8_t)-1);
bool skip_critical = false;
if(ntop_interface == NULL)
ntop_interface = getCurrentInterface(vm);
if(ntop_interface == NULL)
return(CONST_LUA_ERROR);
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
if((lua_type(vm, 1) == LUA_TNUMBER)) {
category_filter = (ndpi_protocol_category_t)lua_tointeger(vm, 1);
if(category_filter >= NDPI_PROTOCOL_NUM_CATEGORIES) {
lua_pushnil(vm);
return(CONST_LUA_OK);
}
}
if((lua_type(vm, 2) == LUA_TBOOLEAN)) skip_critical = lua_toboolean(vm, 2);
ntop_interface->getnDPIProtocols(vm, category_filter, skip_critical);
return(CONST_LUA_OK);
}
/* ****************************************** */
// ***API***
static int ntop_get_ndpi_categories(lua_State* vm) {
NetworkInterface *ntop_interface = getCurrentInterface(vm);
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
if(!ntop_interface) {
lua_pushnil(vm);
return(CONST_LUA_OK);
}
lua_newtable(vm);
for (int i=0; i < NDPI_PROTOCOL_NUM_CATEGORIES; i++) {
char buf[8];
const char *cat_name = ntop_interface->get_ndpi_category_name((ndpi_protocol_category_t)i);
if(cat_name && *cat_name) {
snprintf(buf, sizeof(buf), "%d", i);
lua_push_str_table_entry(vm, cat_name, buf);
}
}
return(CONST_LUA_OK);
}
/* ****************************************** */
static int ntop_load_scaling_factor_prefs(lua_State* vm) {
NetworkInterface *ntop_interface = getCurrentInterface(vm);
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
ntop_interface->loadScalingFactorPrefs();
lua_pushnil(vm);
return(CONST_LUA_OK);
}
/* ****************************************** */
static int ntop_reload_hide_from_top(lua_State* vm) {
NetworkInterface *ntop_interface = getCurrentInterface(vm);
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
if(!ntop_interface) return(CONST_LUA_ERROR);
ntop_interface->reloadHideFromTop();
lua_pushnil(vm);
return(CONST_LUA_OK);
}
/* ****************************************** */
static int ntop_reload_dhcp_ranges(lua_State* vm) {
NetworkInterface *ntop_interface = getCurrentInterface(vm);
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
if(!ntop_interface) return(CONST_LUA_ERROR);
ntop_interface->reloadDhcpRanges();
lua_pushnil(vm);
return(CONST_LUA_OK);
}
/* ****************************************** */
static int ntop_reload_host_prefs(lua_State* vm) {
NetworkInterface *ntop_interface = getCurrentInterface(vm);
char buf[64], *host_ip;
Host *host;
u_int16_t vlan_id;
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
if(!ntop_interface) return(CONST_LUA_ERROR);
if(ntop_lua_check(vm, __FUNCTION__, 1, LUA_TSTRING) != CONST_LUA_OK) return(CONST_LUA_PARAM_ERROR);
get_host_vlan_info((char*)lua_tostring(vm, 1), &host_ip, &vlan_id, buf, sizeof(buf));
if((host = ntop_interface->getHost(host_ip, vlan_id, false /* Not an inline call */)))
host->reloadPrefs();
lua_pushboolean(vm, (host != NULL));
return(CONST_LUA_OK);
}
/* ****************************************** */
#ifdef HAVE_NEDGE
static int ntop_set_lan_ip_address(lua_State* vm) {
NetworkInterface *ntop_interface = getCurrentInterface(vm);
if(ntop_lua_check(vm, __FUNCTION__, 1, LUA_TSTRING) != CONST_LUA_OK) return(CONST_LUA_PARAM_ERROR);
const char* ip = lua_tostring(vm, 1);
if(ntop_interface && (ntop_interface->getIfType() == interface_type_NETFILTER))
((NetfilterInterface *)ntop_interface)->setLanIPAddress(inet_addr(ip));
if(ntop->get_HTTPserver())
ntop->get_HTTPserver()->setCaptiveRedirectAddress(ip);
lua_pushnil(vm);
return(CONST_LUA_OK);
}
/* ****************************************** */
static int ntop_set_lan_interface(lua_State* vm) {
char *lan_ifname;
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
if(ntop_lua_check(vm, __FUNCTION__, 1, LUA_TSTRING) != CONST_LUA_OK) return(CONST_LUA_PARAM_ERROR);
lan_ifname = (char*)lua_tostring(vm, 1);
ntop->getPrefs()->set_lan_interface(lan_ifname);
lua_pushnil(vm);
return(CONST_LUA_OK);
}
/* ****************************************** */
static int ntop_refresh_device_protocols_policies_pref(lua_State* vm) {
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
ntop->getPrefs()->refreshDeviceProtocolsPolicyPref();
lua_pushnil(vm);
return(CONST_LUA_OK);
}
/* ****************************************** */
static int ntop_get_policy_change_marker(lua_State* vm) {
NetworkInterface *ntop_interface = getCurrentInterface(vm);
if(ntop_interface && (ntop_interface->getIfType() == interface_type_NETFILTER))
lua_pushinteger(vm, ((NetfilterInterface *)ntop_interface)->getPolicyChangeMarker());
else
lua_pushnil(vm);
return(CONST_LUA_OK);
}
static int ntop_update_flows_shapers(lua_State* vm) {
NetworkInterface *ntop_interface = getCurrentInterface(vm);
if(ntop_interface)
ntop_interface->updateFlowsL7Policy();
lua_pushnil(vm);
return(CONST_LUA_OK);
}
/* ****************************************** */
static int ntop_get_l7_policy_info(lua_State* vm) {
u_int16_t pool_id;
u_int8_t shaper_id;
ndpi_protocol proto;
DeviceType dev_type;
bool as_client;
NetworkInterface *ntop_interface = getCurrentInterface(vm);
L7PolicySource_t policy_source;
DeviceProtoStatus device_proto_status;
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
if(!ntop_interface || !ntop_interface->getL7Policer()) return(CONST_LUA_ERROR);
if(ntop_lua_check(vm, __FUNCTION__, 1, LUA_TNUMBER) != CONST_LUA_OK) return(CONST_LUA_PARAM_ERROR);
if(ntop_lua_check(vm, __FUNCTION__, 2, LUA_TNUMBER) != CONST_LUA_OK) return(CONST_LUA_PARAM_ERROR);
if(ntop_lua_check(vm, __FUNCTION__, 3, LUA_TNUMBER) != CONST_LUA_OK) return(CONST_LUA_PARAM_ERROR);
if(ntop_lua_check(vm, __FUNCTION__, 4, LUA_TBOOLEAN) != CONST_LUA_OK) return(CONST_LUA_PARAM_ERROR);
pool_id = (u_int16_t)lua_tointeger(vm, 1);
proto.master_protocol = (u_int16_t)lua_tointeger(vm, 2);
proto.app_protocol = proto.master_protocol;
proto.category = NDPI_PROTOCOL_CATEGORY_UNSPECIFIED; // important for ndpi_get_proto_category below
// set appropriate category based on the protocols
proto.category = ndpi_get_proto_category(ntop_interface->get_ndpi_struct(), proto);
dev_type = (DeviceType)lua_tointeger(vm, 3);
as_client = lua_toboolean(vm, 4);
if(ntop->getPrefs()->are_device_protocol_policies_enabled() &&
((device_proto_status = ntop->getDeviceAllowedProtocolStatus(dev_type, proto, pool_id, as_client)) != device_proto_allowed)) {
shaper_id = DROP_ALL_SHAPER_ID;
policy_source = policy_source_device_protocol;
} else {
shaper_id = ntop_interface->getL7Policer()->getShaperIdForPool(pool_id, proto, !as_client, &policy_source);
}
lua_newtable(vm);
lua_push_uint64_table_entry(vm, "shaper_id", shaper_id);
lua_push_str_table_entry(vm, "policy_source", (char*)Utils::policySource2Str(policy_source));
return(CONST_LUA_OK);
}
#endif
/* ****************************************** */
/*
Code partially taken from third-party/rrdtool-1.4.7/bindings/lua/rrdlua.c
and made reentrant
*/
static void reset_rrd_state(void) {
optind = 0;
opterr = 0;
rrd_clear_error();
}
/* ****************************************** */
static const char **make_argv(lua_State * vm, int *argc_out, u_int offset, int extra_args) {
const char **argv;
int i;
int argc = lua_gettop(vm) + 1 - offset + extra_args;
if(!(argv = (const char**)calloc(argc, sizeof (char *))))
/* raise an error and never return */
luaL_error(vm, "Can't allocate memory for arguments array");
/* fprintf(stderr, "%s\n", argv[0]); */
for(i=0; i<argc; i++) {
if(i < extra_args) {
argv[i] = ""; /* put an empty extra argument */
} else {
int idx = (i-extra_args) + offset;
/* accepts string or number */
if(lua_isstring(vm, idx) || lua_isnumber(vm, idx)) {
if(!(argv[i] = (char*)lua_tostring (vm, idx))) {
/* raise an error and never return */
luaL_error(vm, "Error duplicating string area for arg #%d", i);
}
//printf("@%u: %s\n", i, argv[i]);
} else {
/* raise an error and never return */
luaL_error(vm, "Invalid arg #%d: args must be strings or numbers", i);
}
}
// ntop->getTrace()->traceEvent(TRACE_NORMAL, "[%d] %s", i, argv[i]);
}
*argc_out = argc;
return(argv);
}
/* ****************************************** */
#if defined(HAVE_NINDEX) && defined(NTOPNG_PRO)
static int ntop_nindex_select(lua_State* vm) {
u_int8_t id = 1;
char *select = NULL, *where = NULL;
bool use_aggregated_flows, export_results = false;
char *timestamp_begin, *timestamp_end;
unsigned long skip_initial_records, max_num_hits;
NetworkInterface *ntop_interface = getCurrentInterface(vm);
NIndexFlowDB *nindex;
struct mg_connection *conn;
if(!ntop_interface)
return(CONST_LUA_ERROR);
else {
nindex = ntop_interface->getNindex();
if(!nindex) return(CONST_LUA_ERROR);
}
if(ntop_lua_check(vm, __FUNCTION__, id, LUA_TBOOLEAN) != CONST_LUA_OK) return(CONST_LUA_PARAM_ERROR);
use_aggregated_flows = lua_toboolean(vm, id++) ? true : false;
if(ntop_lua_check(vm, __FUNCTION__, id, LUA_TSTRING) != CONST_LUA_OK) return(CONST_LUA_PARAM_ERROR);
if((timestamp_begin = (char*)lua_tostring(vm, id++)) == NULL) return(CONST_LUA_PARAM_ERROR);
if(ntop_lua_check(vm, __FUNCTION__, id, LUA_TSTRING) != CONST_LUA_OK) return(CONST_LUA_PARAM_ERROR);
if((timestamp_end = (char*)lua_tostring(vm, id++)) == NULL) return(CONST_LUA_PARAM_ERROR);
if(ntop_lua_check(vm, __FUNCTION__, id, LUA_TSTRING) != CONST_LUA_OK) return(CONST_LUA_PARAM_ERROR);
if((select = (char*)lua_tostring(vm, id++)) == NULL) return(CONST_LUA_PARAM_ERROR);
if(ntop_lua_check(vm, __FUNCTION__, id, LUA_TSTRING) != CONST_LUA_OK) return(CONST_LUA_PARAM_ERROR);
where = (char*)lua_tostring(vm, id++);
if(ntop_lua_check(vm, __FUNCTION__, id, LUA_TNUMBER) != CONST_LUA_OK) return(CONST_LUA_PARAM_ERROR);
skip_initial_records = (unsigned long)lua_tonumber(vm, id++);
if(ntop_lua_check(vm, __FUNCTION__, id, LUA_TNUMBER) != CONST_LUA_OK) return(CONST_LUA_PARAM_ERROR);
max_num_hits = (unsigned long)lua_tonumber(vm, id++);
if(lua_type(vm, id) == LUA_TBOOLEAN)
export_results = lua_toboolean(vm, id++) ? true : false;
conn = getLuaVMUserdata(vm, conn);
return(nindex->select(vm, use_aggregated_flows,
timestamp_begin, timestamp_end, select,
where, skip_initial_records, max_num_hits,
export_results ? conn : NULL));
}
/* ****************************************** */
static int ntop_nindex_topk(lua_State* vm) {
u_int8_t id = 1;
char *select_keys = NULL, *select_values = NULL,*where = NULL;
bool use_aggregated_flows;
char *timestamp_begin, *timestamp_end;
unsigned long skip_initial_records, max_num_hits;
NetworkInterface *ntop_interface = getCurrentInterface(vm);
NIndexFlowDB *nindex;
char *_topkOperator;
TopKSelectOperator topkOperator = topk_select_operator_sum;
bool topToBottomSort, useApproxQuery;
if(!ntop_interface)
return(CONST_LUA_ERROR);
else {
nindex = ntop_interface->getNindex();
if(!nindex) return(CONST_LUA_ERROR);
}
if(ntop_lua_check(vm, __FUNCTION__, id, LUA_TBOOLEAN) != CONST_LUA_OK) return(CONST_LUA_PARAM_ERROR);
use_aggregated_flows = lua_toboolean(vm, id++) ? true : false;
if(ntop_lua_check(vm, __FUNCTION__, id, LUA_TSTRING) != CONST_LUA_OK) return(CONST_LUA_PARAM_ERROR);
if((timestamp_begin = (char*)lua_tostring(vm, id++)) == NULL) return(CONST_LUA_PARAM_ERROR);
if(ntop_lua_check(vm, __FUNCTION__, id, LUA_TSTRING) != CONST_LUA_OK) return(CONST_LUA_PARAM_ERROR);
if((timestamp_end = (char*)lua_tostring(vm, id++)) == NULL) return(CONST_LUA_PARAM_ERROR);
if(ntop_lua_check(vm, __FUNCTION__, id, LUA_TSTRING) != CONST_LUA_OK) return(CONST_LUA_PARAM_ERROR);
if((select_keys = (char*)lua_tostring(vm, id++)) == NULL) return(CONST_LUA_PARAM_ERROR);
if(ntop_lua_check(vm, __FUNCTION__, id, LUA_TSTRING) != CONST_LUA_OK) return(CONST_LUA_PARAM_ERROR);
if((select_values = (char*)lua_tostring(vm, id++)) == NULL) return(CONST_LUA_PARAM_ERROR);
if(ntop_lua_check(vm, __FUNCTION__, id, LUA_TSTRING) != CONST_LUA_OK) return(CONST_LUA_PARAM_ERROR);
where = (char*)lua_tostring(vm, id++);
if(ntop_lua_check(vm, __FUNCTION__, id, LUA_TSTRING) != CONST_LUA_OK) return(CONST_LUA_PARAM_ERROR);
_topkOperator = (char*)lua_tostring(vm, id++);
if(!strcasecmp(_topkOperator, "sum")) topkOperator = topk_select_operator_sum;
else if(!strcasecmp(_topkOperator, "count")) topkOperator = topk_select_operator_count;
else if(!strcasecmp(_topkOperator, "min")) topkOperator = topk_select_operator_min;
else topkOperator = topk_select_operator_max;
if(ntop_lua_check(vm, __FUNCTION__, id, LUA_TNUMBER) != CONST_LUA_OK) return(CONST_LUA_PARAM_ERROR);
skip_initial_records = (unsigned long)lua_tonumber(vm, id++);
if(ntop_lua_check(vm, __FUNCTION__, id, LUA_TNUMBER) != CONST_LUA_OK) return(CONST_LUA_PARAM_ERROR);
max_num_hits = (unsigned long)lua_tonumber(vm, id++);
if(ntop_lua_check(vm, __FUNCTION__, id, LUA_TBOOLEAN) != CONST_LUA_OK) return(CONST_LUA_PARAM_ERROR);
topToBottomSort = lua_toboolean(vm, id++) ? true : false;
if(ntop_lua_check(vm, __FUNCTION__, id, LUA_TBOOLEAN) != CONST_LUA_OK) return(CONST_LUA_PARAM_ERROR);
useApproxQuery = lua_toboolean(vm, id++) ? true : false;
return(nindex->topk(vm, use_aggregated_flows,
timestamp_begin, timestamp_end,
select_keys, select_values,
where, topkOperator,
useApproxQuery, skip_initial_records,
max_num_hits, topToBottomSort));
}
static int ntop_nindex_enabled(lua_State* vm) {
NetworkInterface *ntop_interface = getCurrentInterface(vm);
lua_pushboolean(vm, ntop_interface && ntop_interface->getNindex());
return(CONST_LUA_OK);
}
#endif
/* ****************************************** */
static void* pcapDumpLoop(void* ptr) {
struct ntopngLuaContext *c = (struct ntopngLuaContext*)ptr;
Utils::setThreadName("pcapDumpLoop");
while(c->pkt_capture.captureInProgress) {
u_char *pkt;
struct pcap_pkthdr *h;
int rc = pcap_next_ex(c->pkt_capture.pd, &h, (const u_char **) &pkt);
if(rc > 0) {
pcap_dump((u_char*)c->pkt_capture.dumper, (const struct pcap_pkthdr*)h, pkt);
if(h->ts.tv_sec > c->pkt_capture.end_capture)
break;
} else if(rc < 0) {
break;
} else if(rc == 0) {
if(time(NULL) > c->pkt_capture.end_capture)
break;
}
} /* while */
if(c->pkt_capture.dumper) {
pcap_dump_close(c->pkt_capture.dumper);
c->pkt_capture.dumper = NULL;
}
if(c->pkt_capture.pd) {
pcap_close(c->pkt_capture.pd);
c->pkt_capture.pd = NULL;
}
c->pkt_capture.captureInProgress = false;
return(NULL);
}
/* ****************************************** */
static int ntop_capture_to_pcap(lua_State* vm) {
NetworkInterface *ntop_interface = getCurrentInterface(vm);
u_int8_t capture_duration;
char *bpfFilter = NULL, ftemplate[64];
char errbuf[PCAP_ERRBUF_SIZE];
struct bpf_program fcode;
struct ntopngLuaContext *c;
if(!ntop->isUserAdministrator(vm)) return(CONST_LUA_ERROR);
c = getLuaVMContext(vm);
if((!ntop_interface) || (!c))
return(CONST_LUA_ERROR);
if(c->pkt_capture.pd != NULL /* Another capture is in progress */)
return(CONST_LUA_ERROR);
if(ntop_lua_check(vm, __FUNCTION__, 1, LUA_TNUMBER) != CONST_LUA_OK) return(CONST_LUA_ERROR);
capture_duration = (u_int32_t)lua_tonumber(vm, 1);
if(lua_type(vm, 2) != LUA_TSTRING) /* Optional */
bpfFilter = (char*)lua_tostring(vm, 2);
#if !defined(__APPLE__) && !defined(WIN32) && !defined(HAVE_NEDGE)
if(Utils::gainWriteCapabilities() == -1)
ntop->getTrace()->traceEvent(TRACE_ERROR, "Unable to enable capabilities");
#endif
if((c->pkt_capture.pd = pcap_open_live(ntop_interface->get_name(),
1514, 0 /* promisc */, 500, errbuf)) == NULL) {
ntop->getTrace()->traceEvent(TRACE_WARNING, "Unable to open %s for capture: %s",
ntop_interface->get_name(), errbuf);
#if !defined(__APPLE__) && !defined(WIN32) && !defined(HAVE_NEDGE)
Utils::dropWriteCapabilities();
#endif
return(CONST_LUA_ERROR);
}
if(bpfFilter != NULL) {
if(pcap_compile(c->pkt_capture.pd, &fcode, bpfFilter, 1, 0xFFFFFF00) < 0) {
ntop->getTrace()->traceEvent(TRACE_WARNING, "pcap_compile error: '%s'", pcap_geterr(c->pkt_capture.pd));
} else {
if(pcap_setfilter(c->pkt_capture.pd, &fcode) < 0) {
ntop->getTrace()->traceEvent(TRACE_WARNING, "pcap_setfilter error: '%s'", pcap_geterr(c->pkt_capture.pd));
}
}
}
#if !defined(__APPLE__) && !defined(WIN32) && !defined(HAVE_NEDGE)
Utils::dropWriteCapabilities();
#endif
snprintf(ftemplate, sizeof(ftemplate), "/tmp/ntopng_%s_%u.pcap",
ntop_interface->get_name(), (unsigned int)time(NULL));
c->pkt_capture.dumper = pcap_dump_open(pcap_open_dead(DLT_EN10MB, 1514 /* MTU */), ftemplate);
if(c->pkt_capture.dumper == NULL) {
ntop->getTrace()->traceEvent(TRACE_WARNING, "Unable to create dump file %s\n", ftemplate);
return(CONST_LUA_ERROR);
}
/* Capture sessions can't be longer than 30 sec */
if(capture_duration > 30) capture_duration = 30;
c->pkt_capture.end_capture = time(NULL) + capture_duration;
c->pkt_capture.captureInProgress = true;
pthread_create(&c->pkt_capture.captureThreadLoop, NULL, pcapDumpLoop, (void*)c);
lua_pushstring(vm, ftemplate);
return(CONST_LUA_OK);
}
/* ****************************************** */
static int ntop_is_capture_running(lua_State* vm) {
NetworkInterface *ntop_interface = getCurrentInterface(vm);
struct ntopngLuaContext *c;
if(!ntop->isUserAdministrator(vm)) return(CONST_LUA_ERROR);
c = getLuaVMContext(vm);
if((!ntop_interface) || (!c))
return(CONST_LUA_ERROR);
lua_pushboolean(vm, (c->pkt_capture.pd != NULL /* Another capture is in progress */) ? true : false);
return(CONST_LUA_OK);
}
/* ****************************************** */
static int ntop_stop_running_capture(lua_State* vm) {
NetworkInterface *ntop_interface = getCurrentInterface(vm);
struct ntopngLuaContext *c;
if(!ntop->isUserAdministrator(vm)) return(CONST_LUA_ERROR);
c = getLuaVMContext(vm);
if((!ntop_interface) || (!c))
return(CONST_LUA_ERROR);
c->pkt_capture.end_capture = 0;
lua_pushnil(vm);
return(CONST_LUA_OK);
}
/* ****************************************** */
static int ntop_rrd_create(lua_State* vm) {
const char *filename;
unsigned long pdp_step;
const char **argv;
int argc, status, offset = 3;
if(ntop_lua_check(vm, __FUNCTION__, 1, LUA_TSTRING) != CONST_LUA_OK) return(CONST_LUA_PARAM_ERROR);
if((filename = (const char*)lua_tostring(vm, 1)) == NULL) return(CONST_LUA_PARAM_ERROR);
if(ntop_lua_check(vm, __FUNCTION__, 2, LUA_TNUMBER) != CONST_LUA_OK) return(CONST_LUA_ERROR);
pdp_step = (unsigned long)lua_tonumber(vm, 2);
ntop->getTrace()->traceEvent(TRACE_INFO, "%s(%s)", __FUNCTION__, filename);
argv = make_argv(vm, &argc, offset, 0);
reset_rrd_state();
status = rrd_create_r(filename, pdp_step, time(NULL)-86400 /* 1 day */, argc, argv);
free(argv);
if(status != 0) {
char *err = rrd_get_error();
if(err != NULL) {
char error_buf[256];
snprintf(error_buf, sizeof(error_buf), "Unable to create %s [%s]", filename, err);
lua_pushstring(vm, error_buf);
} else
lua_pushstring(vm, "Unknown RRD error");
} else {
lua_pushnil(vm);
chmod(filename, CONST_DEFAULT_FILE_MODE);
}
return(CONST_LUA_OK);
}
/* ****************************************** */
static int ntop_rrd_update(lua_State* vm) {
const char *filename, *when = NULL, *v1 = NULL, *v2 = NULL, *v3 = NULL;
int status;
#ifdef WIN32
struct _stat64 s;
#else
struct stat s;
#endif
if(ntop_lua_check(vm, __FUNCTION__, 1, LUA_TSTRING) != CONST_LUA_OK) return(CONST_LUA_PARAM_ERROR);
if((filename = (const char*)lua_tostring(vm, 1)) == NULL) return(CONST_LUA_PARAM_ERROR);
if(stat(filename, &s) != 0) {
char error_buf[256];
snprintf(error_buf, sizeof(error_buf), "File %s does not exist", filename);
lua_pushstring(vm, error_buf);
return(CONST_LUA_OK);
}
if(lua_type(vm, 2) == LUA_TSTRING) {
if((when = (const char*)lua_tostring(vm, 2)) == NULL)
return(CONST_LUA_PARAM_ERROR);
} else if(lua_type(vm, 2) != LUA_TNIL)
return(CONST_LUA_PARAM_ERROR);
if(lua_type(vm, 3) == LUA_TSTRING) v1 = (const char*)lua_tostring(vm, 3);
if(lua_type(vm, 4) == LUA_TSTRING) v2 = (const char*)lua_tostring(vm, 4);
if(lua_type(vm, 5) == LUA_TSTRING) v3 = (const char*)lua_tostring(vm, 5);
/* Apparently RRD does not like static buffers, so we need to malloc */
u_int buf_len = 64;
char *buf = (char*)malloc(buf_len);
if(buf) {
snprintf(buf, buf_len, "%s:%s%s%s%s%s",
when ? when : "N", v1,
v2 ? ":" : "", v2 ? v2 : "",
v3 ? ":" : "", v3 ? v3 : "");
// ntop->getTrace()->traceEvent(TRACE_NORMAL, "%s(%s) %s", __FUNCTION__, filename, buf);
reset_rrd_state();
status = rrd_update_r(filename, NULL, 1, (const char**)&buf);
if(status != 0) {
char *err = rrd_get_error();
if(err != NULL) {
char error_buf[256];
snprintf(error_buf, sizeof(error_buf), "rrd_update_r() [%s][%s] failed [%s]", filename, buf, err);
lua_pushstring(vm, error_buf);
} else
lua_pushstring(vm, "Unknown RRD error");
} else
lua_pushnil(vm);
free(buf);
return(CONST_LUA_OK);
}
return(CONST_LUA_ERROR);
}
/* ****************************************** */
static int ntop_rrd_get_lastupdate(const char *filename, time_t *last_update, unsigned long *ds_count) {
char **ds_names;
char **last_ds;
unsigned long i;
int status;
status = rrd_lastupdate_r(filename, last_update, ds_count, &ds_names, &last_ds);
if(status != 0) {
return(-1);
} else {
for(i = 0; i < *ds_count; i++)
free(last_ds[i]), free(ds_names[i]);
free(last_ds), free(ds_names);
return(0);
}
}
/* ****************************************** */
static int ntop_rrd_lastupdate(lua_State* vm) {
const char *filename;
time_t last_update;
unsigned long ds_count;
if(ntop_lua_check(vm, __FUNCTION__, 1, LUA_TSTRING) != CONST_LUA_OK) return(CONST_LUA_PARAM_ERROR);
if((filename = (const char*)lua_tostring(vm, 1)) == NULL) return(CONST_LUA_PARAM_ERROR);
if(ntop_rrd_get_lastupdate(filename, &last_update, &ds_count) == -1) {
return(CONST_LUA_ERROR);
} else {
lua_pushinteger(vm, last_update);
lua_pushinteger(vm, ds_count);
return(2 /* 2 values returned */);
}
}
/* ****************************************** */
static int ntop_rrd_tune(lua_State* vm) {
const char *filename;
const char **argv;
int argc, status, offset = 1;
int extra_args = 1; /* Program name arg*/
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
argv = make_argv(vm, &argc, offset, extra_args);
if(argc < 2) {
ntop->getTrace()->traceEvent(TRACE_ERROR, "ntop_rrd_tune: invalid number of arguments");
free(argv);
return(CONST_LUA_ERROR);
}
filename = argv[1];
reset_rrd_state();
status = rrd_tune(argc, (char**)argv);
if(status != 0) {
char *err = rrd_get_error();
if(err != NULL) {
char error_buf[256];
snprintf(error_buf, sizeof(error_buf), "Unable to run rrd_tune on %s [%s]", filename, err);
lua_pushstring(vm, error_buf);
} else
lua_pushstring(vm, "Unknown RRD error");
} else
lua_pushnil(vm);
free(argv);
return(CONST_LUA_OK);
}
/* ****************************************** */
/* positional 1:4 parameters for ntop_rrd_fetch */
static int __ntop_rrd_args (lua_State* vm, char **filename, char **cf, time_t *start, time_t *end) {
char *start_s, *end_s, *err;
rrd_time_value_t start_tv, end_tv;
if(ntop_lua_check(vm, __FUNCTION__, 1, LUA_TSTRING) != CONST_LUA_OK) return(CONST_LUA_PARAM_ERROR);
if((*filename = (char*)lua_tostring(vm, 1)) == NULL) return(CONST_LUA_PARAM_ERROR);
if(ntop_lua_check(vm, __FUNCTION__, 2, LUA_TSTRING) != CONST_LUA_OK) return(CONST_LUA_PARAM_ERROR);
if((*cf = (char*)lua_tostring(vm, 2)) == NULL) return(CONST_LUA_PARAM_ERROR);
if((lua_type(vm, 3) == LUA_TNUMBER) && (lua_type(vm, 4) == LUA_TNUMBER))
*start = (time_t)lua_tonumber(vm, 3), *end = (time_t)lua_tonumber(vm, 4);
else {
if(ntop_lua_check(vm, __FUNCTION__, 3, LUA_TSTRING) != CONST_LUA_OK) return(CONST_LUA_PARAM_ERROR);
if((start_s = (char*)lua_tostring(vm, 3)) == NULL) return(CONST_LUA_PARAM_ERROR);
if((err = rrd_parsetime(start_s, &start_tv)) != NULL) {
lua_pushstring(vm, err);
return(CONST_LUA_PARAM_ERROR);
}
if(ntop_lua_check(vm, __FUNCTION__, 4, LUA_TSTRING) != CONST_LUA_OK) return(CONST_LUA_PARAM_ERROR);
if((end_s = (char*)lua_tostring(vm, 4)) == NULL) return(CONST_LUA_PARAM_ERROR);
if((err = rrd_parsetime(end_s, &end_tv)) != NULL) {
lua_pushstring(vm, err);
return(CONST_LUA_PARAM_ERROR);
}
if(rrd_proc_start_end(&start_tv, &end_tv, start, end) == -1)
return(CONST_LUA_PARAM_ERROR);
}
return(CONST_LUA_OK);
}
/* ****************************************** */
static int __ntop_rrd_status(lua_State* vm, int status, char *filename, char *cf) {
char * err;
if(status != 0) {
err = rrd_get_error();
if(err != NULL) {
ntop->getTrace()->traceEvent(TRACE_ERROR,
"Error '%s' while calling rrd_fetch_r(%s, %s): is the RRD corrupted perhaps?",
err, filename, cf);
lua_pushnil(vm);
lua_pushnil(vm);
lua_pushnil(vm);
lua_pushnil(vm);
return(CONST_LUA_ERROR);
}
}
return(CONST_LUA_OK);
}
/* ****************************************** */
/* Fetches data from RRD by rows */
static int ntop_rrd_fetch(lua_State* vm) {
unsigned long i, j, step = 0, ds_cnt = 0;
rrd_value_t *data, *p;
char **names;
char *filename, *cf;
time_t t, start, end;
#if 0
time_t last_update;
unsigned long ds_count;
#endif
int status;
reset_rrd_state();
if((status = __ntop_rrd_args(vm, &filename, &cf, &start, &end)) != CONST_LUA_OK) {
return status;
}
ntop->getTrace()->traceEvent(TRACE_INFO, "%s(%s)", __FUNCTION__, filename);
if((status = __ntop_rrd_status(vm, rrd_fetch_r(filename, cf, &start, &end,
&step, &ds_cnt, &names, &data),
filename, cf)) != CONST_LUA_OK) return status;
lua_pushinteger(vm, (lua_Integer) start);
lua_pushinteger(vm, (lua_Integer) step);
/* fprintf(stderr, "%lu, %lu, %lu, %lu\n", start, end, step, num_points); */
/* create the ds names array */
lua_newtable(vm);
for(i=0; i<ds_cnt; i++) {
lua_pushstring(vm, names[i]);
lua_rawseti(vm, -2, i+1);
rrd_freemem(names[i]);
}
rrd_freemem(names);
/* create the data points array */
lua_newtable(vm);
p = data;
for(t=start+1, i=0; t<end; t+=step, i++) {
#if 0
bool add_point;
/* Check for avoid going after the last point set */
if(t > last_update) {
ntop->getTrace()->traceEvent(TRACE_INFO, "Skipping %u / %u", t, last_update);
break;
}
if((t == last_update) && (i > 3)) {
/* Add the point only if not zero an dwith at least 3 points or more */
add_point = false;
for(j=0; j<ds_cnt; j++) {
rrd_value_t value = *p++;
if(value != DNAN /* Skip NaN */) {
if(value > 0) {
add_point = true;
break;
}
}
}
add_point = true;
} else
add_point = true;
if(add_point) {
#endif
lua_newtable(vm);
for(j=0; j<ds_cnt; j++) {
rrd_value_t value = *p++;
if(value != DNAN /* Skip NaN */) {
lua_pushnumber(vm, (lua_Number)value);
lua_rawseti(vm, -2, j+1);
// ntop->getTrace()->traceEvent(TRACE_NORMAL, "%u / %.f", t, value);
}
}
lua_rawseti(vm, -2, i+1);
#if 0
} else
break;
#endif
}
rrd_freemem(data);
/* return the end as the last value */
lua_pushinteger(vm, (lua_Integer) end);
/* number of return values: start, step, names, data, end */
return(5);
}
/* ****************************************** */
/*
* Similar to ntop_rrd_fetch, but data series oriented (reads RRD by columns)
*
* Positional parameters:
* filename: RRD file path
* cf: RRD cf
* start: the start time you wish to query
* end: the end time you wish to query
*
* Positional return values:
* start: the time of the first data in the series
* step: the fetched data step
* data: a table, where each key is an RRD name, and the value is its series data
* end: the time of the last data in each series
* npoints: the number of points in each series
*/
static int ntop_rrd_fetch_columns(lua_State* vm) {
char *filename, *cf;
time_t start, end;
int status;
unsigned int npoints = 0, i, j;
char **names;
unsigned long step = 0, ds_cnt = 0;
rrd_value_t *data, *p;
reset_rrd_state();
if((status = __ntop_rrd_args(vm, &filename,
&cf, &start, &end)) != CONST_LUA_OK) {
return status;
}
ntop->getTrace()->traceEvent(TRACE_INFO, "%s(%s)", __FUNCTION__, filename);
if((status = __ntop_rrd_status(vm,
rrd_fetch_r(filename, cf, &start,
&end, &step, &ds_cnt,
&names, &data), filename,
cf)) != CONST_LUA_OK) {
return status;
}
npoints = (end - start) / step;
lua_pushinteger(vm, (lua_Integer) start);
lua_pushinteger(vm, (lua_Integer) step);
/* create the data series table */
lua_createtable(vm, 0, ds_cnt);
for(i=0; i<ds_cnt; i++) {
/* a single series table, preallocated */
lua_createtable(vm, npoints, 0);
p = data + i;
for(j=0; j<npoints; j++) {
rrd_value_t value = *p;
/* we are accessing data table by columns */
p = p + ds_cnt;
lua_pushnumber(vm, (lua_Number)value);
lua_rawseti(vm, -2, j+1);
}
/* add the single series to the series table */
lua_setfield(vm, -2, names[i]);
rrd_freemem(names[i]);
}
rrd_freemem(names);
rrd_freemem(data);
/* end and npoints as last values */
lua_pushinteger(vm, (lua_Integer) end);
lua_pushinteger(vm, (lua_Integer) npoints);
/* number of return values */
return(5);
}
/* ****************************************** */
static void build_redirect(const char *url, const char * query_string,
char *buf, size_t bufsize) {
snprintf(buf, bufsize, "HTTP/1.1 302 Found\r\n"
"Location: %s%s%s\r\n\r\n"
"<html>\n"
"<head>\n"
"<title>Moved</title>\n"
"</head>\n"
"<body>\n"
"<h1>Moved</h1>\n"
"<p>This page has moved to <a href=\"%s\">%s</a>.</p>\n"
"</body>\n"
"</html>\n", url,
query_string ? "?" : "",
query_string ? query_string : "",
url, url);
}
/* ****************************************** */
// *** API ***
static int ntop_http_redirect(lua_State* vm) {
char *url, str[512];
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
if(ntop_lua_check(vm, __FUNCTION__, 1, LUA_TSTRING) != CONST_LUA_OK) return(CONST_LUA_PARAM_ERROR);
if((url = (char*)lua_tostring(vm, 1)) == NULL) return(CONST_LUA_PARAM_ERROR);
build_redirect(url, NULL, str, sizeof(str));
lua_pushstring(vm, str);
return(CONST_LUA_OK);
}
/* ****************************************** */
// *** API ***
static int ntop_http_get(lua_State* vm) {
char *url, *username = NULL, *pwd = NULL;
int timeout = 30;
bool return_content = true, use_cookie_authentication = false;
HTTPTranferStats stats;
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
if(ntop_lua_check(vm, __FUNCTION__, 1, LUA_TSTRING) != CONST_LUA_OK)
return(CONST_LUA_PARAM_ERROR);
if((url = (char*)lua_tostring(vm, 1)) == NULL) return(CONST_LUA_PARAM_ERROR);
if(lua_type(vm, 2) == LUA_TSTRING) {
username = (char*)lua_tostring(vm, 2);
if(lua_type(vm, 3) == LUA_TSTRING) {
pwd = (char*)lua_tostring(vm, 3);
if(lua_type(vm, 4) == LUA_TNUMBER) {
timeout = lua_tointeger(vm, 4);
if(timeout < 1) timeout = 1;
/*
This optional parameter specifies if the result of HTTP GET has to be returned
to LUA or not. Usually the content has to be returned, but in some causes
it just matters to time (for instance when use for testing HTTP services)
*/
if(lua_type(vm, 5) == LUA_TBOOLEAN) {
return_content = lua_toboolean(vm, 5) ? true : false;
if(lua_type(vm, 6) == LUA_TBOOLEAN) {
use_cookie_authentication = lua_toboolean(vm, 6) ? true : false;
}
}
}
}
}
Utils::httpGetPost(vm, url, username, pwd, timeout, return_content,
use_cookie_authentication, &stats, NULL, NULL);
return(CONST_LUA_OK);
}
/* ****************************************** */
// ***API***
static int ntop_http_get_prefix(lua_State* vm) {
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
lua_pushstring(vm, ntop->getPrefs()->get_http_prefix());
return(CONST_LUA_OK);
}
/* ****************************************** */
// ***API***
static int ntop_http_get_startup_epoch(lua_State* vm) {
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
lua_pushstring(vm, ntop->getStarttimeString());
return(CONST_LUA_OK);
}
/* ****************************************** */
// ***API***
static int ntop_http_purify_param(lua_State* vm) {
char *str, *buf;
bool strict = false, allowURL = false, allowDots = false;
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
if(ntop_lua_check(vm, __FUNCTION__, 1, LUA_TSTRING) != CONST_LUA_OK) {
lua_pushnil(vm);
return(CONST_LUA_PARAM_ERROR);
}
if((str = (char*)lua_tostring(vm, 1)) == NULL) return(CONST_LUA_PARAM_ERROR);
if(lua_type(vm, 2) == LUA_TBOOLEAN) strict = lua_toboolean(vm, 2) ? true : false;
if(lua_type(vm, 3) == LUA_TBOOLEAN) allowURL = lua_toboolean(vm, 3) ? true : false;
if(lua_type(vm, 4) == LUA_TBOOLEAN) allowDots = lua_toboolean(vm, 4) ? true : false;
buf = strdup(str);
if(buf == NULL) {
lua_pushnil(vm);
return(CONST_LUA_PARAM_ERROR);
}
Utils::purifyHTTPparam(buf, strict, allowURL, allowDots);
lua_pushstring(vm, buf);
free(buf);
return(CONST_LUA_OK);
}
/* ****************************************** */
// ***API***
static int ntop_get_prefs(lua_State* vm) {
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
ntop->getPrefs()->lua(vm);
return(CONST_LUA_OK);
}
/* ****************************************** */
static int ntop_ping_host(lua_State* vm) {
#ifdef WIN32
lua_pushnil(vm);
return(CONST_LUA_PARAM_ERROR);
#else
char *host;
bool is_v6;
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
if(ntop_lua_check(vm, __FUNCTION__, 1, LUA_TSTRING) != CONST_LUA_OK) return(CONST_LUA_PARAM_ERROR);
if((host = (char*)lua_tostring(vm, 1)) == NULL) return(CONST_LUA_PARAM_ERROR);
if(ntop_lua_check(vm, __FUNCTION__, 2, LUA_TBOOLEAN) != CONST_LUA_OK) return(CONST_LUA_PARAM_ERROR);
is_v6 = (bool)lua_toboolean(vm, 2);
if(getLuaVMUservalue(vm, ping) == NULL) {
Ping *ping;
try {
#if !defined(__APPLE__) && !defined(WIN32) && !defined(HAVE_NEDGE)
if(Utils::gainWriteCapabilities() == -1)
ntop->getTrace()->traceEvent(TRACE_ERROR, "Unable to enable capabilities");
#endif
ping = new Ping();
#if !defined(__APPLE__) && !defined(WIN32) && !defined(HAVE_NEDGE)
Utils::dropWriteCapabilities();
#endif
} catch(...) {
ntop->getTrace()->traceEvent(TRACE_ERROR, "Unable to create ping socket: are you root?");
ping = NULL;
}
if(ping == NULL) {
lua_pushnil(vm);
return(CONST_LUA_PARAM_ERROR);
} else
getLuaVMUservalue(vm, ping) = ping;
}
getLuaVMUservalue(vm, ping)->ping(host, is_v6);
return(CONST_LUA_OK);
#endif
}
/* ****************************************** */
static int ntop_collect_ping_results(lua_State* vm) {
#ifdef WIN32
lua_pushnil(vm);
return(CONST_LUA_PARAM_ERROR);
#else
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
if(getLuaVMUservalue(vm, ping) == NULL) {
lua_pushnil(vm);
return(CONST_LUA_PARAM_ERROR);
} else {
getLuaVMUservalue(vm, ping)->collectResponses(vm);
return(CONST_LUA_OK);
}
#endif
}
/* ****************************************** */
static int ntop_get_nologin_username(lua_State* vm) {
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
lua_pushstring(vm, NTOP_NOLOGIN_USER);
return(CONST_LUA_OK);
}
/* ****************************************** */
// ***API***
static int ntop_get_users(lua_State* vm) {
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
ntop->getUsers(vm);
return(CONST_LUA_OK);
}
/* ****************************************** */
// ***API***
static int ntop_get_allowed_networks(lua_State* vm) {
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
ntop->getAllowedNetworks(vm);
return(CONST_LUA_OK);
}
/* ****************************************** */
static int ntop_is_administrator(lua_State* vm) {
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
lua_pushboolean(vm, ntop->isUserAdministrator(vm));
return(CONST_LUA_OK);
}
/* ****************************************** */
// ***API***
static int ntop_reset_user_password(lua_State* vm) {
char *who, *username, *old_password, *new_password;
bool is_admin = ntop->isUserAdministrator(vm);
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
/* Username who requested the password change */
if(ntop_lua_check(vm, __FUNCTION__, 1, LUA_TSTRING) != CONST_LUA_OK) return(CONST_LUA_PARAM_ERROR);
if((who = (char*)lua_tostring(vm, 1)) == NULL) return(CONST_LUA_PARAM_ERROR);
if(ntop_lua_check(vm, __FUNCTION__, 2, LUA_TSTRING) != CONST_LUA_OK) return(CONST_LUA_PARAM_ERROR);
if((username = (char*)lua_tostring(vm, 2)) == NULL) return(CONST_LUA_PARAM_ERROR);
if(ntop_lua_check(vm, __FUNCTION__, 3, LUA_TSTRING) != CONST_LUA_OK) return(CONST_LUA_PARAM_ERROR);
if((old_password = (char*)lua_tostring(vm, 3)) == NULL) return(CONST_LUA_PARAM_ERROR);
if(ntop_lua_check(vm, __FUNCTION__, 4, LUA_TSTRING) != CONST_LUA_OK) return(CONST_LUA_PARAM_ERROR);
if((new_password = (char*)lua_tostring(vm, 4)) == NULL) return(CONST_LUA_PARAM_ERROR);
/* non-local users cannot change their local password */
if(!ntop->isLocalUser(vm))
return(CONST_LUA_ERROR);
/* only the administrator can change other users passwords */
if(!is_admin && (strcmp(who, username)))
return(CONST_LUA_ERROR);
/* only the administrator can use and empty old password */
if((old_password[0] == '\0') && !is_admin)
return(CONST_LUA_ERROR);
lua_pushboolean(vm, ntop->resetUserPassword(username, old_password, new_password));
return CONST_LUA_OK;
}
/* ****************************************** */
// ***API***
static int ntop_change_user_role(lua_State* vm) {
char *username, *user_role;
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
if(!ntop->isUserAdministrator(vm) || !ntop->isLocalUser(vm)) return(CONST_LUA_ERROR);
if(ntop_lua_check(vm, __FUNCTION__, 1, LUA_TSTRING) != CONST_LUA_OK) return(CONST_LUA_PARAM_ERROR);
if((username = (char*)lua_tostring(vm, 1)) == NULL) return(CONST_LUA_PARAM_ERROR);
if(ntop_lua_check(vm, __FUNCTION__, 2, LUA_TSTRING) != CONST_LUA_OK) return(CONST_LUA_PARAM_ERROR);
if((user_role = (char*)lua_tostring(vm, 2)) == NULL) return(CONST_LUA_PARAM_ERROR);
lua_pushboolean(vm, ntop->changeUserRole(username, user_role));
return CONST_LUA_OK;
}
/* ****************************************** */
// ***API***
static int ntop_change_allowed_nets(lua_State* vm) {
char *username, *allowed_nets;
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
if(!ntop->isUserAdministrator(vm) || !ntop->isLocalUser(vm)) return(CONST_LUA_ERROR);
if(ntop_lua_check(vm, __FUNCTION__, 1, LUA_TSTRING) != CONST_LUA_OK) return(CONST_LUA_PARAM_ERROR);
if((username = (char*)lua_tostring(vm, 1)) == NULL) return(CONST_LUA_PARAM_ERROR);
if(ntop_lua_check(vm, __FUNCTION__, 2, LUA_TSTRING) != CONST_LUA_OK) return(CONST_LUA_PARAM_ERROR);
if((allowed_nets = (char*)lua_tostring(vm, 2)) == NULL) return(CONST_LUA_PARAM_ERROR);
lua_pushboolean(vm, ntop->changeAllowedNets(username, allowed_nets));
return CONST_LUA_OK;
}
/* ****************************************** */
// ***API***
static int ntop_change_allowed_ifname(lua_State* vm) {
char *username, *allowed_ifname;
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
if(!ntop->isUserAdministrator(vm) || !ntop->isLocalUser(vm)) return(CONST_LUA_ERROR);
if(ntop_lua_check(vm, __FUNCTION__, 1, LUA_TSTRING) != CONST_LUA_OK) return(CONST_LUA_PARAM_ERROR);
if((username = (char*)lua_tostring(vm, 1)) == NULL) return(CONST_LUA_PARAM_ERROR);
if(ntop_lua_check(vm, __FUNCTION__, 2, LUA_TSTRING) != CONST_LUA_OK) return(CONST_LUA_PARAM_ERROR);
if((allowed_ifname = (char*)lua_tostring(vm, 2)) == NULL) return(CONST_LUA_PARAM_ERROR);
lua_pushboolean(vm, ntop->changeAllowedIfname(username, allowed_ifname));
return CONST_LUA_OK;
}
/* ****************************************** */
static int ntop_change_user_host_pool(lua_State* vm) {
char *username, *host_pool_id;
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
if(!ntop->isUserAdministrator(vm) || !ntop->isLocalUser(vm)) return(CONST_LUA_ERROR);
if(ntop_lua_check(vm, __FUNCTION__, 1, LUA_TSTRING) != CONST_LUA_OK) return(CONST_LUA_PARAM_ERROR);
if((username = (char*)lua_tostring(vm, 1)) == NULL) return(CONST_LUA_PARAM_ERROR);
if(ntop_lua_check(vm, __FUNCTION__, 2, LUA_TSTRING) != CONST_LUA_OK) return(CONST_LUA_PARAM_ERROR);
if((host_pool_id = (char*)lua_tostring(vm, 2)) == NULL) return(CONST_LUA_PARAM_ERROR);
lua_pushboolean(vm, ntop->changeUserHostPool(username, host_pool_id));
return CONST_LUA_OK;
}
/* ****************************************** */
// ***API***
static int ntop_change_user_language(lua_State* vm) {
char *username, *language;
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
if(!ntop->isUserAdministrator(vm) || !ntop->isLocalUser(vm)) return(CONST_LUA_ERROR);
if(ntop_lua_check(vm, __FUNCTION__, 1, LUA_TSTRING) != CONST_LUA_OK) return(CONST_LUA_PARAM_ERROR);
if((username = (char*)lua_tostring(vm, 1)) == NULL) return(CONST_LUA_PARAM_ERROR);
if(ntop_lua_check(vm, __FUNCTION__, 2, LUA_TSTRING) != CONST_LUA_OK) return(CONST_LUA_PARAM_ERROR);
if((language = (char*)lua_tostring(vm, 2)) == NULL) return(CONST_LUA_PARAM_ERROR);
lua_pushboolean(vm, ntop->changeUserLanguage(username, language));
return CONST_LUA_OK;
}
/* ****************************************** */
// ***API***
static int ntop_post_http_json_data(lua_State* vm) {
char *username, *password, *url, *json;
HTTPTranferStats stats;
int timeout = 0;
if(ntop_lua_check(vm, __FUNCTION__, 1, LUA_TSTRING) != CONST_LUA_OK) return(CONST_LUA_PARAM_ERROR);
if((username = (char*)lua_tostring(vm, 1)) == NULL) return(CONST_LUA_PARAM_ERROR);
if(ntop_lua_check(vm, __FUNCTION__, 2, LUA_TSTRING) != CONST_LUA_OK) return(CONST_LUA_PARAM_ERROR);
if((password = (char*)lua_tostring(vm, 2)) == NULL) return(CONST_LUA_PARAM_ERROR);
if(ntop_lua_check(vm, __FUNCTION__, 3, LUA_TSTRING) != CONST_LUA_OK) return(CONST_LUA_PARAM_ERROR);
if((url = (char*)lua_tostring(vm, 3)) == NULL) return(CONST_LUA_PARAM_ERROR);
if(ntop_lua_check(vm, __FUNCTION__, 4, LUA_TSTRING) != CONST_LUA_OK) return(CONST_LUA_PARAM_ERROR);
if((json = (char*)lua_tostring(vm, 4)) == NULL) return(CONST_LUA_PARAM_ERROR);
/* Optional timeout */
if(lua_type(vm, 5) == LUA_TNUMBER) timeout = lua_tonumber(vm, 5);
bool rv = Utils::postHTTPJsonData(username, password, url, json, timeout, &stats);
lua_pushboolean(vm, rv);
return(CONST_LUA_OK);
}
/* ****************************************** */
// ***API***
static int ntop_http_post(lua_State* vm) {
char *username = (char*)"", *password = (char*)"", *url, *form_data;
int timeout = 30;
bool return_content = false;
bool use_cookie_authentication = false;
HTTPTranferStats stats;
if(ntop_lua_check(vm, __FUNCTION__, 1, LUA_TSTRING) != CONST_LUA_OK) return(CONST_LUA_PARAM_ERROR);
if((url = (char*)lua_tostring(vm, 1)) == NULL) return(CONST_LUA_PARAM_ERROR);
if(ntop_lua_check(vm, __FUNCTION__, 2, LUA_TSTRING) != CONST_LUA_OK) return(CONST_LUA_PARAM_ERROR);
if((form_data = (char*)lua_tostring(vm, 2)) == NULL) return(CONST_LUA_PARAM_ERROR);
if(lua_type(vm, 3) == LUA_TSTRING) /* Optional */
if((username = (char*)lua_tostring(vm, 3)) == NULL) return(CONST_LUA_PARAM_ERROR);
if(lua_type(vm, 4) == LUA_TSTRING) /* Optional */
if((password = (char*)lua_tostring(vm, 4)) == NULL) return(CONST_LUA_PARAM_ERROR);
if(lua_type(vm, 5) == LUA_TNUMBER) /* Optional */
timeout = lua_tonumber(vm, 5);
if(lua_type(vm, 6) == LUA_TBOOLEAN) /* Optional */
return_content = lua_toboolean(vm, 6) ? true : false;
if(lua_type(vm, 7) == LUA_TBOOLEAN) /* Optional */
use_cookie_authentication = lua_toboolean(vm, 7) ? true : false;
Utils::httpGetPost(vm, url, username, password, timeout, return_content,
use_cookie_authentication, &stats, form_data, NULL);
return(CONST_LUA_OK);
}
/* ****************************************** */
static int ntop_http_fetch(lua_State* vm) {
char *url, *f, fname[PATH_MAX];
HTTPTranferStats stats;
int timeout = 30;
if(ntop_lua_check(vm, __FUNCTION__, 1, LUA_TSTRING) != CONST_LUA_OK) return(CONST_LUA_PARAM_ERROR);
if((url = (char*)lua_tostring(vm, 1)) == NULL) return(CONST_LUA_PARAM_ERROR);
if(ntop_lua_check(vm, __FUNCTION__, 2, LUA_TSTRING) != CONST_LUA_OK) return(CONST_LUA_PARAM_ERROR);
if((f = (char*)lua_tostring(vm, 2)) == NULL) return(CONST_LUA_PARAM_ERROR);
if(lua_type(vm, 3) == LUA_TNUMBER) /* Optional */
timeout = lua_tonumber(vm, 3);
snprintf(fname, sizeof(fname), "%s", f);
ntop->fixPath(fname);
Utils::httpGetPost(vm, url, NULL, NULL, timeout,
false, false, &stats, NULL, fname);
return(CONST_LUA_OK);
}
/* ****************************************** */
static int ntop_post_http_text_file(lua_State* vm) {
char *username, *password, *url, *path;
bool delete_file_after_post = false;
int timeout = 30;
HTTPTranferStats stats;
if(ntop_lua_check(vm, __FUNCTION__, 1, LUA_TSTRING) != CONST_LUA_OK) return(CONST_LUA_PARAM_ERROR);
if((username = (char*)lua_tostring(vm, 1)) == NULL) return(CONST_LUA_PARAM_ERROR);
if(ntop_lua_check(vm, __FUNCTION__, 2, LUA_TSTRING) != CONST_LUA_OK) return(CONST_LUA_PARAM_ERROR);
if((password = (char*)lua_tostring(vm, 2)) == NULL) return(CONST_LUA_PARAM_ERROR);
if(ntop_lua_check(vm, __FUNCTION__, 3, LUA_TSTRING) != CONST_LUA_OK) return(CONST_LUA_PARAM_ERROR);
if((url = (char*)lua_tostring(vm, 3)) == NULL) return(CONST_LUA_PARAM_ERROR);
if(ntop_lua_check(vm, __FUNCTION__, 4, LUA_TSTRING) != CONST_LUA_OK) return(CONST_LUA_PARAM_ERROR);
if((path = (char*)lua_tostring(vm, 4)) == NULL) return(CONST_LUA_PARAM_ERROR);
if(lua_type(vm, 5) == LUA_TBOOLEAN) /* Optional */
delete_file_after_post = lua_toboolean(vm, 5) ? true : false;
if(lua_type(vm, 6) == LUA_TNUMBER) /* Optional */
timeout = lua_tonumber(vm, 6);
if(timeout < 1)
timeout = 1;
if(Utils::postHTTPTextFile(vm, username, password, url, path, timeout, &stats)) {
if(delete_file_after_post) {
if(unlink(path) != 0)
ntop->getTrace()->traceEvent(TRACE_WARNING, "Unable to delete file %s", path);
else
ntop->getTrace()->traceEvent(TRACE_INFO, "Deleted file %s", path);
}
}
return(CONST_LUA_OK);
}
/* ****************************************** */
#ifdef HAVE_CURL_SMTP
static int ntop_send_mail(lua_State* vm) {
char *from, *to, *msg, *smtp_server, *username = NULL, *password = NULL;
if(ntop_lua_check(vm, __FUNCTION__, 1, LUA_TSTRING) != CONST_LUA_OK) return(CONST_LUA_PARAM_ERROR);
if((from = (char*)lua_tostring(vm, 1)) == NULL) return(CONST_LUA_PARAM_ERROR);
if(ntop_lua_check(vm, __FUNCTION__, 2, LUA_TSTRING) != CONST_LUA_OK) return(CONST_LUA_PARAM_ERROR);
if((to = (char*)lua_tostring(vm, 2)) == NULL) return(CONST_LUA_PARAM_ERROR);
if(ntop_lua_check(vm, __FUNCTION__, 3, LUA_TSTRING) != CONST_LUA_OK) return(CONST_LUA_PARAM_ERROR);
if((msg = (char*)lua_tostring(vm, 3)) == NULL) return(CONST_LUA_PARAM_ERROR);
if(ntop_lua_check(vm, __FUNCTION__, 4, LUA_TSTRING) != CONST_LUA_OK) return(CONST_LUA_PARAM_ERROR);
if((smtp_server = (char*)lua_tostring(vm, 4)) == NULL) return(CONST_LUA_PARAM_ERROR);
if(lua_type(vm, 5) == LUA_TSTRING) /* Optional */
username = (char*)lua_tostring(vm, 5);
if(lua_type(vm, 6) == LUA_TSTRING) /* Optional */
password = (char*)lua_tostring(vm, 6);
bool rv = Utils::sendMail(from, to, msg, smtp_server, username, password);
lua_pushboolean(vm, rv);
return(CONST_LUA_OK);
}
#endif
/* ****************************************** */
// ***API***
static int ntop_add_user(lua_State* vm) {
char *username, *full_name, *password, *host_role, *allowed_networks, *allowed_interface;
char *host_pool_id = NULL, *language = NULL;
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
if(!ntop->isUserAdministrator(vm) || !ntop->isLocalUser(vm)) return(CONST_LUA_ERROR);
if(ntop_lua_check(vm, __FUNCTION__, 1, LUA_TSTRING) != CONST_LUA_OK) return(CONST_LUA_PARAM_ERROR);
if((username = (char*)lua_tostring(vm, 1)) == NULL) return(CONST_LUA_PARAM_ERROR);
if(ntop_lua_check(vm, __FUNCTION__, 2, LUA_TSTRING) != CONST_LUA_OK) return(CONST_LUA_PARAM_ERROR);
if((full_name = (char*)lua_tostring(vm, 2)) == NULL) return(CONST_LUA_PARAM_ERROR);
if(ntop_lua_check(vm, __FUNCTION__, 3, LUA_TSTRING) != CONST_LUA_OK) return(CONST_LUA_PARAM_ERROR);
if((password = (char*)lua_tostring(vm, 3)) == NULL) return(CONST_LUA_PARAM_ERROR);
if(ntop_lua_check(vm, __FUNCTION__, 4, LUA_TSTRING) != CONST_LUA_OK) return(CONST_LUA_PARAM_ERROR);
if((host_role = (char*)lua_tostring(vm, 4)) == NULL) return(CONST_LUA_PARAM_ERROR);
if(ntop_lua_check(vm, __FUNCTION__, 5, LUA_TSTRING) != CONST_LUA_OK) return(CONST_LUA_PARAM_ERROR);
if((allowed_networks = (char*)lua_tostring(vm, 5)) == NULL) return(CONST_LUA_PARAM_ERROR);
if(ntop_lua_check(vm, __FUNCTION__, 6, LUA_TSTRING) != CONST_LUA_OK) return(CONST_LUA_PARAM_ERROR);
if((allowed_interface = (char*)lua_tostring(vm, 6)) == NULL) return(CONST_LUA_PARAM_ERROR);
if(lua_type(vm, 7) == LUA_TSTRING)
if((host_pool_id = (char*)lua_tostring(vm, 7)) == NULL) return(CONST_LUA_PARAM_ERROR);
if(lua_type(vm, 8) == LUA_TSTRING)
if((language = (char*)lua_tostring(vm, 8)) == NULL) return(CONST_LUA_PARAM_ERROR);
lua_pushboolean(vm, ntop->addUser(username, full_name, password, host_role,
allowed_networks, allowed_interface, host_pool_id, language));
return CONST_LUA_OK;
}
/* ****************************************** */
static int ntop_add_user_lifetime(lua_State* vm) {
char *username;
int32_t num_secs;
bool rv = false;
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
if(!ntop->isUserAdministrator(vm) || !ntop->isLocalUser(vm)) return(CONST_LUA_ERROR);
if(ntop_lua_check(vm, __FUNCTION__, 1, LUA_TSTRING) != CONST_LUA_OK) return(CONST_LUA_PARAM_ERROR);
if((username = (char*)lua_tostring(vm, 1)) == NULL) return(CONST_LUA_PARAM_ERROR);
if(ntop_lua_check(vm, __FUNCTION__, 2, LUA_TNUMBER) != CONST_LUA_OK) return(CONST_LUA_PARAM_ERROR);
num_secs = (int32_t)lua_tonumber(vm, 2);
if(num_secs > 0)
rv = ntop->addUserLifetime(username, num_secs);
lua_pushboolean(vm, rv);
return CONST_LUA_OK; /* Negative or zero lifetimes means unlimited */
}
/* ****************************************** */
static int ntop_clear_user_lifetime(lua_State* vm) {
char *username;
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
if(!ntop->isUserAdministrator(vm) || !ntop->isLocalUser(vm)) return(CONST_LUA_ERROR);
if(ntop_lua_check(vm, __FUNCTION__, 1, LUA_TSTRING) != CONST_LUA_OK) return(CONST_LUA_PARAM_ERROR);
if((username = (char*)lua_tostring(vm, 1)) == NULL) return(CONST_LUA_PARAM_ERROR);
lua_pushboolean(vm, ntop->clearUserLifetime(username));
return CONST_LUA_OK;
}
/* ****************************************** */
// ***API***
static int ntop_delete_user(lua_State* vm) {
char *username;
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
if(!ntop->isUserAdministrator(vm) || !ntop->isLocalUser(vm)) return(CONST_LUA_ERROR);
if(ntop_lua_check(vm, __FUNCTION__, 1, LUA_TSTRING) != CONST_LUA_OK) return(CONST_LUA_PARAM_ERROR);
if((username = (char*)lua_tostring(vm, 1)) == NULL) return(CONST_LUA_PARAM_ERROR);
lua_pushboolean(vm, ntop->deleteUser(username));
return CONST_LUA_OK;
}
/* ****************************************** */
/* Similar to ntop_get_resolved_address but actually perfoms the address resolution now */
static int ntop_resolve_address(lua_State* vm) {
char *numIP, symIP[64];
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
if(ntop_lua_check(vm, __FUNCTION__, 1, LUA_TSTRING) != CONST_LUA_OK) return(CONST_LUA_PARAM_ERROR);
if((numIP = (char*)lua_tostring(vm, 1)) == NULL) return(CONST_LUA_PARAM_ERROR);
ntop->resolveHostName(numIP, symIP, sizeof(symIP));
lua_pushstring(vm, symIP);
return(CONST_LUA_OK);
}
/* ****************************************** */
void lua_push_str_table_entry(lua_State *L, const char * const key, const char * const value) {
if(L) {
lua_pushstring(L, key);
lua_pushstring(L, value);
lua_settable(L, -3);
}
}
/* ****************************************** */
void lua_push_nil_table_entry(lua_State *L, const char *key) {
if(L) {
lua_pushstring(L, key);
lua_pushnil(L);
lua_settable(L, -3);
}
}
/* ****************************************** */
void lua_push_bool_table_entry(lua_State *L, const char *key, bool value) {
if(L) {
lua_pushstring(L, key);
lua_pushboolean(L, value ? 1 : 0);
lua_settable(L, -3);
}
}
/* ****************************************** */
void lua_push_uint64_table_entry(lua_State *L, const char *key, u_int64_t value) {
if(L) {
lua_pushstring(L, key);
/* NOTE since LUA 5.3 integers are 64 bits */
#if defined(__i686__)
if(value > 0x7FFFFFFF)
#else
if(value > 0xFFFFFFFF)
#endif
lua_pushnumber(L, (lua_Number)value);
else
lua_pushinteger(L, (lua_Integer)value);
lua_settable(L, -3);
}
}
/* ****************************************** */
void lua_push_int32_table_entry(lua_State *L, const char *key, int32_t value) {
if(L) {
lua_pushstring(L, key);
#if defined(LUA_MAXINTEGER) && defined(LUA_MININTEGER)
if((lua_Integer)value > LUA_MAXINTEGER || (lua_Integer)value < LUA_MININTEGER)
lua_pushnumber(L, (lua_Number)value);
else
#endif
lua_pushinteger(L, (lua_Integer)value);
lua_settable(L, -3);
}
}
/* ****************************************** */
void lua_push_float_table_entry(lua_State *L, const char *key, float value) {
if(L) {
lua_pushstring(L, key);
lua_pushnumber(L, value);
lua_settable(L, -3);
}
}
/* ****************************************** */
static int ntop_get_interface_hash_tables_stats(lua_State* vm) {
NetworkInterface *ntop_interface = getCurrentInterface(vm);
if(ntop_interface)
ntop_interface->lua_hash_tables_stats(vm);
else
lua_pushnil(vm);
return(CONST_LUA_OK);
}
/* ****************************************** */
static int ntop_get_interface_periodic_activities_stats(lua_State* vm) {
NetworkInterface *ntop_interface = getCurrentInterface(vm);
if(ntop_interface)
ntop_interface->lua_periodic_activities_stats(vm);
else
lua_pushnil(vm);
return(CONST_LUA_OK);
}
/* ****************************************** */
static int ntop_periodic_ht_state_update(lua_State* vm) {
NetworkInterface *ntop_interface = getCurrentInterface(vm);
time_t deadline;
if(ntop_lua_check(vm, __FUNCTION__, 1, LUA_TNUMBER) != CONST_LUA_OK || !ntop_interface)
return(CONST_LUA_ERROR);
deadline = (time_t)lua_tonumber(vm, 1);
ntop_interface->periodicHTStateUpdate(deadline, vm);
return(CONST_LUA_OK);
}
/* ****************************************** */
static int ntop_periodic_stats_update(lua_State* vm) {
NetworkInterface *ntop_interface = getCurrentInterface(vm);
if(!ntop_interface)
return(CONST_LUA_ERROR);
ntop_interface->periodicStatsUpdate();
lua_pushnil(vm);
return(CONST_LUA_OK);
}
/* ****************************************** */
static int ntop_get_interface_stats(lua_State* vm) {
NetworkInterface *ntop_interface = getCurrentInterface(vm);
bool get_direction_stats = false;
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
if(lua_type(vm, 1) == LUA_TBOOLEAN)
get_direction_stats = lua_toboolean(vm, 1);
if(ntop_interface) {
if(get_direction_stats)
ntop_interface->updateDirectionStats();
ntop_interface->lua(vm);
} else
lua_pushnil(vm);
return(CONST_LUA_OK);
}
/* ****************************************** */
static int ntop_get_interface_stats_update_freq(lua_State* vm) {
NetworkInterface *ntop_interface = getCurrentInterface(vm);
if(ntop_interface)
lua_pushinteger(vm, ntop_interface->periodicStatsUpdateFrequency());
else
lua_pushnil(vm);
return(CONST_LUA_OK);
}
/* ****************************************** */
// ***API***
static int ntop_interface_reset_counters(lua_State* vm) {
NetworkInterface *ntop_interface = getCurrentInterface(vm);
bool only_drops = true;
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
if(lua_type(vm, 1) == LUA_TBOOLEAN)
only_drops = lua_toboolean(vm, 1) ? true : false;
if(!ntop_interface)
return(CONST_LUA_ERROR);
ntop_interface->checkPointCounters(only_drops);
lua_pushnil(vm);
return(CONST_LUA_OK);
}
/* ****************************************** */
static int ntop_interface_reset_host_stats(lua_State* vm, bool delete_data) {
NetworkInterface *ntop_interface = getCurrentInterface(vm);
char buf[64], *host_ip;
Host *host;
u_int16_t vlan_id;
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
if(ntop_lua_check(vm, __FUNCTION__, 1, LUA_TSTRING) != CONST_LUA_OK) return(CONST_LUA_PARAM_ERROR);
get_host_vlan_info((char*)lua_tostring(vm, 1), &host_ip, &vlan_id, buf, sizeof(buf));
if(!ntop_interface) return(CONST_LUA_ERROR);
host = ntop_interface->findHostByIP(get_allowed_nets(vm), host_ip, vlan_id);
if(host) {
if(delete_data)
host->requestDataReset();
else
host->requestStatsReset();
}
lua_pushboolean(vm, (host != NULL));
return(CONST_LUA_OK);
}
/* ****************************************** */
// ***API***
static inline int ntop_interface_reset_host_stats(lua_State* vm) {
return(ntop_interface_reset_host_stats(vm, false));
}
/* ****************************************** */
// ***API***
static int ntop_interface_delete_host_data(lua_State* vm) {
return(ntop_interface_reset_host_stats(vm, true));
}
/* ****************************************** */
static int ntop_interface_reset_mac_stats(lua_State* vm, bool delete_data) {
NetworkInterface *ntop_interface = getCurrentInterface(vm);
char *mac;
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
if(ntop_lua_check(vm, __FUNCTION__, 1, LUA_TSTRING) != CONST_LUA_OK) return(CONST_LUA_PARAM_ERROR);
mac = (char*)lua_tostring(vm, 1);
if(!ntop_interface) return(CONST_LUA_ERROR);
lua_pushboolean(vm, ntop_interface->resetMacStats(vm, mac, delete_data));
return(CONST_LUA_OK);
}
/* ****************************************** */
// ***API***
static inline int ntop_interface_reset_mac_stats(lua_State* vm) {
return(ntop_interface_reset_mac_stats(vm, false));
}
/* ****************************************** */
// ***API***
static int ntop_interface_delete_mac_data(lua_State* vm) {
return(ntop_interface_reset_mac_stats(vm, true));
}
/* ****************************************** */
static int ntop_is_package(lua_State *vm) {
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
#ifdef NTOPNG_PRO
/* This assumes that pro version is available from packages only.
* Please consider changing this check if this is no longer the case. */
lua_pushboolean(vm, true);
#else
lua_pushboolean(vm, false);
#endif
return(CONST_LUA_OK);
}
/* ****************************************** */
static int ntop_is_pro(lua_State *vm) {
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
lua_pushboolean(vm, ntop->getPrefs()->is_pro_edition());
return(CONST_LUA_OK);
}
/* ****************************************** */
static int ntop_is_enterprise(lua_State *vm) {
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
lua_pushboolean(vm, ntop->getPrefs()->is_enterprise_edition());
return(CONST_LUA_OK);
}
/* ****************************************** */
static int ntop_is_nedge(lua_State *vm) {
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
lua_pushboolean(vm, ntop->getPrefs()->is_nedge_edition());
return(CONST_LUA_OK);
}
/* ****************************************** */
static int ntop_is_nedge_enterprise(lua_State *vm) {
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
lua_pushboolean(vm, ntop->getPrefs()->is_nedge_enterprise_edition());
return(CONST_LUA_OK);
}
/* ****************************************** */
// ***API***
static int ntop_reload_host_pools(lua_State *vm) {
NetworkInterface *ntop_interface = getCurrentInterface(vm);
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
if(ntop_interface) {
ntop_interface->getHostPools()->reloadPools();
lua_pushnil(vm);
return(CONST_LUA_OK);
} else
return(CONST_LUA_ERROR);
}
/* ****************************************** */
#ifdef NTOPNG_PRO
#ifdef HAVE_NEDGE
/* NOTE: do no call this directly - use host_pools_utils.resetPoolsQuotas instead */
static int ntop_reset_pools_quotas(lua_State *vm) {
NetworkInterface *ntop_interface = getCurrentInterface(vm);
u_int16_t pool_id_filter = (u_int16_t)-1;
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
if(lua_type(vm, 1) == LUA_TNUMBER) pool_id_filter = (u_int16_t)lua_tonumber(vm, 1);
if(ntop_interface) {
ntop_interface->resetPoolsStats(pool_id_filter);
lua_pushnil(vm);
return(CONST_LUA_OK);
} else
return(CONST_LUA_ERROR);
}
#endif
/* ****************************************** */
static int ntop_purge_expired_host_pools_members(lua_State *vm) {
NetworkInterface *ntop_interface = getCurrentInterface(vm);
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
if(ntop_interface && ntop_interface->getHostPools()) {
ntop_interface->getHostPools()->purgeExpiredVolatileMembers();
lua_pushnil(vm);
return(CONST_LUA_OK);
} else
return(CONST_LUA_ERROR);
}
/* ****************************************** */
static int ntop_remove_volatile_member_from_pool(lua_State *vm) {
NetworkInterface *ntop_interface = getCurrentInterface(vm);
char *host_or_mac;
u_int16_t pool_id;
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
if(ntop_lua_check(vm, __FUNCTION__, 1, LUA_TSTRING) != CONST_LUA_OK) return(CONST_LUA_PARAM_ERROR);
if((host_or_mac = (char*)lua_tostring(vm, 1)) == NULL) return(CONST_LUA_PARAM_ERROR);
if(ntop_lua_check(vm, __FUNCTION__, 2, LUA_TNUMBER) != CONST_LUA_OK) return(CONST_LUA_PARAM_ERROR);
pool_id = (u_int16_t)lua_tonumber(vm, 2);
if(ntop_interface && ntop_interface->getHostPools()) {
ntop_interface->getHostPools()->removeVolatileMemberFromPool(host_or_mac, pool_id);
lua_pushnil(vm);
return(CONST_LUA_OK);
} else
return(CONST_LUA_ERROR);
}
#endif
/* ****************************************** */
static int ntop_find_member_pool(lua_State *vm) {
char *address;
u_int16_t vlan_id = 0;
bool is_mac;
patricia_node_t *target_node = NULL;
u_int16_t pool_id;
bool pool_found;
char buf[64];
NetworkInterface *ntop_interface = getCurrentInterface(vm);
if(ntop_lua_check(vm, __FUNCTION__, 1, LUA_TSTRING) != CONST_LUA_OK) return(CONST_LUA_PARAM_ERROR);
if((address = (char*)lua_tostring(vm, 1)) == NULL) return(CONST_LUA_PARAM_ERROR);
if(ntop_lua_check(vm, __FUNCTION__, 2, LUA_TNUMBER) != CONST_LUA_OK) return(CONST_LUA_PARAM_ERROR);
vlan_id = (u_int16_t)lua_tonumber(vm, 2);
if(ntop_lua_check(vm, __FUNCTION__, 3, LUA_TBOOLEAN) != CONST_LUA_OK) return(CONST_LUA_PARAM_ERROR);
is_mac = lua_toboolean(vm, 3);
if(ntop_interface && ntop_interface->getHostPools()) {
if(is_mac) {
u_int8_t mac_bytes[6];
Utils::parseMac(mac_bytes, address);
pool_found = ntop_interface->getHostPools()->findMacPool(mac_bytes, &pool_id);
} else {
IpAddress ip;
ip.set(address);
pool_found = ntop_interface->getHostPools()->findIpPool(&ip, vlan_id, &pool_id, &target_node);
}
if(pool_found) {
lua_newtable(vm);
lua_push_uint64_table_entry(vm, "pool_id", pool_id);
if(target_node != NULL) {
lua_push_str_table_entry(vm, "matched_prefix", (char *)inet_ntop(target_node->prefix->family,
(target_node->prefix->family == AF_INET6) ?
(void*)(&target_node->prefix->add.sin6) :
(void*)(&target_node->prefix->add.sin),
buf, sizeof(buf)));
lua_push_uint64_table_entry(vm, "matched_bitmask", target_node->bit);
}
} else
lua_pushnil(vm);
return(CONST_LUA_OK);
} else
return(CONST_LUA_ERROR);
}
/* *******************************************/
// ***API***
static int ntop_find_mac_pool(lua_State *vm) {
const char *mac;
u_int8_t mac_parsed[6];
u_int16_t pool_id;
NetworkInterface *ntop_interface = getCurrentInterface(vm);
if(ntop_lua_check(vm, __FUNCTION__, 1, LUA_TSTRING) != CONST_LUA_OK) return(CONST_LUA_PARAM_ERROR);
mac = lua_tostring(vm, 1);
Utils::parseMac(mac_parsed, mac);
if(ntop_interface && ntop_interface->getHostPools()) {
if(ntop_interface->getHostPools()->findMacPool(mac_parsed, &pool_id))
lua_pushinteger(vm, pool_id);
else
lua_pushnil(vm);
return(CONST_LUA_OK);
} else
return(CONST_LUA_ERROR);
}
/* *******************************************/
static int ntop_get_top_pools_protos(lua_State *vm) {
NetworkInterface *ntop_interface = getCurrentInterface(vm);
if(ntop_interface) {
ntop_interface->luaTopPoolsProtos(vm);
return(CONST_LUA_OK);
} else
return(CONST_LUA_ERROR);
}
/* *******************************************/
static int ntop_get_top_macs_protos(lua_State *vm) {
NetworkInterface *ntop_interface = getCurrentInterface(vm);
if(ntop_interface) {
ntop_interface->luaTopMacsProtos(vm);
return(CONST_LUA_OK);
} else
return(CONST_LUA_ERROR);
}
/* *******************************************/
#ifdef HAVE_NEDGE
static int ntop_reload_l7_rules(lua_State *vm) {
NetworkInterface *ntop_interface = getCurrentInterface(vm);
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
if(ntop_lua_check(vm, __FUNCTION__, 1, LUA_TNUMBER) != CONST_LUA_OK) return(CONST_LUA_PARAM_ERROR);
if(ntop_interface) {
u_int16_t host_pool_id = (u_int16_t)lua_tonumber(vm, 1);
#ifdef SHAPER_DEBUG
ntop->getTrace()->traceEvent(TRACE_NORMAL, "%s(%i)", __FUNCTION__, host_pool_id);
#endif
ntop_interface->refreshL7Rules();
ntop_interface->updateHostsL7Policy(host_pool_id);
ntop_interface->updateFlowsL7Policy();
lua_pushnil(vm);
return(CONST_LUA_OK);
} else
return(CONST_LUA_ERROR);
}
/* ****************************************** */
static int ntop_reload_shapers(lua_State *vm) {
NetworkInterface *ntop_interface = getCurrentInterface(vm);
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
if(ntop_interface) {
#ifdef NTOPNG_PRO
ntop_interface->refreshShapers();
#endif
lua_pushnil(vm);
return(CONST_LUA_OK);
} else
return(CONST_LUA_ERROR);
}
#endif
/* ****************************************** */
static int ntop_reload_device_protocols(lua_State *vm) {
DeviceType device_type = device_unknown;
char *dir; /* client or server */
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
if(ntop_lua_check(vm, __FUNCTION__, 1, LUA_TNUMBER) != CONST_LUA_OK)
return(CONST_LUA_PARAM_ERROR);
if(ntop_lua_check(vm, __FUNCTION__, 2, LUA_TSTRING) != CONST_LUA_OK)
return(CONST_LUA_PARAM_ERROR);
if(ntop_lua_check(vm, __FUNCTION__, 3, LUA_TTABLE) != CONST_LUA_OK)
return(CONST_LUA_PARAM_ERROR);
device_type = (DeviceType) lua_tointeger(vm, 1);
if((dir = (char *) lua_tostring(vm, 2)) == NULL) return(CONST_LUA_PARAM_ERROR);
ntop->refreshAllowedProtocolPresets(device_type, !!strcmp(dir, "server"), vm, 3);
return(CONST_LUA_OK);
}
/* ****************************************** */
static int ntop_run_extraction(lua_State *vm) {
int id, ifid;
time_t time_from, time_to;
char *filter;
u_int64_t max_bytes;
char * timeline_path = NULL;
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
if(!ntop->isUserAdministrator(vm))
return(CONST_LUA_ERROR);
if(ntop_lua_check(vm, __FUNCTION__, 1, LUA_TNUMBER) != CONST_LUA_OK)
return(CONST_LUA_PARAM_ERROR);
if(ntop_lua_check(vm, __FUNCTION__, 2, LUA_TNUMBER) != CONST_LUA_OK)
return(CONST_LUA_PARAM_ERROR);
if(ntop_lua_check(vm, __FUNCTION__, 3, LUA_TNUMBER) != CONST_LUA_OK)
return(CONST_LUA_PARAM_ERROR);
if(ntop_lua_check(vm, __FUNCTION__, 4, LUA_TNUMBER) != CONST_LUA_OK)
return(CONST_LUA_PARAM_ERROR);
if(ntop_lua_check(vm, __FUNCTION__, 5, LUA_TSTRING) != CONST_LUA_OK)
return(CONST_LUA_PARAM_ERROR);
if(lua_type(vm, 6) == LUA_TNUMBER) max_bytes = lua_tonumber(vm, 6);
else max_bytes = 0; /* optional */
if(lua_tostring(vm, 7)) timeline_path = (char *)lua_tostring(vm, 7);
id = lua_tointeger(vm, 1);
ifid = lua_tointeger(vm, 2);
time_from = lua_tointeger(vm, 3);
time_to = lua_tointeger(vm, 4);
if((filter = (char *) lua_tostring(vm, 5)) == NULL) return(CONST_LUA_PARAM_ERROR);
max_bytes = lua_tonumber(vm, 6);
ntop->getTimelineExtract()->runExtractionJob(id,
ntop->getInterfaceById(ifid), time_from, time_to, filter, max_bytes, timeline_path);
return(CONST_LUA_OK);
}
/* ****************************************** */
static int ntop_stop_extraction(lua_State *vm) {
int id;
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
if(!ntop->isUserAdministrator(vm))
return(CONST_LUA_ERROR);
if(ntop_lua_check(vm, __FUNCTION__, 1, LUA_TNUMBER) != CONST_LUA_OK)
return(CONST_LUA_PARAM_ERROR);
id = lua_tointeger(vm, 1);
ntop->getTimelineExtract()->stopExtractionJob(id);
return(CONST_LUA_OK);
}
/* ****************************************** */
static int ntop_is_extraction_running(lua_State *vm) {
bool rv;
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
if(!ntop->isUserAdministrator(vm))
return(CONST_LUA_ERROR);
rv = ntop->getTimelineExtract()->isRunning();
lua_pushboolean(vm, rv);
return(CONST_LUA_OK);
}
/* ****************************************** */
static int ntop_get_extraction_status(lua_State *vm) {
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
if(!ntop->isUserAdministrator(vm))
return(CONST_LUA_ERROR);
ntop->getTimelineExtract()->getStatus(vm);
return(CONST_LUA_OK);
}
/* ****************************************** */
// ***API***
static int ntop_run_live_extraction(lua_State *vm) {
struct ntopngLuaContext *c;
NetworkInterface *iface;
TimelineExtract timeline;
int ifid;
time_t time_from, time_to;
char *filter;
bool allow = false, success = false;
char * timeline_path = NULL;
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
if(!ntop->isUserAdministrator(vm))
return(CONST_LUA_ERROR);
c = getLuaVMContext(vm);
if (!c)
return(CONST_LUA_ERROR);
if(ntop_lua_check(vm, __FUNCTION__, 1, LUA_TNUMBER) != CONST_LUA_OK)
return(CONST_LUA_PARAM_ERROR);
if (ntop_lua_check(vm, __FUNCTION__, 2, LUA_TNUMBER) != CONST_LUA_OK)
return(CONST_LUA_PARAM_ERROR);
if (ntop_lua_check(vm, __FUNCTION__, 3, LUA_TNUMBER) != CONST_LUA_OK)
return(CONST_LUA_PARAM_ERROR);
if (ntop_lua_check(vm, __FUNCTION__, 4, LUA_TSTRING) != CONST_LUA_OK)
return(CONST_LUA_PARAM_ERROR);
ifid = lua_tointeger(vm, 1);
time_from = lua_tointeger(vm, 2);
time_to = lua_tointeger(vm, 3);
if ((filter = (char *) lua_tostring(vm, 4)) == NULL) return(CONST_LUA_PARAM_ERROR);
if(lua_tostring(vm, 5)) timeline_path = (char *)lua_tostring(vm, 5);
iface = ntop->getInterfaceById(ifid);
if(!iface) return(CONST_LUA_ERROR);
live_extraction_num_lock.lock(__FILE__, __LINE__);
if (live_extraction_num < CONST_MAX_NUM_LIVE_EXTRACTIONS) {
allow = true;
live_extraction_num++;
}
live_extraction_num_lock.unlock(__FILE__, __LINE__);
if (allow) {
success = timeline.extractLive(c->conn, iface, time_from, time_to, filter, timeline_path);
live_extraction_num_lock.lock(__FILE__, __LINE__);
live_extraction_num--;
live_extraction_num_lock.unlock(__FILE__, __LINE__);
}
lua_pushboolean(vm, success);
return(CONST_LUA_OK);
}
/* ****************************************** */
static int ntop_bitmap_is_set(lua_State *vm) {
u_int64_t bitmap;
u_int64_t val;
if(ntop_lua_check(vm, __FUNCTION__, 1, LUA_TNUMBER) != CONST_LUA_OK) return(CONST_LUA_ERROR);
bitmap = lua_tointeger(vm, 1);
if(ntop_lua_check(vm, __FUNCTION__, 2, LUA_TNUMBER) != CONST_LUA_OK) return(CONST_LUA_ERROR);
val = lua_tointeger(vm, 2);
lua_pushboolean(vm, Utils::bitmapIsSet(bitmap, val));
return(CONST_LUA_OK);
}
/* ****************************************** */
static int ntop_bitmap_set(lua_State *vm) {
u_int64_t bitmap;
u_int64_t val;
if(ntop_lua_check(vm, __FUNCTION__, 1, LUA_TNUMBER) != CONST_LUA_OK) return(CONST_LUA_ERROR);
bitmap = lua_tointeger(vm, 1);
if(ntop_lua_check(vm, __FUNCTION__, 2, LUA_TNUMBER) != CONST_LUA_OK) return(CONST_LUA_ERROR);
val = lua_tointeger(vm, 2);
lua_pushinteger(vm, Utils::bitmapSet(bitmap, val));
return(CONST_LUA_OK);
}
/* ****************************************** */
static int ntop_bitmap_clear(lua_State *vm) {
u_int64_t bitmap;
u_int64_t val;
if(ntop_lua_check(vm, __FUNCTION__, 1, LUA_TNUMBER) != CONST_LUA_OK) return(CONST_LUA_ERROR);
bitmap = lua_tointeger(vm, 1);
if(ntop_lua_check(vm, __FUNCTION__, 2, LUA_TNUMBER) != CONST_LUA_OK) return(CONST_LUA_ERROR);
val = lua_tointeger(vm, 2);
lua_pushinteger(vm, Utils::bitmapClear(bitmap, val));
return(CONST_LUA_OK);
}
/* ****************************************** */
static int ntop_interface_exec_sql_query(lua_State *vm) {
NetworkInterface *ntop_interface = getCurrentInterface(vm);
bool limit_rows = true; // honour the limit by default
bool wait_for_db_created = true;
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
if(!ntop_interface)
return(CONST_LUA_ERROR);
else {
char *sql;
if(ntop_lua_check(vm, __FUNCTION__, 1, LUA_TSTRING) != CONST_LUA_OK) return(CONST_LUA_PARAM_ERROR);
if((sql = (char*)lua_tostring(vm, 1)) == NULL) return(CONST_LUA_PARAM_ERROR);
if(lua_type(vm, 2) == LUA_TBOOLEAN) {
limit_rows = lua_toboolean(vm, 2) ? true : false;
}
if(lua_type(vm, 3) == LUA_TBOOLEAN) {
wait_for_db_created = lua_toboolean(vm, 3) ? true : false;
}
if(ntop_interface->exec_sql_query(vm, sql, limit_rows, wait_for_db_created) < 0)
lua_pushnil(vm);
return(CONST_LUA_OK);
}
}
/* ****************************************** */
static int ntop_interface_exec_single_sql_query(lua_State *vm) {
char *sql;
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
if(ntop_lua_check(vm, __FUNCTION__, 1, LUA_TSTRING) != CONST_LUA_OK) return(CONST_LUA_PARAM_ERROR);
if((sql = (char*)lua_tostring(vm, 1)) == NULL) return(CONST_LUA_PARAM_ERROR);
#ifdef HAVE_MYSQL
MySQLDB::exec_single_query(vm, sql);
return(CONST_LUA_OK);
#else
return(CONST_LUA_ERROR);
#endif
}
/* ****************************************** */
// ***API***
static int ntop_reset_stats(lua_State* vm) {
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
ntop->resetStats();
lua_pushnil(vm);
return(CONST_LUA_OK);
}
/* ****************************************** */
// ***API***
static int ntop_get_dirs(lua_State* vm) {
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
lua_newtable(vm);
lua_push_str_table_entry(vm, "installdir", ntop->get_install_dir());
lua_push_str_table_entry(vm, "workingdir", ntop->get_working_dir());
lua_push_str_table_entry(vm, "scriptdir", ntop->getPrefs()->get_scripts_dir());
lua_push_str_table_entry(vm, "httpdocsdir", ntop->getPrefs()->get_docs_dir());
lua_push_str_table_entry(vm, "callbacksdir", ntop->getPrefs()->get_callbacks_dir());
lua_push_str_table_entry(vm, "pcapdir", ntop->getPrefs()->get_pcap_dir());
return(CONST_LUA_OK);
}
/* ****************************************** */
// ***API***
static int ntop_get_uptime(lua_State* vm) {
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
lua_pushinteger(vm, ntop->getGlobals()->getUptime());
return(CONST_LUA_OK);
}
/* ****************************************** */
// ***API***
static int ntop_system_host_stat(lua_State* vm) {
float cpu_load;
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
lua_newtable(vm);
if(ntop->getCpuLoad(&cpu_load)) lua_push_float_table_entry(vm, "cpu_load", cpu_load);
Utils::luaMeminfo(vm);
return(CONST_LUA_OK);
}
/* ****************************************** */
static int ntop_refresh_cpu_load(lua_State* vm) {
float cpu_load;
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
ntop->refreshCpuLoad();
if(ntop->getCpuLoad(&cpu_load))
lua_pushnumber(vm, cpu_load);
else
lua_pushnil(vm);
return(CONST_LUA_OK);
}
/* ****************************************** */
static int ntop_check_license(lua_State* vm) {
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
#ifdef NTOPNG_PRO
ntop->getPro()->check_license();
#endif
lua_pushinteger(vm,1);
return(CONST_LUA_OK);
}
/* ****************************************** */
// ***API***
static int ntop_get_info(lua_State* vm) {
char rsp[256];
#ifndef HAVE_NEDGE
int major, minor, patch;
#endif
bool verbose = true;
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
if(lua_type(vm, 1) == LUA_TBOOLEAN)
verbose = lua_toboolean(vm, 1) ? true : false;
lua_newtable(vm);
#ifdef HAVE_NEDGE
lua_push_str_table_entry(vm, "product", ntop->getPro()->get_product_name());
lua_push_bool_table_entry(vm, "oem", ntop->getPro()->is_oem());
#else
lua_push_str_table_entry(vm, "product", (char*)"ntopng");
#endif
lua_push_str_table_entry(vm, "copyright",
#ifdef HAVE_NEDGE
ntop->getPro()->is_oem() ? (char*)"" :
#endif
(char*)"&copy; 1998-19 - ntop.org");
lua_push_str_table_entry(vm, "authors", (char*)"The ntop.org team");
lua_push_str_table_entry(vm, "license", (char*)"GNU GPLv3");
lua_push_str_table_entry(vm, "platform", (char*)PACKAGE_MACHINE);
lua_push_str_table_entry(vm, "version", (char*)PACKAGE_VERSION);
lua_push_str_table_entry(vm, "revision", (char*)PACKAGE_REVISION);
lua_push_str_table_entry(vm, "git", (char*)NTOPNG_GIT_RELEASE);
#ifndef WIN32
lua_push_uint64_table_entry(vm, "pid", getpid());
#endif
snprintf(rsp, sizeof(rsp), "%s [%s][%s]",
PACKAGE_OSNAME, PACKAGE_MACHINE, PACKAGE_OS);
lua_push_str_table_entry(vm, "platform", rsp);
lua_push_str_table_entry(vm, "OS",
#ifdef WIN32
(char*)"Windows"
#else
(char*)PACKAGE_OS
#endif
);
lua_push_uint64_table_entry(vm, "bits", (sizeof(void*) == 4) ? 32 : 64);
lua_push_uint64_table_entry(vm, "uptime", ntop->getGlobals()->getUptime());
lua_push_str_table_entry(vm, "command_line", ntop->getPrefs()->get_command_line());
if(verbose) {
lua_push_str_table_entry(vm, "version.rrd", rrd_strversion());
lua_push_str_table_entry(vm, "version.redis", ntop->getRedis()->getVersion());
lua_push_str_table_entry(vm, "version.httpd", (char*)mg_version());
lua_push_str_table_entry(vm, "version.git", (char*)NTOPNG_GIT_RELEASE);
lua_push_str_table_entry(vm, "version.curl", (char*)LIBCURL_VERSION);
lua_push_str_table_entry(vm, "version.luajit", (char*)LUA_RELEASE);
#ifdef HAVE_MAXMINDDB
lua_push_str_table_entry(vm, "version.geoip", (char*)MMDB_lib_version());
#endif
lua_push_str_table_entry(vm, "version.ndpi", ndpi_revision());
lua_push_bool_table_entry(vm, "version.enterprise_edition", ntop->getPrefs()->is_enterprise_edition());
lua_push_bool_table_entry(vm, "version.embedded_edition", ntop->getPrefs()->is_embedded_edition());
lua_push_bool_table_entry(vm, "version.nedge_edition", ntop->getPrefs()->is_nedge_edition());
lua_push_bool_table_entry(vm, "version.nedge_enterprise_edition", ntop->getPrefs()->is_nedge_enterprise_edition());
lua_push_bool_table_entry(vm, "pro.release", ntop->getPrefs()->is_pro_edition());
lua_push_uint64_table_entry(vm, "pro.demo_ends_at", ntop->getPrefs()->pro_edition_demo_ends_at());
#ifdef NTOPNG_PRO
#ifndef FORCE_VALID_LICENSE
time_t until_then;
int days_left;
if(ntop->getPro()->get_maintenance_expiration_time(&until_then, &days_left)) {
lua_push_uint64_table_entry(vm, "pro.license_ends_at", (u_int64_t)until_then);
lua_push_uint64_table_entry(vm, "pro.license_days_left", days_left);
}
#endif
lua_push_str_table_entry(vm, "pro.license", ntop->getPro()->get_license());
lua_push_bool_table_entry(vm, "pro.out_of_maintenance", ntop->getPro()->is_out_of_maintenance());
lua_push_bool_table_entry(vm, "pro.use_redis_license", ntop->getPro()->use_redis_license());
lua_push_str_table_entry(vm, "pro.systemid", ntop->getPro()->get_system_id());
#if defined(HAVE_NINDEX)
lua_push_str_table_entry(vm, "version.nindex", nindex_version());
#endif
#endif
lua_push_uint64_table_entry(vm, "constants.max_num_host_pools", MAX_NUM_HOST_POOLS);
lua_push_uint64_table_entry(vm, "constants.max_num_pool_members", MAX_NUM_POOL_MEMBERS);
lua_push_uint64_table_entry(vm, "constants.max_num_profiles", MAX_NUM_PROFILES);
#ifndef HAVE_NEDGE
zmq_version(&major, &minor, &patch);
snprintf(rsp, sizeof(rsp), "%d.%d.%d", major, minor, patch);
lua_push_str_table_entry(vm, "version.zmq", rsp);
#endif
}
#ifdef HAVE_TEST_MODE
lua_push_bool_table_entry(vm, "test_mode", true);
#endif
return(CONST_LUA_OK);
}
/* ****************************************** */
static int ntop_get_cookie_attributes(lua_State* vm) {
struct mg_request_info *request_info;
struct mg_connection *conn;
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
if(!(conn = getLuaVMUserdata(vm, conn)))
return(CONST_LUA_ERROR);
if(!(request_info = mg_get_request_info(conn)))
return(CONST_LUA_ERROR);
lua_pushstring(vm, (char*)get_secure_cookie_attributes(request_info));
return(CONST_LUA_OK);
}
/* ****************************************** */
static int ntop_is_allowed_interface(lua_State* vm) {
int id;
NetworkInterface *iface;
bool rv = false;
char *allowed_ifname = getLuaVMUserdata(vm, allowed_ifname);
if(ntop_lua_check(vm, __FUNCTION__, 1, LUA_TNUMBER) != CONST_LUA_OK) return(CONST_LUA_ERROR);
id = lua_tointeger(vm, 1);
if((allowed_ifname == NULL) || (allowed_ifname[0] == '\0'))
rv = true;
else if(((iface = ntop->getNetworkInterface(vm, id)) != NULL) && (iface->get_id() == id) &&
matches_allowed_ifname(allowed_ifname, iface->get_name()))
rv = true;
lua_pushboolean(vm, rv);
return(CONST_LUA_OK);
}
/* ****************************************** */
static int ntop_is_allowed_network(lua_State* vm) {
bool rv = false;
u_int16_t vlan_id = 0;
char *host, buf[64];
AddressTree *allowed_nets = get_allowed_nets(vm);
if(ntop_lua_check(vm, __FUNCTION__, 1, LUA_TSTRING) != CONST_LUA_OK) return(CONST_LUA_ERROR);
get_host_vlan_info((char*)lua_tostring(vm, 1), &host, &vlan_id, buf, sizeof(buf));
if(!allowed_nets /* e.g., when the user is 'nologin' there's no allowed network to enforce */
|| allowed_nets->match(host))
rv = true;
lua_pushboolean(vm, rv);
return(CONST_LUA_OK);
}
/* ****************************************** */
static int ntop_get_resolved_address(lua_State* vm) {
char *key, *tmp,rsp[256],value[64];
Redis *redis = ntop->getRedis();
u_int16_t vlan_id = 0;
char buf[64];
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
if(ntop_lua_check(vm, __FUNCTION__, 1, LUA_TSTRING) != CONST_LUA_OK) return(CONST_LUA_ERROR);
get_host_vlan_info((char*)lua_tostring(vm, 1), &key, &vlan_id, buf, sizeof(buf));
if(key == NULL)
return(CONST_LUA_ERROR);
if((redis->getAddress(key, rsp, sizeof(rsp), true) == 0) && (rsp[0] != '\0'))
tmp = rsp;
else
tmp = key;
if(vlan_id != 0)
snprintf(value, sizeof(value), "%s@%u", tmp, vlan_id);
else
snprintf(value, sizeof(value), "%s", tmp);
#if 0
if(!strcmp(value, key)) {
char rsp[64];
if((ntop->getRedis()->hashGet((char*)HOST_LABEL_NAMES, key, rsp, sizeof(rsp)) == 0)
&& (rsp[0] !='\0'))
lua_pushfstring(vm, "%s", rsp);
else
lua_pushfstring(vm, "%s", value);
} else
lua_pushfstring(vm, "%s", value);
#else
lua_pushfstring(vm, "%s", value);
#endif
return(CONST_LUA_OK);
}
/* ****************************************** */
static int ntop_resolve_host(lua_State* vm) {
char buf[64];
char *host;
bool ipv4 = false;
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
if(ntop_lua_check(vm, __FUNCTION__, 1, LUA_TSTRING) != CONST_LUA_OK) return(CONST_LUA_ERROR);
if(ntop_lua_check(vm, __FUNCTION__, 2, LUA_TBOOLEAN) != CONST_LUA_OK) return(CONST_LUA_ERROR);
if((host = (char*)lua_tostring(vm, 1)) == NULL) return(CONST_LUA_PARAM_ERROR);
ipv4 = lua_toboolean(vm, 2);
if(ntop->resolveHost(host, buf, sizeof(buf), ipv4))
lua_pushstring(vm, buf);
else
lua_pushnil(vm);
return(CONST_LUA_OK);
}
/* ****************************************** */
#ifndef HAVE_NEDGE
static int ntop_snmpget(lua_State* vm) { SNMP s; return(s.get(vm)); }
static int ntop_snmpgetnext(lua_State* vm) { SNMP s; return(s.getnext(vm)); }
#endif
/* ****************************************** */
// ***API***
#ifndef WIN32
static int ntop_syslog(lua_State* vm) {
char *msg;
int syslog_severity = LOG_INFO;
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
if(ntop_lua_check(vm, __FUNCTION__, 1, LUA_TSTRING) != CONST_LUA_OK) {
lua_pushnil(vm);
return(CONST_LUA_ERROR);
}
msg = (char*)lua_tostring(vm, 1);
if(lua_type(vm, 2) == LUA_TNUMBER)
syslog_severity = (int)lua_tonumber(vm, 2);
syslog(syslog_severity, "%s", msg);
lua_pushnil(vm);
return(CONST_LUA_OK);
}
#endif
/* ****************************************** */
/**
* @brief Generate a random value to prevent CSRF and XSRF attacks
* @details See http://blog.codinghorror.com/preventing-csrf-and-xsrf-attacks/
*/
// ***API***
static int ntop_generate_csrf_value(lua_State* vm) {
char random_a[32], random_b[32], csrf[33];
Redis *redis = ntop->getRedis();
const char *user = getLuaVMUservalue(vm, user);
if(!user) return(CONST_LUA_ERROR);
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
#ifdef __OpenBSD__
snprintf(random_a, sizeof(random_a), "%d", arc4random());
snprintf(random_b, sizeof(random_b), "%lu", time(NULL)*arc4random());
#else
snprintf(random_a, sizeof(random_a), "%d", rand());
snprintf(random_b, sizeof(random_b), "%lu", time(NULL)*rand());
#endif
mg_md5(csrf, random_a, random_b, NULL);
redis->set(csrf, (char*)user, MAX_CSRF_DURATION);
lua_pushfstring(vm, "%s", csrf);
return(CONST_LUA_OK);
}
/* ****************************************** */
static int ntop_md5(lua_State* vm) {
char result[33];
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
if(ntop_lua_check(vm, __FUNCTION__, 1, LUA_TSTRING) != CONST_LUA_OK) return(CONST_LUA_ERROR);
mg_md5(result, lua_tostring(vm, 1), NULL);
lua_pushstring(vm, result);
return(CONST_LUA_OK);
}
/* ****************************************** */
static int ntop_has_radius_support(lua_State* vm) {
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
#ifdef HAVE_RADIUS
lua_pushboolean(vm, true);
#else
lua_pushboolean(vm, false);
#endif
return(CONST_LUA_OK);
}
/* ****************************************** */
static int ntop_has_ldap_support(lua_State* vm) {
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
#if defined(NTOPNG_PRO) && defined(HAVE_LDAP) && !defined(HAVE_NEDGE)
lua_pushboolean(vm, true);
#else
lua_pushboolean(vm, false);
#endif
return(CONST_LUA_OK);
}
/* ****************************************** */
#ifdef UNUSED_CODE
struct ntopng_sqlite_state {
lua_State* vm;
u_int num_rows;
};
static int sqlite_callback(void *data, int argc,
char **argv, char **azColName) {
struct ntopng_sqlite_state *s = (struct ntopng_sqlite_state*)data;
lua_newtable(s->vm);
for(int i=0; i<argc; i++)
lua_push_str_table_entry(s->vm, (const char*)azColName[i],
(char*)(argv[i] ? argv[i] : "NULL"));
lua_pushinteger(s->vm, ++s->num_rows);
lua_insert(s->vm, -2);
lua_settable(s->vm, -3);
return(0);
}
#endif
/* ****************************************** */
/**
* @brief Insert a new minute sampling in the historical database
* @details Given a certain sampling point, store statistics for said
* sampling point.
*
* @param vm The lua state.
* @return @ref CONST_LUA_PARAM_ERROR in case of wrong parameter,
* CONST_LUA_ERROR in case of generic error, CONST_LUA_OK otherwise.
*/
static int ntop_stats_insert_minute_sampling(lua_State *vm) {
char *sampling;
time_t rawtime;
int ifid;
NetworkInterface* iface;
StatsManager *sm;
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
if(ntop_lua_check(vm, __FUNCTION__, 1, LUA_TNUMBER) != CONST_LUA_OK) return(CONST_LUA_ERROR);
ifid = lua_tointeger(vm, 1);
if(ifid < 0)
return(CONST_LUA_ERROR);
if(ntop_lua_check(vm, __FUNCTION__, 2, LUA_TSTRING) != CONST_LUA_OK) return(CONST_LUA_ERROR);
if((sampling = (char*)lua_tostring(vm, 2)) == NULL) return(CONST_LUA_PARAM_ERROR);
if(!(iface = ntop->getInterfaceById(ifid)) ||
!(sm = iface->getStatsManager()))
return(CONST_LUA_ERROR);
time(&rawtime);
if(sm->insertMinuteSampling(rawtime, sampling))
return(CONST_LUA_ERROR);
lua_pushnil(vm);
return(CONST_LUA_OK);
}
/* ****************************************** */
/**
* @brief Insert a new hour sampling in the historical database
* @details Given a certain sampling point, store statistics for said
* sampling point.
*
* @param vm The lua state.
* @return @ref CONST_LUA_PARAM_ERROR in case of wrong parameter,
* CONST_LUA_ERROR in case of generic error, CONST_LUA_OK otherwise.
*/
static int ntop_stats_insert_hour_sampling(lua_State *vm) {
char *sampling;
time_t rawtime;
int ifid;
NetworkInterface* iface;
StatsManager *sm;
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
if(ntop_lua_check(vm, __FUNCTION__, 1, LUA_TNUMBER) != CONST_LUA_OK) return(CONST_LUA_ERROR);
ifid = lua_tointeger(vm, 1);
if(ifid < 0)
return(CONST_LUA_ERROR);
if(ntop_lua_check(vm, __FUNCTION__, 2, LUA_TSTRING) != CONST_LUA_OK) return(CONST_LUA_ERROR);
if((sampling = (char*)lua_tostring(vm, 2)) == NULL) return(CONST_LUA_PARAM_ERROR);
if(!(iface = ntop->getInterfaceById(ifid)) ||
!(sm = iface->getStatsManager()))
return(CONST_LUA_ERROR);
time(&rawtime);
rawtime -= (rawtime % 60);
if(sm->insertHourSampling(rawtime, sampling))
return(CONST_LUA_ERROR);
lua_pushnil(vm);
return(CONST_LUA_OK);
}
/* ****************************************** */
/**
* @brief Insert a new day sampling in the historical database
* @details Given a certain sampling point, store statistics for said
* sampling point.
*
* @param vm The lua state.
* @return @ref CONST_LUA_PARAM_ERROR in case of wrong parameter,
* CONST_LUA_ERROR in case of generic error, CONST_LUA_OK otherwise.
*/
static int ntop_stats_insert_day_sampling(lua_State *vm) {
char *sampling;
time_t rawtime;
int ifid;
NetworkInterface* iface;
StatsManager *sm;
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
if(ntop_lua_check(vm, __FUNCTION__, 1, LUA_TNUMBER) != CONST_LUA_OK) return(CONST_LUA_ERROR);
ifid = lua_tointeger(vm, 1);
if(ifid < 0)
return(CONST_LUA_ERROR);
if(ntop_lua_check(vm, __FUNCTION__, 2, LUA_TSTRING) != CONST_LUA_OK) return(CONST_LUA_ERROR);
if((sampling = (char*)lua_tostring(vm, 2)) == NULL) return(CONST_LUA_PARAM_ERROR);
if(!(iface = ntop->getInterfaceById(ifid)) ||
!(sm = iface->getStatsManager()))
return(CONST_LUA_ERROR);
time(&rawtime);
rawtime -= (rawtime % 60);
if(sm->insertDaySampling(rawtime, sampling))
return(CONST_LUA_ERROR);
lua_pushnil(vm);
return(CONST_LUA_OK);
}
/* ****************************************** */
/**
* @brief Get a minute sampling from the historical database
* @details Given a certain sampling point, get statistics for said
* sampling point.
*
* @param vm The lua state.
* @return @ref CONST_LUA_PARAM_ERROR in case of wrong parameter,
* CONST_LUA_ERROR in case of generic error, CONST_LUA_OK otherwise.
*/
static int ntop_stats_get_minute_sampling(lua_State *vm) {
time_t epoch;
string sampling;
int ifid;
NetworkInterface* iface;
StatsManager *sm;
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
if(ntop_lua_check(vm, __FUNCTION__, 1, LUA_TNUMBER) != CONST_LUA_OK) return(CONST_LUA_ERROR);
ifid = lua_tointeger(vm, 1);
if(ifid < 0)
return(CONST_LUA_ERROR);
if(ntop_lua_check(vm, __FUNCTION__, 2, LUA_TNUMBER) != CONST_LUA_OK) return(CONST_LUA_ERROR);
epoch = (time_t)lua_tointeger(vm, 2);
if(!(iface = ntop->getInterfaceById(ifid)) ||
!(sm = iface->getStatsManager()))
return(CONST_LUA_ERROR);
if(sm->getMinuteSampling(epoch, &sampling))
return(CONST_LUA_ERROR);
lua_pushstring(vm, sampling.c_str());
return(CONST_LUA_OK);
}
/* ****************************************** */
/**
* @brief Delete minute stats older than a certain number of days.
* @details Given a number of days, delete stats for the current interface that
* are older than a certain number of days.
*
* @param vm The lua state.
* @return @ref CONST_LUA_PARAM_ERROR in case of wrong parameter,
* CONST_LUA_ERROR in case of generic error, CONST_LUA_OK otherwise.
*/
static int ntop_stats_delete_minute_older_than(lua_State *vm) {
int num_days;
int ifid;
NetworkInterface* iface;
StatsManager *sm;
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
if(!ntop->isUserAdministrator(vm)) return(CONST_LUA_ERROR);
if(ntop_lua_check(vm, __FUNCTION__, 1, LUA_TNUMBER) != CONST_LUA_OK) return(CONST_LUA_ERROR);
ifid = lua_tointeger(vm, 1);
if(ifid < 0)
return(CONST_LUA_ERROR);
if(ntop_lua_check(vm, __FUNCTION__, 2, LUA_TNUMBER) != CONST_LUA_OK) return(CONST_LUA_ERROR);
num_days = lua_tointeger(vm, 2);
if(num_days < 0)
return(CONST_LUA_ERROR);
if(!(iface = ntop->getInterfaceById(ifid)) ||
!(sm = iface->getStatsManager()))
return(CONST_LUA_ERROR);
if(sm->deleteMinuteStatsOlderThan(num_days))
return(CONST_LUA_ERROR);
lua_pushnil(vm);
return(CONST_LUA_OK);
}
/* ****************************************** */
/**
* @brief Delete hour stats older than a certain number of days.
* @details Given a number of days, delete stats for the current interface that
* are older than a certain number of days.
*
* @param vm The lua state.
* @return @ref CONST_LUA_PARAM_ERROR in case of wrong parameter,
* CONST_LUA_ERROR in case of generic error, CONST_LUA_OK otherwise.
*/
static int ntop_stats_delete_hour_older_than(lua_State *vm) {
int num_days;
int ifid;
NetworkInterface* iface;
StatsManager *sm;
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
if(!ntop->isUserAdministrator(vm)) return(CONST_LUA_ERROR);
if(ntop_lua_check(vm, __FUNCTION__, 1, LUA_TNUMBER) != CONST_LUA_OK) return(CONST_LUA_ERROR);
ifid = lua_tointeger(vm, 1);
if(ifid < 0)
return(CONST_LUA_ERROR);
if(ntop_lua_check(vm, __FUNCTION__, 2, LUA_TNUMBER) != CONST_LUA_OK) return(CONST_LUA_ERROR);
num_days = lua_tointeger(vm, 2);
if(num_days < 0)
return(CONST_LUA_ERROR);
if(!(iface = ntop->getInterfaceById(ifid)) ||
!(sm = iface->getStatsManager()))
return(CONST_LUA_ERROR);
if(sm->deleteHourStatsOlderThan(num_days))
return(CONST_LUA_ERROR);
lua_pushnil(vm);
return(CONST_LUA_OK);
}
/* ****************************************** */
/**
* @brief Delete day stats older than a certain number of days.
* @details Given a number of days, delete stats for the current interface that
* are older than a certain number of days.
*
* @param vm The lua state.
* @return @ref CONST_LUA_PARAM_ERROR in case of wrong parameter,
* CONST_LUA_ERROR in case of generic error, CONST_LUA_OK otherwise.
*/
static int ntop_stats_delete_day_older_than(lua_State *vm) {
int num_days;
int ifid;
NetworkInterface* iface;
StatsManager *sm;
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
if(!ntop->isUserAdministrator(vm)) return(CONST_LUA_ERROR);
if(ntop_lua_check(vm, __FUNCTION__, 1, LUA_TNUMBER) != CONST_LUA_OK) return(CONST_LUA_ERROR);
ifid = lua_tointeger(vm, 1);
if(ifid < 0)
return(CONST_LUA_ERROR);
if(ntop_lua_check(vm, __FUNCTION__, 2, LUA_TNUMBER) != CONST_LUA_OK) return(CONST_LUA_ERROR);
num_days = lua_tointeger(vm, 2);
if(num_days < 0)
return(CONST_LUA_ERROR);
if(!(iface = ntop->getInterfaceById(ifid)) ||
!(sm = iface->getStatsManager()))
return(CONST_LUA_ERROR);
if(sm->deleteDayStatsOlderThan(num_days))
return(CONST_LUA_ERROR);
lua_pushnil(vm);
return(CONST_LUA_OK);
}
/* ****************************************** */
/**
* @brief Get an interval of minute stats samplings from the historical database
* @details Given a certain interval of sampling points, get statistics for said
* sampling points.
*
* @param vm The lua state.
* @return @ref CONST_LUA_PARAM_ERROR in case of wrong parameter,
* CONST_LUA_ERROR in case of generic error, CONST_LUA_OK otherwise.
*/
static int ntop_stats_get_minute_samplings_interval(lua_State *vm) {
time_t epoch_start, epoch_end;
int ifid;
NetworkInterface* iface;
StatsManager *sm;
struct statsManagerRetrieval retvals;
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
if(ntop_lua_check(vm, __FUNCTION__, 1, LUA_TNUMBER) != CONST_LUA_OK) return(CONST_LUA_ERROR);
ifid = lua_tointeger(vm, 1);
if(ifid < 0)
return(CONST_LUA_ERROR);
if(ntop_lua_check(vm, __FUNCTION__, 2, LUA_TNUMBER) != CONST_LUA_OK) return(CONST_LUA_ERROR);
epoch_start = lua_tointeger(vm, 2);
if(epoch_start < 0)
return(CONST_LUA_ERROR);
if(ntop_lua_check(vm, __FUNCTION__, 3, LUA_TNUMBER) != CONST_LUA_OK) return(CONST_LUA_ERROR);
epoch_end = lua_tointeger(vm, 3);
if(epoch_end < 0)
return(CONST_LUA_ERROR);
if(!(iface = ntop->getInterfaceById(ifid)) ||
!(sm = iface->getStatsManager()))
return(CONST_LUA_ERROR);
if(sm->retrieveMinuteStatsInterval(epoch_start, epoch_end, &retvals))
return(CONST_LUA_ERROR);
lua_newtable(vm);
for (unsigned i = 0 ; i < retvals.rows.size() ; i++)
lua_push_str_table_entry(vm, retvals.rows[i].c_str(), (char*)"");
return(CONST_LUA_OK);
}
/* ****************************************** */
/**
* @brief Given an epoch, get minute stats for the latest n minutes
* @details Given a certain sampling point, get statistics for that point and
* for all timepoints spanning an interval of a given number of
* minutes.
*
* @param vm The lua state.
* @return @ref CONST_LUA_PARAM_ERROR in case of wrong parameter,
* CONST_LUA_ERROR in case of generic error, CONST_LUA_OK otherwise.
*/
static int ntop_stats_get_samplings_of_minutes_from_epoch(lua_State *vm) {
time_t epoch_start, epoch_end;
int num_minutes;
int ifid;
NetworkInterface* iface;
StatsManager *sm;
struct statsManagerRetrieval retvals;
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
if(ntop_lua_check(vm, __FUNCTION__, 1, LUA_TNUMBER) != CONST_LUA_OK) return(CONST_LUA_ERROR);
ifid = lua_tointeger(vm, 1);
if(ifid < 0)
return(CONST_LUA_ERROR);
if(ntop_lua_check(vm, __FUNCTION__, 2, LUA_TNUMBER) != CONST_LUA_OK) return(CONST_LUA_ERROR);
epoch_end = lua_tointeger(vm, 2);
epoch_end -= (epoch_end % 60);
if(epoch_end < 0)
return(CONST_LUA_ERROR);
if(ntop_lua_check(vm, __FUNCTION__, 3, LUA_TNUMBER) != CONST_LUA_OK) return(CONST_LUA_ERROR);
num_minutes = lua_tointeger(vm, 3);
if(num_minutes < 0)
return(CONST_LUA_ERROR);
if(!(iface = ntop->getInterfaceById(ifid)) ||
!(sm = iface->getStatsManager()))
return(CONST_LUA_ERROR);
epoch_start = epoch_end - (60 * num_minutes);
if(sm->retrieveMinuteStatsInterval(epoch_start, epoch_end, &retvals))
return(CONST_LUA_ERROR);
lua_newtable(vm);
for (unsigned i = 0 ; i < retvals.rows.size() ; i++)
lua_push_str_table_entry(vm, retvals.rows[i].c_str(), (char*)"");
return(CONST_LUA_OK);
}
/* ****************************************** */
/**
* @brief Given an epoch, get hour stats for the latest n hours
* @details Given a certain sampling point, get statistics for that point and
* for all timepoints spanning an interval of a given number of
* hours.
*
* @param vm The lua state.
* @return @ref CONST_LUA_PARAM_ERROR in case of wrong parameter,
* CONST_LUA_ERROR in case of generic error, CONST_LUA_OK otherwise.
*/
static int ntop_stats_get_samplings_of_hours_from_epoch(lua_State *vm) {
time_t epoch_start, epoch_end;
int num_hours;
int ifid;
NetworkInterface* iface;
StatsManager *sm;
struct statsManagerRetrieval retvals;
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
if(ntop_lua_check(vm, __FUNCTION__, 1, LUA_TNUMBER) != CONST_LUA_OK) return(CONST_LUA_ERROR);
ifid = lua_tointeger(vm, 1);
if(ifid < 0)
return(CONST_LUA_ERROR);
if(ntop_lua_check(vm, __FUNCTION__, 2, LUA_TNUMBER) != CONST_LUA_OK) return(CONST_LUA_ERROR);
epoch_end = lua_tointeger(vm, 2);
epoch_end -= (epoch_end % 60);
if(epoch_end < 0)
return(CONST_LUA_ERROR);
if(ntop_lua_check(vm, __FUNCTION__, 3, LUA_TNUMBER) != CONST_LUA_OK) return(CONST_LUA_ERROR);
num_hours = lua_tointeger(vm, 3);
if(num_hours < 0)
return(CONST_LUA_ERROR);
if(!(iface = ntop->getInterfaceById(ifid)) ||
!(sm = iface->getStatsManager()))
return(CONST_LUA_ERROR);
epoch_start = epoch_end - (num_hours * 60 * 60);
if(sm->retrieveHourStatsInterval(epoch_start, epoch_end, &retvals))
return(CONST_LUA_ERROR);
lua_newtable(vm);
for (unsigned i = 0 ; i < retvals.rows.size() ; i++)
lua_push_str_table_entry(vm, retvals.rows[i].c_str(), (char*)"");
return(CONST_LUA_OK);
}
/* ****************************************** */
/**
* @brief Given an epoch, get hour stats for the latest n days
* @details Given a certain sampling point, get statistics for that point and
* for all timepoints spanning an interval of a given number of
* days.
*
* @param vm The lua state.
* @return @ref CONST_LUA_PARAM_ERROR in case of wrong parameter,
* CONST_LUA_ERROR in case of generic error, CONST_LUA_OK otherwise.
*/
static int ntop_stats_get_samplings_of_days_from_epoch(lua_State *vm) {
time_t epoch_start, epoch_end;
int num_days;
int ifid;
NetworkInterface* iface;
StatsManager *sm;
struct statsManagerRetrieval retvals;
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
if(ntop_lua_check(vm, __FUNCTION__, 1, LUA_TNUMBER) != CONST_LUA_OK) return(CONST_LUA_ERROR);
ifid = lua_tointeger(vm, 1);
if(ifid < 0)
return(CONST_LUA_ERROR);
if(ntop_lua_check(vm, __FUNCTION__, 2, LUA_TNUMBER) != CONST_LUA_OK) return(CONST_LUA_ERROR);
epoch_end = lua_tointeger(vm, 2);
epoch_end -= (epoch_end % 60);
if(epoch_end < 0)
return(CONST_LUA_ERROR);
if(ntop_lua_check(vm, __FUNCTION__, 3, LUA_TNUMBER) != CONST_LUA_OK) return(CONST_LUA_ERROR);
num_days = lua_tointeger(vm, 3);
if(num_days < 0)
return(CONST_LUA_ERROR);
if(!(iface = ntop->getInterfaceById(ifid)) ||
!(sm = iface->getStatsManager()))
return(CONST_LUA_ERROR);
epoch_start = epoch_end - (num_days * 24 * 60 * 60);
if(sm->retrieveDayStatsInterval(epoch_start, epoch_end, &retvals))
return(CONST_LUA_ERROR);
lua_newtable(vm);
for (unsigned i = 0 ; i < retvals.rows.size() ; i++)
lua_push_str_table_entry(vm, retvals.rows[i].c_str(), (char*)"");
return(CONST_LUA_OK);
}
/* ****************************************** */
static bool ntop_delete_old_rrd_files_recursive(const char *dir_name, time_t now, int older_than_seconds) {
struct dirent *result;
int path_length;
char path[MAX_PATH];
DIR *d;
time_t last_update;
unsigned long ds_count;
if(!dir_name || strlen(dir_name) > MAX_PATH)
return false;
d = opendir(dir_name);
if(!d) return false;
while((result = readdir(d)) != NULL) {
if(result->d_type & DT_REG) {
if((path_length = snprintf(path, MAX_PATH, "%s/%s", dir_name, result->d_name)) <= MAX_PATH) {
ntop->fixPath(path);
if(ntop_rrd_get_lastupdate(path, &last_update, &ds_count) == 0) {
if((now >= last_update) && ((now - last_update) > older_than_seconds)) {
//printf("DELETE %s\n", path);
unlink(path);
}
}
}
} else if(result->d_type & DT_DIR) {
if(strncmp(result->d_name, "..", 2) && strncmp(result->d_name, ".", 1)) {
if((path_length = snprintf(path, MAX_PATH, "%s/%s", dir_name, result->d_name)) <= MAX_PATH) {
ntop->fixPath(path);
ntop_delete_old_rrd_files_recursive(path, now, older_than_seconds);
}
}
}
}
rmdir(dir_name); /* Remove the directory, if empty */
closedir(d);
return true;
}
/* ****************************************** */
static int ntop_delete_old_rrd_files(lua_State *vm) {
char path[PATH_MAX];
int older_than_seconds;
time_t now = time(NULL);
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
if(ntop_lua_check(vm, __FUNCTION__, 1, LUA_TSTRING) != CONST_LUA_OK) return(CONST_LUA_ERROR);
strncpy(path, lua_tostring(vm, 1), sizeof(path));
if(ntop_lua_check(vm, __FUNCTION__, 2, LUA_TNUMBER) != CONST_LUA_OK) return(CONST_LUA_ERROR);
if((older_than_seconds = lua_tointeger(vm, 2)) < 0) return(CONST_LUA_ERROR);
ntop->fixPath(path);
if(ntop_delete_old_rrd_files_recursive(path, now, older_than_seconds))
return(CONST_LUA_ERROR);
lua_pushnil(vm);
return(CONST_LUA_OK);
}
/* ****************************************** */
// ***API***
static int ntop_mkdir_tree(lua_State* vm) {
char *dir;
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
lua_pushnil(vm);
if(ntop_lua_check(vm, __FUNCTION__, 1, LUA_TSTRING) != CONST_LUA_OK) return(CONST_LUA_ERROR);
if((dir = (char*)lua_tostring(vm, 1)) == NULL) return(CONST_LUA_PARAM_ERROR);
if(dir[0] == '\0') return(CONST_LUA_OK); /* Nothing to do */
lua_pushboolean(vm, Utils::mkdir_tree(dir));
return(CONST_LUA_OK);
}
/* ****************************************** */
static int ntop_list_reports(lua_State* vm) {
DIR *dir;
char fullpath[MAX_PATH+8];
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
lua_newtable(vm);
snprintf(fullpath, sizeof(fullpath)-1, "%s/%s", ntop->get_working_dir(), "reports");
ntop->fixPath(fullpath);
if((dir = opendir(fullpath)) != NULL) {
struct dirent *ent;
while ((ent = readdir(dir)) != NULL) {
char filepath[MAX_PATH+3];
#ifdef WIN32
struct _stat64 buf;
#else
struct stat buf;
#endif
snprintf(filepath, sizeof(filepath), "%s/%s", fullpath, ent->d_name);
ntop->fixPath(filepath);
if(!stat(filepath, &buf) && !S_ISDIR(buf.st_mode))
lua_push_str_table_entry(vm, ent->d_name, (char*)"");
}
closedir(dir);
}
return(CONST_LUA_OK);
}
/* ****************************************** */
// ***API***
static int ntop_info_redis(lua_State* vm) {
char *rsp;
u_int rsp_len = CONST_MAX_LEN_REDIS_VALUE;
Redis *redis = ntop->getRedis();
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
lua_newtable(vm);
if((rsp = (char*)malloc(rsp_len)) != NULL) {
lua_push_str_table_entry(vm, "info", (redis->info(rsp, rsp_len) == 0) ? rsp : (char*)"");
lua_push_uint64_table_entry(vm, "dbsize", redis->dbsize());
free(rsp);
}
return(CONST_LUA_OK);
}
/* ****************************************** */
// ***API***
static int ntop_get_redis(lua_State* vm) {
char *key, *rsp;
u_int rsp_len = CONST_MAX_LEN_REDIS_VALUE;
Redis *redis = ntop->getRedis();
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
if(ntop_lua_check(vm, __FUNCTION__, 1, LUA_TSTRING) != CONST_LUA_OK) return(CONST_LUA_ERROR);
if((key = (char*)lua_tostring(vm, 1)) == NULL) return(CONST_LUA_PARAM_ERROR);
if((rsp = (char*)malloc(rsp_len)) != NULL) {
lua_pushfstring(vm, "%s", (redis->get(key, rsp, rsp_len) == 0) ? rsp : (char*)"");
free(rsp);
return(CONST_LUA_OK);
} else
return(CONST_LUA_ERROR);
}
/* ****************************************** */
// ***API***
static int ntop_incr_redis(lua_State* vm) {
char *key;
u_int rsp;
int amount = 1;
Redis *redis = ntop->getRedis();
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
if(ntop_lua_check(vm, __FUNCTION__, 1, LUA_TSTRING) != CONST_LUA_OK) return(CONST_LUA_ERROR);
if((key = (char*)lua_tostring(vm, 1)) == NULL) return(CONST_LUA_PARAM_ERROR);
if(lua_type(vm, 2) == LUA_TNUMBER)
amount = lua_tonumber(vm, 2);
rsp = redis->incr(key, amount);
lua_pushinteger(vm, rsp);
return(CONST_LUA_OK);
}
/* ****************************************** */
// ***API***
static int ntop_get_hash_redis(lua_State* vm) {
char *key, *member, *rsp;
Redis *redis = ntop->getRedis();
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
if(ntop_lua_check(vm, __FUNCTION__, 1, LUA_TSTRING) != CONST_LUA_OK) return(CONST_LUA_ERROR);
if((key = (char*)lua_tostring(vm, 1)) == NULL) return(CONST_LUA_PARAM_ERROR);
if((member = (char*)lua_tostring(vm, 2)) == NULL) return(CONST_LUA_PARAM_ERROR);
if((rsp = (char*)malloc(CONST_MAX_LEN_REDIS_VALUE)) == NULL) return(CONST_LUA_PARAM_ERROR);
lua_pushfstring(vm, "%s", (redis->hashGet(key, member, rsp, CONST_MAX_LEN_REDIS_VALUE) == 0) ? rsp : (char*)"");
free(rsp);
return(CONST_LUA_OK);
}
/* ****************************************** */
// ***API***
static int ntop_set_hash_redis(lua_State* vm) {
char *key, *member, *value;
Redis *redis = ntop->getRedis();
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
if(ntop_lua_check(vm, __FUNCTION__, 1, LUA_TSTRING) != CONST_LUA_OK) return(CONST_LUA_ERROR);
if((key = (char*)lua_tostring(vm, 1)) == NULL) return(CONST_LUA_PARAM_ERROR);
if((member = (char*)lua_tostring(vm, 2)) == NULL) return(CONST_LUA_PARAM_ERROR);
if((value = (char*)lua_tostring(vm, 3)) == NULL) return(CONST_LUA_PARAM_ERROR);
redis->hashSet(key, member, value);
lua_pushnil(vm);
return(CONST_LUA_OK);
}
/* ****************************************** */
// ***API***
static int ntop_delete_hash_redis_key(lua_State* vm) {
char *key, *member;
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
if(ntop_lua_check(vm, __FUNCTION__, 1, LUA_TSTRING) != CONST_LUA_OK) return(CONST_LUA_PARAM_ERROR);
if((key = (char*)lua_tostring(vm, 1)) == NULL) return(CONST_LUA_PARAM_ERROR);
if(ntop_lua_check(vm, __FUNCTION__, 2, LUA_TSTRING) != CONST_LUA_OK) return(CONST_LUA_PARAM_ERROR);
if((member = (char*)lua_tostring(vm, 2)) == NULL) return(CONST_LUA_PARAM_ERROR);
ntop->getRedis()->hashDel(key, member);
lua_pushnil(vm);
return(CONST_LUA_OK);
}
/* ****************************************** */
// ***API***
static int ntop_get_hash_keys_redis(lua_State* vm) {
char *key, **vals;
Redis *redis = ntop->getRedis();
int rc;
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
if(ntop_lua_check(vm, __FUNCTION__, 1, LUA_TSTRING) != CONST_LUA_OK) return(CONST_LUA_ERROR);
if((key = (char*)lua_tostring(vm, 1)) == NULL) return(CONST_LUA_PARAM_ERROR);
rc = redis->hashKeys(key, &vals);
if(rc > 0) {
lua_newtable(vm);
for(int i = 0; i < rc; i++) {
lua_push_str_table_entry(vm, vals[i] ? vals[i] : "", (char*)"");
if(vals[i]) free(vals[i]);
}
free(vals);
} else
lua_pushnil(vm);
return(CONST_LUA_OK);
}
/* ****************************************** */
// ***API***
static int ntop_get_hash_all_redis(lua_State* vm) {
char *key, **keys, **values;
Redis *redis = ntop->getRedis();
int rc;
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
if(ntop_lua_check(vm, __FUNCTION__, 1, LUA_TSTRING) != CONST_LUA_OK) return(CONST_LUA_ERROR);
if((key = (char*)lua_tostring(vm, 1)) == NULL) return(CONST_LUA_PARAM_ERROR);
rc = redis->hashGetAll(key, &keys, &values);
if(rc > 0) {
lua_newtable(vm);
for(int i = 0; i < rc; i++) {
lua_push_str_table_entry(vm, keys[i] ? keys[i] : (char *)"", values[i] ? values[i] : (char *)"");
if(values[i]) free(values[i]);
if(keys[i]) free(keys[i]);
}
free(keys);
free(values);
} else
lua_pushnil(vm);
return(CONST_LUA_OK);
}
/* ****************************************** */
// ***API***
static int ntop_get_keys_redis(lua_State* vm) {
char *pattern, **keys = NULL;
Redis *redis = ntop->getRedis();
int rc;
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
if(ntop_lua_check(vm, __FUNCTION__, 1, LUA_TSTRING) != CONST_LUA_OK) return(CONST_LUA_ERROR);
if((pattern = (char*)lua_tostring(vm, 1)) == NULL) return(CONST_LUA_PARAM_ERROR);
rc = redis->keys(pattern, &keys);
if(rc > 0) {
lua_newtable(vm);
for(int i = 0; i < rc; i++) {
lua_push_str_table_entry(vm, keys[i] ? keys[i] : "", (char*)"");
if(keys[i]) free(keys[i]);
}
} else
lua_pushnil(vm);
if(keys) free(keys);
return(CONST_LUA_OK);
}
/* ****************************************** */
// ***API***
static int ntop_lrange_redis(lua_State* vm) {
char *l_name, **l_elements;
Redis *redis = ntop->getRedis();
int start_offset = 0, end_offset = -1;
int rc;
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
if(ntop_lua_check(vm, __FUNCTION__, 1, LUA_TSTRING) != CONST_LUA_OK) return(CONST_LUA_ERROR);
if((l_name = (char*)lua_tostring(vm, 1)) == NULL) return(CONST_LUA_PARAM_ERROR);
if(lua_type(vm, 2) == LUA_TNUMBER) {
start_offset = lua_tointeger(vm, 2);
}
if(lua_type(vm, 3) == LUA_TNUMBER) {
end_offset = lua_tointeger(vm, 3);
}
rc = redis->lrange(l_name, &l_elements, start_offset, end_offset);
if(rc > 0) {
lua_newtable(vm);
for(int i = 0; i < rc; i++) {
lua_pushstring(vm, l_elements[i] ? l_elements[i] : "");
lua_rawseti(vm, -2, i+1);
if(l_elements[i]) free(l_elements[i]);
}
free(l_elements);
} else
lua_pushnil(vm);
return(CONST_LUA_OK);
}
/* ****************************************** */
static int ntop_llen_redis(lua_State* vm) {
char *l_name;
Redis *redis = ntop->getRedis();
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
if(!redis) return(CONST_LUA_ERROR);
if(ntop_lua_check(vm, __FUNCTION__, 1, LUA_TSTRING) != CONST_LUA_OK) return(CONST_LUA_ERROR);
if((l_name = (char*)lua_tostring(vm, 1)) == NULL) return(CONST_LUA_PARAM_ERROR);
lua_pushinteger(vm, redis->llen(l_name));
return(CONST_LUA_OK);
}
/* ****************************************** */
static int ntop_redis_dump(lua_State* vm) {
char *key, *dump;
Redis *redis = ntop->getRedis();
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
if(!redis->haveRedisDump())
lua_pushnil(vm); /* This is old redis */
else {
if(ntop_lua_check(vm, __FUNCTION__, 1, LUA_TSTRING) != CONST_LUA_OK) return(CONST_LUA_ERROR);
if((key = (char*)lua_tostring(vm, 1)) == NULL) return(CONST_LUA_PARAM_ERROR);
dump = redis->dump(key);
if(dump) {
lua_pushfstring(vm, "%s", dump);
free(dump);
} else
return(CONST_LUA_ERROR);
}
return(CONST_LUA_OK);
}
/* ****************************************** */
static int ntop_redis_restore(lua_State* vm) {
char *key, *dump;
Redis *redis = ntop->getRedis();
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
if(!redis->haveRedisDump()) {
lua_pushnil(vm); /* This is old redis */
return(CONST_LUA_OK);
} else {
if(ntop_lua_check(vm, __FUNCTION__, 1, LUA_TSTRING) != CONST_LUA_OK) return(CONST_LUA_ERROR);
if((key = (char*)lua_tostring(vm, 1)) == NULL) return(CONST_LUA_PARAM_ERROR);
if(ntop_lua_check(vm, __FUNCTION__, 2, LUA_TSTRING) != CONST_LUA_OK) return(CONST_LUA_ERROR);
if((dump = (char*)lua_tostring(vm, 2)) == NULL) return(CONST_LUA_PARAM_ERROR);
return((redis->restore(key, dump) != 0) ? CONST_LUA_ERROR : CONST_LUA_OK);
}
}
/* ****************************************** */
static int ntop_list_index_redis(lua_State* vm) {
char *index_name, *rsp;
Redis *redis = ntop->getRedis();
int idx;
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
if(ntop_lua_check(vm, __FUNCTION__, 1, LUA_TSTRING) != CONST_LUA_OK) return(CONST_LUA_ERROR);
if((index_name = (char*)lua_tostring(vm, 1)) == NULL) return(CONST_LUA_PARAM_ERROR);
if(ntop_lua_check(vm, __FUNCTION__, 2, LUA_TNUMBER) != CONST_LUA_OK) return(CONST_LUA_ERROR);
idx = lua_tointeger(vm, 2);
if((rsp = (char*)malloc(CONST_MAX_LEN_REDIS_VALUE)) == NULL)
return(CONST_LUA_PARAM_ERROR);
if(redis->lindex(index_name, idx, rsp, CONST_MAX_LEN_REDIS_VALUE) != 0) {
free(rsp);
return(CONST_LUA_ERROR);
}
lua_pushfstring(vm, "%s", rsp);
free(rsp);
return(CONST_LUA_OK);
}
/* ****************************************** */
static int ntop_lrpop_redis(lua_State* vm, bool lpop) {
char msg[1024], *list_name;
Redis *redis = ntop->getRedis();
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
if(ntop_lua_check(vm, __FUNCTION__, 1, LUA_TSTRING) != CONST_LUA_OK) return(CONST_LUA_ERROR);
if((list_name = (char*)lua_tostring(vm, 1)) == NULL) return(CONST_LUA_PARAM_ERROR);
if((lpop ? redis->lpop(list_name, msg, sizeof(msg)) : redis->rpop(list_name, msg, sizeof(msg))) == 0) {
lua_pushfstring(vm, "%s", msg);
return(CONST_LUA_OK);
} else
return(CONST_LUA_ERROR);
}
/* ****************************************** */
// ***API***
static int ntop_lpop_redis(lua_State* vm) {
return ntop_lrpop_redis(vm, true /* LPOP */);
}
/* ****************************************** */
// ***API***
static int ntop_rpop_redis(lua_State* vm) {
return ntop_lrpop_redis(vm, false /* RPOP */);
}
/* ****************************************** */
// ***API***
static int ntop_lrem_redis(lua_State* vm) {
char *list_name, *rem_value;
int ret;
Redis *redis = ntop->getRedis();
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
if(ntop_lua_check(vm, __FUNCTION__, 1, LUA_TSTRING) != CONST_LUA_OK) return(CONST_LUA_ERROR);
if(ntop_lua_check(vm, __FUNCTION__, 2, LUA_TSTRING) != CONST_LUA_OK) return(CONST_LUA_ERROR);
if((list_name = (char*)lua_tostring(vm, 1)) == NULL) return(CONST_LUA_PARAM_ERROR);
if((rem_value = (char*)lua_tostring(vm, 2)) == NULL) return(CONST_LUA_PARAM_ERROR);
ret = redis->lrem(list_name, rem_value);
lua_pushnil(vm);
if(ret == 0)
return(CONST_LUA_OK);
else
return(CONST_LUA_ERROR);
}
/* ****************************************** */
// ***API***
static int ntop_ltrim_redis(lua_State* vm) {
char *list_name;
int start_idx, end_idx;
Redis *redis = ntop->getRedis();
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
if(ntop_lua_check(vm, __FUNCTION__, 1, LUA_TSTRING) != CONST_LUA_OK) return(CONST_LUA_ERROR);
if((list_name = (char*)lua_tostring(vm, 1)) == NULL) return(CONST_LUA_PARAM_ERROR);
if(ntop_lua_check(vm, __FUNCTION__, 2, LUA_TNUMBER) != CONST_LUA_OK) return(CONST_LUA_ERROR);
start_idx = lua_tonumber(vm, 2);
if(ntop_lua_check(vm, __FUNCTION__, 3, LUA_TNUMBER) != CONST_LUA_OK) return(CONST_LUA_ERROR);
end_idx = lua_tonumber(vm, 3);
if(redis && redis->ltrim(list_name, start_idx, end_idx) == 0) {
lua_pushnil(vm);
return(CONST_LUA_OK);
}
return(CONST_LUA_ERROR);
}
/* ****************************************** */
static int ntop_push_redis(lua_State* vm, bool use_lpush) {
char *list_name, *value;
u_int list_trim_size = 0; // default 0 = no trim
Redis *redis = ntop->getRedis();
int rv;
if(ntop_lua_check(vm, __FUNCTION__, 1, LUA_TSTRING) != CONST_LUA_OK) return(CONST_LUA_ERROR);
if((list_name = (char*)lua_tostring(vm, 1)) == NULL) return(CONST_LUA_PARAM_ERROR);
if(ntop_lua_check(vm, __FUNCTION__, 2, LUA_TSTRING) != CONST_LUA_OK) return(CONST_LUA_ERROR);
if((value = (char*)lua_tostring(vm, 2)) == NULL) return(CONST_LUA_PARAM_ERROR);
/* Optional trim list up to the specified number of elements */
if(lua_type(vm, 3) == LUA_TNUMBER)
list_trim_size = (u_int)lua_tonumber(vm, 3);
if(use_lpush)
rv = redis->lpush(list_name, value, list_trim_size);
else
rv = redis->rpush(list_name, value, list_trim_size);
if(rv == 0) {
lua_pushnil(vm);
return(CONST_LUA_OK);
} else
return(CONST_LUA_ERROR);
}
/* ****************************************** */
// ***API***
static int ntop_lpush_redis(lua_State* vm) {
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
return ntop_push_redis(vm, true);
}
/* ****************************************** */
// ***API***
static int ntop_rpush_redis(lua_State* vm) {
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
return ntop_push_redis(vm, false);
}
/* ****************************************** */
// ***API***
static int ntop_add_local_network(lua_State* vm) {
char *local_network;
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
if(!ntop->isUserAdministrator(vm))
return(CONST_LUA_ERROR);
if(ntop_lua_check(vm, __FUNCTION__, 1, LUA_TSTRING) != CONST_LUA_OK) return(CONST_LUA_ERROR);
if((local_network = (char*)lua_tostring(vm, 1)) == NULL) return(CONST_LUA_PARAM_ERROR);
ntop->addLocalNetwork(local_network);
lua_pushnil(vm);
return(CONST_LUA_OK);
}
/* ****************************************** */
/* NOTE: do not call directly, use alerts_api instead */
static int ntop_interface_store_alert(lua_State* vm) {
NetworkInterface *ntop_interface = getCurrentInterface(vm);
char *entity_value;
AlertLevel alert_severity;
AlertType alert_type;
AlertEntity alert_entity;
char *alert_json;
AlertsManager *am;
int ret, granularity;
char *alert_subtype;
bool ignore_disabled = false, check_maximum = true, is_new_alert;
time_t tstart, tend;
u_int64_t rowid;
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
if((!ntop_interface)
|| ((am = ntop_interface->getAlertsManager()) == NULL))
return(CONST_LUA_ERROR);
if(ntop_lua_check(vm, __FUNCTION__, 1, LUA_TNUMBER) != CONST_LUA_OK) return(CONST_LUA_ERROR);
tstart = (time_t)lua_tonumber(vm, 1);
if(ntop_lua_check(vm, __FUNCTION__, 2, LUA_TNUMBER) != CONST_LUA_OK) return(CONST_LUA_ERROR);
tend = (time_t)lua_tonumber(vm, 2);
if(ntop_lua_check(vm, __FUNCTION__, 3, LUA_TNUMBER) != CONST_LUA_OK) return(CONST_LUA_ERROR);
granularity = (int)lua_tonumber(vm, 3);
if(ntop_lua_check(vm, __FUNCTION__, 4, LUA_TNUMBER) != CONST_LUA_OK) return(CONST_LUA_ERROR);
alert_type = (AlertType)((int)lua_tonumber(vm, 4));
if(ntop_lua_check(vm, __FUNCTION__, 5, LUA_TSTRING) != CONST_LUA_OK) return(CONST_LUA_ERROR);
alert_subtype = (char*)lua_tostring(vm, 5);
if(ntop_lua_check(vm, __FUNCTION__, 6, LUA_TNUMBER) != CONST_LUA_OK) return(CONST_LUA_ERROR);
alert_severity = (AlertLevel)((int)lua_tonumber(vm, 6));
if(ntop_lua_check(vm, __FUNCTION__, 7, LUA_TNUMBER) != CONST_LUA_OK) return(CONST_LUA_ERROR);
alert_entity = (AlertEntity)((int)lua_tonumber(vm, 7));
if(ntop_lua_check(vm, __FUNCTION__, 8, LUA_TSTRING) != CONST_LUA_OK) return(CONST_LUA_ERROR);
entity_value = (char*)lua_tostring(vm, 8);
if(ntop_lua_check(vm, __FUNCTION__, 9, LUA_TSTRING) != CONST_LUA_OK) return(CONST_LUA_ERROR);
alert_json = (char*)lua_tostring(vm, 9);
ret = am->storeAlert(tstart, tend, granularity, alert_type, alert_subtype, alert_severity,
alert_entity, entity_value, alert_json, &is_new_alert, &rowid, ignore_disabled, check_maximum);
if(ret != 0)
ntop->getTrace()->traceEvent(TRACE_ERROR, "triggerAlert failed with code %d", ret);
if(ret == 0) {
lua_newtable(vm);
lua_push_uint64_table_entry(vm, "rowid", rowid);
} else
lua_pushnil(vm);
return(CONST_LUA_OK);
}
/* ****************************************** */
static int ntop_interface_store_flow_alert(lua_State* vm) {
NetworkInterface *ntop_interface = getCurrentInterface(vm);
AlertsManager *am;
u_int64_t rowid = 0;
int ret;
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
if((!ntop_interface)
|| ((am = ntop_interface->getAlertsManager()) == NULL))
return(CONST_LUA_ERROR);
if(lua_type(vm, 1) != LUA_TTABLE)
return(CONST_LUA_ERROR);
ret = am->storeFlowAlert(vm, 1, &rowid);
if(ret == 0) {
lua_newtable(vm);
lua_push_uint64_table_entry(vm, "rowid", rowid);
} else {
ntop->getTrace()->traceEvent(TRACE_ERROR, "storeFlowAlert failed (%d)", ret);
lua_pushnil(vm);
}
return(CONST_LUA_OK);
}
/* ****************************************** */
static int ntop_interface_set_has_alerts(lua_State* vm) {
bool has_alerts;
NetworkInterface *ntop_interface = getCurrentInterface(vm);
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
if(ntop_lua_check(vm, __FUNCTION__, 1, LUA_TBOOLEAN) != CONST_LUA_OK) return(CONST_LUA_ERROR);
has_alerts = lua_toboolean(vm, 1);
if(!ntop_interface)
return(CONST_LUA_ERROR);
ntop_interface->setHasAlerts(has_alerts);
lua_pushnil(vm);
return(CONST_LUA_OK);
}
/* ****************************************** */
static int ntop_interface_get_pods_stats(lua_State* vm) {
NetworkInterface *ntop_interface = getCurrentInterface(vm);
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
if(!ntop_interface)
return(CONST_LUA_ERROR);
ntop_interface->getPodsStats(vm);
return(CONST_LUA_OK);
}
/* ****************************************** */
static int ntop_interface_get_containers_stats(lua_State* vm) {
NetworkInterface *ntop_interface = getCurrentInterface(vm);
char *pod_filter = NULL;
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
if(!ntop_interface)
return(CONST_LUA_ERROR);
if(lua_type(vm, 1) == LUA_TSTRING)
pod_filter = (char*)lua_tostring(vm, 1);
ntop_interface->getContainersStats(vm, pod_filter);
return(CONST_LUA_OK);
}
/* ****************************************** */
static int ntop_interface_reload_companions(lua_State* vm) {
int ifid;
NetworkInterface *iface;
if(ntop_lua_check(vm, __FUNCTION__, 1, LUA_TNUMBER) != CONST_LUA_OK) return CONST_LUA_ERROR;
ifid = lua_tonumber(vm, 1);
if((iface = ntop->getInterfaceById(ifid)))
iface->reloadCompanions();
return CONST_LUA_OK;
}
/* ****************************************** */
static int ntop_host_get_fields(lua_State* vm, bool all_fields) {
struct ntopngLuaContext *c = getLuaVMContext(vm);
Host *h = c ? c->host : NULL;
if(h) {
h->lua(vm, NULL, all_fields, all_fields, false, false);
return(CONST_LUA_OK);
} else
return(CONST_LUA_ERROR);
}
/* ****************************************** */
static int ntop_host_get_basic_fields(lua_State* vm) {
return(ntop_host_get_fields(vm, false));
}
static int ntop_host_get_all_fields(lua_State* vm) {
return(ntop_host_get_fields(vm, true));
}
/* ****************************************** */
static int ntop_host_get_cached_alert_value(lua_State* vm) {
struct ntopngLuaContext *c = getLuaVMContext(vm);
Host *h = c ? c->host : NULL;
char *key;
std::string val;
ScriptPeriodicity periodicity;
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
if(!h) return(CONST_LUA_ERROR);
if(ntop_lua_check(vm, __FUNCTION__, 1, LUA_TSTRING) != CONST_LUA_OK) return(CONST_LUA_ERROR);
if((key = (char*)lua_tostring(vm, 1)) == NULL) return(CONST_LUA_PARAM_ERROR);
if(ntop_lua_check(vm, __FUNCTION__, 2, LUA_TNUMBER) != CONST_LUA_OK) return(CONST_LUA_ERROR);
if((periodicity = (ScriptPeriodicity)lua_tonumber(vm, 2)) >= MAX_NUM_PERIODIC_SCRIPTS) return(CONST_LUA_PARAM_ERROR);
val = h->getAlertCachedValue(std::string(key), periodicity);
lua_pushstring(vm, val.c_str());
return(CONST_LUA_OK);
}
/* ****************************************** */
static int ntop_host_set_cached_alert_value(lua_State* vm) {
struct ntopngLuaContext *c = getLuaVMContext(vm);
Host *h = c ? c->host : NULL;
char *key, *value;
ScriptPeriodicity periodicity;
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
if(!h) return(CONST_LUA_ERROR);
if(ntop_lua_check(vm, __FUNCTION__, 1, LUA_TSTRING) != CONST_LUA_OK) return(CONST_LUA_ERROR);
if((key = (char*)lua_tostring(vm, 1)) == NULL) return(CONST_LUA_PARAM_ERROR);
if(ntop_lua_check(vm, __FUNCTION__, 2, LUA_TSTRING) != CONST_LUA_OK) return(CONST_LUA_ERROR);
if((value = (char*)lua_tostring(vm, 2)) == NULL) return(CONST_LUA_PARAM_ERROR);
if(ntop_lua_check(vm, __FUNCTION__, 3, LUA_TNUMBER) != CONST_LUA_OK) return(CONST_LUA_ERROR);
if((periodicity = (ScriptPeriodicity)lua_tonumber(vm, 3)) >= MAX_NUM_PERIODIC_SCRIPTS) return(CONST_LUA_PARAM_ERROR);
if((!key) || (!value))
return(CONST_LUA_PARAM_ERROR);
h->setAlertCacheValue(std::string(key), std::string(value), periodicity);
return(CONST_LUA_OK);
}
/* ****************************************** */
static int ntop_get_alerts(lua_State* vm, AlertableEntity *entity) {
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
u_int idx = 0;
ScriptPeriodicity periodicity = no_periodicity;
if(!entity) return(CONST_LUA_ERROR);
if(lua_type(vm, 1) == LUA_TNUMBER) periodicity = (ScriptPeriodicity)lua_tointeger(vm, 1);
lua_newtable(vm);
entity->getAlerts(vm, periodicity, alert_none, alert_level_none, &idx);
return(CONST_LUA_OK);
}
/* ****************************************** */
static int ntop_interface_get_alerts(lua_State* vm) {
struct ntopngLuaContext *c = getLuaVMContext(vm);
return ntop_get_alerts(vm, c->iface);
}
static int ntop_host_get_alerts(lua_State* vm) {
struct ntopngLuaContext *c = getLuaVMContext(vm);
return ntop_get_alerts(vm, c->host);
}
static int ntop_network_get_alerts(lua_State* vm) {
struct ntopngLuaContext *c = getLuaVMContext(vm);
return ntop_get_alerts(vm, c->network);
}
/* ****************************************** */
static int ntop_network_check_context(lua_State* vm) {
struct ntopngLuaContext *c = getLuaVMContext(vm);
char *entity_val;
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
if(ntop_lua_check(vm, __FUNCTION__, 1, LUA_TSTRING) != CONST_LUA_OK) return(CONST_LUA_ERROR);
if((entity_val = (char*)lua_tostring(vm, 1)) == NULL) return(CONST_LUA_PARAM_ERROR);
if((c->network == NULL) || (strcmp(c->network->getEntityValue().c_str(), entity_val)) != 0) {
NetworkInterface *iface = getCurrentInterface(vm);
u_int8_t network_id = ntop->getLocalNetworkId(entity_val);
if(!iface || (network_id == (u_int8_t)-1) || ((c->network = iface->getNetworkStats(network_id)) == NULL)) {
ntop->getTrace()->traceEvent(TRACE_WARNING, "Could not set context for network %s", entity_val);
return(CONST_LUA_ERROR);
}
}
lua_pushnil(vm);
return(CONST_LUA_OK);
}
/* ****************************************** */
static int ntop_host_check_context(lua_State* vm) {
struct ntopngLuaContext *c = getLuaVMContext(vm);
char *entity_val;
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
if(ntop_lua_check(vm, __FUNCTION__, 1, LUA_TSTRING) != CONST_LUA_OK) return(CONST_LUA_ERROR);
if((entity_val = (char*)lua_tostring(vm, 1)) == NULL) return(CONST_LUA_PARAM_ERROR);
if((c->host == NULL) || (strcmp(c->host->getEntityValue().c_str(), entity_val)) != 0) {
NetworkInterface *iface = getCurrentInterface(vm);
char *host_ip, buf[64];
u_int16_t vlan_id;
get_host_vlan_info(entity_val, &host_ip, &vlan_id, buf, sizeof(buf));
if(!iface || !host_ip || ((c->host = iface->getHost(host_ip, vlan_id, false /* not inline */)) == NULL)) {
ntop->getTrace()->traceEvent(TRACE_WARNING, "Could not set context for host %s", entity_val);
return(CONST_LUA_ERROR);
}
}
lua_pushnil(vm);
return(CONST_LUA_OK);
}
/* ****************************************** */
static int ntop_interface_check_context(lua_State* vm) {
struct ntopngLuaContext *c = getLuaVMContext(vm);
char *entity_val;
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
if(ntop_lua_check(vm, __FUNCTION__, 1, LUA_TSTRING) != CONST_LUA_OK) return(CONST_LUA_ERROR);
if((entity_val = (char*)lua_tostring(vm, 1)) == NULL) return(CONST_LUA_PARAM_ERROR);
if((c->iface == NULL) || (strcmp(c->iface->getEntityValue().c_str(), entity_val)) != 0) {
/* NOTE: settting a context for a differnt interface is currently not supported */
ntop->getTrace()->traceEvent(TRACE_WARNING, "Bad context for interface %s", entity_val);
return(CONST_LUA_ERROR);
}
lua_pushnil(vm);
return(CONST_LUA_OK);
}
/* ****************************************** */
/* Manually refresh alerts for scripts outside the periodic scripts */
static int ntop_interface_refresh_alerts(lua_State* vm) {
struct ntopngLuaContext *c = getLuaVMContext(vm);
if(c->host)
c->host->refreshAlerts();
else if(c->network)
c->network->refreshAlerts();
else if(c->iface)
c->iface->refreshAlerts();
lua_pushnil(vm);
return(CONST_LUA_OK);
}
/* ****************************************** */
static Host* ntop_host_get_context_host(lua_State* vm) {
struct ntopngLuaContext *c = getLuaVMContext(vm);
return c->host;
}
/* ****************************************** */
static int ntop_host_get_ip(lua_State* vm) {
Host *h = ntop_host_get_context_host(vm);
lua_newtable(vm);
if(h)
h->lua_get_ip(vm);
return(CONST_LUA_OK);
}
/* ****************************************** */
static int ntop_host_get_localhost_info(lua_State* vm) {
Host *h = ntop_host_get_context_host(vm);
lua_newtable(vm);
if(h)
h->lua_get_localhost_info(vm);
return(CONST_LUA_OK);
}
/* ****************************************** */
static int ntop_host_get_application_bytes(lua_State* vm) {
Host *h = ntop_host_get_context_host(vm);
u_int app_id;
lua_newtable(vm);
if(h && ntop_lua_check(vm, __FUNCTION__, 1, LUA_TNUMBER) == CONST_LUA_OK) {
app_id = lua_tonumber(vm, 1);
h->lua_get_app_bytes(vm, app_id);
}
return(CONST_LUA_OK);
}
/* ****************************************** */
static int ntop_host_get_category_bytes(lua_State* vm) {
Host *h = ntop_host_get_context_host(vm);
ndpi_protocol_category_t cat_id;
lua_newtable(vm);
if(h && ntop_lua_check(vm, __FUNCTION__, 1, LUA_TNUMBER) == CONST_LUA_OK) {
cat_id = (ndpi_protocol_category_t)lua_tonumber(vm, 1);
h->lua_get_cat_bytes(vm, cat_id);
}
return(CONST_LUA_OK);
}
/* ****************************************** */
static int ntop_host_get_bytes(lua_State* vm) {
Host *h = ntop_host_get_context_host(vm);
lua_newtable(vm);
if(h)
h->lua_get_bytes(vm);
return(CONST_LUA_OK);
}
/* ****************************************** */
static int ntop_host_get_packets(lua_State* vm) {
Host *h = ntop_host_get_context_host(vm);
lua_newtable(vm);
if(h)
h->lua_get_packets(vm);
return(CONST_LUA_OK);
}
/* ****************************************** */
static int ntop_host_get_num_total_flows(lua_State* vm) {
Host *h = ntop_host_get_context_host(vm);
lua_newtable(vm);
if(h)
h->lua_get_num_total_flows(vm);
return(CONST_LUA_OK);
}
/* ****************************************** */
static int ntop_host_get_time(lua_State* vm) {
Host *h = ntop_host_get_context_host(vm);
lua_newtable(vm);
if(h)
h->lua_get_time(vm);
return(CONST_LUA_OK);
}
/* ****************************************** */
static int ntop_host_get_syn_flood(lua_State* vm) {
Host *h = ntop_host_get_context_host(vm);
lua_newtable(vm);
if(h)
h->lua_get_syn_flood(vm);
return(CONST_LUA_OK);
}
/* ****************************************** */
static int ntop_host_get_flow_flood(lua_State* vm) {
Host *h = ntop_host_get_context_host(vm);
lua_newtable(vm);
if(h)
h->lua_get_flow_flood(vm);
return(CONST_LUA_OK);
}
/* ****************************************** */
static int ntop_host_get_syn_scan(lua_State* vm) {
Host *h = ntop_host_get_context_host(vm);
lua_newtable(vm);
if(h)
h->lua_get_syn_scan(vm);
return(CONST_LUA_OK);
}
/* ****************************************** */
static int ntop_host_get_dns_info(lua_State* vm) {
Host *h = ntop_host_get_context_host(vm);
lua_newtable(vm);
if(h)
h->luaDNS(vm, true /* Verbose */);
return(CONST_LUA_OK);
}
/* ****************************************** */
static int ntop_host_get_http_info(lua_State* vm) {
Host *h = ntop_host_get_context_host(vm);
lua_newtable(vm);
if(h)
h->luaHTTP(vm);
return(CONST_LUA_OK);
}
/* ****************************************** */
static Flow* ntop_flow_get_context_flow(lua_State* vm) {
struct ntopngLuaContext *c = getLuaVMContext(vm);
return c->flow;
}
/* ****************************************** */
// ***API***
static int ntop_flow_get_info(lua_State* vm) {
Flow *f = ntop_flow_get_context_flow(vm);
if(!f) return(CONST_LUA_ERROR);
f->lua_get_min_info(vm);
return(CONST_LUA_OK);
}
/* ****************************************** */
static int ntop_flow_get_full_info(lua_State* vm) {
AddressTree *ptree = get_allowed_nets(vm);
Flow *f = ntop_flow_get_context_flow(vm);
if(!f) return(CONST_LUA_ERROR);
f->lua(vm, ptree, details_high, false);
return(CONST_LUA_OK);
}
/* ****************************************** */
// ***API***
static int ntop_flow_get_unicast_info(lua_State* vm) {
Flow *f = ntop_flow_get_context_flow(vm);
if(!f) return(CONST_LUA_ERROR);
f->lua_get_unicast_info(vm);
return(CONST_LUA_OK);
}
/* ****************************************** */
static int ntop_flow_get_key(lua_State* vm) {
Flow *f = ntop_flow_get_context_flow(vm);
if(!f) return(CONST_LUA_ERROR);
lua_pushinteger(vm, f->key());
return(CONST_LUA_OK);
}
/* ****************************************** */
static int ntop_flow_get_hash_entry_id(lua_State* vm) {
Flow *f = ntop_flow_get_context_flow(vm);
if(!f) return(CONST_LUA_ERROR);
lua_pushinteger(vm, f->get_hash_entry_id());
return(CONST_LUA_OK);
}
/* ****************************************** */
/* Get ICMP information that is specific for the serialization of ICMP data
* into the flow status_info */
static int ntop_flow_get_icmp_status_info(lua_State* vm) {
Flow *f = ntop_flow_get_context_flow(vm);
if(!f) return(CONST_LUA_ERROR);
if(f->getICMPInfo()) {
u_int8_t icmp_type, icmp_code;
f->getICMP(&icmp_type, &icmp_code);
lua_newtable(vm);
lua_push_int32_table_entry(vm, "type", icmp_type);
lua_push_int32_table_entry(vm, "code", icmp_code);
} else
lua_pushnil(vm);
return(CONST_LUA_OK);
}
/* ****************************************** */
static int ntop_flow_is_local(lua_State* vm) {
Flow *f = ntop_flow_get_context_flow(vm);
bool is_local = false;
if(!f) return(CONST_LUA_ERROR);
if(f->get_cli_host() && f->get_srv_host())
is_local = f->get_cli_host()->isLocalHost() && f->get_srv_host()->isLocalHost();
lua_pushboolean(vm, is_local);
return(CONST_LUA_OK);
}
/* ****************************************** */
static int ntop_flow_set_score(lua_State* vm) {
Flow *f = ntop_flow_get_context_flow(vm);
u_int16_t score;
if(!f) return(CONST_LUA_ERROR);
if(ntop_lua_check(vm, __FUNCTION__, 1, LUA_TNUMBER) != CONST_LUA_OK) return(CONST_LUA_ERROR);
score = (u_int16_t)lua_tonumber(vm, 1);
f->setScore(score);
lua_pushnil(vm);
return(CONST_LUA_OK);
}
/* ****************************************** */
static int ntop_flow_get_score(lua_State* vm) {
Flow *f = ntop_flow_get_context_flow(vm);
if(!f) return(CONST_LUA_ERROR);
lua_pushinteger(vm, f->getScore());
return(CONST_LUA_OK);
}
/* ****************************************** */
static int ntop_flow_get_score_info(lua_State* vm) {
Flow *f = ntop_flow_get_context_flow(vm);
Host *cli_host, *srv_host;
const char *status_info;
if(!f) return(CONST_LUA_ERROR);
cli_host = f->get_cli_host();
srv_host = f->get_srv_host();
status_info = f->getStatusInfo();
lua_newtable(vm);
lua_push_uint64_table_entry(vm, "status_map", f->getStatusBitmap().get());
lua_push_int32_table_entry(vm, "score", f->getScore());
lua_push_int32_table_entry(vm, "cli.score", ((cli_host && cli_host->getScore() != CONST_NO_SCORE_SET) ? cli_host->getScore() : 0));
lua_push_int32_table_entry(vm, "srv.score", ((srv_host && srv_host->getScore() != CONST_NO_SCORE_SET) ? srv_host->getScore() : 0));
if(status_info) lua_push_str_table_entry(vm, "status_info", status_info);
return(CONST_LUA_OK);
}
/* ****************************************** */
static int ntop_flow_set_peer_score(lua_State* vm, bool client) {
Flow *f = ntop_flow_get_context_flow(vm);
int score;
Host *host;
if(!f) return(CONST_LUA_ERROR);
if(ntop_lua_check(vm, __FUNCTION__, 1, LUA_TNUMBER) != CONST_LUA_OK) return(CONST_LUA_ERROR);
score = lua_tonumber(vm, 1);
host = client ? f->get_cli_host() : f->get_srv_host();
if(!host)
return(CONST_LUA_ERROR);
host->setScore(max(min(score, (int)CONST_NO_SCORE_SET - 1), 0));
lua_pushnil(vm);
return(CONST_LUA_OK);
}
static int ntop_flow_set_client_score(lua_State* vm) {
return(ntop_flow_set_peer_score(vm, true /* client */));
}
static int ntop_flow_set_server_score(lua_State* vm) {
return(ntop_flow_set_peer_score(vm, false /* server */));
}
/* ****************************************** */
static int ntop_flow_is_not_purged(lua_State* vm) {
Flow *f = ntop_flow_get_context_flow(vm);
if(!f) return(CONST_LUA_ERROR);
lua_pushboolean(vm, f->isNotPurged());
return(CONST_LUA_OK);
}
/* ****************************************** */
static int ntop_flow_get_tls_version(lua_State* vm) {
Flow *f = ntop_flow_get_context_flow(vm);
if(!f) return(CONST_LUA_ERROR);
lua_pushinteger(vm, f->getTLSVersion());
return(CONST_LUA_OK);
}
/* ****************************************** */
static int ntop_flow_get_tcp_stats(lua_State* vm) {
Flow *f = ntop_flow_get_context_flow(vm);
if(!f) return(CONST_LUA_ERROR);
f->lua_get_tcp_stats(vm);
return(CONST_LUA_OK);
}
/* ****************************************** */
static int ntop_flow_get_blacklisted_info(lua_State* vm) {
Flow *f = ntop_flow_get_context_flow(vm);
Host *cli_host, *srv_host;
if(!f) return(CONST_LUA_ERROR);
cli_host = f->get_cli_host();
srv_host = f->get_srv_host();
lua_newtable(vm);
if(cli_host && cli_host->isBlacklisted())
lua_push_bool_table_entry(vm, "blacklisted.cli", true);
if(srv_host && srv_host->isBlacklisted())
lua_push_bool_table_entry(vm, "blacklisted.srv", true);
if(f->get_protocol_category() == CUSTOM_CATEGORY_MALWARE)
lua_push_bool_table_entry(vm, "blacklisted.cat", true);
return(CONST_LUA_OK);
}
/* ****************************************** */
#ifdef HAVE_NEDGE
static int ntop_flow_is_pass_verdict(lua_State* vm) {
Flow *f = ntop_flow_get_context_flow(vm);
if(!f) return(CONST_LUA_ERROR);
lua_pushboolean(vm, f->isPassVerdict());
return(CONST_LUA_OK);
}
#endif
/* ****************************************** */
static int ntop_flow_get_first_seen(lua_State* vm) {
Flow *f = ntop_flow_get_context_flow(vm);
if(!f) return(CONST_LUA_ERROR);
lua_pushinteger(vm, f->get_first_seen());
return(CONST_LUA_OK);
}
/* ****************************************** */
static int ntop_flow_get_last_seen(lua_State* vm) {
Flow *f = ntop_flow_get_context_flow(vm);
if(!f) return(CONST_LUA_ERROR);
lua_pushinteger(vm, f->get_last_seen());
return(CONST_LUA_OK);
}
/* ****************************************** */
static int ntop_flow_get_duration(lua_State* vm) {
Flow *f = ntop_flow_get_context_flow(vm);
if(!f) return(CONST_LUA_ERROR);
lua_pushinteger(vm, f->get_duration());
return(CONST_LUA_OK);
}
/* ****************************************** */
static int ntop_flow_is_twh_ok(lua_State* vm) {
Flow *f = ntop_flow_get_context_flow(vm);
if(!f) return(CONST_LUA_ERROR);
lua_pushboolean(vm, f->isThreeWayHandshakeOK());
return(CONST_LUA_OK);
}
/* ****************************************** */
static int ntop_flow_is_bidirectional(lua_State* vm) {
Flow *f = ntop_flow_get_context_flow(vm);
if(!f) return(CONST_LUA_ERROR);
lua_pushboolean(vm, f->isBidirectional());
return(CONST_LUA_OK);
}
/* ****************************************** */
static int ntop_flow_get_packets_sent(lua_State* vm) {
Flow *f = ntop_flow_get_context_flow(vm);
if(!f) return(CONST_LUA_ERROR);
lua_pushinteger(vm, f->get_packets_cli2srv());
return(CONST_LUA_OK);
}
/* ****************************************** */
static int ntop_flow_get_packets_rcvd(lua_State* vm) {
Flow *f = ntop_flow_get_context_flow(vm);
if(!f) return(CONST_LUA_ERROR);
lua_pushinteger(vm, f->get_packets_srv2cli());
return(CONST_LUA_OK);
}
/* ****************************************** */
static int ntop_flow_get_bytes_sent(lua_State* vm) {
Flow *f = ntop_flow_get_context_flow(vm);
if(!f) return(CONST_LUA_ERROR);
lua_pushinteger(vm, f->get_bytes_cli2srv());
return(CONST_LUA_OK);
}
/* ****************************************** */
static int ntop_flow_get_bytes_rcvd(lua_State* vm) {
Flow *f = ntop_flow_get_context_flow(vm);
if(!f) return(CONST_LUA_ERROR);
lua_pushinteger(vm, f->get_bytes_srv2cli());
return(CONST_LUA_OK);
}
/* ****************************************** */
static int ntop_flow_get_bytes(lua_State* vm) {
Flow *f = ntop_flow_get_context_flow(vm);
if(!f) return(CONST_LUA_ERROR);
lua_pushinteger(vm, f->get_bytes());
return(CONST_LUA_OK);
}
/* ****************************************** */
static int ntop_flow_get_goodput_bytes(lua_State* vm) {
Flow *f = ntop_flow_get_context_flow(vm);
if(!f) return(CONST_LUA_ERROR);
lua_pushinteger(vm, f->get_goodput_bytes());
return(CONST_LUA_OK);
}
/* ****************************************** */
static int ntop_flow_get_client_key(lua_State* vm) {
Flow *f = ntop_flow_get_context_flow(vm);
Host *h;
char buf[64];
if(!f) return(CONST_LUA_ERROR);
h = f->get_cli_host();
lua_pushstring(vm, h ? h->get_hostkey(buf, sizeof(buf), true /* force VLAN, required by flow.lua */) : "");
return(CONST_LUA_OK);
}
/* ****************************************** */
static int ntop_flow_get_server_key(lua_State* vm) {
Flow *f = ntop_flow_get_context_flow(vm);
Host *h;
char buf[64];
if(!f) return(CONST_LUA_ERROR);
h = f->get_srv_host();
lua_pushstring(vm, h ? h->get_hostkey(buf, sizeof(buf), true /* force VLAN, required by flow.lua */) : "");
return(CONST_LUA_OK);
}
/* ****************************************** */
static int ntop_flow_can_trigger_alert(lua_State* vm) {
Flow *f = ntop_flow_get_context_flow(vm);
if(!f) return(CONST_LUA_ERROR);
lua_pushboolean(vm, !f->isFlowAlerted());
return(CONST_LUA_OK);
}
/* ****************************************** */
static int ntop_flow_is_dp_not_allowed(lua_State* vm) {
Flow *f = ntop_flow_get_context_flow(vm);
if(!f) return(CONST_LUA_ERROR);
lua_pushboolean(vm, !f->isDeviceAllowedProtocol());
return(CONST_LUA_OK);
}
/* ****************************************** */
static int ntop_flow_is_connection_refused(lua_State* vm) {
Flow *f = ntop_flow_get_context_flow(vm);
if(!f) return(CONST_LUA_ERROR);
lua_pushboolean(vm, (f->isTCPReset() && !f->hasTCP3WHSCompleted()));
return(CONST_LUA_OK);
}
/* ****************************************** */
static int ntop_flow_get_ssl_cipher_class(lua_State* vm) {
Flow *f = ntop_flow_get_context_flow(vm);
const char *rv;
if(!f) return(CONST_LUA_ERROR);
rv = f->getServerCipherClass();
if(rv)
lua_pushstring(vm, rv);
else
lua_pushnil(vm);
return(CONST_LUA_OK);
}
/* ****************************************** */
static int ntop_flow_get_icmp_type(lua_State* vm) {
Flow *f = ntop_flow_get_context_flow(vm);
if(!f) return(CONST_LUA_ERROR);
lua_pushinteger(vm, f->getICMPType());
return(CONST_LUA_OK);
}
/* ****************************************** */
static int ntop_flow_get_max_seen_icmp_size(lua_State* vm) {
Flow *f = ntop_flow_get_context_flow(vm);
if(!f) return(CONST_LUA_ERROR);
lua_pushinteger(vm, f->getICMPPayloadSize());
return(CONST_LUA_OK);
}
/* ****************************************** */
static int ntop_flow_dns_query_invalid_chars(lua_State* vm) {
Flow *f = ntop_flow_get_context_flow(vm);
if(!f) return(CONST_LUA_ERROR);
lua_pushboolean(vm, f->hasInvalidDNSQueryChars());
return(CONST_LUA_OK);
}
/* ****************************************** */
static int ntop_flow_get_dns_query(lua_State* vm) {
Flow *f = ntop_flow_get_context_flow(vm);
if(!f) return(CONST_LUA_ERROR);
lua_pushstring(vm, f->getDNSQuery());
return(CONST_LUA_OK);
}
/* ****************************************** */
static int ntop_flow_get_proto_breed(lua_State* vm) {
Flow *f = ntop_flow_get_context_flow(vm);
if(!f) return(CONST_LUA_ERROR);
lua_pushstring(vm, f->get_protocol_breed_name());
return(CONST_LUA_OK);
}
/* ****************************************** */
static int ntop_flow_has_malicious_tls_sign(lua_State* vm) {
Flow *f = ntop_flow_get_context_flow(vm);
if(!f) return(CONST_LUA_ERROR);
lua_pushboolean(vm, f->hasMaliciousSignature());
return(CONST_LUA_OK);
}
/* ****************************************** */
static int ntop_flow_check_tls_certificate(lua_State* vm) {
Flow *f = ntop_flow_get_context_flow(vm);
if(!f) return(CONST_LUA_ERROR);
lua_pushboolean(vm, f->shouldCheckTLSCertificate());
return(CONST_LUA_OK);
}
/* ****************************************** */
static int ntop_flow_is_client_unicast(lua_State* vm) {
Flow *f = ntop_flow_get_context_flow(vm);
if(!f) return(CONST_LUA_ERROR);
lua_pushboolean(vm, (f->get_cli_ip_addr() && !f->get_cli_ip_addr()->isBroadMulticastAddress()));
return(CONST_LUA_OK);
}
/* ****************************************** */
static int ntop_flow_is_server_unicast(lua_State* vm) {
Flow *f = ntop_flow_get_context_flow(vm);
if(!f) return(CONST_LUA_ERROR);
lua_pushboolean(vm, (f->get_srv_ip_addr() && !f->get_srv_ip_addr()->isBroadMulticastAddress()));
return(CONST_LUA_OK);
}
/* ****************************************** */
static int ntop_flow_is_unicast(lua_State* vm) {
Flow *f = ntop_flow_get_context_flow(vm);
const IpAddress *cli_ip, *srv_ip;
if(!f) return(CONST_LUA_ERROR);
cli_ip = f->get_cli_ip_addr();
srv_ip = f->get_srv_ip_addr();
lua_pushboolean(vm, (cli_ip && srv_ip &&
!cli_ip->isBroadMulticastAddress() && !srv_ip->isBroadMulticastAddress()));
return(CONST_LUA_OK);
}
/* ****************************************** */
static int ntop_flow_is_remote_to_remote(lua_State* vm) {
Host *cli_host, *srv_host;
Flow *f = ntop_flow_get_context_flow(vm);
if(!f) return(CONST_LUA_ERROR);
cli_host = f->get_cli_host();
srv_host = f->get_srv_host();
lua_pushboolean(vm, (cli_host && srv_host &&
!cli_host->isLocalHost() && !srv_host->isLocalHost()));
return(CONST_LUA_OK);
}
/* ****************************************** */
static int ntop_flow_is_local_to_remote(lua_State* vm) {
Host *cli_host, *srv_host;
Flow *f = ntop_flow_get_context_flow(vm);
if(!f) return(CONST_LUA_ERROR);
cli_host = f->get_cli_host();
srv_host = f->get_srv_host();
lua_pushboolean(vm, (cli_host && srv_host &&
cli_host->isLocalHost() && !srv_host->isLocalHost()));
return(CONST_LUA_OK);
}
/* ****************************************** */
static int ntop_flow_is_remote_to_local(lua_State* vm) {
Host *cli_host, *srv_host;
Flow *f = ntop_flow_get_context_flow(vm);
if(!f) return(CONST_LUA_ERROR);
cli_host = f->get_cli_host();
srv_host = f->get_srv_host();
lua_pushboolean(vm, (cli_host && srv_host &&
!cli_host->isLocalHost() && srv_host->isLocalHost()));
return(CONST_LUA_OK);
}
/* ****************************************** */
static int ntop_flow_get_ndpi_cat_name(lua_State* vm) {
Flow *f = ntop_flow_get_context_flow(vm);
if(!f) return(CONST_LUA_ERROR);
lua_pushstring(vm, f->get_protocol_category_name());
return(CONST_LUA_OK);
}
/* ****************************************** */
static int ntop_flow_get_cli_tcp_issues(lua_State* vm) {
Flow *f = ntop_flow_get_context_flow(vm);
if(!f) return(CONST_LUA_ERROR);
lua_pushinteger(vm, f->getCliTcpIssues());
return(CONST_LUA_OK);
}
/* ****************************************** */
static int ntop_flow_get_srv_tcp_issues(lua_State* vm) {
Flow *f = ntop_flow_get_context_flow(vm);
if(!f) return(CONST_LUA_ERROR);
lua_pushinteger(vm, f->getSrvTcpIssues());
return(CONST_LUA_OK);
}
/* ****************************************** */
static int ntop_flow_retrieve_external_alert_info(lua_State* vm) {
Flow *f = ntop_flow_get_context_flow(vm);
if(!f) return(CONST_LUA_ERROR);
f->luaRetrieveExternalAlert(vm);
return(CONST_LUA_OK);
}
/* ****************************************** */
static int ntop_flow_get_device_proto_allowed_info(lua_State* vm) {
Flow *f = ntop_flow_get_context_flow(vm);
if(!f) return(CONST_LUA_ERROR);
f->lua_device_protocol_allowed_info(vm);
return(CONST_LUA_OK);
}
/* ****************************************** */
static const char* mud_pref_2_str(MudRecording mud_pref) {
switch(mud_pref) {
case mud_recording_general_purpose:
return(MUD_RECORDING_GENERAL_PURPOSE);
case mud_recording_special_purpose:
return(MUD_RECORDING_SPECIAL_PURPOSE);
default:
return(MUD_RECORDING_DISABLED);
}
}
static int ntop_flow_get_mud_info(lua_State* vm) {
Flow *f = ntop_flow_get_context_flow(vm);
Host *cli_host, *srv_host;
char buf[32];
if(!f) return(CONST_LUA_ERROR);
lua_newtable(vm);
cli_host = f->get_cli_host();
srv_host = f->get_srv_host();
if(!cli_host || !srv_host)
return(CONST_LUA_OK);
lua_push_str_table_entry(vm, "host_server_name", f->getFlowServerInfo());
lua_push_str_table_entry(vm, "protos.dns.last_query", f->getDNSQuery());
lua_push_bool_table_entry(vm, "is_local", cli_host->isLocalHost() && srv_host->isLocalHost());
lua_push_str_table_entry(vm, "cli.mud_recording", mud_pref_2_str(cli_host->getMUDRecording()));
lua_push_str_table_entry(vm, "srv.mud_recording", mud_pref_2_str(srv_host->getMUDRecording()));
lua_push_bool_table_entry(vm, "cli.serialize_by_mac", cli_host->serializeByMac());
lua_push_bool_table_entry(vm, "srv.serialize_by_mac", srv_host->serializeByMac());
lua_push_str_table_entry(vm, "cli.mac", Utils::formatMac(cli_host->get_mac(), buf, sizeof(buf)));
lua_push_str_table_entry(vm, "srv.mac", Utils::formatMac(srv_host->get_mac(), buf, sizeof(buf)));
return(CONST_LUA_OK);
}
/* ****************************************** */
// ***API***
static int ntop_flow_get_status(lua_State* vm) {
Flow *f = ntop_flow_get_context_flow(vm);
if(!f) return(CONST_LUA_ERROR);
lua_pushinteger(vm, f->getStatusBitmap().get());
return(CONST_LUA_OK);
}
/* ****************************************** */
// ***API***
static int ntop_flow_set_status(lua_State* vm) {
FlowStatus new_status;
Bitmap old_bitmap;
Flow *f = ntop_flow_get_context_flow(vm);
bool changed = false;
if(!f) return(CONST_LUA_ERROR);
if(ntop_lua_check(vm, __FUNCTION__, 1, LUA_TNUMBER) != CONST_LUA_OK) return(CONST_LUA_ERROR);
new_status = (FlowStatus)lua_tonumber(vm, 1);
old_bitmap = f->getStatusBitmap();
if(!old_bitmap.issetBit(new_status)) {
f->setStatus(new_status);
changed = true;
}
lua_pushboolean(vm, changed);
return(CONST_LUA_OK);
}
/* ****************************************** */
// ***API***
static int ntop_flow_clear_status(lua_State* vm) {
FlowStatus new_status;
Bitmap old_bitmap;
Flow *f = ntop_flow_get_context_flow(vm);
bool changed = false;
if(!f) return(CONST_LUA_ERROR);
if(ntop_lua_check(vm, __FUNCTION__, 1, LUA_TNUMBER) != CONST_LUA_OK) return(CONST_LUA_ERROR);
new_status = (FlowStatus)lua_tonumber(vm, 1);
old_bitmap = f->getStatusBitmap();
if(old_bitmap.issetBit(new_status)) {
f->clearStatus(new_status);
changed = true;
}
lua_pushboolean(vm, changed);
return(CONST_LUA_OK);
}
/* ****************************************** */
static int ntop_get_predominant_status(lua_State* vm) {
Flow *f = ntop_flow_get_context_flow(vm);
if(!f) return(CONST_LUA_ERROR);
lua_pushinteger(vm, f->getPredominantStatus());
return(CONST_LUA_OK);
}
/* ****************************************** */
static int ntop_set_predominant_status(lua_State* vm) {
FlowStatus status;
Flow *f = ntop_flow_get_context_flow(vm);
if(!f) return(CONST_LUA_ERROR);
if(ntop_lua_check(vm, __FUNCTION__, 1, LUA_TNUMBER) != CONST_LUA_OK) return(CONST_LUA_ERROR);
status = (FlowStatus)lua_tonumber(vm, 1);
f->setPredominantStatus(status);
lua_pushnil(vm);
return(CONST_LUA_OK);
}
/* ****************************************** */
static int ntop_flow_trigger_alert(lua_State* vm) {
Flow *f = ntop_flow_get_context_flow(vm);
FlowStatus status;
AlertType atype;
AlertLevel severity;
bool triggered = false;
const char *status_info = NULL;
u_int32_t buflen;
time_t now;
if(!f) return(CONST_LUA_ERROR);
if(f->isFlowAlerted()) {
/* Already alerted */
lua_pushboolean(vm, false);
return(CONST_LUA_OK);
}
if(ntop_lua_check(vm, __FUNCTION__, 1, LUA_TNUMBER) != CONST_LUA_OK) return(CONST_LUA_ERROR);
status = (FlowStatus)lua_tonumber(vm, 1);
if(ntop_lua_check(vm, __FUNCTION__, 2, LUA_TNUMBER) != CONST_LUA_OK) return(CONST_LUA_ERROR);
atype = (AlertType)lua_tonumber(vm, 2);
if(ntop_lua_check(vm, __FUNCTION__, 3, LUA_TNUMBER) != CONST_LUA_OK) return(CONST_LUA_ERROR);
severity = (AlertLevel)lua_tonumber(vm, 3);
if(ntop_lua_check(vm, __FUNCTION__, 4, LUA_TNUMBER) != CONST_LUA_OK) return(CONST_LUA_ERROR);
now = (time_t) lua_tonumber(vm, 4);
if(lua_type(vm, 5) == LUA_TSTRING)
status_info = lua_tostring(vm, 5);
if(f->triggerAlert(status, atype, severity, status_info)) {
/* The alert was successfully triggered */
FifoStringsQueue *sqlite_queue = ntop->getSqliteAlertsQueue();
FifoStringsQueue *notif_queue = ntop->getAlertsNotificationsQueue();
triggered = true;
if(sqlite_queue->canEnqueue() || notif_queue->canEnqueue()) {
ndpi_serializer flow_json;
const char *flow_str;
ndpi_init_serializer(&flow_json, ndpi_serialization_format_json);
/* Only proceed if there is some space in the queues */
f->flow2alertJson(&flow_json, now);
flow_str = ndpi_serializer_get_buffer(&flow_json, &buflen);
if(flow_str) {
if(!sqlite_queue->enqueue(flow_str))
f->getInterface()->incNumDroppedAlerts(1);
notif_queue->enqueue(flow_str);
}
ndpi_term_serializer(&flow_json);
} else
f->getInterface()->incNumDroppedAlerts(1);
}
lua_pushboolean(vm, triggered);
return(CONST_LUA_OK);
}
/* ****************************************** */
static int ntop_push_sqlite_alert(lua_State* vm) {
const char *alert;
bool rv;
if(ntop_lua_check(vm, __FUNCTION__, 1, LUA_TSTRING) != CONST_LUA_OK) return(CONST_LUA_ERROR);
alert = lua_tostring(vm, 1);
if(ntop->getSqliteAlertsQueue()->enqueue(alert))
rv = true;
else {
NetworkInterface *iface = getCurrentInterface(vm);
rv = false;
if(iface)
iface->incNumDroppedAlerts(1);
}
lua_pushboolean(vm, rv);
return(CONST_LUA_OK);
}
/* ****************************************** */
static int ntop_pop_sqlite_alert(lua_State* vm) {
char *alert = ntop->getSqliteAlertsQueue()->dequeue();
if(alert) {
lua_pushstring(vm, alert);
free(alert);
} else
lua_pushnil(vm);
return(CONST_LUA_OK);
}
/* ****************************************** */
static int ntop_push_alert_notification(lua_State* vm) {
const char *notif;
if(ntop_lua_check(vm, __FUNCTION__, 1, LUA_TSTRING) != CONST_LUA_OK) return(CONST_LUA_ERROR);
notif = lua_tostring(vm, 1);
lua_pushboolean(vm, ntop->getAlertsNotificationsQueue()->enqueue(notif));
return(CONST_LUA_OK);
}
/* ****************************************** */
static int ntop_pop_alert_notification(lua_State* vm) {
char *notification = ntop->getAlertsNotificationsQueue()->dequeue();
if(notification) {
lua_pushstring(vm, notification);
free(notification);
} else
lua_pushnil(vm);
return(CONST_LUA_OK);
}
/* ****************************************** */
static int ntop_pop_internal_alerts(lua_State* vm) {
char *internal_alerts = ntop->getInternalAlertsQueue()->dequeue();
if(internal_alerts) {
lua_pushstring(vm, internal_alerts);
free(internal_alerts);
} else
lua_pushnil(vm);
return(CONST_LUA_OK);
}
/* ****************************************** */
// ***API***
static int ntop_flow_is_blacklisted(lua_State* vm) {
Flow *f = ntop_flow_get_context_flow(vm);
if(!f) return(CONST_LUA_ERROR);
lua_pushboolean(vm, f->isBlacklistedFlow());
return(CONST_LUA_OK);
}
/* ****************************************** */
static int ntop_flow_get_dir_iat(lua_State* vm, bool cli2srv) {
Flow *f = ntop_flow_get_context_flow(vm);
lua_newtable(vm);
if(f) f->lua_get_dir_iat(vm, cli2srv);
return CONST_LUA_OK;
}
/* ****************************************** */
static int ntop_flow_get_cli2srv_iat(lua_State* vm) {
return ntop_flow_get_dir_iat(vm, true /* Client to Server */);
}
/* ****************************************** */
static int ntop_flow_get_srv2cli_iat(lua_State* vm) {
return ntop_flow_get_dir_iat(vm, false /* Server to Client */);
}
/* ****************************************** */
static int ntop_flow_get_tls_info(lua_State* vm) {
Flow *f = ntop_flow_get_context_flow(vm);
lua_newtable(vm);
if(f) f->lua_get_tls_info(vm);
return CONST_LUA_OK;
}
/* ****************************************** */
static int ntop_flow_get_ssh_info(lua_State* vm) {
Flow *f = ntop_flow_get_context_flow(vm);
lua_newtable(vm);
if(f) f->lua_get_ssh_info(vm);
return CONST_LUA_OK;
}
/* ****************************************** */
static int ntop_flow_get_http_info(lua_State* vm) {
Flow *f = ntop_flow_get_context_flow(vm);
lua_newtable(vm);
if(f) f->lua_get_http_info(vm);
return CONST_LUA_OK;
}
/* ****************************************** */
static int ntop_flow_get_dns_info(lua_State* vm) {
Flow *f = ntop_flow_get_context_flow(vm);
lua_newtable(vm);
if(f) f->lua_get_dns_info(vm);
return CONST_LUA_OK;
}
/* ****************************************** */
static int ntop_interface_release_engaged_alerts(lua_State* vm) {
NetworkInterface *iface = getCurrentInterface(vm);
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
if(!iface) return(CONST_LUA_ERROR);
iface->releaseAllEngagedAlerts();
lua_pushnil(vm);
return(CONST_LUA_OK);
}
/* ****************************************** */
static int ntop_interface_inc_total_host_alerts(lua_State* vm) {
NetworkInterface *iface = getCurrentInterface(vm);
u_int16_t vlan_id = 0;
AlertType alert_type;
char buf[64], *host_ip;
Host *h;
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
if(!iface) return(CONST_LUA_ERROR);
if(ntop_lua_check(vm, __FUNCTION__, 1, LUA_TSTRING) != CONST_LUA_OK) return(CONST_LUA_ERROR);
get_host_vlan_info((char*)lua_tostring(vm, 1), &host_ip, &vlan_id, buf, sizeof(buf));
if(ntop_lua_check(vm, __FUNCTION__, 2, LUA_TNUMBER) != CONST_LUA_OK) return(CONST_LUA_ERROR);
alert_type = (AlertType)lua_tonumber(vm, 2);
h = iface->findHostByIP(get_allowed_nets(vm), host_ip, vlan_id);
if(h)
h->incTotalAlerts(alert_type);
lua_pushboolean(vm, h ? true : false);
return(CONST_LUA_OK);
}
/* ****************************************** */
static int ntop_network_get_cached_alert_value(lua_State* vm) {
struct ntopngLuaContext *c = getLuaVMContext(vm);
NetworkStats *ns = c ? c->network : NULL;
char *key;
std::string val;
ScriptPeriodicity periodicity;
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
if(!ns) return(CONST_LUA_ERROR);
if(ntop_lua_check(vm, __FUNCTION__, 1, LUA_TSTRING) != CONST_LUA_OK) return(CONST_LUA_ERROR);
if((key = (char*)lua_tostring(vm, 1)) == NULL) return(CONST_LUA_PARAM_ERROR);
if(ntop_lua_check(vm, __FUNCTION__, 2, LUA_TNUMBER) != CONST_LUA_OK) return(CONST_LUA_ERROR);
if((periodicity = (ScriptPeriodicity)lua_tonumber(vm, 2)) >= MAX_NUM_PERIODIC_SCRIPTS) return(CONST_LUA_PARAM_ERROR);
val = ns->getAlertCachedValue(std::string(key), periodicity);
lua_pushstring(vm, val.c_str());
return(CONST_LUA_OK);
}
/* ****************************************** */
static int ntop_network_set_cached_alert_value(lua_State* vm) {
struct ntopngLuaContext *c = getLuaVMContext(vm);
NetworkStats *ns = c ? c->network : NULL;
char *key, *value;
ScriptPeriodicity periodicity;
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
if(!ns) return(CONST_LUA_ERROR);
if(ntop_lua_check(vm, __FUNCTION__, 1, LUA_TSTRING) != CONST_LUA_OK) return(CONST_LUA_ERROR);
if((key = (char*)lua_tostring(vm, 1)) == NULL) return(CONST_LUA_PARAM_ERROR);
if(ntop_lua_check(vm, __FUNCTION__, 2, LUA_TSTRING) != CONST_LUA_OK) return(CONST_LUA_ERROR);
if((value = (char*)lua_tostring(vm, 2)) == NULL) return(CONST_LUA_PARAM_ERROR);
if(ntop_lua_check(vm, __FUNCTION__, 3, LUA_TNUMBER) != CONST_LUA_OK) return(CONST_LUA_ERROR);
if((periodicity = (ScriptPeriodicity)lua_tonumber(vm, 3)) >= MAX_NUM_PERIODIC_SCRIPTS) return(CONST_LUA_PARAM_ERROR);
if((!key) || (!value))
return(CONST_LUA_PARAM_ERROR);
ns->setAlertCacheValue(std::string(key), std::string(value), periodicity);
return(CONST_LUA_OK);
}
/* ****************************************** */
static int ntop_interface_get_cached_alert_value(lua_State* vm) {
struct ntopngLuaContext *c = getLuaVMContext(vm);
char *key;
std::string val;
ScriptPeriodicity periodicity;
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
if(!c->iface) return(CONST_LUA_ERROR);
if(ntop_lua_check(vm, __FUNCTION__, 1, LUA_TSTRING) != CONST_LUA_OK) return(CONST_LUA_ERROR);
if((key = (char*)lua_tostring(vm, 1)) == NULL) return(CONST_LUA_PARAM_ERROR);
if(ntop_lua_check(vm, __FUNCTION__, 2, LUA_TNUMBER) != CONST_LUA_OK) return(CONST_LUA_ERROR);
if((periodicity = (ScriptPeriodicity)lua_tonumber(vm, 2)) >= MAX_NUM_PERIODIC_SCRIPTS) return(CONST_LUA_PARAM_ERROR);
val = c->iface->getAlertCachedValue(std::string(key), periodicity);
lua_pushstring(vm, val.c_str());
return(CONST_LUA_OK);
}
/* ****************************************** */
static int ntop_interface_set_cached_alert_value(lua_State* vm) {
struct ntopngLuaContext *c = getLuaVMContext(vm);
char *key, *value;
ScriptPeriodicity periodicity;
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
if(!c->iface) return(CONST_LUA_ERROR);
if(ntop_lua_check(vm, __FUNCTION__, 1, LUA_TSTRING) != CONST_LUA_OK) return(CONST_LUA_ERROR);
if((key = (char*)lua_tostring(vm, 1)) == NULL) return(CONST_LUA_PARAM_ERROR);
if(ntop_lua_check(vm, __FUNCTION__, 2, LUA_TSTRING) != CONST_LUA_OK) return(CONST_LUA_ERROR);
if((value = (char*)lua_tostring(vm, 2)) == NULL) return(CONST_LUA_PARAM_ERROR);
if(ntop_lua_check(vm, __FUNCTION__, 3, LUA_TNUMBER) != CONST_LUA_OK) return(CONST_LUA_ERROR);
if((periodicity = (ScriptPeriodicity)lua_tonumber(vm, 3)) >= MAX_NUM_PERIODIC_SCRIPTS) return(CONST_LUA_PARAM_ERROR);
if((!key) || (!value))
return(CONST_LUA_PARAM_ERROR);
c->iface->setAlertCacheValue(std::string(key), std::string(value), periodicity);
return(CONST_LUA_OK);
}
/* ****************************************** */
static int ntop_store_triggered_alert(lua_State* vm, AlertableEntity *alertable, int idx = 1) {
struct ntopngLuaContext *c = getLuaVMContext(vm);
char *key, *alert_subtype, *alert_json;
ScriptPeriodicity periodicity;
AlertLevel alert_severity;
AlertType alert_type;
Host *host;
bool triggered;
if(!alertable || !c->iface) return(CONST_LUA_PARAM_ERROR);
if(ntop_lua_check(vm, __FUNCTION__, idx, LUA_TSTRING) != CONST_LUA_OK) return(CONST_LUA_ERROR);
if((key = (char*)lua_tostring(vm, idx++)) == NULL) return(CONST_LUA_PARAM_ERROR);
if(ntop_lua_check(vm, __FUNCTION__, idx, LUA_TNUMBER) != CONST_LUA_OK) return(CONST_LUA_ERROR);
if((periodicity = (ScriptPeriodicity)lua_tonumber(vm, idx++)) >= MAX_NUM_PERIODIC_SCRIPTS) return(CONST_LUA_PARAM_ERROR);
if(ntop_lua_check(vm, __FUNCTION__, idx, LUA_TNUMBER) != CONST_LUA_OK) return(CONST_LUA_ERROR);
alert_severity = (AlertLevel)lua_tonumber(vm, idx++);
if(ntop_lua_check(vm, __FUNCTION__, idx, LUA_TNUMBER) != CONST_LUA_OK) return(CONST_LUA_ERROR);
alert_type = (AlertType)lua_tonumber(vm, idx++);
if(ntop_lua_check(vm, __FUNCTION__, idx, LUA_TSTRING) != CONST_LUA_OK) return(CONST_LUA_ERROR);
if((alert_subtype = (char*)lua_tostring(vm, idx++)) == NULL) return(CONST_LUA_PARAM_ERROR);
if(ntop_lua_check(vm, __FUNCTION__, idx, LUA_TSTRING) != CONST_LUA_OK) return(CONST_LUA_ERROR);
if((alert_json = (char*)lua_tostring(vm, idx++)) == NULL) return(CONST_LUA_PARAM_ERROR);
triggered = alertable->triggerAlert(vm, std::string(key), periodicity, time(NULL),
alert_severity, alert_type, alert_subtype, alert_json);
if(triggered && (host = dynamic_cast<Host*>(alertable)))
host->incTotalAlerts(alert_type);
return(CONST_LUA_OK);
}
/* ****************************************** */
static int ntop_interface_store_triggered_alert(lua_State* vm) {
struct ntopngLuaContext *c = getLuaVMContext(vm);
return ntop_store_triggered_alert(vm, c->iface);
}
/* ****************************************** */
static int ntop_host_store_triggered_alert(lua_State* vm) {
struct ntopngLuaContext *c = getLuaVMContext(vm);
return ntop_store_triggered_alert(vm, c->host);
}
/* ****************************************** */
static int ntop_network_store_triggered_alert(lua_State* vm) {
struct ntopngLuaContext *c = getLuaVMContext(vm);
return ntop_store_triggered_alert(vm, c->network);
}
/* ****************************************** */
static int ntop_interface_store_external_alert(lua_State* vm) {
AlertEntity entity;
const char *entity_value;
AlertableEntity *alertable;
NetworkInterface *iface = getCurrentInterface(vm);
int idx = 1;
if(!iface)
return(CONST_LUA_ERROR);
if(ntop_lua_check(vm, __FUNCTION__, idx, LUA_TNUMBER) != CONST_LUA_OK) return(CONST_LUA_ERROR);
entity = (AlertEntity)lua_tointeger(vm, idx++);
if(ntop_lua_check(vm, __FUNCTION__, idx, LUA_TSTRING) != CONST_LUA_OK) return(CONST_LUA_ERROR);
entity_value = lua_tostring(vm, idx++);
alertable = iface->lockExternalAlertable(entity, entity_value, true /* Create if not exists */);
if(!alertable)
return(CONST_LUA_ERROR);
ntop_store_triggered_alert(vm, alertable, idx);
/* End of critical section */
iface->unlockExternalAlertable(alertable);
return(CONST_LUA_OK);
}
/* ****************************************** */
static int ntop_release_triggered_alert(lua_State* vm, AlertableEntity *alertable, int idx = 1) {
struct ntopngLuaContext *c = getLuaVMContext(vm);
char *key;
ScriptPeriodicity periodicity;
time_t when;
if(!c->iface || !alertable) return(CONST_LUA_PARAM_ERROR);
if(ntop_lua_check(vm, __FUNCTION__, idx, LUA_TSTRING) != CONST_LUA_OK) return(CONST_LUA_ERROR);
if((key = (char*)lua_tostring(vm, idx++)) == NULL) return(CONST_LUA_PARAM_ERROR);
if(ntop_lua_check(vm, __FUNCTION__, idx, LUA_TNUMBER) != CONST_LUA_OK) return(CONST_LUA_ERROR);
if((periodicity = (ScriptPeriodicity)lua_tonumber(vm, idx++)) >= MAX_NUM_PERIODIC_SCRIPTS) return(CONST_LUA_PARAM_ERROR);
if(ntop_lua_check(vm, __FUNCTION__, idx, LUA_TNUMBER) != CONST_LUA_OK) return(CONST_LUA_ERROR);
when = (time_t)lua_tonumber(vm, idx++);
/* The released alert will be pushed to LUA */
alertable->releaseAlert(vm, std::string(key), periodicity, when);
return(CONST_LUA_OK);
}
/* ****************************************** */
static int ntop_interface_release_triggered_alert(lua_State* vm) {
struct ntopngLuaContext *c = getLuaVMContext(vm);
return ntop_release_triggered_alert(vm, c->iface);
}
/* ****************************************** */
static int ntop_host_release_triggered_alert(lua_State* vm) {
struct ntopngLuaContext *c = getLuaVMContext(vm);
return ntop_release_triggered_alert(vm, c->host);
}
/* ****************************************** */
static int ntop_network_release_triggered_alert(lua_State* vm) {
struct ntopngLuaContext *c = getLuaVMContext(vm);
return ntop_release_triggered_alert(vm, c->network);
}
/* ****************************************** */
static int ntop_interface_release_external_alert(lua_State* vm) {
AlertEntity entity;
const char *entity_value;
AlertableEntity *alertable;
NetworkInterface *iface = getCurrentInterface(vm);
int idx = 1;
if(!iface)
return(CONST_LUA_ERROR);
if(ntop_lua_check(vm, __FUNCTION__, idx, LUA_TNUMBER) != CONST_LUA_OK) return(CONST_LUA_ERROR);
entity = (AlertEntity)lua_tointeger(vm, idx++);
if(ntop_lua_check(vm, __FUNCTION__, idx, LUA_TSTRING) != CONST_LUA_OK) return(CONST_LUA_ERROR);
entity_value = lua_tostring(vm, idx++);
alertable = iface->lockExternalAlertable(entity, entity_value, false /* don't create if not exists */);
if(!alertable) {
lua_pushnil(vm);
return(CONST_LUA_OK);
}
ntop_release_triggered_alert(vm, alertable, idx);
/* End of critical section */
iface->unlockExternalAlertable(alertable);
return(CONST_LUA_OK);
}
/* ****************************************** */
static void parseEntityExcludes(const char *exclude_str, std::set<int> *entity_excludes) {
/* NOTE: using std::set<int> instead of std::set<AlertableEntity> to provide automatic
* comparison operator, required by the set. */
const char *begin = exclude_str;
const char *token;
while((token = strchr(begin, ','))) {
entity_excludes->insert(atoi(begin));
begin = token+1;
}
/* Last value */
if(*begin)
entity_excludes->insert(atoi(begin));
}
/* ****************************************** */
static int ntop_interface_get_engaged_alerts_count(lua_State* vm) {
AlertEntity entity_type = alert_entity_none;
const char *entity_value = NULL;
NetworkInterface *iface = getCurrentInterface(vm);
std::set<int> entity_excludes;
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
if(!iface) return(CONST_LUA_ERROR);
if(lua_type(vm, 1) == LUA_TNUMBER) entity_type = (AlertEntity)lua_tointeger(vm, 1);
if(lua_type(vm, 2) == LUA_TSTRING) entity_value = (char*)lua_tostring(vm, 2);
if(lua_type(vm, 3) == LUA_TSTRING) parseEntityExcludes(lua_tostring(vm, 3), &entity_excludes);
iface->getEngagedAlertsCount(vm, entity_type, entity_value, &entity_excludes);
return(CONST_LUA_OK);
}
/* ****************************************** */
static int ntop_interface_inc_num_dropped_alerts(lua_State* vm) {
NetworkInterface *iface = getCurrentInterface(vm);
u_int32_t num_dropped;
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
if(!iface) return(CONST_LUA_ERROR);
if(ntop_lua_check(vm, __FUNCTION__, 1, LUA_TNUMBER) != CONST_LUA_OK) return(CONST_LUA_ERROR);
num_dropped = lua_tonumber(vm, 1);
iface->incNumDroppedAlerts(num_dropped);
lua_pushnil(vm);
return(CONST_LUA_OK);
}
/* ****************************************** */
static int ntop_interface_get_engaged_alerts(lua_State* vm) {
AlertEntity entity_type = alert_entity_none;
const char *entity_value = NULL;
AlertType alert_type = alert_none;
AlertLevel alert_severity = alert_level_none;
NetworkInterface *iface = getCurrentInterface(vm);
std::set<int> entity_excludes;
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
if(!iface) return(CONST_LUA_ERROR);
if(lua_type(vm, 1) == LUA_TNUMBER) entity_type = (AlertEntity)lua_tointeger(vm, 1);
if(lua_type(vm, 2) == LUA_TSTRING) entity_value = (char*)lua_tostring(vm, 2);
if(lua_type(vm, 3) == LUA_TNUMBER) alert_type = (AlertType)lua_tointeger(vm, 3);
if(lua_type(vm, 4) == LUA_TNUMBER) alert_severity = (AlertLevel)lua_tointeger(vm, 4);
if(lua_type(vm, 5) == LUA_TSTRING) parseEntityExcludes(lua_tostring(vm, 5), &entity_excludes);
iface->getEngagedAlerts(vm, entity_type, entity_value, alert_type, alert_severity, &entity_excludes);
return(CONST_LUA_OK);
}
/* ****************************************** */
static int ntop_interface_optimize_alerts(lua_State* vm) {
NetworkInterface *iface = getCurrentInterface(vm);
AlertsManager *am;
if(!iface || !(am = iface->getAlertsManager()))
return(CONST_LUA_ERROR);
if(am->optimizeStore())
return(CONST_LUA_ERROR);
return(CONST_LUA_OK);
}
/* ****************************************** */
static int ntop_interface_query_alerts_raw(lua_State* vm) {
NetworkInterface *iface = getCurrentInterface(vm);
AlertsManager *am;
char *selection = NULL, *clauses = NULL;
bool ignore_disabled = false;
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
if(!iface || !(am = iface->getAlertsManager()))
return(CONST_LUA_ERROR);
if(lua_type(vm, 1) == LUA_TSTRING)
if((selection = (char*)lua_tostring(vm, 1)) == NULL)
return(CONST_LUA_PARAM_ERROR);
if(lua_type(vm, 2) == LUA_TSTRING)
if((clauses = (char*)lua_tostring(vm, 2)) == NULL)
return(CONST_LUA_PARAM_ERROR);
if(lua_type(vm, 3) == LUA_TBOOLEAN)
ignore_disabled = lua_toboolean(vm, 3);
if(am->queryAlertsRaw(vm, selection, clauses, ignore_disabled))
return(CONST_LUA_ERROR);
return(CONST_LUA_OK);
}
/* ****************************************** */
static int ntop_interface_query_flow_alerts_raw(lua_State* vm) {
NetworkInterface *iface = getCurrentInterface(vm);
AlertsManager *am;
char *selection = NULL, *clauses = NULL;
bool ignore_disabled = false;
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
if(!iface || !(am = iface->getAlertsManager()))
return(CONST_LUA_ERROR);
if(lua_type(vm, 1) == LUA_TSTRING)
if((selection = (char*)lua_tostring(vm, 1)) == NULL)
return(CONST_LUA_PARAM_ERROR);
if(lua_type(vm, 2) == LUA_TSTRING)
if((clauses = (char*)lua_tostring(vm, 2)) == NULL)
return(CONST_LUA_PARAM_ERROR);
if(lua_type(vm, 3) == LUA_TBOOLEAN)
ignore_disabled = lua_toboolean(vm, 3);
if(am->queryFlowAlertsRaw(vm, selection, clauses, ignore_disabled))
return(CONST_LUA_ERROR);
return(CONST_LUA_OK);
}
/* ****************************************** */
#if NTOPNG_PRO
#ifndef WIN32
static int ntop_nagios_reload_config(lua_State* vm) {
NagiosManager *nagios = ntop->getNagios();
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
if(!nagios) {
ntop->getTrace()->traceEvent(TRACE_ERROR, "%s(): unable to get the nagios manager",
__FUNCTION__);
return(CONST_LUA_ERROR);
}
nagios->loadConfig();
lua_pushnil(vm);
return(CONST_LUA_OK);
}
/* ****************************************** */
static int ntop_nagios_send_alert(lua_State* vm) {
NagiosManager *nagios = ntop->getNagios();
char *alert_source;
char *alert_key;
char *alert_msg;
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
if(ntop_lua_check(vm, __FUNCTION__, 1, LUA_TSTRING) != CONST_LUA_OK) return(CONST_LUA_ERROR);
alert_source = (char*)lua_tostring(vm, 1);
if(ntop_lua_check(vm, __FUNCTION__, 2, LUA_TSTRING) != CONST_LUA_OK) return(CONST_LUA_ERROR);
alert_key = (char*)lua_tostring(vm, 2);
if(ntop_lua_check(vm, __FUNCTION__, 3, LUA_TSTRING) != CONST_LUA_OK) return(CONST_LUA_ERROR);
alert_msg = (char*)lua_tostring(vm, 3);
bool rv = nagios->sendAlert(alert_source, alert_key, alert_msg);
lua_pushboolean(vm, rv);
return(CONST_LUA_OK);
}
/* ****************************************** */
static int ntop_nagios_withdraw_alert(lua_State* vm) {
NagiosManager *nagios = ntop->getNagios();
char *alert_source;
char *alert_key;
char *alert_msg;
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
if(ntop_lua_check(vm, __FUNCTION__, 1, LUA_TSTRING) != CONST_LUA_OK) return(CONST_LUA_ERROR);
alert_source = (char*)lua_tostring(vm, 1);
if(ntop_lua_check(vm, __FUNCTION__, 2, LUA_TSTRING) != CONST_LUA_OK) return(CONST_LUA_ERROR);
alert_key = (char*)lua_tostring(vm, 2);
if(ntop_lua_check(vm, __FUNCTION__, 3, LUA_TSTRING) != CONST_LUA_OK) return(CONST_LUA_ERROR);
alert_msg = (char*)lua_tostring(vm, 3);
bool rv = nagios->withdrawAlert(alert_source, alert_key, alert_msg);
lua_pushboolean(vm, rv);
return(CONST_LUA_OK);
}
#endif
#endif
/* ****************************************** */
#ifndef HAVE_NEDGE
#ifdef NTOPNG_PRO
static int ntop_check_sub_interface_syntax(lua_State* vm) {
char *filter;
NetworkInterface *ntop_interface = getCurrentInterface(vm);
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
if(ntop_lua_check(vm, __FUNCTION__, 1, LUA_TSTRING) != CONST_LUA_OK) return(CONST_LUA_ERROR);
filter = (char*)lua_tostring(vm, 1);
lua_pushboolean(vm, ntop_interface ? ntop_interface->checkSubInterfaceSyntax(filter) : false);
return(CONST_LUA_OK);
}
#endif
#endif
/* ****************************************** */
#ifndef HAVE_NEDGE
#ifdef NTOPNG_PRO
static int ntop_check_profile_syntax(lua_State* vm) {
char *filter;
NetworkInterface *ntop_interface = getCurrentInterface(vm);
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
if(ntop_lua_check(vm, __FUNCTION__, 1, LUA_TSTRING) != CONST_LUA_OK) return(CONST_LUA_ERROR);
filter = (char*)lua_tostring(vm, 1);
lua_pushboolean(vm, ntop_interface ? ntop_interface->checkProfileSyntax(filter) : false);
return(CONST_LUA_OK);
}
#endif
#endif
/* ****************************************** */
#ifndef HAVE_NEDGE
#ifdef NTOPNG_PRO
static int ntop_reload_traffic_profiles(lua_State* vm) {
NetworkInterface *ntop_interface = getCurrentInterface(vm);
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
if(ntop_interface)
ntop_interface->updateFlowProfiles(); /* Reload profiles in memory */
lua_pushnil(vm);
return(CONST_LUA_OK);
}
#endif
#endif
/* ****************************************** */
static int ntop_set_redis(lua_State* vm) {
char *key, *value;
u_int expire_secs = 0; // default 0 = no expiration
Redis *redis = ntop->getRedis();
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
if(ntop_lua_check(vm, __FUNCTION__, 1, LUA_TSTRING) != CONST_LUA_OK) return(CONST_LUA_ERROR);
if((key = (char*)lua_tostring(vm, 1)) == NULL) return(CONST_LUA_PARAM_ERROR);
if(ntop_lua_check(vm, __FUNCTION__, 2, LUA_TSTRING) != CONST_LUA_OK) return(CONST_LUA_ERROR);
if((value = (char*)lua_tostring(vm, 2)) == NULL) return(CONST_LUA_PARAM_ERROR);
/* Optional key expiration in SECONDS */
if(lua_type(vm, 3) == LUA_TNUMBER)
expire_secs = (u_int)lua_tonumber(vm, 3);
lua_pushnil(vm);
if(redis->set(key, value, expire_secs) == 0)
return(CONST_LUA_OK);
return(CONST_LUA_ERROR);
}
/* ****************************************** */
static int ntop_set_preference(lua_State* vm) {
return(ntop_set_redis(vm));
}
/* ****************************************** */
static int ntop_lua_http_print(lua_State* vm) {
struct mg_connection *conn;
char *printtype;
int t;
conn = getLuaVMUserdata(vm, conn);
/* ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__); */
/* Handle binary blob */
if((lua_type(vm, 2) == LUA_TSTRING)
&& (printtype = (char*)lua_tostring(vm, 2)) != NULL)
if(!strncmp(printtype, "blob", 4)) {
char *str = NULL;
if(ntop_lua_check(vm, __FUNCTION__, 1, LUA_TSTRING) != CONST_LUA_OK) return(CONST_LUA_ERROR);
if((str = (char*)lua_tostring(vm, 1)) != NULL) {
int len = strlen(str);
if(len <= 1)
mg_printf(conn, "%c", str[0]);
else
return(CONST_LUA_PARAM_ERROR);
}
lua_pushnil(vm);
return(CONST_LUA_OK);
}
switch(t = lua_type(vm, 1)) {
case LUA_TNIL:
mg_printf(conn, "%s", "nil");
break;
case LUA_TBOOLEAN:
{
int v = lua_toboolean(vm, 1);
mg_printf(conn, "%s", v ? "true" : "false");
}
break;
case LUA_TSTRING:
{
char *str = (char*)lua_tostring(vm, 1);
if(str && (strlen(str) > 0))
mg_printf(conn, "%s", str);
}
break;
case LUA_TNUMBER:
{
char str[64];
snprintf(str, sizeof(str), "%f", (float)lua_tonumber(vm, 1));
mg_printf(conn, "%s", str);
}
break;
default:
ntop->getTrace()->traceEvent(TRACE_WARNING, "%s(): Lua type %d is not handled",
__FUNCTION__, t);
return(CONST_LUA_ERROR);
}
lua_pushnil(vm);
return(CONST_LUA_OK);
}
/* ****************************************** */
int ntop_lua_cli_print(lua_State* vm) {
int t;
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
switch(t = lua_type(vm, 1)) {
case LUA_TSTRING:
{
char *str = (char*)lua_tostring(vm, 1);
if(str && (strlen(str) > 0))
ntop->getTrace()->traceEvent(TRACE_NORMAL, "%s", str);
}
break;
case LUA_TNUMBER:
ntop->getTrace()->traceEvent(TRACE_NORMAL, "%f", (float)lua_tonumber(vm, 1));
break;
default:
ntop->getTrace()->traceEvent(TRACE_WARNING, "%s(): Lua type %d is not handled",
__FUNCTION__, t);
return(CONST_LUA_ERROR);
}
lua_pushnil(vm);
return(CONST_LUA_OK);
}
/* ****************************************** */
#if defined(NTOPNG_PRO) || defined(HAVE_NEDGE)
static int __ntop_lua_handlefile(lua_State* L, char *script_path, bool ex) {
int rc;
LuaHandler *lh = new LuaHandler(L, script_path);
rc = lh->luaL_dofileM(ex);
delete lh;
return rc;
}
/* ****************************************** */
/* This function is called by Lua scripts when the call require(...) */
static int ntop_lua_require(lua_State* L) {
char *script_name;
if(lua_type(L, 1) != LUA_TSTRING ||
(script_name = (char*)lua_tostring(L, 1)) == NULL)
return 0;
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s(%s)", __FUNCTION__, script_name);
lua_getglobal( L, "package" );
lua_getfield( L, -1, "path" );
string cur_path = lua_tostring( L, -1 ), parsed, script_path = "";
stringstream input_stringstream(cur_path);
while(getline(input_stringstream, parsed, ';')) {
/* Example: package.path = dirs.installdir .. "/scripts/lua/modules/?.lua;" .. package.path */
unsigned found = parsed.find_last_of("?");
if(found) {
string s = parsed.substr(0, found) + script_name + ".lua";
size_t first_dot = s.find("."), last_dot = s.rfind(".");
/*
Lua transforms file names when directories are used.
Example: i18n/version.lua -> i18n.version.lua
So we need to revert this logic back and the code
below is doing exactly this
*/
if((first_dot != string::npos)
&& (last_dot != string::npos)
&& (first_dot != last_dot))
s.replace(first_dot, 1, "/");
ntop->getTrace()->traceEvent(TRACE_DEBUG, "[%s] Searching %s", __FUNCTION__, s.c_str());
if(Utils::file_exists(s.c_str())) {
script_path = s;
ntop->getTrace()->traceEvent(TRACE_DEBUG, "[%s] Found %s", __FUNCTION__, s.c_str());
break;
}
}
}
if(script_path == "" ||
__ntop_lua_handlefile(L, (char *)script_path.c_str(), false)) {
if(lua_type(L, -1) == LUA_TSTRING) {
const char *err = lua_tostring(L, -1);
ntop->getTrace()->traceEvent(TRACE_WARNING, "Script failure [%s][%s]", script_path.c_str(), err ? err : "");
}
return 0;
}
return 1;
}
/* ****************************************** */
static int ntop_lua_xfile(lua_State* L, bool ex) {
char *script_path;
int ret;
if(lua_type(L, 1) != LUA_TSTRING ||
(script_path = (char*)lua_tostring(L, 1)) == NULL)
return 0;
ret = __ntop_lua_handlefile(L, script_path, ex);
if(ret && (!lua_isnil(L, -1))) {
const char *msg = lua_tostring(L, -1);
ntop->getTrace()->traceEvent(TRACE_WARNING, "Script failure %s", msg);
}
return !ret;
}
/* ****************************************** */
static int ntop_lua_dofile(lua_State* L) {
return ntop_lua_xfile(L, true);
}
/* ****************************************** */
static int ntop_lua_loadfile(lua_State* L) {
return ntop_lua_xfile(L, false);
}
#endif
/* ****************************************** */
// ***API***
static int ntop_is_login_disabled(lua_State* vm) {
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
bool ret = ntop->getPrefs()->is_localhost_users_login_disabled()
|| !ntop->getPrefs()->is_users_login_enabled();
lua_pushboolean(vm, ret);
return(CONST_LUA_OK);
}
/* ****************************************** */
static int ntop_is_login_blacklisted(lua_State* vm) {
struct mg_connection *conn;
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
if((conn = getLuaVMUserdata(vm, conn)) == NULL)
return(CONST_LUA_ERROR);
lua_pushboolean(vm, ntop->isBlacklistedLogin(conn));
return(CONST_LUA_OK);
}
/* ****************************************** */
// ***API***
static int ntop_network_name_by_id(lua_State* vm) {
int id;
char *name;
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
if(ntop_lua_check(vm, __FUNCTION__, 1, LUA_TNUMBER) != CONST_LUA_OK) return(CONST_LUA_ERROR);
id = (u_int32_t)lua_tonumber(vm, 1);
name = ntop->getLocalNetworkName(id);
lua_pushstring(vm, name ? name : "");
return(CONST_LUA_OK);
}
/* ****************************************** */
static int ntop_network_id_by_name(lua_State* vm) {
u_int8_t num_local_networks = ntop->getNumLocalNetworks();
int found_id = -1;
char *name;
ntop->getTrace()->traceEvent(TRACE_INFO, "%s() called", __FUNCTION__);
if(ntop_lua_check(vm, __FUNCTION__, 1, LUA_TSTRING) != CONST_LUA_OK) return(CONST_LUA_ERROR);
name = (char*)lua_tostring(vm, 1);
for(u_int8_t network_id = 0; network_id < num_local_networks; network_id++) {
if(!strcmp(ntop->getLocalNetworkName(network_id), name)) {
found_id = network_id;
break;
}
}
lua_pushinteger(vm, found_id);
return(CONST_LUA_OK);
}
/* ****************************************** */
static int ntop_is_gui_access_restricted(lua_State* vm) {
ntop->getTrace()->traceEvent(TRACE_INFO, "%s() called", __FUNCTION__);
lua_pushboolean(vm, ntop->get_HTTPserver()->is_gui_access_restricted());
return(CONST_LUA_OK);
}
/* ****************************************** */
// ***API***
static int ntop_set_logging_level(lua_State* vm) {
char *lvlStr;
ntop->getTrace()->traceEvent(TRACE_INFO, "%s() called", __FUNCTION__);
if(ntop->getPrefs()->hasCmdlTraceLevel()) return(CONST_LUA_OK);
if(ntop_lua_check(vm, __FUNCTION__, 1, LUA_TSTRING) != CONST_LUA_OK)
return(CONST_LUA_ERROR);
lvlStr = (char*)lua_tostring(vm, 1);
if(!strcmp(lvlStr, "trace")){
ntop->getTrace()->set_trace_level(TRACE_LEVEL_TRACE);
}
else if(!strcmp(lvlStr, "debug")){
ntop->getTrace()->set_trace_level(TRACE_LEVEL_DEBUG);
}
else if(!strcmp(lvlStr, "info")){
ntop->getTrace()->set_trace_level(TRACE_LEVEL_INFO);
}
else if(!strcmp(lvlStr, "normal")){
ntop->getTrace()->set_trace_level(TRACE_LEVEL_NORMAL);
}
else if(!strcmp(lvlStr, "warning")){
ntop->getTrace()->set_trace_level(TRACE_LEVEL_WARNING);
}
else if(!strcmp(lvlStr, "error")){
ntop->getTrace()->set_trace_level(TRACE_LEVEL_ERROR);
}
else{
return(CONST_LUA_ERROR);
}
lua_pushnil(vm);
return(CONST_LUA_OK);
}
/* ****************************************** */
/* NOTE: use lua traceError function */
static int ntop_trace_event(lua_State* vm) {
char *msg, *fname;
int level, line;
ntop->getTrace()->traceEvent(TRACE_INFO, "%s() called", __FUNCTION__);
if(ntop_lua_check(vm, __FUNCTION__, 1, LUA_TNUMBER) != CONST_LUA_OK) return(CONST_LUA_ERROR);
level = lua_tointeger(vm, 1);
if(ntop_lua_check(vm, __FUNCTION__, 2, LUA_TSTRING) != CONST_LUA_OK) return(CONST_LUA_ERROR);
if((fname = (char*)lua_tostring(vm, 2)) == NULL) return(CONST_LUA_PARAM_ERROR);
if(ntop_lua_check(vm, __FUNCTION__, 3, LUA_TNUMBER) != CONST_LUA_OK) return(CONST_LUA_ERROR);
line = lua_tointeger(vm, 3);
if(ntop_lua_check(vm, __FUNCTION__, 4, LUA_TSTRING) != CONST_LUA_OK) return(CONST_LUA_ERROR);
if((msg = (char*)lua_tostring(vm, 4)) == NULL) return(CONST_LUA_PARAM_ERROR);
ntop->getTrace()->traceEvent(level, fname, line, "%s", msg);
lua_pushnil(vm);
return(CONST_LUA_OK);
}
/* ****************************************** */
static int ntop_get_arp_matrix_info(lua_State*vm){
NetworkInterface *ntop_interface = getCurrentInterface(vm);
if((!ntop_interface)
|| (!ntop_interface->getArpStatsMatrixInfo(vm)))
return(CONST_LUA_ERROR);
return(CONST_LUA_OK);
}
/* ****************************************** */
static const luaL_Reg ntop_interface_reg[] = {
{ "setActiveInterfaceId", ntop_set_active_interface_id },
{ "getIfNames", ntop_get_interface_names },
{ "getFirstInterfaceId", ntop_get_first_interface_id },
{ "select", ntop_select_interface },
{ "getId", ntop_get_interface_id },
{ "getMaxIfSpeed", ntop_get_max_if_speed },
{ "hasVLANs", ntop_interface_has_vlans },
{ "hasEBPF", ntop_interface_has_ebpf },
{ "hasHighResTs", ntop_interface_has_high_res_ts },
{ "getStats", ntop_get_interface_stats },
{ "getStatsUpdateFreq", ntop_get_interface_stats_update_freq },
{ "getInterfaceTimeseries", ntop_get_interface_timeseries },
{ "resetCounters", ntop_interface_reset_counters },
{ "resetHostStats", ntop_interface_reset_host_stats },
{ "deleteHostData", ntop_interface_delete_host_data },
{ "resetMacStats", ntop_interface_reset_mac_stats },
{ "deleteMacData", ntop_interface_delete_mac_data },
/* Functions related to the management of the internal hash tables */
{ "getHashTablesStats", ntop_get_interface_hash_tables_stats },
{ "periodicHTStateUpdate", ntop_periodic_ht_state_update },
/* Function for the periodic update of hash tables stats (e.g., throughputs) */
{ "periodicStatsUpdate", ntop_periodic_stats_update },
/* Function to get the duration of periodic threaded activities */
{ "getPeriodicActivitiesStats", ntop_get_interface_periodic_activities_stats },
#ifndef HAVE_NEDGE
{ "processFlow", ntop_process_flow },
#endif
{ "getActiveFlowsStats", ntop_get_active_flows_stats },
{ "getnDPIProtoName", ntop_get_ndpi_protocol_name },
{ "getnDPIProtoId", ntop_get_ndpi_protocol_id },
{ "getnDPICategoryId", ntop_get_ndpi_category_id },
{ "getnDPICategoryName", ntop_get_ndpi_category_name },
{ "getnDPIProtoCategory", ntop_get_ndpi_protocol_category },
{ "setnDPIProtoCategory", ntop_set_ndpi_protocol_category },
{ "getnDPIFlowsCount", ntop_get_ndpi_interface_flows_count },
{ "getFlowsStatus", ntop_get_ndpi_interface_flows_status },
{ "getnDPIProtoBreed", ntop_get_ndpi_protocol_breed },
{ "getnDPIProtocols", ntop_get_ndpi_protocols },
{ "getnDPICategories", ntop_get_ndpi_categories },
{ "getHostsInfo", ntop_get_interface_hosts_info },
{ "getLocalHostsInfo", ntop_get_interface_local_hosts_info },
{ "getRemoteHostsInfo", ntop_get_interface_remote_hosts_info },
{ "getBroadcastDomainHostsInfo", ntop_get_interface_broadcast_domain_hosts_info },
{ "getBatchedFlowsInfo", ntop_get_batched_interface_flows_info },
{ "getBatchedHostsInfo", ntop_get_batched_interface_hosts_info },
{ "getBatchedLocalHostsInfo", ntop_get_batched_interface_local_hosts_info },
{ "getBatchedRemoteHostsInfo", ntop_get_batched_interface_remote_hosts_info },
{ "getBatchedLocalHostsTs", ntop_get_batched_interface_local_hosts_ts },
{ "getHostInfo", ntop_get_interface_host_info },
{ "getHostUsedPorts", ntop_get_interface_host_used_ports },
{ "getHostTimeseries", ntop_get_interface_host_timeseries },
{ "getHostCountry", ntop_get_interface_host_country },
{ "getGroupedHosts", ntop_get_grouped_interface_hosts },
{ "addMacsIpAddresses", ntop_add_macs_ip_addresses },
{ "getNetworksStats", ntop_get_interface_networks_stats },
{ "getNetworkStats", ntop_get_interface_network_stats },
{ "restoreHost", ntop_restore_interface_host },
{ "checkpointHostTalker", ntop_checkpoint_host_talker },
{ "getFlowsInfo", ntop_get_interface_flows_info },
{ "getGroupedFlows", ntop_get_interface_get_grouped_flows },
{ "getFlowsStats", ntop_get_interface_flows_stats },
{ "getFlowKey", ntop_get_interface_flow_key },
{ "findFlowByKeyAndHashId", ntop_get_interface_find_flow_by_key_and_hash_id },
{ "findFlowByTuple", ntop_get_interface_find_flow_by_tuple },
{ "dropFlowTraffic", ntop_drop_flow_traffic },
{ "dumpLocalHosts2redis", ntop_dump_local_hosts_2_redis },
{ "dropMultipleFlowsTraffic", ntop_drop_multiple_flows_traffic },
{ "findPidFlows", ntop_get_interface_find_pid_flows },
{ "findNameFlows", ntop_get_interface_find_proc_name_flows },
{ "listHTTPhosts", ntop_list_http_hosts },
{ "findHost", ntop_get_interface_find_host },
{ "findHostByMac", ntop_get_interface_find_host_by_mac },
{ "updateTrafficMirrored", ntop_update_traffic_mirrored },
{ "updateDynIfaceTrafficPolicy", ntop_update_dynamic_interface_traffic_policy },
{ "updateLbdIdentifier", ntop_update_lbd_identifier },
{ "updateHostTrafficPolicy", ntop_update_host_traffic_policy },
{ "getEndpoint", ntop_get_interface_endpoint },
{ "isPacketInterface", ntop_interface_is_packet_interface },
{ "isDiscoverableInterface", ntop_interface_is_discoverable_interface },
{ "isBridgeInterface", ntop_interface_is_bridge_interface },
{ "isPcapDumpInterface", ntop_interface_is_pcap_dump_interface },
{ "isView", ntop_interface_is_view },
{ "isLoopback", ntop_interface_is_loopback },
{ "isRunning", ntop_interface_is_running },
{ "isIdle", ntop_interface_is_idle },
{ "setInterfaceIdleState", ntop_interface_set_idle },
{ "name2id", ntop_interface_name2id },
{ "loadScalingFactorPrefs", ntop_load_scaling_factor_prefs },
{ "reloadHideFromTop", ntop_reload_hide_from_top },
{ "reloadDhcpRanges", ntop_reload_dhcp_ranges },
{ "reloadHostPrefs", ntop_reload_host_prefs },
{ "setHostOperatingSystem", ntop_set_host_operating_system },
/* Mac */
{ "getMacsInfo", ntop_get_interface_macs_info },
{ "getBatchedMacsInfo", ntop_get_batched_interface_macs_info },
{ "getMacInfo", ntop_get_interface_mac_info },
{ "getMacHosts", ntop_get_interface_mac_hosts },
{ "getMacManufacturers", ntop_get_interface_macs_manufacturers },
{ "getTopMacsProtos", ntop_get_top_macs_protos },
{ "setMacDeviceType", ntop_set_mac_device_type },
{ "getMacDeviceTypes", ntop_get_mac_device_types },
/* Autonomous Systems */
{ "getASesInfo", ntop_get_interface_ases_info },
{ "getASInfo", ntop_get_interface_as_info },
/* Countries */
{ "getCountriesInfo", ntop_get_interface_countries_info },
{ "getCountryInfo", ntop_get_interface_country_info },
/*ARP stats matrix*/
{ "getArpStatsMatrixInfo", ntop_get_arp_matrix_info },
/* VLANs */
{ "getVLANsList", ntop_get_interface_vlans_list },
{ "getVLANsInfo", ntop_get_interface_vlans_info },
{ "getVLANInfo", ntop_get_interface_vlan_info } ,
/* Host pools */
{ "reloadHostPools", ntop_reload_host_pools },
{ "findMemberPool", ntop_find_member_pool },
{ "findMacPool", ntop_find_mac_pool },
{ "getTopPoolsProtos", ntop_get_top_pools_protos },
{ "getHostPoolsInfo", ntop_get_host_pools_info },
/* InfluxDB */
{ "appendInfluxDB", ntop_append_influx_db },
{ "getHostPoolsStats", ntop_get_host_pools_interface_stats },
{ "getHostPoolStats", ntop_get_host_pool_interface_stats },
#ifdef NTOPNG_PRO
#ifdef HAVE_NEDGE
{ "resetPoolsQuotas", ntop_reset_pools_quotas },
#endif
{ "getHostPoolsVolatileMembers", ntop_get_host_pool_volatile_members },
{ "purgeExpiredPoolsMembers", ntop_purge_expired_host_pools_members },
{ "removeVolatileMemberFromPool", ntop_remove_volatile_member_from_pool },
{ "getHostUsedQuotasStats", ntop_get_host_used_quotas_stats },
/* SNMP */
{ "getSNMPStats", ntop_interface_get_snmp_stats },
/* Flow Devices */
{ "getFlowDevices", ntop_get_flow_devices },
{ "getFlowDeviceInfo", ntop_get_flow_device_info },
#ifdef HAVE_NEDGE
/* L7 */
{ "reloadL7Rules", ntop_reload_l7_rules },
{ "reloadShapers", ntop_reload_shapers },
{ "setLanIpAddress", ntop_set_lan_ip_address },
{ "getPolicyChangeMarker", ntop_get_policy_change_marker },
{ "updateFlowsShapers", ntop_update_flows_shapers },
{ "getl7PolicyInfo", ntop_get_l7_policy_info },
#endif
#endif
/* Network Discovery */
{ "discoverHosts", ntop_discover_iface_hosts },
{ "arpScanHosts", ntop_arpscan_iface_hosts },
{ "mdnsResolveName", ntop_mdns_resolve_name },
{ "mdnsQueueNameToResolve", ntop_mdns_queue_name_to_resolve },
{ "mdnsQueueAnyQuery", ntop_mdns_batch_any_query },
{ "mdnsReadQueuedResponses", ntop_mdns_read_queued_responses },
#ifndef HAVE_NEDGE
{ "snmpGetBatch", ntop_snmp_batch_get },
{ "snmpReadResponses", ntop_snmp_read_responses },
#endif
/* DB */
{ "execSQLQuery", ntop_interface_exec_sql_query },
/* sFlow */
{ "getSFlowDevices", ntop_getsflowdevices },
{ "getSFlowDeviceInfo", ntop_getsflowdeviceinfo },
#if defined(HAVE_NINDEX) && defined(NTOPNG_PRO)
/* nIndex */
{ "nIndexEnabled", ntop_nindex_enabled },
{ "nIndexSelect", ntop_nindex_select },
{ "nIndexTopK", ntop_nindex_topk },
#endif
/* Live Capture */
{ "liveCapture", ntop_interface_live_capture },
{ "stopLiveCapture", ntop_interface_stop_live_capture },
{ "dumpLiveCaptures", ntop_interface_dump_live_captures },
/* Packet Capture */
{ "captureToPcap", ntop_capture_to_pcap },
{ "isCaptureRunning", ntop_is_capture_running },
{ "stopRunningCapture", ntop_stop_running_capture },
/* Alerts */
{ "optimizeAlerts", ntop_interface_optimize_alerts },
{ "queryAlertsRaw", ntop_interface_query_alerts_raw },
{ "queryFlowAlertsRaw", ntop_interface_query_flow_alerts_raw },
{ "storeAlert", ntop_interface_store_alert },
{ "storeFlowAlert", ntop_interface_store_flow_alert },
{ "setInterfaceHasAlerts", ntop_interface_set_has_alerts },
{ "getCachedAlertValue", ntop_interface_get_cached_alert_value },
{ "setCachedAlertValue", ntop_interface_set_cached_alert_value },
{ "storeTriggeredAlert", ntop_interface_store_triggered_alert },
{ "releaseTriggeredAlert", ntop_interface_release_triggered_alert },
{ "triggerExternalAlert", ntop_interface_store_external_alert },
{ "releaseExternalAlert", ntop_interface_release_external_alert },
{ "checkContext", ntop_interface_check_context },
{ "refreshAlerts", ntop_interface_refresh_alerts },
{ "getEngagedAlerts", ntop_interface_get_engaged_alerts },
{ "getEngagedAlertsCount", ntop_interface_get_engaged_alerts_count },
{ "incNumDroppedAlerts", ntop_interface_inc_num_dropped_alerts },
{ "getAlerts", ntop_interface_get_alerts },
{ "releaseEngagedAlerts", ntop_interface_release_engaged_alerts },
{ "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 },
/* 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 },
/* 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 },
/* eBPF, Containers and Companion Interfaces */
{ "getPodsStats", ntop_interface_get_pods_stats },
{ "getContainersStats", ntop_interface_get_containers_stats },
{ "reloadCompanions", ntop_interface_reload_companions },
{ NULL, NULL }
};
/* **************************************************************** */
static const luaL_Reg ntop_host_reg[] = {
{ "getInfo", ntop_host_get_basic_fields },
{ "getFullInfo", ntop_host_get_all_fields },
{ "getCachedAlertValue", ntop_host_get_cached_alert_value },
{ "setCachedAlertValue", ntop_host_set_cached_alert_value },
{ "storeTriggeredAlert", ntop_host_store_triggered_alert },
{ "releaseTriggeredAlert", ntop_host_release_triggered_alert },
{ "getAlerts", ntop_host_get_alerts },
{ "checkContext", ntop_host_check_context },
{ "getIp", ntop_host_get_ip },
{ "getLocalhostInfo", ntop_host_get_localhost_info },
{ "getApplicationBytes", ntop_host_get_application_bytes },
{ "getCategoryBytes", ntop_host_get_category_bytes },
{ "getBytes", ntop_host_get_bytes },
{ "getPackets", ntop_host_get_packets },
{ "getNumFlows", ntop_host_get_num_total_flows },
{ "getTime", ntop_host_get_time },
{ "getSynFlood", ntop_host_get_syn_flood },
{ "getFlowFlood", ntop_host_get_flow_flood },
{ "getSynScan", ntop_host_get_syn_scan },
{ "getDNSInfo", ntop_host_get_dns_info },
{ "getHTTPInfo", ntop_host_get_http_info },
{ NULL, NULL }
};
/* **************************************************************** */
static const luaL_Reg ntop_network_reg[] = {
{ "getNetworkStats", ntop_network_get_network_stats },
{ "getCachedAlertValue", ntop_network_get_cached_alert_value },
{ "setCachedAlertValue", ntop_network_set_cached_alert_value },
{ "storeTriggeredAlert", ntop_network_store_triggered_alert },
{ "releaseTriggeredAlert", ntop_network_release_triggered_alert },
{ "getAlerts", ntop_network_get_alerts },
{ "checkContext", ntop_network_check_context },
{ NULL, NULL }
};
/* **************************************************************** */
static const luaL_Reg ntop_flow_reg[] = {
/* Documented */
{ "getStatus", ntop_flow_get_status },
{ "isBlacklisted", ntop_flow_is_blacklisted },
{ "setStatus", ntop_flow_set_status },
{ "clearStatus", ntop_flow_clear_status },
{ "getInfo", ntop_flow_get_info },
{ "getFullInfo", ntop_flow_get_full_info },
{ "getUnicastInfo", ntop_flow_get_unicast_info },
/* Internal */
{ "triggerAlert", ntop_flow_trigger_alert },
{ "getPredominantStatus", ntop_get_predominant_status },
{ "setPredominantStatus", ntop_set_predominant_status },
{ "getKey", ntop_flow_get_key },
{ "getHashEntryId", ntop_flow_get_hash_entry_id },
{ "getICMPStatusInfo", ntop_flow_get_icmp_status_info },
/* Fast calls */
{ "getFirstSeen", ntop_flow_get_first_seen },
{ "getLastSeen", ntop_flow_get_last_seen },
{ "getDuration", ntop_flow_get_duration },
{ "isTwhOK", ntop_flow_is_twh_ok },
{ "isBidirectional", ntop_flow_is_bidirectional },
{ "getPacketsSent", ntop_flow_get_packets_sent },
{ "getPacketsRcvd", ntop_flow_get_packets_rcvd },
{ "getBytesSent", ntop_flow_get_bytes_sent },
{ "getBytesRcvd", ntop_flow_get_bytes_rcvd },
{ "getBytes", ntop_flow_get_bytes },
{ "getGoodputBytes", ntop_flow_get_goodput_bytes },
{ "getClientKey", ntop_flow_get_client_key },
{ "getServerKey", ntop_flow_get_server_key },
{ "isClientUnicast", ntop_flow_is_client_unicast },
{ "isServerUnicast", ntop_flow_is_server_unicast },
{ "isUnicast", ntop_flow_is_unicast },
{ "isRemoteToRemote", ntop_flow_is_remote_to_remote },
{ "isLocalToRemote", ntop_flow_is_local_to_remote },
{ "isRemoteToLocal", ntop_flow_is_remote_to_local },
{ "getnDPICategoryName", ntop_flow_get_ndpi_cat_name },
{ "getClientTCPIssues", ntop_flow_get_cli_tcp_issues },
{ "getServerTCPIssues", ntop_flow_get_srv_tcp_issues },
{ "canTriggerAlert", ntop_flow_can_trigger_alert },
{ "isDeviceProtocolNotAllowed", ntop_flow_is_dp_not_allowed },
{ "isConnectionRefused", ntop_flow_is_connection_refused },
{ "getServerCipherClass", ntop_flow_get_ssl_cipher_class },
{ "getICMPType", ntop_flow_get_icmp_type },
{ "getMaxSeenIcmpPayloadSize", ntop_flow_get_max_seen_icmp_size },
{ "dnsQueryHasInvalidChars", ntop_flow_dns_query_invalid_chars },
{ "getDnsQuery", ntop_flow_get_dns_query },
{ "getProtoBreed", ntop_flow_get_proto_breed },
{ "hasMaliciousTlsSignature", ntop_flow_has_malicious_tls_sign },
{ "shouldCheckTlsCertificate", ntop_flow_check_tls_certificate },
/* TODO document */
{ "isLocal", ntop_flow_is_local },
{ "setScore", ntop_flow_set_score },
{ "getScore", ntop_flow_get_score },
{ "getScoreInfo", ntop_flow_get_score_info },
{ "setClientScore", ntop_flow_set_client_score },
{ "setServerScore", ntop_flow_set_server_score },
{ "getMUDInfo", ntop_flow_get_mud_info },
{ "isNotPurged", ntop_flow_is_not_purged },
{ "getTLSVersion", ntop_flow_get_tls_version },
{ "getTCPStats", ntop_flow_get_tcp_stats },
{ "getBlacklistedInfo", ntop_flow_get_blacklisted_info },
#ifdef HAVE_NEDGE
{ "isPassVerdict", ntop_flow_is_pass_verdict },
#endif
{ "retrieveExternalAlertInfo", ntop_flow_retrieve_external_alert_info },
{ "getDeviceProtoAllowedInfo", ntop_flow_get_device_proto_allowed_info},
{ "getClient2ServerIAT", ntop_flow_get_cli2srv_iat },
{ "getServer2ClientIAT", ntop_flow_get_srv2cli_iat },
{ "getTLSInfo", ntop_flow_get_tls_info },
{ "getSSHInfo", ntop_flow_get_ssh_info },
{ "getHTTPInfo", ntop_flow_get_http_info },
{ "getDNSInfo", ntop_flow_get_dns_info },
{ NULL, NULL }
};
/* **************************************************************** */
static const luaL_Reg ntop_reg[] = {
{ "getDirs", ntop_get_dirs },
{ "getInfo", ntop_get_info },
{ "getUptime", ntop_get_uptime },
{ "dumpFile", ntop_dump_file },
{ "dumpBinaryFile", ntop_dump_binary_file },
{ "checkLicense", ntop_check_license },
{ "systemHostStat", ntop_system_host_stat },
{ "refreshCpuLoad", ntop_refresh_cpu_load },
{ "getCookieAttributes", ntop_get_cookie_attributes },
{ "isAllowedInterface", ntop_is_allowed_interface },
{ "isAllowedNetwork", ntop_is_allowed_network },
{ "md5", ntop_md5 },
{ "hasRadiusSupport", ntop_has_radius_support },
{ "hasLdapSupport", ntop_has_ldap_support },
{ "execSingleSQLQuery", ntop_interface_exec_single_sql_query },
{ "resetStats", ntop_reset_stats },
/* Redis */
{ "getCacheStatus", ntop_info_redis },
{ "getCache", ntop_get_redis },
{ "setCache", ntop_set_redis },
{ "incrCache", ntop_incr_redis },
{ "getCacheStats", ntop_get_redis_stats },
{ "delCache", ntop_delete_redis_key },
{ "flushCache", ntop_flush_redis },
{ "listIndexCache", ntop_list_index_redis },
{ "lpushCache", ntop_lpush_redis },
{ "rpushCache", ntop_rpush_redis },
{ "lpopCache", ntop_lpop_redis },
{ "rpopCache", ntop_rpop_redis },
{ "lremCache", ntop_lrem_redis },
{ "ltrimCache", ntop_ltrim_redis },
{ "lrangeCache", ntop_lrange_redis },
{ "llenCache", ntop_llen_redis },
{ "setMembersCache", ntop_add_set_member_redis },
{ "delMembersCache", ntop_del_set_member_redis },
{ "getMembersCache", ntop_get_set_members_redis },
{ "getHashCache", ntop_get_hash_redis },
{ "setHashCache", ntop_set_hash_redis },
{ "delHashCache", ntop_delete_hash_redis_key },
{ "getHashKeysCache", ntop_get_hash_keys_redis },
{ "getHashAllCache", ntop_get_hash_all_redis },
{ "getKeysCache", ntop_get_keys_redis },
{ "dumpCache", ntop_redis_dump },
{ "restoreCache", ntop_redis_restore },
{ "addLocalNetwork", ntop_add_local_network },
/* Redis Preferences */
{ "setPref", ntop_set_preference },
{ "getPref", ntop_get_redis },
{ "isdir", ntop_is_dir },
{ "mkdir", ntop_mkdir_tree },
{ "notEmptyFile", ntop_is_not_empty_file },
{ "exists", ntop_get_file_dir_exists },
{ "listReports", ntop_list_reports },
{ "fileLastChange", ntop_get_file_last_change },
{ "readdir", ntop_list_dir_files },
{ "rmdir", ntop_remove_dir_recursively },
#ifndef HAVE_NEDGE
{ "zmq_connect", ntop_zmq_connect },
{ "zmq_disconnect", ntop_zmq_disconnect },
{ "zmq_receive", ntop_zmq_receive },
#endif
{ "reloadPreferences", ntop_reload_preferences },
{ "setAlertsTemporaryDisabled", ntop_temporary_disable_alerts },
{ "setDefaultFilePermissions", ntop_set_default_file_permissions },
#ifdef NTOPNG_PRO
#ifndef WIN32
{ "sendNagiosAlert", ntop_nagios_send_alert },
{ "withdrawNagiosAlert", ntop_nagios_withdraw_alert },
{ "reloadNagiosConfig", ntop_nagios_reload_config },
#endif
#ifndef HAVE_NEDGE
{ "checkSubInterfaceSyntax", ntop_check_sub_interface_syntax },
{ "checkProfileSyntax", ntop_check_profile_syntax },
{ "reloadProfiles", ntop_reload_traffic_profiles },
#endif
#endif
{ "isPro", ntop_is_pro },
{ "isEnterprise", ntop_is_enterprise },
{ "isnEdge", ntop_is_nedge },
{ "isnEdgeEnterprise", ntop_is_nedge_enterprise },
{ "isPackage", ntop_is_package },
/* Historical database */
{ "insertMinuteSampling", ntop_stats_insert_minute_sampling },
{ "insertHourSampling", ntop_stats_insert_hour_sampling },
{ "insertDaySampling", ntop_stats_insert_day_sampling },
{ "getMinuteSampling", ntop_stats_get_minute_sampling },
{ "deleteMinuteStatsOlderThan", ntop_stats_delete_minute_older_than },
{ "deleteHourStatsOlderThan", ntop_stats_delete_hour_older_than },
{ "deleteDayStatsOlderThan", ntop_stats_delete_day_older_than },
{ "getMinuteSamplingsFromEpoch", ntop_stats_get_samplings_of_minutes_from_epoch },
{ "getHourSamplingsFromEpoch", ntop_stats_get_samplings_of_hours_from_epoch },
{ "getDaySamplingsFromEpoch", ntop_stats_get_samplings_of_days_from_epoch },
{ "getMinuteSamplingsInterval", ntop_stats_get_minute_samplings_interval },
{ "deleteOldRRDs", ntop_delete_old_rrd_files },
/* Time */
{ "gettimemsec", ntop_gettimemsec },
{ "tzset", ntop_tzset },
{ "roundTime", ntop_round_time },
/* Ticks */
{ "getticks", ntop_getticks },
{ "gettickspersec", ntop_gettickspersec },
/* UDP */
{ "send_udp_data", ntop_send_udp_data },
/* IP */
{ "inet_ntoa", ntop_inet_ntoa },
{ "networkPrefix", ntop_network_prefix },
/* RRD */
{ "rrd_create", ntop_rrd_create },
{ "rrd_update", ntop_rrd_update },
{ "rrd_fetch", ntop_rrd_fetch },
{ "rrd_fetch_columns", ntop_rrd_fetch_columns },
{ "rrd_lastupdate", ntop_rrd_lastupdate },
{ "rrd_tune", ntop_rrd_tune },
/* Prefs */
{ "getPrefs", ntop_get_prefs },
/* Ping */
{ "pingHost", ntop_ping_host },
{ "collectPingResults", ntop_collect_ping_results },
/* HTTP utils */
{ "httpRedirect", ntop_http_redirect },
{ "getHttpPrefix", ntop_http_get_prefix },
{ "getStartupEpoch", ntop_http_get_startup_epoch },
{ "httpPurifyParam", ntop_http_purify_param },
/* Admin */
{ "getNologinUser", ntop_get_nologin_username },
{ "getUsers", ntop_get_users },
{ "isAdministrator", ntop_is_administrator },
{ "getAllowedNetworks", ntop_get_allowed_networks },
{ "resetUserPassword", ntop_reset_user_password },
{ "changeUserRole", ntop_change_user_role },
{ "changeAllowedNets", ntop_change_allowed_nets },
{ "changeAllowedIfname", ntop_change_allowed_ifname },
{ "changeUserHostPool", ntop_change_user_host_pool },
{ "changeUserLanguage", ntop_change_user_language },
{ "addUser", ntop_add_user },
{ "addUserLifetime", ntop_add_user_lifetime },
{ "clearUserLifetime", ntop_clear_user_lifetime },
{ "deleteUser", ntop_delete_user },
{ "isLoginDisabled", ntop_is_login_disabled },
{ "isLoginBlacklisted", ntop_is_login_blacklisted },
{ "getNetworkNameById", ntop_network_name_by_id },
{ "getNetworkIdByName", ntop_network_id_by_name },
{ "isGuiAccessRestricted", ntop_is_gui_access_restricted },
/* Security */
{ "getRandomCSRFValue", ntop_generate_csrf_value },
/* HTTP */
{ "httpGet", ntop_http_get },
{ "httpPost", ntop_http_post },
{ "httpFetch", ntop_http_fetch },
{ "postHTTPJsonData", ntop_post_http_json_data },
{ "postHTTPTextFile", ntop_post_http_text_file },
#ifdef HAVE_CURL_SMTP
/* SMTP */
{ "sendMail", ntop_send_mail },
#endif
/* Address Resolution */
{ "resolveName", ntop_resolve_address }, /* Note: you should use resolveAddress() to call from Lua */
{ "getResolvedName", ntop_get_resolved_address }, /* Note: you should use getResolvedAddress() to call from Lua */
{ "resolveHost", ntop_resolve_host },
/* Logging */
#ifndef WIN32
{ "syslog", ntop_syslog },
#endif
{ "setLoggingLevel", ntop_set_logging_level },
{ "traceEvent", ntop_trace_event },
{ "verboseTrace", ntop_verbose_trace },
/* SNMP */
#ifndef HAVE_NEDGE
{ "snmpget", ntop_snmpget },
{ "snmpgetnext", ntop_snmpgetnext },
#endif
/* Runtime */
{ "hasGeoIP", ntop_has_geoip },
{ "isWindows", ntop_is_windows },
/* Custom Categories - only inteded to be called from housekeeping.lua */
{ "startCustomCategoriesReload", ntop_startCustomCategoriesReload },
{ "loadCustomCategoryIp", ntop_loadCustomCategoryIp },
{ "loadCustomCategoryHost", ntop_loadCustomCategoryHost },
{ "reloadCustomCategories", ntop_reloadCustomCategories },
/* Privileges */
{ "gainWriteCapabilities", ntop_gainWriteCapabilities },
{ "dropWriteCapabilities", ntop_dropWriteCapabilities },
/* Misc */
{ "getservbyport", ntop_getservbyport },
{ "msleep", ntop_msleep },
{ "tcpProbe", ntop_tcp_probe },
{ "getMacManufacturer", ntop_get_mac_manufacturer },
{ "getHostInformation", ntop_get_host_information },
{ "isShutdown", ntop_is_shutdown },
{ "listInterfaces", ntop_list_interfaces },
{ "ipCmp", ntop_ip_cmp },
{ "matchCustomCategory", ntop_match_custom_category },
/* JA3 */
{ "loadMaliciousJA3Hash", ntop_load_malicious_ja3_hash },
{ "reloadJA3Hashes", ntop_reload_ja3_hashes },
/* Device Protocols */
{ "reloadDeviceProtocols", ntop_reload_device_protocols },
/* Traffic Recording/Extraction */
{ "runExtraction", ntop_run_extraction },
{ "stopExtraction", ntop_stop_extraction },
{ "isExtractionRunning", ntop_is_extraction_running },
{ "getExtractionStatus", ntop_get_extraction_status },
{ "runLiveExtraction", ntop_run_live_extraction },
/* Bitmap functions */
{ "bitmapIsSet", ntop_bitmap_is_set },
{ "bitmapSet", ntop_bitmap_set },
{ "bitmapClear", ntop_bitmap_clear },
/* Alerts queues */
{ "pushSqliteAlert", ntop_push_sqlite_alert },
{ "popSqliteAlert", ntop_pop_sqlite_alert },
{ "pushAlertNotification", ntop_push_alert_notification },
{ "popAlertNotification", ntop_pop_alert_notification },
{ "popInternalAlerts", ntop_pop_internal_alerts },
/* nEdge */
#ifdef HAVE_NEDGE
{ "setHTTPBindAddr", ntop_set_http_bind_addr },
{ "setHTTPSBindAddr", ntop_set_https_bind_addr },
{ "shutdown", ntop_shutdown },
{ "setRoutingMode", ntop_set_routing_mode },
{ "isRoutingMode", ntop_is_routing_mode },
{ "setLanInterface", ntop_set_lan_interface },
{ "refreshDeviceProtocolsPoliciesConf", ntop_refresh_device_protocols_policies_pref },
#endif
/* System User Scripts */
{ "checkSystemScriptsMin", ntop_check_system_scripts_min },
{ "checkSystemScripts5Min", ntop_check_system_scripts_5min },
{ "checkSystemScriptsHour", ntop_check_system_scripts_hour },
{ "checkSystemScriptsDay", ntop_check_system_scripts_day },
{ "checkSNMPDeviceAlerts5Min", ntop_check_snmp_device_alerts_5min },
{ NULL, NULL}
};
/* ****************************************** */
void LuaEngine::luaRegister(lua_State *L, const ntop_class_reg *reg) {
static const luaL_Reg _meta[] = { { NULL, NULL } };
int lib_id, meta_id;
/* newclass = {} */
lua_createtable(L, 0, 0);
lib_id = lua_gettop(L);
/* metatable = {} */
luaL_newmetatable(L, reg->class_name);
meta_id = lua_gettop(L);
luaL_setfuncs(L, _meta, 0);
/* metatable.__index = class_methods */
lua_newtable(L);
luaL_setfuncs(L, reg->class_methods, 0);
lua_setfield(L, meta_id, "__index");
/* class.__metatable = metatable */
lua_setmetatable(L, lib_id);
/* _G["Foo"] = newclass */
lua_setglobal(L, reg->class_name);
}
void LuaEngine::luaRegisterInternalRegs(lua_State *L) {
int i;
ntop_class_reg ntop_lua_reg[] = {
{ "interface", ntop_interface_reg },
{ "ntop", ntop_reg },
{ "host", ntop_host_reg },
{ "network", ntop_network_reg },
{ "flow", ntop_flow_reg },
{NULL, NULL}
};
for(i=0; ntop_lua_reg[i].class_name != NULL; i++)
LuaEngine::luaRegister(L, &ntop_lua_reg[i]);
}
void LuaEngine::lua_register_classes(lua_State *L, bool http_mode) {
if(!L) return;
LuaEngine::luaRegisterInternalRegs(L);
if(http_mode) {
/* Overload the standard Lua print() with ntop_lua_http_print that dumps data on HTTP server */
lua_register(L, "print", ntop_lua_http_print);
} else
lua_register(L, "print", ntop_lua_cli_print);
#if defined(NTOPNG_PRO) || defined(HAVE_NEDGE)
if(ntop->getPro()->has_valid_license()) {
lua_register(L, "ntopRequire", ntop_lua_require);
/* Lua 5.2.x uses package.loaders */
luaL_dostring(L, "package.loaders = { ntopRequire }");
/* Lua 5.3.x uses package.searchers */
luaL_dostring(L, "package.searchers = { ntopRequire }");
lua_register(L, "dofile", ntop_lua_dofile);
lua_register(L, "loadfile", ntop_lua_loadfile);
}
#endif
}
/* ****************************************** */
#if 0
/**
* Iterator over key-value pairs where the value
* maybe made available in increments and/or may
* not be zero-terminated. Used for processing
* POST data.
*
* @param cls user-specified closure
* @param kind type of the value
* @param key 0-terminated key for the value
* @param filename name of the uploaded file, NULL if not known
* @param content_type mime-type of the data, NULL if not known
* @param transfer_encoding encoding of the data, NULL if not known
* @param data pointer to size bytes of data at the
* specified offset
* @param off offset of data in the overall value
* @param size number of bytes in data available
* @return MHD_YES to continue iterating,
* MHD_NO to abort the iteration
*/
static int post_iterator(void *cls,
enum MHD_ValueKind kind,
const char *key,
const char *filename,
const char *content_type,
const char *transfer_encoding,
const char *data, uint64_t off, size_t size)
{
struct Request *request = cls;
char tmp[1024];
u_int len = min(size, sizeof(tmp)-1);
memcpy(tmp, &data[off], len);
tmp[len] = '\0';
fprintf(stdout, "[POST] [%s][%s]\n", key, tmp);
return MHD_YES;
}
#endif
/* ****************************************** */
/*
Run a Lua script from within ntopng (no HTTP GUI)
*/
int LuaEngine::run_script(char *script_path, NetworkInterface *iface, bool load_only, time_t deadline) {
int rc = 0;
if(!L) return(-1);
try {
luaL_openlibs(L); /* Load base libraries */
lua_register_classes(L, false); /* Load custom classes */
if(iface) {
/* Select the specified inteface */
getLuaVMUservalue(L, iface) = iface;
}
/* An optional deadline can be passed to the script so actions
can be taken from lua to stop the execution of the dealine is approaching */
if(deadline) {
lua_pushinteger(L, deadline);
lua_setglobal(L, "deadline");
}
#ifdef NTOPNG_PRO
if(ntop->getPro()->has_valid_license())
rc = __ntop_lua_handlefile(L, script_path, !load_only /* Execute? */);
else
#endif
rc = !load_only ? luaL_dofile(L, script_path) : luaL_loadfile(L, script_path);
if(rc == 0 && load_only)
rc = lua_pcall(L, 0, 0, 0); /* Prevents loaded scripts from failing silently by showing possible syntax errors */
if(rc != 0) {
const char *err = lua_tostring(L, -1);
ntop->getTrace()->traceEvent(TRACE_WARNING, "Script failure [%s][%s]", script_path, err ? err : "");
rc = -1;
}
} catch(...) {
ntop->getTrace()->traceEvent(TRACE_WARNING, "Script failure [%s]", script_path);
rc = -2;
}
return(rc);
}
/* ****************************************** */
/* http://www.geekhideout.com/downloads/urlcode.c */
#if 0
/* Converts an integer value to its hex character*/
static char to_hex(char code) {
static char hex[] = "0123456789abcdef";
return hex[code & 15];
}
/* ****************************************** */
/* Returns a url-encoded version of str */
/* IMPORTANT: be sure to free() the returned string after use */
static char* http_encode(char *str) {
char *pstr = str, *buf = (char*)malloc(strlen(str) * 3 + 1), *pbuf = buf;
while (*pstr) {
if(isalnum(*pstr) || *pstr == '-' || *pstr == '_' || *pstr == '.' || *pstr == '~')
*pbuf++ = *pstr;
else if(*pstr == ' ')
*pbuf++ = '+';
else
*pbuf++ = '%', *pbuf++ = to_hex(*pstr >> 4), *pbuf++ = to_hex(*pstr & 15);
pstr++;
}
*pbuf = '\0';
return buf;
}
#endif
/* ****************************************** */
#ifdef NOT_USED
void LuaEngine::purifyHTTPParameter(char *param) {
char *ampersand;
bool utf8_found = false;
if((ampersand = strchr(param, '%')) != NULL) {
/* We allow only a few chars, removing all the others */
if((ampersand[1] != 0) && (ampersand[2] != 0)) {
char c;
char b = ampersand[3];
ampersand[3] = '\0';
c = (char)strtol(&ampersand[1], NULL, 16);
ampersand[3] = b;
switch(c) {
case '/':
case ':':
case '(':
case ')':
case '{':
case '}':
case '[':
case ']':
case '?':
case '!':
case '$':
case ',':
case '^':
case '*':
case '_':
case '&':
case ' ':
case '=':
case '<':
case '>':
case '@':
case '#':
break;
default:
if(((u_char)c == 0xC3) && (ampersand[3] == '%')) {
/* Latin-1 within UTF-8 */
b = ampersand[6];
ampersand[6] = '\0';
c = (char)strtol(&ampersand[4], NULL, 16);
ampersand[6] = b;
/* Align to ASCII encoding */
c |= 0x40;
utf8_found = true;
}
if(!Utils::isPrintableChar(c)) {
ntop->getTrace()->traceEvent(TRACE_WARNING, "Discarded char '0x%02x' in URI [%s]", c, param);
ampersand[0] = '\0';
return;
}
}
purifyHTTPParameter(utf8_found ? &ampersand[6] : &ampersand[3]);
} else
ampersand[0] = '\0';
}
}
#endif
/* ****************************************** */
bool LuaEngine::switchInterface(struct lua_State *vm, const char *ifid,
const char *user, const char *session) {
NetworkInterface *iface = NULL;
char iface_key[64], ifname_key[64];
char iface_id[16];
iface = ntop->getNetworkInterface(vm, atoi(ifid));
if(iface == NULL)
return false;
if(user != NULL) {
if(!strlen(session) && strcmp(user, NTOP_NOLOGIN_USER))
return false;
snprintf(iface_key, sizeof(iface_key), NTOPNG_PREFS_PREFIX ".%s.iface", user);
snprintf(ifname_key, sizeof(ifname_key), NTOPNG_PREFS_PREFIX ".%s.ifname", user);
} else { // Login disabled
snprintf(iface_key, sizeof(iface_key), NTOPNG_PREFS_PREFIX ".iface");
snprintf(ifname_key, sizeof(ifname_key), NTOPNG_PREFS_PREFIX ".ifname");
}
snprintf(iface_id, sizeof(iface_id), "%d", iface->get_id());
ntop->getRedis()->set(iface_key, iface_id, 0);
ntop->getRedis()->set(ifname_key, iface->get_name(), 0);
return true;
}
/* ****************************************** */
void LuaEngine::setInterface(const char * user, char * const ifname,
u_int16_t ifname_len, bool * const is_allowed) const {
NetworkInterface *iface = NULL;
char key[CONST_MAX_LEN_REDIS_KEY];
ifname[0] = '\0';
if((user == NULL) || (user[0] == '\0'))
user = NTOP_NOLOGIN_USER;
if(is_allowed) *is_allowed = false;
// check if the user is restricted to browse only a given interface
if(snprintf(key, sizeof(key), CONST_STR_USER_ALLOWED_IFNAME, user)
&& ntop->getRedis()->get(key, ifname, ifname_len) == 0
&& ifname[0] != '\0') {
/* If here is only one allowed interface for the user.
The interface must exists otherwise we hould have prevented the login */
if(is_allowed) *is_allowed = true;
ntop->getTrace()->traceEvent(TRACE_DEBUG, "Allowed interface found. [Interface: %s][user: %s]",
ifname, user);
} else if(snprintf(key, sizeof(key), "ntopng.prefs.%s.ifname", user)
&& (ntop->getRedis()->get(key, ifname, ifname_len) < 0
|| (!ntop->isExistingInterface(ifname)))) {
/* No allowed interface and no default (or not existing) set interface */
snprintf(ifname, ifname_len, "%s",
ntop->getFirstInterface()->get_name());
ntop->getRedis()->set(key, ifname, 3600 /* 1h */);
ntop->getTrace()->traceEvent(TRACE_DEBUG,
"No interface interface found. Using default. [Interface: %s][user: %s]",
ifname, user);
}
if((iface = ntop->getNetworkInterface(ifname, NULL /* allowed user interface check already enforced */)) != NULL) {
/* The specified interface still exists */
lua_push_str_table_entry(L, "ifname", iface->get_name());
snprintf(ifname, ifname_len, "%s", iface->get_name());
ntop->getTrace()->traceEvent(TRACE_DEBUG, "Interface found [Interface: %s][user: %s]", iface->get_name(), user);
}
}
/* ****************************************** */
bool LuaEngine::setParamsTable(lua_State* vm,
const struct mg_request_info *request_info,
const char* table_name,
const char* query) const {
char *where;
char *tok;
char *query_string = query ? strdup(query) : NULL;
bool ret = false;
lua_newtable(L);
if(query_string
&& strcmp(request_info->uri, CAPTIVE_PORTAL_INFO_URL) /* Ignore informative portal */
) {
// ntop->getTrace()->traceEvent(TRACE_WARNING, "[HTTP] %s", query_string);
tok = strtok_r(query_string, "&", &where);
while(tok != NULL) {
char *_equal;
if(strncmp(tok, "csrf", strlen("csrf")) != 0 /* Do not put csrf into the params table */
&& strncmp(tok, "switch_interface", strlen("switch_interface")) != 0
&& (_equal = strchr(tok, '='))){
char *decoded_buf;
int len;
_equal[0] = '\0';
_equal = &_equal[1];
len = strlen(_equal);
// ntop->getTrace()->traceEvent(TRACE_WARNING, "%s = %s", tok, _equal);
if((decoded_buf = (char*)malloc(len+1)) != NULL) {
bool rsp = false;
Utils::urlDecode(_equal, decoded_buf, len + 1);
rsp = Utils::purifyHTTPparam(tok, true, false, false);
/* don't purify decoded_buf, it's purified in lua */
if(rsp) {
ntop->getTrace()->traceEvent(TRACE_WARNING, "[HTTP] Invalid '%s'", query);
ret = true;
}
/* Now make sure that decoded_buf is not a file path */
if(strchr(decoded_buf, CONST_PATH_SEP)
&& Utils::file_exists(decoded_buf)
&& !Utils::dir_exists(decoded_buf)
&& strcmp(tok, "pid_name") /* This is the only exception */
)
ntop->getTrace()->traceEvent(TRACE_WARNING, "Discarded '%s'='%s' as argument is a valid file path",
tok, decoded_buf);
else
lua_push_str_table_entry(vm, tok, decoded_buf);
free(decoded_buf);
} else
ntop->getTrace()->traceEvent(TRACE_WARNING, "Not enough memory");
}
tok = strtok_r(NULL, "&", &where);
} /* while */
}
if(query_string) free(query_string);
if(table_name)
lua_setglobal(L, table_name);
else
lua_setglobal(L, (char*)"_GET"); /* Default */
return(ret);
}
/* ****************************************** */
int LuaEngine::handle_script_request(struct mg_connection *conn,
const struct mg_request_info *request_info,
char *script_path, bool *attack_attempt,
const char *user,
const char *group, bool localuser) {
NetworkInterface *iface = NULL;
char key[64], ifname[MAX_INTERFACE_NAME_LEN];
bool is_interface_allowed;
AddressTree ptree;
int rc, post_data_len;
const char * content_type;
u_int8_t valid_csrf = 1;
char *post_data = NULL;
char rsp[32];
char csrf[64] = { '\0' };
char switch_interface[2] = { '\0' };
char addr_buf[64];
char session_buf[64];
char ifid_buf[32];
bool send_redirect = false;
IpAddress client_addr;
*attack_attempt = false;
if(!L) return(-1);
luaL_openlibs(L); /* Load base libraries */
lua_register_classes(L, true); /* Load custom classes */
getLuaVMUservalue(L, conn) = conn;
content_type = mg_get_header(conn, "Content-Type");
mg_get_cookie(conn, "session", session_buf, sizeof(session_buf));
/* Check for POST requests */
if((strcmp(request_info->request_method, "POST") == 0) && (content_type != NULL)) {
if((post_data = (char*)malloc(HTTP_MAX_POST_DATA_LEN * sizeof(char))) == NULL
|| (post_data_len = mg_read(conn, post_data, HTTP_MAX_POST_DATA_LEN)) == 0) {
valid_csrf = 0;
} else if(post_data_len > HTTP_MAX_POST_DATA_LEN - 1) {
ntop->getTrace()->traceEvent(TRACE_WARNING,
"Too much data submitted with the form. [post_data_len: %u]",
post_data_len);
valid_csrf = 0;
} else {
post_data[post_data_len] = '\0';
/* CSRF is mandatory in POST request */
mg_get_var(post_data, post_data_len, "csrf", csrf, sizeof(csrf));
if(strstr(content_type, "application/json"))
valid_csrf = 1;
else {
if((ntop->getRedis()->get(csrf, rsp, sizeof(rsp)) == -1) || (strcmp(rsp, user) != 0))
valid_csrf = 0;
else {
/* Invalidate csrf */
ntop->getRedis()->del(csrf);
}
}
}
if(valid_csrf) {
if(strstr(content_type, "application/x-www-form-urlencoded") == content_type)
*attack_attempt = setParamsTable(L, request_info, "_POST", post_data); /* CSRF is valid here, now fill the _POST table with POST parameters */
else {
/* application/json" */
lua_newtable(L);
lua_push_str_table_entry(L, "payload", post_data);
lua_setglobal(L, "_POST");
}
/* Check for interface switch requests */
mg_get_var(post_data, post_data_len, "switch_interface", switch_interface, sizeof(switch_interface));
if (strlen(switch_interface) > 0 && request_info->query_string) {
mg_get_var(request_info->query_string, strlen(request_info->query_string), "ifid", ifid_buf, sizeof(ifid_buf));
if (strlen(ifid_buf) > 0) {
switchInterface(L, ifid_buf, user, session_buf);
/* Sending a redirect is needed to prevent the current lua script
* from receiving the POST request, as it could exchange the request
* as a configuration save request. */
send_redirect = true;
}
}
} else
*attack_attempt = setParamsTable(L, request_info, "_POST", NULL /* Empty */);
if(post_data)
free(post_data);
} else
*attack_attempt = setParamsTable(L, request_info, "_POST", NULL /* Empty */);
if(send_redirect) {
char buf[512];
build_redirect(request_info->uri, request_info->query_string, buf, sizeof(buf));
/* Redirect the page and terminate this request */
mg_printf(conn, "%s", buf);
return(CONST_LUA_OK);
}
/* Put the GET params into the environment */
if(request_info->query_string)
*attack_attempt = setParamsTable(L, request_info, "_GET", request_info->query_string);
else
*attack_attempt = setParamsTable(L, request_info, "_GET", NULL /* Empty */);
/* _SERVER */
lua_newtable(L);
lua_push_str_table_entry(L, "REQUEST_METHOD", (char*)request_info->request_method);
lua_push_str_table_entry(L, "URI", (char*)request_info->uri ? (char*)request_info->uri : (char*)"");
lua_push_str_table_entry(L, "REFERER", (char*)mg_get_header(conn, "Referer") ? (char*)mg_get_header(conn, "Referer") : (char*)"");
const char *host = mg_get_header(conn, "Host");
if(host) {
lua_pushfstring(L, "%s://%s", (request_info->is_ssl) ? "https" : "http", host);
lua_pushstring(L, "HTTP_HOST");
lua_insert(L, -2);
lua_settable(L, -3);
}
if(request_info->remote_user) lua_push_str_table_entry(L, "REMOTE_USER", (char*)request_info->remote_user);
if(request_info->query_string) lua_push_str_table_entry(L, "QUERY_STRING", (char*)request_info->query_string);
for(int i=0; ((request_info->http_headers[i].name != NULL)
&& request_info->http_headers[i].name[0] != '\0'); i++)
lua_push_str_table_entry(L,
request_info->http_headers[i].name,
(char*)request_info->http_headers[i].value);
client_addr.set(mg_get_client_address(conn));
lua_push_str_table_entry(L, "REMOTE_ADDR", (char*) client_addr.print(addr_buf, sizeof(addr_buf)));
lua_setglobal(L, (char*)"_SERVER");
#ifdef NOT_USED
/* NOTE: ntopng cannot rely on user provided cookies, it must use session data */
char *_cookies;
/* Cookies */
lua_newtable(L);
if((_cookies = (char*)mg_get_header(conn, "Cookie")) != NULL) {
char *cookies = strdup(_cookies);
char *tok, *where;
// ntop->getTrace()->traceEvent(TRACE_WARNING, "=> '%s'", cookies);
tok = strtok_r(cookies, "=", &where);
while(tok != NULL) {
char *val;
while(tok[0] == ' ') tok++;
if((val = strtok_r(NULL, ";", &where)) != NULL) {
lua_push_str_table_entry(L, tok, val);
// ntop->getTrace()->traceEvent(TRACE_WARNING, "'%s'='%s'", tok, val);
} else
break;
tok = strtok_r(NULL, "=", &where);
}
free(cookies);
}
lua_setglobal(L, "_COOKIE"); /* Like in php */
#endif
/* Put the _SESSION params into the environment */
lua_newtable(L);
lua_push_str_table_entry(L, "session", session_buf);
lua_push_str_table_entry(L, "user", (char*)user);
lua_push_str_table_entry(L, "group", (char*)group);
lua_push_bool_table_entry(L, "localuser", localuser);
// now it's time to set the interface.
setInterface(user, ifname, sizeof(ifname), &is_interface_allowed);
if(!valid_csrf)
lua_push_bool_table_entry(L, "INVALID_CSRF", true);
lua_setglobal(L, "_SESSION"); /* Like in php */
if(user[0] != '\0') {
char val[255];
getLuaVMUservalue(L, user) = (char*)user;
snprintf(key, sizeof(key), CONST_STR_USER_NETS, user);
if((ntop->getRedis()->get(key, val, sizeof(val)) != -1)
&& (val[0] != '\0')) {
ptree.addAddresses(val);
getLuaVMUservalue(L, allowedNets) = &ptree;
// ntop->getTrace()->traceEvent(TRACE_WARNING, "SET [p: %p][val: %s][user: %s]", &ptree, val, user);
}
snprintf(key, sizeof(key), CONST_STR_USER_LANGUAGE, user);
if((ntop->getRedis()->get(key, val, sizeof(val)) != -1)
&& (val[0] != '\0')) {
lua_pushstring(L, val);
} else {
lua_pushstring(L, NTOP_DEFAULT_USER_LANG);
}
lua_setglobal(L, CONST_USER_LANGUAGE);
}
getLuaVMUservalue(L, group) = (char*)(group ? (group) : "");
getLuaVMUservalue(L, localuser) = localuser;
iface = ntop->getNetworkInterface(ifname); /* Can't be null */
/* 'select' ther interface that has already been set into the _SESSION */
getLuaVMUservalue(L,iface) = iface;
if(is_interface_allowed)
getLuaVMUservalue(L, allowed_ifname) = iface->get_name();
#ifndef NTOPNG_PRO
rc = luaL_dofile(L, script_path);
#else
if(ntop->getPro()->has_valid_license())
rc = __ntop_lua_handlefile(L, script_path, true);
else
rc = luaL_dofile(L, script_path);
#endif
if(rc != 0) {
const char *err = lua_tostring(L, -1);
ntop->getTrace()->traceEvent(TRACE_WARNING, "Script failure [%s][%s]", script_path, err);
return(send_error(conn, 500 /* Internal server error */,
"Internal server error", PAGE_ERROR, script_path, err));
}
return(CONST_LUA_OK);
}
/* ****************************************** */
void LuaEngine::setHost(Host* h) {
struct ntopngLuaContext *c = getLuaVMContext(L);
if(c) c->host = h;
}
/* ****************************************** */
void LuaEngine::setNetwork(NetworkStats* ns) {
struct ntopngLuaContext *c = getLuaVMContext(L);
if(c) c->network = ns;
}
/* ****************************************** */
void LuaEngine::setFlow(Flow* f) {
struct ntopngLuaContext *c = getLuaVMContext(L);
if(c) c->flow = f;
}