mirror of
https://github.com/ntop/ntopng.git
synced 2026-04-28 23:19:33 +00:00
247 lines
8 KiB
Lua
247 lines
8 KiB
Lua
--
|
|
-- (C) 2013-20 - ntop.org
|
|
--
|
|
|
|
dirs = ntop.getDirs()
|
|
package.path = dirs.installdir .. "/scripts/lua/modules/?.lua;" .. package.path
|
|
require "lua_utils"
|
|
require "db_utils"
|
|
local json = require ("dkjson")
|
|
|
|
sendHTTPContentTypeHeader('text/html')
|
|
|
|
ifid = getInterfaceId(ifname)
|
|
|
|
local prefs = ntop.getPrefs()
|
|
|
|
-- query parameters
|
|
local epoch_start = _GET["epoch_begin"]
|
|
local epoch_end = _GET["epoch_end"]
|
|
|
|
-- use this two params to see statistics of a single host
|
|
-- or for a pair of them
|
|
local peer1 = _GET["peer1"]
|
|
local peer2 = _GET["peer2"]
|
|
if peer2 and not peer1 then
|
|
peer1 = peer2
|
|
peer2 = nil
|
|
end
|
|
|
|
-- this is to retrieve L7 application data
|
|
local l7_proto_id = _GET["l7_proto_id"]
|
|
|
|
-- and this to focus only on a certain l4 proto
|
|
local l4_proto_id = _GET["l4_proto_id"]
|
|
|
|
-- also add a port
|
|
local port = _GET["port"]
|
|
|
|
local vlan = _GET["vlan"]
|
|
local profile = _GET["profile"]
|
|
|
|
local host_info = url2hostinfo(_GET)
|
|
local host = nil
|
|
if host_info["host"] then
|
|
host = interface.getHostInfo(host_info["host"],host_info["vlan"])
|
|
end
|
|
|
|
|
|
-- specify the type of stats
|
|
local stats_type = _GET["stats_type"]
|
|
if stats_type == nil or (stats_type ~= "top_talkers" and stats_type ~= "top_applications") then
|
|
-- default to top traffic
|
|
stats_type = "top_talkers"
|
|
end
|
|
|
|
-- datatable parameters
|
|
local current_page = _GET["currentPage"]
|
|
local per_page = _GET["perPage"]
|
|
local sort_column = _GET["sortColumn"]
|
|
local sort_order = _GET["sortOrder"]
|
|
local total_rows = _GET["totalRows"]
|
|
|
|
if not sort_column or sort_column == "" then
|
|
sort_column = getDefaultTableSort("historical_stats_"..stats_type)
|
|
else
|
|
if sort_column ~= "column_" then
|
|
tablePreferences("sort_historical_stats_"..stats_type, sort_column)
|
|
end
|
|
end
|
|
|
|
tablePreferences("sort_order_historical_stats_"..stats_type,sort_order)
|
|
--[[
|
|
if not sort_order or sort_order == "" then
|
|
sort_order = getDefaultTableSortOrder("historical_stats_"..stats_type)
|
|
io.write('got by default '..sort_order..'\n')
|
|
else
|
|
tablePreferences("sort_order_historical_stats_"..stats_type,sort_order)
|
|
end
|
|
]]
|
|
|
|
if sort_order == "asc" then
|
|
funct = asc
|
|
else
|
|
funct = rev
|
|
end
|
|
|
|
if current_page == nil then
|
|
current_page = 1
|
|
else
|
|
current_page = tonumber(current_page)
|
|
end
|
|
|
|
if per_page == nil then
|
|
per_page = getDefaultTableSize()
|
|
else
|
|
per_page = tonumber(per_page)
|
|
tablePreferences("historical_rows_number", per_page)
|
|
end
|
|
local to_skip = (current_page - 1) * per_page
|
|
if to_skip < 0 then to_skip = 0 end
|
|
|
|
-- prepare queries offset an limit depending on
|
|
-- received values. A received value total_rows = -1 (or total_rows == nil)
|
|
-- means that the interface doesn't know the number of rows
|
|
-- and thus it is up to this script to compute it, and
|
|
-- send it back to the caller
|
|
|
|
if total_rows == nil or tonumber(total_rows) == nil then
|
|
total_rows = -1
|
|
else
|
|
total_rows = tonumber(total_rows)
|
|
end
|
|
|
|
-- default: 100 rows starting from offset 0
|
|
local offset = 0
|
|
local limit = 100
|
|
if total_rows ~= -1 then
|
|
offset = to_skip
|
|
limit = per_page
|
|
end
|
|
|
|
-- start building the response
|
|
local res = {["status"] = "unable to parse the request, please check input parameters."}
|
|
if stats_type == "top_talkers" then
|
|
if not peer1 and not peer2 and not l7_proto_id then
|
|
-- CASE 01: compute interface-wide top-talkers for the selected time interval
|
|
res = getOverallTopTalkers(ifid, l4_proto_id, port, vlan, profile, nil, epoch_start, epoch_end, sort_column, sort_order, offset, limit)
|
|
for _, record in pairs(res) do
|
|
local hinfo = hostkey2hostinfo(record["addr"])
|
|
record["label"] = host2name(hinfo["host"], hinfo["vlan"])
|
|
end
|
|
elseif not peer1 and not peer2 and l7_proto_id and l7_proto_id ~= "" then
|
|
-- CASE 02: compute top-talkers for the specified L7 protocol
|
|
res = getAppTopTalkers(ifid, l7_proto_id, l4_proto_id, port, vlan, profile, nil, epoch_start, epoch_end, sort_column, sort_order, offset, limit)
|
|
|
|
for _, record in pairs(res) do
|
|
local hinfo = hostkey2hostinfo(record["addr"])
|
|
record["label"] = host2name(hinfo["host"], hinfo["vlan"])
|
|
end
|
|
elseif peer1 and peer1 ~="" then
|
|
-- CASE 03: compute top-talkers with the given peer1
|
|
-- if l7_proto_id is specified and non-nil, then top-talkers are computed
|
|
-- with reference to peer1 and restricted to the application identified by l7_proto_id
|
|
res = getHostTopTalkers(ifid, peer1, l7_proto_id, l4_proto_id, port, vlan, profile, nil, epoch_start, epoch_end, sort_column, sort_order, offset, limit)
|
|
|
|
for _, record in pairs(res) do
|
|
local hinfo = hostkey2hostinfo(record["addr"])
|
|
record["label"] = host2name(hinfo["host"], hinfo["vlan"])
|
|
end
|
|
-- tprint(res)
|
|
end
|
|
if res ~= nil then
|
|
for _, record in pairs(res) do
|
|
record["label"] = shortenString(record["label"])
|
|
end
|
|
end
|
|
elseif stats_type =="top_applications" then
|
|
res = getTopApplications(ifid, peer1, peer2, l7_proto_id, l4_proto_id, port, vlan, profile, nil, epoch_start, epoch_end, sort_column, sort_order, offset, limit)
|
|
|
|
-- add protocol labels
|
|
for _, record in pairs(res) do
|
|
record["label"] = getApplicationLabel(interface.getnDPIProtoName(tonumber(record["application"])))
|
|
end
|
|
if res ~= nil then
|
|
for _, record in pairs(res) do
|
|
end
|
|
end
|
|
-- tprint(res)
|
|
end
|
|
|
|
-- slice the result if the interface didn't know the total_rows
|
|
local res_sliced = {}
|
|
if total_rows ~= -1 then
|
|
-- nothing to slice here, query has already sliced the result
|
|
res_sliced = res
|
|
else -- i.e., total_rows == -1, that it, it was unknown
|
|
-- slice the first page of the results
|
|
-- and update total_rows
|
|
local cur = 0
|
|
for _, record in pairs(res) do
|
|
if cur < per_page then
|
|
table.insert(res_sliced, record)
|
|
end
|
|
cur = cur + 1
|
|
end
|
|
total_rows = cur
|
|
end
|
|
|
|
-- make res_formatted compliant with column_ notation
|
|
-- also add hyperlinks, bytes format, etc.
|
|
local res_formatted = {}
|
|
for _, record in pairs(res_sliced) do
|
|
local record_contents = {}
|
|
if not record["label"] or record["label"] == "" then record["label"] = record["addr"] end
|
|
record_contents["column_label"] = record["label"]
|
|
record_contents["column_addr"] = record["addr"]
|
|
if record["application"] then record_contents["column_application"] = record["application"] end
|
|
-- 'normalize' possible different names, e.g., group bytes or tot_bytes in bytes
|
|
-- and rename fields with the 'column_' prefix that is conventionally used in the interface
|
|
if record["bytes"] then
|
|
record_contents["column_bytes"] = bytesToSize(tonumber(record["bytes"]))
|
|
elseif record["tot_bytes"] then
|
|
record_contents["column_bytes"] = bytesToSize(tonumber(record["tot_bytes"]))
|
|
else
|
|
record_contents["column_bytes"] = "n.a."
|
|
end
|
|
if record["packets"] then
|
|
record_contents["column_packets"] = formatValue(tonumber(record["packets"]))
|
|
elseif record["tot_packets"] then
|
|
record_contents["column_packets"] = formatValue(tonumber(record["tot_packets"]))
|
|
else
|
|
record_contents["column_packets"] = "n.a."
|
|
end
|
|
if record["bytes_sent"] then
|
|
record_contents["column_bytes_sent"] = bytesToSize(tonumber(record["bytes_sent"]))
|
|
else
|
|
record_contents["column_bytes_sent"] = "n.a."
|
|
end
|
|
if record["bytes_rcvd"] then
|
|
record_contents["column_bytes_rcvd"] = bytesToSize(tonumber(record["bytes_rcvd"]))
|
|
else
|
|
record_contents["column_bytes_rcvd"] = "n.a."
|
|
end
|
|
if record["flows"] then
|
|
record_contents["column_flows"] = formatValue(tonumber(record["flows"]))
|
|
elseif record["tot_flows"] then
|
|
record_contents["column_flows"] = formatValue(tonumber(record["tot_flows"]))
|
|
else
|
|
record_contents["column_flows"] = "n.a."
|
|
end
|
|
if record["avg_flow_duration"] then
|
|
record_contents["column_avg_flow_duration"] = secondsToTime(tonumber(record["avg_flow_duration"]))
|
|
end
|
|
table.insert(res_formatted, record_contents)
|
|
end
|
|
|
|
-- tprint(res_formatted)
|
|
-- tprint(res)
|
|
|
|
local result = {}
|
|
result["perPage"] = per_page
|
|
result["currentPage"] = current_page
|
|
result["totalRows"] = total_rows
|
|
result["data"] = res_formatted
|
|
result["sort"] = {{sort_column, sort_order}}
|
|
|
|
print(json.encode(result, nil))
|