diff --git a/include/NetworkInterface.h b/include/NetworkInterface.h index 747cc0bdc0..4b0d55bc67 100644 --- a/include/NetworkInterface.h +++ b/include/NetworkInterface.h @@ -378,10 +378,7 @@ class NetworkInterface { u_int32_t asnFilter, int16_t networkFilter, u_int16_t pool_filter, bool filtered_hosts, u_int8_t ipver_filter, bool hostsOnly, char *groupColumn); - int getActiveASList(lua_State* vm, - char *sortColumn, u_int32_t maxHits, - u_int32_t toSkip, bool a2zSortOrder, - DetailsLevel details_level); + int getActiveASList(lua_State* vm, const Paginator *p); int getActiveVLANList(lua_State* vm, char *sortColumn, u_int32_t maxHits, u_int32_t toSkip, bool a2zSortOrder, diff --git a/include/Paginator.h b/include/Paginator.h index 2eb0abecb1..c5c3cfc148 100644 --- a/include/Paginator.h +++ b/include/Paginator.h @@ -36,6 +36,7 @@ class Paginator { u_int16_t vlan_id_filter; u_int8_t ip_version /* Either 4 or 6 */; int8_t unicast_traffic, unidirectional_traffic, alerted_flows, filtered_flows; + u_int32_t client_asn, server_asn; u_int32_t deviceIP; u_int16_t inIndex, outIndex; u_int16_t pool_filter; @@ -116,6 +117,14 @@ class Paginator { if(server_mode) { (*f) = server_mode; return true; } return false; } + inline bool clientASN(u_int32_t *f) const { + if(client_asn != (u_int32_t)-1) { (*f) = client_asn; return true; } return false; + } + + inline bool serverASN(u_int32_t *f) const { + if(server_asn != (u_int32_t)-1) { (*f) = server_asn; return true; } return false; + } + inline bool unidirectionalTraffic(bool *f) const { if(unidirectional_traffic != -1) { (*f) = (unidirectional_traffic==1) ? true : false; return true; } return false; } diff --git a/scripts/callbacks/5min.lua b/scripts/callbacks/5min.lua index 44c4dca51b..7784349345 100644 --- a/scripts/callbacks/5min.lua +++ b/scripts/callbacks/5min.lua @@ -237,7 +237,7 @@ callback_utils.foreachInterface(ifnames, interface_rrd_creation_enabled, functio if asn_rrd_creation == "1" then local basedir = fixPath(dirs.workingdir .. "/" .. ifstats.id..'/asnstats') - local asn_info = interface.getASesInfo() + local asn_info = interface.getASesInfo({detailsLevel = "higher"}) for _, asn_stats in ipairs(asn_info["ASes"]) do local asn = asn_stats["asn"] diff --git a/scripts/locales/en.lua b/scripts/locales/en.lua index 5d5fa56820..e3d2d4d081 100644 --- a/scripts/locales/en.lua +++ b/scripts/locales/en.lua @@ -83,6 +83,7 @@ local en = { mac_address = "MAC Address", as_number = "AS number", asn = "ASN", + as = "AS", peers = "Peers", activities = "Activities", dns = "DNS", @@ -171,6 +172,9 @@ local en = { all_outIfIdx = "All Output Interfaces", vlan = "VLAN", all_vlan_ids = "All VLANs", + client_as = "Client AS", + server_as = "Server AS", + all_ases = "All ASes", actual_throughput = "Actual Thpt", total_bytes = "Total Bytes", applications = "Applications", diff --git a/scripts/lua/flows_stats.lua b/scripts/lua/flows_stats.lua index 81830a0934..4af2475558 100644 --- a/scripts/lua/flows_stats.lua +++ b/scripts/lua/flows_stats.lua @@ -42,6 +42,9 @@ local port = _GET["port"] local network_id = _GET["network"] +local client_asn = _GET["client_asn"] +local server_asn = _GET["server_asn"] + local prefs = ntop.getPrefs() interface.select(ifname) local ifstats = interface.getStats() @@ -151,6 +154,14 @@ if(network_id ~= nil) then page_params["network"] = network_id end +if(client_asn ~= nil) then + page_params["client_asn"] = client_asn +end + +if(server_asn ~= nil) then + page_params["server_asn"] = server_asn +end + if(flowhosts_type ~= nil) then page_params["flowhosts_type"] = flowhosts_type flowhosts_type_filter = '' @@ -217,7 +228,6 @@ local function printDropdownEntries(entries, param_arr, param_filter, curr_filte print[[>]] print(htype[2]) print[[]] end end - print[['\
\ \ @@ -319,6 +329,11 @@ end if ntop.isPro() and interface.isPacketInterface() == false then printFlowDevicesFilterDropdown(base_url, vlan_params) end + +if ntop.isEnterprise() then + printFlowASesFilterDropdown(base_url, table.clone(page_params)) +end + -- end buttons print(" ],\n") diff --git a/scripts/lua/get_ases_data.lua b/scripts/lua/get_ases_data.lua index f26124f00b..cdc3cf956e 100644 --- a/scripts/lua/get_ases_data.lua +++ b/scripts/lua/get_ases_data.lua @@ -55,8 +55,9 @@ to_skip = (currentPage-1) * perPage if(sortOrder == "desc") then sOrder = false else sOrder = true end -local ases_stats = interface.getASesInfo(sortColumn, perPage, to_skip, sOrder, - false --[[high, but not higher details as there's no need for nDPI here --]]) +local ases_stats = interface.getASesInfo({sortColumn = sortColumn, + maxHits = perPage, toSkip = to_skip, + a2zSortOrder = sOrder, detailsLevel = "high"}) local total_rows = 0 diff --git a/scripts/lua/get_flows_data.lua b/scripts/lua/get_flows_data.lua index 0f6f42d84d..d809b87d7b 100644 --- a/scripts/lua/get_flows_data.lua +++ b/scripts/lua/get_flows_data.lua @@ -32,6 +32,9 @@ local deviceIP = _GET["deviceIP"] local inIfIdx = _GET["inIfIdx"] local outIfIdx = _GET["outIfIdx"] +local client_asn = _GET["client_asn"] +local server_asn = _GET["server_asn"] + local vhost = _GET["vhost"] local flowhosts_type = _GET["flowhosts_type"] local ipversion = _GET["version"] @@ -167,6 +170,14 @@ if not isEmptyString(deviceIP) then end end +if not isEmptyString(client_asn) then + pageinfo["clientASNFilter"] = tonumber(client_asn) +end + +if not isEmptyString(server_asn) then + pageinfo["serverASNFilter"] = tonumber(server_asn) +end + local flows_stats = interface.getFlowsInfo(host, pageinfo) local total = flows_stats["numFlows"] flows_stats = flows_stats["flows"] diff --git a/scripts/lua/modules/http_lint.lua b/scripts/lua/modules/http_lint.lua index 1a0828f887..ab60a3169c 100644 --- a/scripts/lua/modules/http_lint.lua +++ b/scripts/lua/modules/http_lint.lua @@ -770,6 +770,8 @@ local known_parameters = { ["alert_severity"] = validateNumber, -- An alert severity enum ["entity"] = validateNumber, -- An alert entity type ["asn"] = validateNumber, -- An ASN number + ["client_asn"] = validateNumber, -- A client ASN number + ["server_asn"] = validateNumber, -- A server ASN number ["module"] = validateTopModule, -- A top script module ["step"] = validateNumber, -- A step value ["cf"] = validateConsolidationFunction, -- An RRD consolidation function diff --git a/scripts/lua/modules/lua_utils.lua b/scripts/lua/modules/lua_utils.lua index 29439753a0..8758d18a98 100644 --- a/scripts/lua/modules/lua_utils.lua +++ b/scripts/lua/modules/lua_utils.lua @@ -402,6 +402,59 @@ end -- ############################################## +function printFlowASesFilterDropdown(base_url, page_params) + if(ntop.isEnterprise()) then + package.path = dirs.installdir .. "/pro/scripts/lua/modules/?.lua;" .. package.path + end + + local ases = interface.getASesInfo({sortColumn = "column_asn", detailsLevel = "normal"}) + + if ases == nil then ases = {ASes = {}} end + + for _, p in ipairs({ + {side = "server_asn", title = i18n("flows_page.server_as")}, + {side = "client_asn", title = i18n("flows_page.client_as")}} + ) do + + local side = p["side"] + local title = p["title"] + + local cur_as = _GET[side] + local cur_as_filter = '' + if not isEmptyString(cur_as) then + cur_as_filter = '' + end + + local as_params = table.clone(page_params) + as_params[side] = nil + + print[[, '
\ + \ + \ +
']] + + end + +end + +-- ############################################## + -- -- Returns indexes to be used for string shortening. The portion of to_shorten between -- middle_start and middle_end will be inside the bounds. diff --git a/src/AutonomousSystem.cpp b/src/AutonomousSystem.cpp index 2bcb3eab84..28c232b103 100644 --- a/src/AutonomousSystem.cpp +++ b/src/AutonomousSystem.cpp @@ -76,16 +76,16 @@ void AutonomousSystem::lua(lua_State* vm, DetailsLevel details_level, bool asLis if(details_level >= details_high) { ((GenericTrafficElement*)this)->lua(vm, true); + lua_push_int_table_entry(vm, "seen.first", first_seen); + lua_push_int_table_entry(vm, "seen.last", last_seen); + lua_push_int_table_entry(vm, "duration", get_duration()); + + lua_push_int_table_entry(vm, "num_hosts", getNumHosts()); + if(details_level >= details_higher) if(ndpiStats) ndpiStats->lua(iface, vm); } - lua_push_int_table_entry(vm, "seen.first", first_seen); - lua_push_int_table_entry(vm, "seen.last", last_seen); - lua_push_int_table_entry(vm, "duration", get_duration()); - - lua_push_int_table_entry(vm, "num_hosts", getNumHosts()); - if(asListElement) { lua_pushnumber(vm, asn); lua_insert(vm, -2); diff --git a/src/Lua.cpp b/src/Lua.cpp index 0cb8ed2b75..23f4a9d969 100644 --- a/src/Lua.cpp +++ b/src/Lua.cpp @@ -882,37 +882,25 @@ static int ntop_get_mac_device_types(lua_State* vm) { static int ntop_get_interface_ases_info(lua_State* vm) { NetworkInterface *ntop_interface = getCurrentInterface(vm); - char *sortColumn = (char*)"column_asn"; - 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); + Paginator *p = NULL; - 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->getActiveASList(vm, - sortColumn, maxHits, - toSkip, a2zSortOrder, details_level) < 0) + 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 || + ntop_interface->getActiveASList(vm, p) < 0) { + if(p) delete(p); + return(CONST_LUA_ERROR); + } + + if(p) delete(p); return(CONST_LUA_OK); } diff --git a/src/NetworkInterface.cpp b/src/NetworkInterface.cpp index 57a0d8aee7..3f5d670aa5 100644 --- a/src/NetworkInterface.cpp +++ b/src/NetworkInterface.cpp @@ -2930,6 +2930,7 @@ static bool flow_matches(Flow *f, struct flowHostRetriever *retriever) { LocationPolicy client_policy; LocationPolicy server_policy; bool unicast, unidirectional, alerted_flows; + u_int32_t client_asn, server_asn; u_int32_t deviceIP; u_int16_t inIndex, outIndex; #ifdef NTOPNG_PRO @@ -2967,6 +2968,16 @@ static bool flow_matches(Flow *f, struct flowHostRetriever *retriever) { return(false); } + if(retriever->pag + && retriever->pag->clientASN(&client_asn) + && (!f->get_cli_host() || f->get_cli_host()->get_asn() != client_asn)) + return(false); + + if(retriever->pag + && retriever->pag->serverASN(&server_asn) + && (!f->get_srv_host() || f->get_srv_host()->get_asn() != server_asn)) + return(false); + if(retriever->pag && retriever->pag->portFilter(&port) && f->get_cli_port() != port @@ -5601,33 +5612,37 @@ int NetworkInterface::getActiveMacList(lua_State* vm, /* **************************************** */ -int NetworkInterface::getActiveASList(lua_State* vm, - char *sortColumn, u_int32_t maxHits, - u_int32_t toSkip, bool a2zSortOrder, - DetailsLevel details_level) { +int NetworkInterface::getActiveASList(lua_State* vm, const Paginator *p) { struct flowHostRetriever retriever; + DetailsLevel details_level; + + if(!p) + return -1; disablePurge(false); - if(sortASes(&retriever, sortColumn) < 0) { + if(sortASes(&retriever, p->sortColumn()) < 0) { enablePurge(false); return -1; } + if(!p->getDetailsLevel(&details_level)) + details_level = details_normal; + lua_newtable(vm); lua_push_int_table_entry(vm, "numASes", retriever.actNumEntries); lua_newtable(vm); - if(a2zSortOrder) { - for(int i = toSkip, num=0; i<(int)retriever.actNumEntries && num < (int)maxHits; i++, num++) { + if(p->a2zSortOrder()) { + for(int i = p->toSkip(), num = 0; i < (int)retriever.actNumEntries && num < (int)p->maxHits(); i++, num++) { AutonomousSystem *as = retriever.elems[i].asValue; as->lua(vm, details_level, false); lua_rawseti(vm, -2, num + 1); /* Must use integer keys to preserve and iterate inorder with ipairs */ } } else { - for(int i = (retriever.actNumEntries-1-toSkip), num=0; i >= 0 && num < (int)maxHits; i--, num++) { + for(int i = (retriever.actNumEntries - 1 - p->toSkip()), num = 0; i >= 0 && num < (int)p->maxHits(); i--, num++) { AutonomousSystem *as = retriever.elems[i].asValue; as->lua(vm, details_level, false); diff --git a/src/Paginator.cpp b/src/Paginator.cpp index 2685ec210c..4903b24cb4 100644 --- a/src/Paginator.cpp +++ b/src/Paginator.cpp @@ -51,6 +51,7 @@ Paginator::Paginator() { mac_filter = NULL; deviceIP = inIndex = outIndex = 0; + client_asn = server_asn = (u_int32_t)-1; details_level = details_normal; details_level_set = false; @@ -164,6 +165,11 @@ void Paginator::readOptions(lua_State *L, int index) { ip_version = lua_tointeger(L, -1); else if(!strcmp(key, "poolFilter")) pool_filter = lua_tointeger(L, -1); + else if(!strcmp(key, "clientASNFilter")) + client_asn = lua_tointeger(L, -1); + else if(!strcmp(key, "serverASNFilter")) + server_asn = lua_tointeger(L, -1); + //else //ntop->getTrace()->traceEvent(TRACE_ERROR, "Invalid int type (%d) for option %s", lua_tointeger(L, -1), key); break;