mirror of
https://github.com/ntop/ntopng.git
synced 2026-04-30 16:09:32 +00:00
The user scripts configuration can now be configured from the "User Scripts" entry under the cog icon. It allows the creation of multiple configuration presets to be applied to hosts, networks and interfaces.
2204 lines
87 KiB
Lua
2204 lines
87 KiB
Lua
--
|
|
-- (C) 2013-19 - ntop.org
|
|
--
|
|
|
|
local dirs = ntop.getDirs()
|
|
package.path = dirs.installdir .. "/scripts/lua/modules/?.lua;" .. package.path
|
|
if((dirs.scriptdir ~= nil) and (dirs.scriptdir ~= "")) then package.path = dirs.scriptdir .. "/lua/modules/?.lua;" .. package.path end
|
|
active_page = "if_stats"
|
|
|
|
if ntop.isPro() then
|
|
package.path = dirs.installdir .. "/scripts/lua/pro/modules/?.lua;" .. package.path
|
|
package.path = dirs.installdir .. "/pro/scripts/callbacks/?.lua;" .. package.path
|
|
require "snmp_utils"
|
|
end
|
|
|
|
local json = require "dkjson"
|
|
local host_pools_utils = require "host_pools_utils"
|
|
local template = require "template_utils"
|
|
local os_utils = require "os_utils"
|
|
local format_utils = require "format_utils"
|
|
local top_talkers_utils = require "top_talkers_utils"
|
|
local internals_utils = require "internals_utils"
|
|
local page_utils = require("page_utils")
|
|
|
|
require "lua_utils"
|
|
require "prefs_utils"
|
|
require "graph_utils"
|
|
require "alert_utils"
|
|
require "db_utils"
|
|
local ts_utils = require "ts_utils"
|
|
local recording_utils = require "recording_utils"
|
|
local companion_interface_utils = require "companion_interface_utils"
|
|
local storage_utils = require "storage_utils"
|
|
|
|
local have_nedge = ntop.isnEdge()
|
|
|
|
if ntop.isPro() then
|
|
shaper_utils = require("shaper_utils")
|
|
end
|
|
|
|
sendHTTPContentTypeHeader('text/html')
|
|
|
|
page = _GET["page"]
|
|
ifid = _GET["ifid"]
|
|
|
|
ifname_clean = "iface_"..tostring(ifid)
|
|
msg = ""
|
|
|
|
local disaggregation_criterion_key = "ntopng.prefs.dynamic_sub_interfaces.ifid_"..tostring(ifid)..".mode"
|
|
|
|
function inline_input_form(name, placeholder, tooltip, value, can_edit, input_opts, input_class)
|
|
if(can_edit) then
|
|
print('<input style="width:12em;" title="'..tooltip..'" '..(input_opts or "")..' class="form-control '..(input_class or "")..'" name="'..name..'" placeholder="'..placeholder..'" value="')
|
|
if(value ~= nil) then print(value.."") end
|
|
print[[">]]
|
|
else
|
|
if(value ~= nil) then print(value) end
|
|
end
|
|
end
|
|
|
|
function inline_select_form(name, keys, values, curval)
|
|
print[[<select class="form-control" style="width:12em; display:inline;" name="]] print(name) print[[">]]
|
|
for idx, k in ipairs(keys) do
|
|
local v = values[idx]
|
|
print[[<option value="]] print(v) print[[" ]]
|
|
|
|
if curval == v then
|
|
print("selected")
|
|
end
|
|
|
|
print[[>]] print(k) print[[</option>]]
|
|
end
|
|
print[[</select>]]
|
|
end
|
|
|
|
-- parse interface names and possibly fall back to the selected interface:
|
|
-- priority goes to the interface id
|
|
if ifid ~= nil and ifid ~= "" then
|
|
if_name = getInterfaceName(ifid)
|
|
else
|
|
-- fall-back to the default interface
|
|
if_name = ifname
|
|
ifid = interface.name2id(ifname)
|
|
end
|
|
|
|
interface.select(ifname)
|
|
|
|
local is_packet_interface = interface.isPacketInterface()
|
|
local is_pcap_dump = interface.isPcapDumpInterface()
|
|
|
|
local ifstats = interface.getStats()
|
|
|
|
-- this is a user-browseable page, so we must return counters from
|
|
-- the latest reset as the user may have chosen to reset statistics at some point
|
|
if ifstats.stats and ifstats.stats_since_reset then
|
|
-- override stats with the values calculated from the latest user reset
|
|
for k, v in pairs(ifstats.stats_since_reset) do
|
|
ifstats.stats[k] = v
|
|
end
|
|
end
|
|
|
|
if ifstats.zmqRecvStats and ifstats.zmqRecvStats_since_reset then
|
|
-- override stats with the values calculated from the latest user reset
|
|
for k, v in pairs(ifstats.zmqRecvStats_since_reset) do
|
|
ifstats.zmqRecvStats[k] = v
|
|
end
|
|
end
|
|
|
|
local ext_interfaces = {}
|
|
|
|
-- refresh traffic recording availability as one may have installed n2disk
|
|
-- with a running instance of ntopng
|
|
recording_utils.checkAvailable()
|
|
|
|
if recording_utils.isAvailable() and recording_utils.isSupportedZMQInterface(ifid) then
|
|
ext_interfaces = recording_utils.getExtInterfaces(ifid)
|
|
end
|
|
|
|
if (isAdministrator()) then
|
|
if (page == "config") and (not table.empty(_POST)) then
|
|
local custom_name = _POST["custom_name"]
|
|
|
|
if starts(custom_name, "tcp:__") then
|
|
-- Was mangled by sanitization
|
|
custom_name = "tcp://" .. string.sub(custom_name, 7)
|
|
end
|
|
|
|
-- TODO move keys to new schema: replace ifstats.name with ifid
|
|
ntop.setCache('ntopng.prefs.'..ifstats.name..'.name', custom_name)
|
|
|
|
local ifspeed_cache = 'ntopng.prefs.'..ifstats.name..'.speed'
|
|
if isEmptyString(_POST["ifSpeed"]) then
|
|
ntop.delCache(ifspeed_cache)
|
|
else
|
|
ntop.setCache(ifspeed_cache, _POST["ifSpeed"])
|
|
end
|
|
|
|
local hide_set = getHideFromTopSet(ifstats.id)
|
|
ntop.delCache(hide_set)
|
|
|
|
for _, net in pairs(split(_POST["hide_from_top"] or "", ",")) do
|
|
net = trimSpace(net)
|
|
|
|
if not isEmptyString(net) then
|
|
local address, prefix, vlan = splitNetworkWithVLANPrefix(net)
|
|
|
|
if isIPv6(address) and prefix == "128" then
|
|
net = address
|
|
elseif isIPv4(address) and prefix == "32" then
|
|
net = address
|
|
end
|
|
|
|
ntop.setMembersCache(hide_set, net)
|
|
end
|
|
end
|
|
|
|
interface.reloadHideFromTop()
|
|
|
|
setInterfaceRegreshRate(ifstats.id, tonumber(_POST["ifRate"]))
|
|
|
|
local sf = tonumber(_POST["scaling_factor"])
|
|
if(sf == nil) then sf = 1 end
|
|
ntop.setCache(getRedisIfacePrefix(ifid)..'.scaling_factor',tostring(sf))
|
|
interface.loadScalingFactorPrefs()
|
|
end
|
|
end
|
|
|
|
page_utils.print_header(i18n("interface_ifname", { ifname=if_name }))
|
|
|
|
print("<link href=\""..ntop.getHttpPrefix().."/css/tablesorted.css\" rel=\"stylesheet\">")
|
|
|
|
dofile(dirs.installdir .. "/scripts/lua/inc/menu.lua")
|
|
|
|
print(msg)
|
|
|
|
if _SERVER["REQUEST_METHOD"] == "POST" and _POST["companion_interface"] ~= nil then
|
|
companion_interface_utils.setCompanion(ifstats.id, _POST["companion_interface"])
|
|
end
|
|
|
|
if _SERVER["REQUEST_METHOD"] == "POST" and _POST["disaggregation_criterion"] ~= nil then
|
|
if _POST["disaggregation_criterion"] == "none" then
|
|
ntop.delCache(disaggregation_criterion_key)
|
|
else
|
|
ntop.setCache(disaggregation_criterion_key, _POST["disaggregation_criterion"])
|
|
end
|
|
end
|
|
|
|
if _SERVER["REQUEST_METHOD"] == "POST" and not isEmptyString(_POST["traffic_recording_provider"]) then
|
|
local prev_provider = recording_utils.getCurrentTrafficRecordingProvider(ifstats.id)
|
|
|
|
-- if the current provider is the builtin ntopng and we are changing to another provider
|
|
-- then it may be necessary to stop the builtin ntopng
|
|
if prev_provider == "ntopng" and _POST["traffic_recording_provider"] ~= "ntopng" then
|
|
recording_utils.stop(ifstats.id)
|
|
ntop.setCache('ntopng.prefs.ifid_'..ifstats.id..'.traffic_recording.enabled', "false")
|
|
end
|
|
|
|
recording_utils.setCurrentTrafficRecordingProvider(ifstats.id, _POST["traffic_recording_provider"])
|
|
end
|
|
|
|
local has_traffic_recording_page = (recording_utils.isAvailable()
|
|
and (interface.isPacketInterface()
|
|
or ((recording_utils.isSupportedZMQInterface(ifid) and not table.empty(ext_interfaces)))
|
|
or (recording_utils.getCurrentTrafficRecordingProvider(ifid) ~= "ntopng")))
|
|
|
|
local dismiss_recording_providers_reminder = recording_utils.isExternalProvidersReminderDismissed(ifstats.id)
|
|
|
|
local num_pool_hosts = ifstats.num_members.num_hosts
|
|
if ifstats.num_members_per_pool[host_pools_utils.DEFAULT_POOL_ID] then
|
|
-- don't show unassigned hosts in the counter
|
|
num_pool_hosts = num_pool_hosts - ifstats.num_members_per_pool[host_pools_utils.DEFAULT_POOL_ID].num_hosts
|
|
end
|
|
|
|
|
|
local url = ntop.getHttpPrefix()..'/lua/if_stats.lua?ifid=' .. ifid
|
|
|
|
-- Added global javascript variable, in order to disable the refresh of pie chart in case
|
|
-- of historical interface
|
|
print('\n<script>var refresh = '..getInterfaceRefreshRate(ifstats.id)..' * 1000; /* ms */;</script>\n')
|
|
|
|
local short_name = getHumanReadableInterfaceName(ifname)
|
|
local title = i18n("interface") .. ": " .. short_name
|
|
page_utils.print_navbar(title, url,
|
|
{
|
|
{
|
|
hidden = only_historical,
|
|
active = page == "overview" or page == nil,
|
|
page_name = "overview",
|
|
label = "<i class=\"fas fa-lg fa-home\"></i>",
|
|
},
|
|
{
|
|
hidden = not interface.isPacketInterface() or ntop.isnEdge() or interface.isView(),
|
|
active = page == "networks",
|
|
page_name = "networks",
|
|
label = i18n("networks"),
|
|
},
|
|
{
|
|
hidden = not ifstats or ifstats.stats.packets == 0 or ntop.isnEdge(),
|
|
active = page == "packets",
|
|
page_name = "packets",
|
|
label = i18n("packets"),
|
|
},
|
|
{
|
|
active = page == "ndpi",
|
|
page_name = "ndpi",
|
|
label = i18n("applications"),
|
|
},
|
|
{
|
|
hidden = ntop.isnEdge(),
|
|
active = page == "ICMP",
|
|
page_name = "ICMP",
|
|
label = i18n("icmp"),
|
|
},
|
|
{
|
|
hidden = not ifstats or not ifstats["has_macs"] or ntop.isnEdge(),
|
|
active = page == "ARP",
|
|
page_name = "ARP",
|
|
label = i18n("arp"),
|
|
},
|
|
{
|
|
hidden = not ts_utils.exists("iface:traffic", {ifid=ifid}),
|
|
active = page == "historical",
|
|
page_name = "historical",
|
|
label = "<i class='fas fa-lg fa-chart-area'></i>",
|
|
},
|
|
{
|
|
hidden = have_nedge or not ifstats or not ifstats.profiles,
|
|
active = page == "trafficprofiles",
|
|
page_name = "trafficprofiles",
|
|
label = "<i class=\"fas fa-lg fa-user-md\"></i>",
|
|
},
|
|
{
|
|
hidden = not has_traffic_recording_page,
|
|
active = page == "traffic_recording",
|
|
page_name = "traffic_recording",
|
|
label = "<i class=\"fas fa-lg fa-hdd\"></i>",
|
|
},
|
|
{
|
|
hidden = not isAdministrator() or not areAlertsEnabled(),
|
|
active = page == "alerts",
|
|
page_name = "alerts",
|
|
label = "<i class=\"fas fa-lg fa-exclamation-triangle\"></i>",
|
|
},
|
|
{
|
|
hidden = is_pcap_dump or not ts_utils.getDriverName() == "rrd",
|
|
active = page == "traffic_report",
|
|
page_name = "traffic_report",
|
|
label = "<i class='fas fa-lg fa-file-alt report-icon'></i>",
|
|
},
|
|
{
|
|
hidden = not isAdministrator() or is_pcap_dump,
|
|
active = page == "config",
|
|
page_name = "config",
|
|
label = "<i class=\"fas fa-lg fa-cog\"></i></a></li>",
|
|
},
|
|
{
|
|
active = page == "internals",
|
|
page_name = "internals",
|
|
label = "<i class=\"fas fa-lg fa-wrench\"></i>",
|
|
},
|
|
{
|
|
hidden = not isAdministrator() or not ntop.isEnterprise() or ifstats.isDynamic or ifstats.isView,
|
|
active = page == "sub_interfaces",
|
|
page_name = "sub_interfaces",
|
|
label = "<i class=\"fas fa-lg fa-code-branch\"></i>",
|
|
},
|
|
{
|
|
hidden = not isAdministrator() or have_nedge,
|
|
active = page == "pools",
|
|
page_name = "pools",
|
|
label = "<i class=\"fas fa-lg fa-users\"></i>",
|
|
badge_num = num_pool_hosts,
|
|
},
|
|
{
|
|
hidden = not isAdministrator() or is_pcap_dump,
|
|
active = page == "dhcp",
|
|
page_name = "dhcp",
|
|
label = "<i class=\"fas fa-lg fa-bolt\"></i>",
|
|
},
|
|
}
|
|
)
|
|
|
|
if((page == "overview") or (page == nil)) then
|
|
local tags = {ifid = ifstats.id}
|
|
print("<table class=\"table table-striped table-bordered\">\n")
|
|
print("<tr><th width=15%>"..i18n("if_stats_overview.id").."</th><td colspan=6>" .. ifstats.id .. " ")
|
|
if(ifstats.description ~= ifstats.name) then print(" ("..ifstats.description..")") end
|
|
print("</td></tr>\n")
|
|
|
|
if not is_pcap_dump and ifstats["type"] ~= "netfilter" then
|
|
print("<tr><th width=250>"..i18n("if_stats_overview.state").."</th><td colspan=6>")
|
|
state = toggleTableButton("", "", i18n("if_stats_overview.active"), "1","primary", i18n("if_stats_overview.paused"), "0","primary", "toggle_local", "ntopng.prefs."..if_name.."_not_idle")
|
|
|
|
if(state == "0") then
|
|
on_state = true
|
|
else
|
|
on_state = false
|
|
end
|
|
|
|
interface.setInterfaceIdleState(on_state)
|
|
|
|
print("</td></tr>\n")
|
|
end
|
|
|
|
if(ifstats["remote.name"] ~= nil) then
|
|
local remote_if_addr, remote_probe_ip, remote_probe_public_ip = '', '', ''
|
|
local num_remote_flow_exports, num_remote_flow_exporters = '', ''
|
|
|
|
|
|
if not isEmptyString(ifstats["remote.if_addr"]) then
|
|
remote_if_addr = "<b>"..i18n("if_stats_overview.interface_ip").."</b>: "..ifstats["remote.if_addr"]
|
|
end
|
|
|
|
if not isEmptyString(ifstats["probe.ip"]) then
|
|
remote_probe_ip = "<b>"..i18n("if_stats_overview.probe_ip").."</b>: "..ifstats["probe.ip"]
|
|
end
|
|
|
|
if not isEmptyString(ifstats["probe.public_ip"]) then
|
|
remote_probe_public_ip = "<b>"..i18n("if_stats_overview.public_probe_ip").."</b>: <A HREF=\"http://"..ifstats["probe.public_ip"].."\">"..ifstats["probe.public_ip"].."</A> <i class='fas fa-external-link-alt'></i></td>\n"
|
|
end
|
|
|
|
if not isEmptyString(ifstats["zmq.num_flow_exports"]) then
|
|
num_remote_flow_exports = "<b>"..i18n("if_stats_overview.probe_zmq_num_flow_exports").."</b>: <span id=if_num_remote_zmq_flow_exports>"..formatValue(ifstats["zmq.num_flow_exports"]).."</span>"
|
|
end
|
|
|
|
if not isEmptyString(ifstats["zmq.num_exporters"]) then
|
|
num_remote_flow_exporters = "<b>"..i18n("if_stats_overview.probe_zmq_num_endpoints").."</b>: <span id=if_num_remote_zmq_exporters>"..formatValue(ifstats["zmq.num_exporters"]).."</span>"
|
|
end
|
|
|
|
local remote_ifname = ''
|
|
if ifstats["remote.name"] == "none" then
|
|
remote_ifname = i18n("if_stats_overview.remote_probe_collector_mode")
|
|
else
|
|
remote_ifname = string.format("<b>%s</b>: %s [%s]", i18n("if_stats_overview.interface_name"), ifstats["remote.name"], bitsToSize(ifstats.speed*1000000))
|
|
end
|
|
|
|
print("<tr><th rowspan=3>"..i18n("if_stats_overview.remote_probe").."</th><td nowrap>"..remote_ifname.."</td>")
|
|
print("<td nowrap>"..remote_if_addr.."</td>")
|
|
print("<td nowrap>"..remote_probe_ip.."</td>")
|
|
print("<td nowrap colspan=2>"..remote_probe_public_ip.."</td>\n")
|
|
print("</tr>\n")
|
|
|
|
print("<tr>")
|
|
local colspan = 4
|
|
|
|
if ifstats["timeout.lifetime"] > 0 then
|
|
print("<td nowrap><b>"..i18n("if_stats_overview.probe_timeout_lifetime").."</b>: "..secondsToTime(ifstats["timeout.lifetime"]).."</td>")
|
|
else
|
|
colspan = colspan - 1
|
|
end
|
|
if ifstats["timeout.idle"] > 0 then
|
|
print("<td nowrap><b>"..i18n("if_stats_overview.probe_timeout_idle").."</b>: "..secondsToTime(ifstats["timeout.idle"]).."</td>")
|
|
else
|
|
colspan = colspan - 1
|
|
end
|
|
|
|
print("<td nowrap colspan="..colspan..">"..num_remote_flow_exporters.."</td>")
|
|
print("</tr>")
|
|
|
|
local has_drops_export_queue_full = (tonumber(ifstats["zmq.drops.export_queue_full"]) and tonumber(ifstats["zmq.drops.export_queue_full"]) > 0)
|
|
local has_drops_flow_collection_drops = (tonumber(ifstats["zmq.drops.flow_collection_drops"]) or 0) > 0
|
|
local has_drops_flow_collection_udp_socket_drops = (tonumber(ifstats["zmq.drops.flow_collection_udp_socket_drops"]) or 0) > 0
|
|
local has_remote_drops = (has_drops_export_queue_full or has_drops_flow_collection_drops)
|
|
|
|
if not has_remote_drops then
|
|
print('<tr style="display: none;">')
|
|
else
|
|
print("<tr>")
|
|
local export_queue_full, flow_collection_drops
|
|
local colspan = 6
|
|
|
|
if has_drops_export_queue_full then
|
|
local num_full = tonumber(ifstats["zmq.drops.export_queue_full"])
|
|
local span_class = ' '
|
|
if num_full > 0 then
|
|
span_class = 'class="badge badge-danger"'
|
|
end
|
|
export_queue_full = "<b>"..i18n("if_stats_overview.probe_zmq_drops_export_queue_full").." <sup><i class='fas fa-info-circle' title='"..i18n("if_stats_overview.note_probe_zmq_drops_export_queue_full").."'></i></sup></b>: <span "..span_class.." id=if_zmq_drops_export_queue_full>"..formatValue(ifstats["zmq.drops.export_queue_full"]).."</span>"
|
|
end
|
|
|
|
if has_drops_flow_collection_drops then
|
|
local num_full = tonumber(ifstats["zmq.drops.flow_collection_drops"])
|
|
local span_class = ' '
|
|
if num_full > 0 then
|
|
span_class = 'class="badge badge-danger"'
|
|
end
|
|
flow_collection_drops = "<b>"..i18n("if_stats_overview.probe_zmq_drops_flow_collection_drops").." <sup><i class='fas fa-info-circle' title='"..i18n("if_stats_overview.note_probe_zmq_drops_flow_collection_drops").."'></i></sup></b>: <span "..span_class.." id=if_zmq_drops_flow_collection_drops>"..formatValue(ifstats["zmq.drops.flow_collection_drops"]).."</span>"
|
|
end
|
|
|
|
if has_drops_flow_collection_udp_socket_drops then
|
|
local num_full = tonumber(ifstats["zmq.drops.flow_collection_udp_socket_drops"])
|
|
local span_class = ' '
|
|
if num_full > 0 then
|
|
span_class = 'class="badge badge-danger"'
|
|
end
|
|
flow_collection_udp_socket_drops = "<b>"..i18n("if_stats_overview.probe_zmq_drops_flow_collection_udp_socket_drops").." <sup><i class='fas fa-info-circle' title='"..i18n("if_stats_overview.note_probe_zmq_drops_flow_collection_udp_socket_drops").."'></i></sup></b>: <span "..span_class.." id=if_zmq_drops_flow_collection_udp_socket_drops>"..formatValue(ifstats["zmq.drops.flow_collection_udp_socket_drops"]).."</span>"
|
|
end
|
|
|
|
if export_queue_full then
|
|
print("<td>"..export_queue_full.."</td>")
|
|
colspan = colspan - 1
|
|
end
|
|
if flow_collection_drops then
|
|
print("<td>"..flow_collection_drops.."</td>")
|
|
colspan = colspan - 1
|
|
end
|
|
if flow_collection_udp_socket_drops then
|
|
print("<td>"..flow_collection_udp_socket_drops.."</td>")
|
|
colspan = colspan - 1
|
|
end
|
|
if colspan then
|
|
print("<td colspan="..colspan.."></td>")
|
|
end
|
|
end
|
|
|
|
print("</tr>")
|
|
end
|
|
|
|
local is_physical_iface = (interface.isPacketInterface()) and (not is_pcap_dump)
|
|
|
|
local label = getHumanReadableInterfaceName(ifstats.name)
|
|
local s
|
|
if ((not isEmptyString(label)) and (label ~= ifstats.name)) then
|
|
s = label.." (" .. ifstats.name .. ")"
|
|
else
|
|
s = ifstats.name
|
|
end
|
|
|
|
if((isAdministrator()) and (not is_pcap_dump)) then
|
|
s = s .. " <a href=\""..url.."&page=config\"><i class=\"fas fa-cog fa-sm\" title=\"Configure Interface Name\"></i></a>"
|
|
end
|
|
|
|
print('<tr><th width="250">'..i18n("name")..'</th><td colspan="2">' .. s ..' </td>\n')
|
|
|
|
print("<th>"..i18n("if_stats_overview.family").."</th><td colspan=2>")
|
|
print(ifstats.type)
|
|
|
|
if(ifstats.inline) then
|
|
print(" "..i18n("if_stats_overview.in_path_interface"))
|
|
end
|
|
|
|
if(ifstats.has_traffic_directions) then
|
|
print(" ".. i18n("if_stats_overview.has_traffic_directions") .. " ")
|
|
end
|
|
print("</tr>")
|
|
|
|
if ifstats.encryption and ifstats.encryption.public_key then
|
|
print("<tr><th width=250>"..i18n("if_stats_overview.zmq_encryption_public_key").."</th><td colspan=6>")
|
|
print(ifstats.encryption.public_key)
|
|
print("<p><small> <b>"..i18n("if_stats_overview.note").."</b>: ".. i18n("if_stats_overview.zmq_encryption_public_key_note", {key=ifstats.encryption.public_key}).."</small>")
|
|
print("</td></tr>\n")
|
|
end
|
|
|
|
if is_physical_iface then
|
|
print("<tr>")
|
|
print("<th>"..i18n("mtu").."</th><td colspan=2 nowrap>"..ifstats.mtu.." "..i18n("bytes").."</td>\n")
|
|
local speed_key = 'ntopng.prefs.'..ifname..'.speed'
|
|
local speed = ntop.getCache(speed_key)
|
|
if (tonumber(speed) == nil) then
|
|
speed = ifstats.speed
|
|
end
|
|
print("<th width=250>"..i18n("speed").."</th><td colspan=2>" .. bitsToSize(speed * 1000000) .. "</td>")
|
|
print("</tr>")
|
|
end
|
|
|
|
if((ifstats.num_alerts_engaged > 0) or (ifstats.num_dropped_alerts > 0)) then
|
|
print("<tr>")
|
|
local warning = "<i class='fas fa-exclamation-triangle fa-lg' style='color: #B94A48;'></i> "
|
|
local engaged_alerts_chart_available = ts_utils.exists("iface:engaged_alerts", tags)
|
|
|
|
print("<th>".. ternary(ifstats.num_alerts_engaged > 0, warning, "") ..i18n("show_alerts.engaged_alerts")..
|
|
ternary(engaged_alerts_chart_available, " <A HREF='"..url.."&page=historical&ts_schema=iface:engaged_alerts'><i class='fas fa-chart-area fa-sm'></i></A>", "").."</th><td colspan=2 nowrap><a href='".. ntop.getHttpPrefix() .."/lua/show_alerts.lua?ifid="..ifstats.id.."'>".. formatValue(ifstats.num_alerts_engaged) .."</a> <span id=engaged_alerts_trend></span></td>\n")
|
|
print("<th width=250>".. ternary(ifstats.num_dropped_alerts > 0, warning, "")..i18n("show_alerts.dropped_alerts")..
|
|
"</th><td colspan=2>" .. formatValue(ifstats.num_dropped_alerts) .. " <span id=dropped_alerts_trend></span></td>\n</td>")
|
|
end
|
|
|
|
label = i18n("pkts")
|
|
|
|
print[[ <tr><th colspan=1 nowrap>]] print(i18n("if_stats_overview.traffic_breakdown")) print[[</th> ]]
|
|
|
|
if(ifstats.type ~= "zmq") then
|
|
print [[ <td colspan=2><div class="pie-chart" id="ifaceTrafficBreakdown"></div></td><td colspan=3> <div class="pie-chart" id="ifaceTrafficDistribution"></div></td></tr> ]]
|
|
else
|
|
print [[ <td colspan=5><div class="pie-chart" id="ifaceTrafficBreakdown"></div></td></tr> ]]
|
|
end
|
|
|
|
print [[
|
|
<script type='text/javascript'>
|
|
window.onload=function() {
|
|
do_pie("#ifaceTrafficBreakdown", ']]
|
|
print (ntop.getHttpPrefix())
|
|
print [[/lua/iface_local_stats.lua', { ifid: ]] print(ifstats.id .. " }, \"\", refresh); \n")
|
|
|
|
if(ifstats.type ~= "zmq") then
|
|
print [[ do_pie("#ifaceTrafficDistribution", ']]
|
|
print (ntop.getHttpPrefix())
|
|
print [[/lua/iface_local_stats.lua', { ifid: ]] print(ifstats.id .. ", iflocalstat_mode: \"distribution\" }, \"\", refresh); \n")
|
|
end
|
|
print [[ }
|
|
|
|
]]
|
|
print("</script>\n")
|
|
|
|
if(ifstats.zmqRecvStats ~= nil) then
|
|
print("<tr><th colspan=7 nowrap>"..i18n("if_stats_overview.zmq_rx_statistics").."</th></tr>\n")
|
|
|
|
local collected_flows_chart_available = ts_utils.exists("iface:zmq_recv_flows", tags)
|
|
print("<tr><th nowrap>"..i18n("if_stats_overview.collected_flows")..ternary(collected_flows_chart_available, " <A HREF='"..url.."&page=historical&ts_schema=iface:zmq_recv_flows'><i class='fas fa-chart-area fa-sm'></i></A>", "").."</th><td width=20%><span id=if_zmq_flows>"..formatValue(ifstats.zmqRecvStats.flows).."</span></td>")
|
|
|
|
print("<th nowrap>"..i18n("if_stats_overview.interface_rx_updates").."</th><td width=20%><span id=if_zmq_events>"..formatValue(ifstats.zmqRecvStats.events).."</span></td>")
|
|
|
|
print("<th nowrap>"..i18n("if_stats_overview.sflow_counter_updates").."</th><td width=20%><span id=if_zmq_counters>"..formatValue(ifstats.zmqRecvStats.counters).."</span></td></tr>")
|
|
|
|
local collected_msgs_chart_available = ts_utils.exists("iface:zmq_rcvd_msgs", tags)
|
|
print("<tr><th nowrap>"..i18n("if_stats_overview.zmq_message_rcvd")..ternary(collected_msgs_chart_available, " <A HREF='"..url.."&page=historical&ts_schema=custom:zmq_msg_rcvd_vs_drops'><i class='fas fa-chart-area fa-sm'></i></A>", "").."</th><td width=20%><span id=if_zmq_msg_rcvd>"..formatValue(ifstats.zmqRecvStats.zmq_msg_rcvd).."</span></td>")
|
|
|
|
print("<th nowrap> <i class='fas fa-tint' aria-hidden='true'></i> "..i18n("if_stats_overview.zmq_message_drops")..ternary(collected_msgs_chart_available, " <A HREF='"..url.."&page=historical&ts_schema=custom:zmq_msg_rcvd_vs_drops'><i class='fas fa-chart-area fa-sm'></i></A>", "").."</th><td width=20%><span id=if_zmq_msg_drops>"..formatValue(ifstats.zmqRecvStats.zmq_msg_drops).."</span></td>")
|
|
print("<th nowrap> "..i18n("if_stats_overview.zmq_avg_msg_flows").."</th><td width=20%><span id=if_zmq_avg_msg_flows></span></td></tr>")
|
|
end
|
|
|
|
print("<tr><th colspan=7 nowrap>"..i18n("if_stats_overview.traffic_statistics").."</th></tr>\n")
|
|
|
|
local traffic_chart_available = ts_utils.exists("iface:traffic", tags)
|
|
print("<tr><th nowrap>"..i18n("report.total_traffic")..ternary(traffic_chart_available, " <A HREF='"..url.."&page=historical&ts_schema=iface:traffic'><i class='fas fa-chart-area fa-sm'></i></A>", "").."</th><td width=20%><span id=if_bytes>"..bytesToSize(ifstats.stats.bytes).."</span> [<span id=if_pkts>".. formatValue(ifstats.stats.packets) .. " ".. label .."</span>] ")
|
|
|
|
print("<span id=pkts_trend></span></td>")
|
|
|
|
if not ifstats.isDynamic then
|
|
print("<th width=20%><span id='if_packet_drops_drop'><i class='fas fa-tint' aria-hidden='true'></i></span> ")
|
|
|
|
local drops_chart_available = ts_utils.exists("iface:drops", tags)
|
|
print(i18n("if_stats_overview.dropped_packets")..ternary(drops_chart_available, " <A HREF='"..url.."&page=historical&ts_schema=iface:drops'><i class='fas fa-chart-area fa-sm'></i></A>", "").."</th>")
|
|
|
|
print("<td width=20% colspan=3><span id=if_drops>")
|
|
|
|
if(ifstats.stats.drops > 0) then
|
|
print('<span class="badge badge-danger">')
|
|
end
|
|
|
|
print(formatValue(ifstats.stats.drops).. " " .. label)
|
|
|
|
if((ifstats.stats.packets+ifstats.stats.drops) > 0) then
|
|
local pctg = round((ifstats.stats.drops*100)/(ifstats.stats.packets+ifstats.stats.drops), 2)
|
|
if(pctg > 0) then print(" [ " .. pctg .. " % ] ") end
|
|
end
|
|
|
|
if(ifstats.stats.drops > 0) then print('</span>') end
|
|
print("</span> <span id=drops_trend></span>")
|
|
|
|
if(ifstats.zmqRecvStats ~= nil) then
|
|
print("<p><small> <b>"..i18n("if_stats_overview.note").."</b>:<br>".. i18n("if_stats_overview.note_drops_sflow").."</small>")
|
|
end
|
|
|
|
print("</td>")
|
|
else
|
|
print("<td width=20% colspan=3>")
|
|
print("<small><b>"..i18n("if_stats_overview.note")..":</b> "..i18n("if_stats_overview.note_drop_ifstats_dynamic").."</small>")
|
|
print("</td>")
|
|
end
|
|
|
|
print("</tr>")
|
|
|
|
if(ifstats.has_traffic_directions) then
|
|
local txrx_chart_available = ts_utils.exists("iface:traffic_rxtx", tags)
|
|
|
|
print("<tr><th nowrap>"..i18n("http_page.traffic_sent")..ternary(txrx_chart_available, " <A HREF='"..url.."&page=historical&ts_schema=iface:traffic_rxtx'><i class='fas fa-chart-area fa-sm'></i></A>", "").."</th><td width=20%><span id=if_out_bytes>"..bytesToSize(ifstats.eth.egress.bytes).."</span> [<span id=if_out_pkts>".. formatValue(ifstats.eth.egress.packets) .. " ".. label .."</span>] <span id=pkts_out_trend></span></td>")
|
|
print("<th nowrap>"..i18n("http_page.traffic_received")..ternary(txrx_chart_available, " <A HREF='"..url.."&page=historical&ts_schema=iface:traffic_rxtx'><i class='fas fa-chart-area fa-sm'></i></A>", "").."</th><td width=20%><span id=if_in_bytes>"..bytesToSize(ifstats.eth.ingress.bytes).."</span> [<span id=if_in_pkts>".. formatValue(ifstats.eth.ingress.packets) .. " ".. label .."</span>] <span id=pkts_in_trend></span><td></td></tr>")
|
|
end
|
|
|
|
if not interface.isPacketInterface() then
|
|
local external_json_stats = ntop.getCache(getRedisIfacePrefix(ifid)..".external_stats")
|
|
if not isEmptyString(external_json_stats) then
|
|
local external_stats = json.decode(external_json_stats)
|
|
if external_stats ~= nil then
|
|
local external_stats_title = i18n("external_stats.title")
|
|
if external_stats.i18n_title then
|
|
external_stats_title = i18n(external_stats.i18n_title)
|
|
external_stats.i18n_title = nil
|
|
end
|
|
print("<tr><th colspan=7 nowrap>"..external_stats_title.."</th></tr>\n")
|
|
for key, value in pairsByKeys(external_stats, asc) do
|
|
print("<tr>")
|
|
print("<th nowrap>"..ternary(i18n("external_stats."..key), i18n("external_stats."..key), key).."</th>")
|
|
print("<td colspan=4>"..ternary(type(value) == "number", formatValue(value), value).."</td>")
|
|
print("</tr>")
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
if(prefs.is_dump_flows_enabled and ifstats.isView == false) then
|
|
local dump_to = "MySQL"
|
|
if prefs.is_dump_flows_to_es_enabled == true then
|
|
dump_to = "ElasticSearch"
|
|
end
|
|
if prefs.is_dump_flows_to_ls_enabled == true then
|
|
dump_to = "Logstash"
|
|
end
|
|
if prefs.is_nindex_enabled == true then
|
|
dump_to = "nIndex"
|
|
end
|
|
|
|
local export_count = ifstats.stats.flow_export_count
|
|
local export_rate = ifstats.stats.flow_export_rate
|
|
local export_drops = ifstats.stats.flow_export_drops
|
|
local export_drops_pct = 0
|
|
if export_drops == nill then
|
|
|
|
elseif export_drops > 0 and export_count > 0 then
|
|
export_drops_pct = export_drops / export_count * 100
|
|
elseif export_drops > 0 then
|
|
export_drops_pct = 100
|
|
end
|
|
|
|
print("<tr><th colspan=7 nowrap>"..dump_to.." "..i18n("if_stats_overview.flows_export_statistics").."</th></tr>\n")
|
|
|
|
print("<tr>")
|
|
print("<th nowrap>"..i18n("if_stats_overview.exported_flows").."</th>")
|
|
print("<td><span id=exported_flows>"..formatValue(export_count).."</span>")
|
|
if export_rate == nil then
|
|
export_rate = 0
|
|
end
|
|
print(" [<span id=exported_flows_rate>"..formatValue(round(export_rate, 2)).."</span> Flows/s]</td>")
|
|
|
|
print("<th><span id='if_flow_drops_drop'<i class='fas fa-tint' aria-hidden='true'></i></span> ")
|
|
print(i18n("if_stats_overview.dropped_flows").."</th>")
|
|
|
|
local span_danger = ""
|
|
if export_drops == nil then
|
|
|
|
|
|
elseif(export_drops > 0) then
|
|
span_danger = ' class="badge badge-danger"'
|
|
end
|
|
print("<td><span id=exported_flows_drops "..span_danger..">"..formatValue(export_drops).."</span> ")
|
|
print("<span id=exported_flows_drops_pct "..span_danger..">["
|
|
..formatValue(round(export_drops_pct, 2)).."%]</span></td>")
|
|
print("<td colspan=3> </td>")
|
|
print("</tr>")
|
|
end
|
|
|
|
if ifstats.stats.discarded_probing_packets then
|
|
local discarded_probing_traffic_chart_available = ts_utils.exists("iface:disc_prob_pkts", tags)
|
|
|
|
print("<tr><td colspan=2></td><th nowrap> <i class='fas fa-trash' aria-hidden='true'></i> "..i18n("if_stats_overview.discarded_probing_traffic")..ternary(discarded_probing_traffic_chart_available, " <A HREF='"..url.."&page=historical&ts_schema=iface:disc_prob_pkts'><i class='fas fa-chart-area fa-sm'></i></A>", "").."</th><td colspan=4width=20%><span id=if_discarded_probing_bytes>"..bytesToSize(ifstats.stats.discarded_probing_bytes).."</span> [<span id=if_discarded_probing_pkts>".. formatPackets(ifstats.stats.discarded_probing_packets) .."</span>] ")
|
|
|
|
print("<span id=if_discarded_probing_trend></span></td></tr>\n")
|
|
end
|
|
|
|
if isAdministrator() and ifstats.isView == false then
|
|
local storage_info = storage_utils.interfaceStorageInfo(ifid)
|
|
local storage_items = {}
|
|
|
|
if ts_utils.getDriverName() == "rrd" then
|
|
if storage_info.rrd ~= nil and storage_info.rrd > 0 then
|
|
table.insert(storage_items, {
|
|
title = i18n("if_stats_overview.rrd_timeseries"),
|
|
value = storage_info.rrd,
|
|
class = "primary",
|
|
})
|
|
end
|
|
end
|
|
|
|
if storage_info.flows ~= nil and storage_info.flows > 0 then
|
|
table.insert(storage_items, {
|
|
title = i18n("flows"),
|
|
value = storage_info.flows,
|
|
class = "info",
|
|
})
|
|
end
|
|
|
|
if storage_info.pcap ~= nil and storage_info.pcap > 0 then
|
|
local link = nil
|
|
|
|
if recording_utils.isAvailable(ifstats.id) then
|
|
link = ntop.getHttpPrefix() .. "/lua/if_stats.lua?ifid=" .. ifid .. "&page=traffic_recording"
|
|
end
|
|
|
|
table.insert(storage_items, {
|
|
title = i18n("traffic_recording.packet_dumps"),
|
|
value = storage_info.pcap,
|
|
class = "warning",
|
|
link = link
|
|
})
|
|
end
|
|
|
|
if #storage_items > 0 then
|
|
print("<tr><th>"..i18n("traffic_recording.storage_utilization").."</th><td colspan=5>")
|
|
print(stackedProgressBars(storage_info.total, storage_items, nil, bytesToSize))
|
|
print("</td></tr>\n")
|
|
end
|
|
end
|
|
|
|
if (isAdministrator() and ifstats.isView == false and ifstats.isDynamic == false and interface.isPacketInterface()) then
|
|
print("<tr><th>"..i18n("download").." <i class=\"fas fa-download fa-lg\"></i></th><td colspan=5>")
|
|
|
|
local live_traffic_utils = require("live_traffic_utils")
|
|
live_traffic_utils.printLiveTrafficForm(ifId)
|
|
|
|
print("</td></tr>\n")
|
|
end
|
|
|
|
if isAdministrator() then
|
|
print("<tr><th width=250>"..i18n("if_stats_overview.reset_counters").."</th>")
|
|
print("<td colspan=5>")
|
|
|
|
local tot = ifstats.stats.bytes + ifstats.stats.packets + ifstats.stats.drops
|
|
if(ifstats.stats.flow_export_count ~= nil) then
|
|
tot = tot + ifstats.stats.flow_export_count + ifstats.stats.flow_export_drops
|
|
end
|
|
|
|
print('<button id="btn_reset_all" type="button" class="btn btn-secondary" onclick="resetInterfaceCounters(false);">'..i18n("if_stats_overview.all_counters")..'</button> ')
|
|
|
|
print('<button id="btn_reset_drops" type="button" class="btn btn-secondary" onclick="resetInterfaceCounters(true);">'..i18n("if_stats_overview.drops_only")..'</button>')
|
|
print("</td>")
|
|
|
|
print("</tr>\n")
|
|
end
|
|
|
|
if have_nedge and ifstats.type == "netfilter" and ifstats.netfilter then
|
|
local st = ifstats.netfilter
|
|
|
|
print("<tr><th nowrap>"..i18n("if_stats_overview.nf_queue_total").."</th>")
|
|
local span_class = ''
|
|
if st.nfq.queue_pct > 80 then
|
|
span_class = "class='badge badge-danger'"
|
|
end
|
|
print("<td width=20%><span id=nfq_queue_total "..span_class..">"..string.format("%s [%s %%]", formatValue(st.nfq.queue_total), formatValue(st.nfq.queue_pct)).." </span> <span id=nfq_queue_total_trend></span></td>")
|
|
print("<th nowrap>"..i18n("if_stats_overview.nf_handle_packet_failed").."</th>")
|
|
print("<td width=20%><span id=nfq_handling_failed>"..formatValue(st.failures.handle_packet).."</span> <span id=nfq_handling_failed_trend></span></td>")
|
|
print("<th nowrap>"..i18n("if_stats_overview.nf_enobufs").."</th>")
|
|
print("<td width=20%><span id=nfq_enobufs>"..formatValue(st.failures.no_buffers).."</span> <span id=nfq_enobufs_trend></span></td>")
|
|
print("</tr>")
|
|
|
|
print("<tr><th nowrap>Conntrack Flow Entries</th><td colspan=5>")
|
|
print("<span id=num_conntrack_entries>"..formatValue(st.nfq.num_conntrack_entries).."</span></td>")
|
|
print("</tr>")
|
|
end
|
|
|
|
print [[
|
|
<tr><td colspan=7> <small> <b>]] print(i18n("if_stats_overview.note").."</b>:<p>"..i18n("if_stats_overview.note_packets")) print[[</small> </td></tr>
|
|
]]
|
|
|
|
print("</table>\n")
|
|
|
|
elseif page == "networks" and interface.isPacketInterface() then
|
|
print("<table class=\"table table-striped table-bordered\">")
|
|
|
|
if(ifstats.ip_addresses ~= "") then
|
|
local tokens = split(ifstats.ip_addresses, ",")
|
|
|
|
if(tokens ~= nil) then
|
|
print("<tr><th width=250>"..i18n("ip_address").."</th><td colspan=5><ul><li>")
|
|
local addresses = {}
|
|
|
|
for _,s in pairs(tokens) do
|
|
t = string.split(s, "/")
|
|
host = interface.getHostInfo(t[1])
|
|
|
|
if(host ~= nil) then
|
|
addresses[#addresses+1] = "<a href=\""..ntop.getHttpPrefix().."/lua/host_details.lua?host="..t[1].."\">".. t[1].."</a>".."/"..t[2]
|
|
else
|
|
addresses[#addresses+1] = s
|
|
end
|
|
end
|
|
|
|
print(table.concat(addresses, "\n<li>"))
|
|
|
|
print("</ul></td></tr>")
|
|
end
|
|
end
|
|
|
|
local has_ghost_networks = false
|
|
local ghost_icon = '<font color=red><i class="fas fa-ghost" aria-hidden="true"></i></font>'
|
|
if ifstats.bcast_domains and table.len(ifstats.bcast_domains) > 0 then
|
|
print("<tr><th width=250>"..i18n("broadcast_domain").."</th><td colspan=5>")
|
|
|
|
local bcast_domains = {}
|
|
for bcast_domain, domain_info in pairsByKeys(ifstats.bcast_domains) do
|
|
bcast_domain = string.format("<a href='%s/lua/hosts_stats.lua?network_cidr=%s'>%s</a>", ntop.getHttpPrefix(), bcast_domain, bcast_domain)
|
|
|
|
if domain_info.ghost_network then
|
|
has_ghost_networks = true
|
|
bcast_domain = bcast_domain..' '..ghost_icon
|
|
end
|
|
|
|
bcast_domains[#bcast_domains + 1] = bcast_domain
|
|
end
|
|
|
|
if #bcast_domains > 0 then
|
|
print("<ul>")
|
|
for _, bcast_domain in ipairs(bcast_domains) do
|
|
print("<li>"..bcast_domain.."</li>")
|
|
end
|
|
print("</ul>")
|
|
end
|
|
|
|
print("</td></tr>")
|
|
end
|
|
print("</table>")
|
|
|
|
print("<p><b>"..i18n("if_stats_overview.note").."</b>:<ul>")
|
|
print("<li>"..i18n("if_stats_networks.note_iface_addresses").."</li>")
|
|
print("<li>"..i18n("if_stats_networks.note_iface_bcast_domains").."</li>")
|
|
|
|
if has_ghost_networks then
|
|
print("<li>"..i18n("if_stats_networks.note_ghost_bcast_domains", {ghost_icon = ghost_icon}).."</li>")
|
|
end
|
|
print("</ul>")
|
|
|
|
elseif((page == "packets")) then
|
|
local nedge_hidden = ternary(have_nedge, 'class="hidden"', '')
|
|
|
|
print [[ <table class="table table-bordered table-striped"> ]]
|
|
print("<tr " .. nedge_hidden .. "><th width=30% rowspan=3>" .. i18n("packets_page.tcp_packets_analysis") .. "</th><th>" .. i18n("packets_page.retransmissions") .."</th><td align=right><span id=pkt_retransmissions>".. formatPackets(ifstats.tcpPacketStats.retransmissions) .."</span> <span id=pkt_retransmissions_trend></span></td></tr>\n")
|
|
print("<tr " .. nedge_hidden .. "></th><th>" .. i18n("packets_page.out_of_order") .. "</th><td align=right><span id=pkt_ooo>".. formatPackets(ifstats.tcpPacketStats.out_of_order) .."</span> <span id=pkt_ooo_trend></span></td></tr>\n")
|
|
print("<tr " .. nedge_hidden .. "></th><th>" .. i18n("packets_page.lost") .. "</th><td align=right><span id=pkt_lost>".. formatPackets(ifstats.tcpPacketStats.lost) .."</span> <span id=pkt_lost_trend></span></td></tr>\n")
|
|
|
|
if(ifstats.type ~= "zmq") then
|
|
print [[<tr ]] print(nedge_hidden) print[[><th class="text-left">]] print(i18n("packets_page.size_distribution")) print [[</th><td colspan=5><div class="pie-chart" id="sizeDistro"></div></td></tr>]]
|
|
end
|
|
|
|
print[[
|
|
<tr ]] print(nedge_hidden) print[[><th class="text-left">]] print(i18n("packets_page.version_vs_flags_distribution")) print[[</th>
|
|
<td colspan=1><div class="pie-chart" id="ipverDistro"></div></td><td colspan=1><div class="pie-chart" id="flagsDistro"></div></td></tr>
|
|
</table>
|
|
|
|
<script type='text/javascript'>
|
|
window.onload=function() {
|
|
|
|
do_pie("#sizeDistro", ']]
|
|
print (ntop.getHttpPrefix())
|
|
print [[/lua/if_pkt_distro.lua', { distr: "size", ifid: "]] print(ifstats.id.."\"")
|
|
print [[
|
|
}, "", refresh);
|
|
|
|
do_pie("#flagsDistro", ']]
|
|
print (ntop.getHttpPrefix())
|
|
print [[/lua/if_tcpflags_pkt_distro.lua', { ifid: "]] print(ifstats.id.."\"")
|
|
print [[
|
|
}, "", refresh);
|
|
|
|
do_pie("#ipverDistro", ']]
|
|
print (ntop.getHttpPrefix())
|
|
print [[/lua/if_pkt_distro.lua', { distr: "ipver", ifid: "]] print(ifstats.id.."\"")
|
|
print [[
|
|
}, "", refresh);
|
|
}
|
|
|
|
</script><p>
|
|
]]
|
|
elseif(page == "ndpi") then
|
|
print[[
|
|
<ul id="ndpiNav" class="nav nav-tabs" role="tablist">
|
|
<li class="nav-item active"><a class="nav-link active" data-toggle="tab" role="tab" href="#applications" active>]] print(i18n("applications")) print[[</a></li>
|
|
<li class="nav-item"><a class="nav-link" data-toggle="tab" role="tab" href="#categories">]] print(i18n("categories")) print[[</a></li>
|
|
</ul>
|
|
<div class="tab-content">
|
|
<div id="applications" class="tab-pane in active">
|
|
<br>
|
|
<table class="table table-bordered table-striped">
|
|
]]
|
|
|
|
if ntop.isPro() and ifstats["custom_apps"] then
|
|
print[[
|
|
<tr>
|
|
<th class="text-left">]] print(i18n("ndpi_page.overview", {what = i18n("ndpi_page.custom_applications")})) print [[</th>
|
|
<td colspan=5><div class="pie-chart" id="topCustomApps"></td>
|
|
</tr>
|
|
]]
|
|
end
|
|
|
|
print[[
|
|
<tr>
|
|
<th class="text-left">]] print(i18n("ndpi_page.overview", {what = i18n("applications")})) print [[</th>
|
|
<td colspan=3><div class="pie-chart" id="topApplicationProtocols"></td>
|
|
<td colspan=2><div class="pie-chart" id="topApplicationBreeds"></td>
|
|
</tr>
|
|
<tr>
|
|
<th class="text-left">]] print(i18n("ndpi_page.live_flows_count")) print [[</th>
|
|
<td colspan=3><div class="pie-chart" id="topFlowsCount"></td>
|
|
<td colspan=2><div class="pie-chart" id="topTCPFlowsStats">
|
|
<br><small><b>]] print(i18n("ndpi_page.note")) print [[ :</b>]] print(i18n("ndpi_page.note_live_flows_chart")) print [[
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
<table id="if_stats_ndpi" class="table table-bordered table-striped tablesorter">
|
|
<thead>
|
|
<tr>
|
|
<th>]] print(i18n("application")) print[[</th>
|
|
<th>]] print(i18n("ndpi_page.total_since_startup")) print[[</th>
|
|
<th>]] print(i18n("percentage")) print[[</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody id="if_stats_ndpi_tbody"></tbody>
|
|
</table>
|
|
</div>
|
|
<div id="categories" class="tab-pane">
|
|
<br>
|
|
<table class="table table-bordered table-striped">
|
|
<tr>
|
|
<th class="text-left">]] print(i18n("ndpi_page.overview", {what = i18n("categories")})) print [[</th>
|
|
<td colspan=5><div class="pie-chart" id="topApplicationCategories"></td>
|
|
</tr>
|
|
</table>
|
|
<table id="if_stats_ndpi_categories" class="table table-bordered table-striped tablesorter">
|
|
<thead>
|
|
<tr>
|
|
<th>]] print(i18n("category")) print[[</th>
|
|
<th>]] print(i18n("ndpi_page.total_since_startup")) print[[</th>
|
|
<th>]] print(i18n("percentage")) print[[</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody id="if_stats_ndpi_categories_tbody"></tbody>
|
|
</table>
|
|
</div>
|
|
]]
|
|
|
|
print [[
|
|
<script type="text/javascript" src="]] print(ntop.getHttpPrefix()) print [[/js/jquery.tablesorter.js"></script>
|
|
<script type='text/javascript'>
|
|
window.onload=function() {]]
|
|
|
|
if ntop.isPro() and ifstats["custom_apps"] then
|
|
print[[do_pie("#topCustomApps", ']]
|
|
print (ntop.getHttpPrefix())
|
|
print [[/lua/pro/get_custom_app_stats.lua', { ifid: "]] print(ifid) print [[" }, "", refresh);
|
|
]]
|
|
end
|
|
|
|
print[[do_pie("#topApplicationProtocols", ']]
|
|
print (ntop.getHttpPrefix())
|
|
print [[/lua/iface_ndpi_stats.lua', { ndpistats_mode: "sinceStartup", ifid: "]] print(ifid) print [[" }, "", refresh);
|
|
|
|
do_pie("#topApplicationBreeds", ']]
|
|
print (ntop.getHttpPrefix())
|
|
print [[/lua/iface_ndpi_stats.lua', { breed: "true", ndpistats_mode: "sinceStartup", ifid: "]] print(ifid) print [[" }, "", refresh);
|
|
|
|
do_pie("#topApplicationCategories", ']]
|
|
print (ntop.getHttpPrefix())
|
|
print [[/lua/iface_ndpi_stats.lua', { ndpi_category: "true", ndpistats_mode: "sinceStartup", ifid: "]] print(ifid) print [[" }, "", refresh);
|
|
|
|
do_pie("#topFlowsCount", ']]
|
|
print (ntop.getHttpPrefix())
|
|
print [[/lua/iface_ndpi_stats.lua', { breed: "true", ndpistats_mode: "count", ifid: "]] print(ifid) print [[" }, "", refresh);
|
|
|
|
do_pie("#topTCPFlowsStats", ']]
|
|
print (ntop.getHttpPrefix())
|
|
print [[/lua/iface_tcp_stats.lua', { ifid: "]] print(ifid) print [[" }, "", refresh);
|
|
}
|
|
|
|
function update_ndpi_table() {
|
|
$.ajax({
|
|
type: 'GET',
|
|
url: ']]
|
|
print (ntop.getHttpPrefix())
|
|
print [[/lua/if_stats_ndpi.lua',
|
|
data: { ifid: "]] print(ifid) print [[" },
|
|
success: function(content) {
|
|
if(content) {
|
|
$('#if_stats_ndpi_tbody').html(content);
|
|
// Let the TableSorter plugin know that we updated the table
|
|
$('#if_stats_ndpi_tbody').trigger("update");
|
|
}
|
|
}
|
|
});
|
|
}
|
|
update_ndpi_table();
|
|
setInterval(update_ndpi_table, 5000);
|
|
|
|
function update_ndpi_categories_table() {
|
|
$.ajax({
|
|
type: 'GET',
|
|
url: ']]
|
|
print (ntop.getHttpPrefix())
|
|
print [[/lua/if_stats_ndpi_categories.lua',
|
|
data: { ifid: "]] print(ifid) print [[" },
|
|
success: function(content) {
|
|
if(content) {
|
|
$('#if_stats_ndpi_categories_tbody').html(content);
|
|
// Let the TableSorter plugin know that we updated the table
|
|
$('#if_stats_ndpi_categories_tbody').trigger("update");
|
|
}
|
|
}
|
|
});
|
|
}
|
|
update_ndpi_categories_table();
|
|
setInterval(update_ndpi_categories_table, 5000);
|
|
|
|
</script>
|
|
]]
|
|
|
|
elseif(page == "ICMP") then
|
|
print[[
|
|
<ul id="icmp_nav" class="nav nav-tabs" role="tablist">
|
|
<li class="nav-item active"><a class="nav-link active" data-toggle="tab" role="tab" href="#icmp" active>]] print(i18n("icmp")) print[[</a></li>
|
|
<li class="nav-item"><a class="nav-link" data-toggle="tab" role="tab" href="#icmpv6">]] print(i18n("icmp")) print[[V6</a></li>
|
|
</ul>
|
|
<div class="tab-content">
|
|
<div id="icmp" class="tab-pane in active">
|
|
<br>
|
|
<table id="icmp_table_4" class="table table-bordered table-striped tablesorter">
|
|
<thead><tr><th>]] print(i18n("icmp_page.icmp_message")) print [[</th><th>]] print(i18n("icmp_page.icmp_type")) print [[</th><th>]] print(i18n("icmp_page.icmp_code")) print [[</th><th style='text-align:right;'>]] print(i18n("packets")) print[[</th></tr></thead>
|
|
<tbody id="iface_details_icmp_tbody_4">
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
<div id="icmpv6" class="tab-pane">
|
|
<br>
|
|
<table id="icmp_table_6" class="table table-bordered table-striped tablesorter">
|
|
<thead><tr><th>]] print(i18n("icmp_page.icmp_message")) print [[</th><th>]] print(i18n("icmp_page.icmp_type")) print [[</th><th>]] print(i18n("icmp_page.icmp_code")) print [[</th><th style='text-align:right;'>]] print(i18n("packets")) print[[</th></tr></thead>
|
|
<tbody id="iface_details_icmp_tbody_6">
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
|
|
<script>
|
|
function update_icmp_table(ip_version) {
|
|
var icmp_table_id = '#icmp_table_' + ip_version;
|
|
var icmp_table_body_id = '#iface_details_icmp_tbody_' + ip_version;
|
|
|
|
$.ajax({
|
|
type: 'GET',
|
|
url: ']]
|
|
print(ntop.getHttpPrefix())
|
|
print [[/lua/get_icmp_data.lua',
|
|
data: { ifid: "]] print(ifId.."") print [[", version: ip_version },
|
|
success: function(content) {
|
|
if(content) {
|
|
$(icmp_table_body_id).html(content);
|
|
$(icmp_table_id).trigger("update");
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
function update_icmp_tables() {
|
|
update_icmp_table(4);
|
|
update_icmp_table(6);
|
|
}
|
|
|
|
update_icmp_tables();
|
|
setInterval(update_icmp_tables, 5000);
|
|
</script>
|
|
|
|
]]
|
|
elseif(page == "ARP") then
|
|
|
|
print [[
|
|
<table id="arp_table" class="table table-bordered table-striped tablesorter">
|
|
<thead><tr><th>]] print(i18n("arp_page.arp_type")) print [[</th><th style='text-align:right;'>]] print(i18n("packets")) print[[</th></tr></thead>
|
|
<tbody id="iface_details_arp_tbody">
|
|
</tbody>
|
|
</table>
|
|
|
|
<script>
|
|
function update_arp_table() {
|
|
$.ajax({
|
|
type: 'GET',
|
|
url: ']]
|
|
print(ntop.getHttpPrefix())
|
|
print [[/lua/get_arp_data.lua',
|
|
data: { ifid: "]] print(ifId.."") print [[" },
|
|
success: function(content) {
|
|
if(content) {
|
|
$('#iface_details_arp_tbody').html(content);
|
|
$('#arp_table').trigger("update");
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
update_arp_table();
|
|
setInterval(update_arp_table, 5000);
|
|
</script>
|
|
|
|
]]
|
|
|
|
elseif(page == "historical") then
|
|
local schema = _GET["ts_schema"] or "iface:traffic"
|
|
local selected_epoch = _GET["epoch"] or ""
|
|
local tags = {
|
|
ifid = ifid,
|
|
protocol = _GET["protocol"],
|
|
category = _GET["category"],
|
|
l4proto = _GET["l4proto"],
|
|
}
|
|
url = url.."&page=historical"
|
|
|
|
local top_enabled = top_talkers_utils.areTopEnabled(ifid)
|
|
|
|
drawGraphs(ifstats.id, schema, tags, _GET["zoom"], url, selected_epoch, {
|
|
top_protocols = "top:iface:ndpi",
|
|
top_categories = "top:iface:ndpi_categories",
|
|
top_profiles = "top:profile:traffic",
|
|
top_senders = ternary(top_enabled, "top:local_senders", nil),
|
|
top_receivers = ternary(top_enabled, "top:local_receivers", nil),
|
|
l4_protocols = "iface:l4protos",
|
|
show_historical = not ifstats.isViewed,
|
|
timeseries = {
|
|
{schema="iface:flows", label=i18n("graphs.active_flows")},
|
|
{schema="iface:new_flows", label=i18n("graphs.new_flows"), value_formatter = {"fflows", "formatFlows"}},
|
|
{schema="iface:hosts", label=i18n("graphs.active_hosts")},
|
|
{schema="iface:engaged_alerts", label=i18n("show_alerts.engaged_alerts")},
|
|
{schema="custom:flows_vs_local_hosts", label=i18n("graphs.flows_vs_local_hosts"), check={"iface:flows", "iface:local_hosts"}, step=60},
|
|
{schema="custom:flows_vs_traffic", label=i18n("graphs.flows_vs_traffic"), check={"iface:flows", "iface:traffic"}, step=60},
|
|
{schema="custom:memory_vs_flows_hosts", label=i18n("graphs.memory_vs_hosts_flows"), check={"process:resident_memory", "iface:flows", "iface:hosts"}},
|
|
{schema="iface:devices", label=i18n("graphs.active_devices")},
|
|
{schema="iface:http_hosts", label=i18n("graphs.active_http_servers"), nedge_exclude=1},
|
|
{schema="iface:traffic", label=i18n("traffic")},
|
|
{schema="iface:traffic_rxtx", label=i18n("graphs.traffic_txrx")},
|
|
|
|
{schema="iface:1d_delta_traffic_volume", label="1 Day Traffic Delta"}, -- TODO localize
|
|
{schema="iface:1d_delta_flows", label="1 Day Active Flows Delta"}, -- TODO localize
|
|
|
|
{schema="iface:packets", label=i18n("packets")},
|
|
{schema="iface:drops", label=i18n("graphs.packet_drops")},
|
|
{schema="iface:nfq_pct", label=i18n("graphs.num_nfq_pct"), nedge_only=1},
|
|
|
|
{schema="iface:disc_prob_bytes", label=i18n("graphs.discarded_probing_bytes"), nedge_exclude=1},
|
|
{schema="iface:disc_prob_pkts", label=i18n("graphs.discarded_probing_packets"), nedge_exclude=1},
|
|
|
|
{schema="iface:zmq_recv_flows", label=i18n("graphs.zmq_received_flows"), nedge_exclude=1},
|
|
{schema="custom:zmq_msg_rcvd_vs_drops",label=i18n("graphs.zmq_msg_rcvd_vs_drops"), check={"iface:zmq_rcvd_msgs", "iface:zmq_msg_drops"}, metrics_labels = {i18n("if_stats_overview.zmq_message_rcvd"), i18n("if_stats_overview.zmq_message_drops")}, value_formatter = {"fmsgs", "formatMessages"}},
|
|
{schema="iface:zmq_flow_coll_drops", label=i18n("graphs.zmq_flow_coll_drops"), nedge_exclude=1, value_formatter = {"fflows", "formatFlows"}},
|
|
{schema="iface:zmq_flow_coll_udp_drops", label=i18n("graphs.zmq_flow_coll_udp_drops"), nedge_exclude=1, value_formatter = {"fpackets", "formatPackets"}},
|
|
{schema="iface:exported_flows", label=i18n("if_stats_overview.exported_flows"), nedge_exclude=1},
|
|
{schema="iface:dropped_flows", label=i18n("if_stats_overview.dropped_flows"), nedge_exclude=1},
|
|
{separator=1, nedge_exclude=1, label=i18n("tcp_stats")},
|
|
{schema="iface:tcp_lost", label=i18n("graphs.tcp_packets_lost"), nedge_exclude=1},
|
|
{schema="iface:tcp_out_of_order", label=i18n("graphs.tcp_packets_ooo"), nedge_exclude=1},
|
|
--{schema="tcp_retr_ooo_lost", label=i18n("graphs.tcp_retr_ooo_lost"), nedge_exclude=1},
|
|
{schema="iface:tcp_retransmissions", label=i18n("graphs.tcp_packets_retr"), nedge_exclude=1},
|
|
{schema="iface:tcp_keep_alive", label=i18n("graphs.tcp_packets_keep_alive"), nedge_exclude=1},
|
|
{separator=1, label=i18n("tcp_flags")},
|
|
{schema="iface:tcp_syn", label=i18n("graphs.tcp_syn_packets"), nedge_exclude=1, pro_skip=1},
|
|
{schema="iface:tcp_synack", label=i18n("graphs.tcp_synack_packets"), nedge_exclude=1, pro_skip=1},
|
|
{schema="custom:iface_tcp_syn_vs_tcp_synack", label=i18n("graphs.tcp_syn_vs_tcp_synack"), metrics_labels = {"SYN", "SYN+ACK"}},
|
|
{schema="iface:tcp_finack", label=i18n("graphs.tcp_finack_packets"), nedge_exclude=1},
|
|
{schema="iface:tcp_rst", label=i18n("graphs.tcp_rst_packets"), nedge_exclude=1},
|
|
}
|
|
})
|
|
elseif(page == "trafficprofiles") then
|
|
print("<table class=\"table table-striped table-bordered\">\n")
|
|
print("<tr><th width=15%><a href=\""..ntop.getHttpPrefix().."/lua/pro/admin/edit_profiles.lua\">" .. i18n("traffic_profiles.profile_name") .. "</A></th><th width=5%>" .. i18n("chart") .. "</th><th>" .. i18n("traffic") .. "</th></tr>\n")
|
|
for pname,pbytes in pairs(ifstats.profiles) do
|
|
local trimmed = trimSpace(pname)
|
|
local statschart_icon = ''
|
|
|
|
if ts_utils.exists("profile:traffic", {ifid=ifid}) then
|
|
statschart_icon = '<A HREF=\"'..ntop.getHttpPrefix()..'/lua/profile_details.lua?profile='..pname..'\"><i class=\'fas fa-chart-area fa-lg\'></i></A>'
|
|
end
|
|
|
|
print("<tr><th>"..pname.."</th><td align=center>"..statschart_icon.."</td><td><span id=profile_"..trimmed..">"..bytesToSize(pbytes).."</span> <span id=profile_"..trimmed.."_trend></span></td></tr>\n")
|
|
end
|
|
|
|
print [[
|
|
</table>
|
|
|
|
<script>
|
|
var last_profile = [];
|
|
var traffic_profiles_interval = window.setInterval(function() {
|
|
$.ajax({
|
|
type: 'GET',
|
|
url: ']]
|
|
print (ntop.getHttpPrefix())
|
|
print [[/lua/rest/get/interface/data.lua',
|
|
data: { iffilter: "]] print(tostring(interface.name2id(if_name))) print [[" },
|
|
success: function(content) {
|
|
var profiles = content;
|
|
|
|
if(profiles["profiles"] != null) {
|
|
for (key in profiles["profiles"]) {
|
|
k = '#profile_'+key.replace(" ", "");
|
|
v = profiles["profiles"][key];
|
|
$(k).html(bytesToVolume(v));
|
|
k += "_trend";
|
|
last = last_profile[key];
|
|
if(last == null) { last = 0; }
|
|
$(k).html(get_trend(last, v));
|
|
}
|
|
|
|
last_profile = profiles["profiles"];
|
|
}
|
|
}
|
|
});
|
|
}, ]] print(getInterfaceRefreshRate(ifstats.id).."") print[[ * 1000);
|
|
|
|
</script>
|
|
]]
|
|
|
|
elseif(page == "traffic_recording" and has_traffic_recording_page) then
|
|
if not dismiss_recording_providers_reminder then
|
|
print('<div id="traffic-recording-providers-detected" class="alert alert-info alert-dismissable"><button type="button" class="close" data-dismiss="alert" aria-label="close">×</button>'..i18n('traffic_recording.msg_external_providers_detected', {url = ntop.getHttpPrefix().."/lua/if_stats.lua?page=config"})..'</div>')
|
|
|
|
print [[
|
|
<script>
|
|
$('#traffic-recording-providers-detected').on('close.bs.alert', function () {
|
|
var dismiss_notice = $.ajax({
|
|
type: 'POST',
|
|
url: ']]
|
|
print (ntop.getHttpPrefix())
|
|
print [[/lua/traffic_recording_config.lua',
|
|
data: { ifid: ]] print(tostring(ifstats.id)) print[[,
|
|
dismiss_external_providers_reminder: true,
|
|
csrf: "]] print(ntop.getRandomCSRFValue()) print[["},
|
|
success: function() {},
|
|
complete: function() {},
|
|
});
|
|
|
|
});
|
|
</script>
|
|
]]
|
|
end
|
|
|
|
local tab = _GET["tab"] or "config"
|
|
local recording_enabled = recording_utils.isEnabled(ifstats.id)
|
|
-- config tab is only shown when the recording service is managed by ntopng
|
|
-- otherwise it is assumed that the user is managing the service manually with n2disk
|
|
local config_enabled = (recording_utils.getCurrentTrafficRecordingProvider(ifstats.id) == "ntopng")
|
|
|
|
if tab == "config" and not config_enabled then
|
|
if recording_enabled then tab = "status" else tab = "" end
|
|
end
|
|
if (tab == "status" or tab == "jobs") and not recording_enabled then
|
|
if config_enabled then tab = "config" else tab = "" end
|
|
end
|
|
|
|
if(_SERVER["REQUEST_METHOD"] == "POST") and (tab == "config") then
|
|
recording_enabled = not isEmptyString(_POST["record_traffic"])
|
|
end
|
|
|
|
print('<ul id="traffic-recording-nav" class="nav nav-tabs" role="tablist">')
|
|
|
|
if config_enabled then
|
|
print('<li class="nav-item '.. ternary(tab == "config", "active", "") ..'"><a class="nav-link '.. ternary(tab == "config", "active", "") ..'" href="?ifid='.. ifstats.id
|
|
..'&page=traffic_recording"><i class="fas fa-cog"></i> '.. i18n("traffic_recording.settings") ..'</a></li>')
|
|
end
|
|
|
|
if recording_enabled then
|
|
print('<li class="nav-item '.. ternary(tab == "status", "active", "") ..'"><a class="nav-link '.. ternary(tab == "status", "active", "") ..'" href="?ifid='.. ifstats.id
|
|
..'&page=traffic_recording&tab=status">'.. i18n("status") ..'</a></li>')
|
|
|
|
if ntop.isEnterprise() then
|
|
print('<li class="nav-item '.. ternary(tab == "jobs", "active", "") ..'"><a class="nav-link '.. ternary(tab == "jobs", "active", "") ..'" href="?ifid='.. ifstats.id
|
|
..'&page=traffic_recording&tab=jobs">'.. i18n("traffic_recording.jobs") ..'</a></li>')
|
|
end
|
|
end
|
|
|
|
print('</ul>')
|
|
print('<div class="tab-content">')
|
|
|
|
if recording_enabled and tab == "status" then
|
|
dofile(dirs.installdir .. "/scripts/lua/inc/traffic_recording_status.lua")
|
|
elseif recording_enabled and ntop.isEnterprise() and tab == "jobs" then
|
|
dofile(dirs.installdir .. "/scripts/lua/inc/traffic_recording_jobs.lua")
|
|
elseif config_enabled and tab == "config" then -- config, default
|
|
dofile(dirs.installdir .. "/scripts/lua/inc/traffic_recording_config.lua")
|
|
end
|
|
|
|
print('</div></div>')
|
|
elseif(page == "alerts") then
|
|
|
|
printAlertTables("interface", ifname_clean,
|
|
"if_stats.lua", {ifid=ifid}, if_name, "interface",
|
|
{enable_label = i18n("show_alerts.trigger_iface_alert_descr", {iface = short_name})})
|
|
|
|
elseif(page == "config") then
|
|
if(not isAdministrator()) then
|
|
return
|
|
end
|
|
|
|
local messages = {}
|
|
|
|
-- Flow dump check
|
|
local interface_flow_dump = true
|
|
if(prefs.is_dump_flows_enabled and ifstats.isView == false) then
|
|
interface_flow_dump = (ntop.getPref("ntopng.prefs.ifid_"..ifId..".is_flow_dump_disabled") ~= "1")
|
|
|
|
if _SERVER["REQUEST_METHOD"] == "POST" then
|
|
local new_value = (_POST["interface_flow_dump"] == "1")
|
|
|
|
if new_value ~= interface_flow_dump then
|
|
-- Value changed
|
|
interface_flow_dump = new_value
|
|
ntop.setPref("ntopng.prefs.ifid_"..ifId..".is_flow_dump_disabled", ternary(interface_flow_dump, "0", "1"))
|
|
|
|
messages[#messages + 1] = {
|
|
type = "warning",
|
|
text = i18n("prefs.restart_needed", {product=info.product}),
|
|
}
|
|
end
|
|
end
|
|
end
|
|
|
|
if not table.empty(messages) then
|
|
printMessageBanners(messages)
|
|
print("<br>")
|
|
end
|
|
|
|
print[[
|
|
<form id="iface_config" lass="form-inline" method="post">
|
|
<input name="csrf" type="hidden" value="]] print(ntop.getRandomCSRFValue()) print[[" />
|
|
<table id="iface_config_table" class="table table-bordered table-striped">]]
|
|
|
|
if ((not is_pcap_dump) and
|
|
(ifstats.name ~= nil) and
|
|
(ifstats.name ~= "dummy")) then
|
|
-- Custom name
|
|
print[[
|
|
<tr>
|
|
<th>]] print(i18n("if_stats_config.custom_name")) print[[</th>
|
|
<td>]]
|
|
local label = getHumanReadableInterfaceName(ifstats.name)
|
|
inline_input_form("custom_name", "Custom Name",
|
|
i18n("if_stats_config.custom_name_popup_msg"),
|
|
label, isAdministrator(), 'autocorrect="off" spellcheck="false"')
|
|
print[[
|
|
</td>
|
|
</tr>]]
|
|
|
|
-- Interface speed
|
|
if not have_nedge then
|
|
print[[
|
|
<tr>
|
|
<th>]] print(i18n("if_stats_config.interface_speed")) print[[</th>
|
|
<td>]]
|
|
local ifspeed = getInterfaceSpeed(ifstats.id)
|
|
inline_input_form("ifSpeed", "Interface Speed",
|
|
i18n("if_stats_config.interface_speed_popup_msg"),
|
|
ifspeed, isAdministrator(), 'type="number" min="1"')
|
|
print[[
|
|
</td>
|
|
</tr>]]
|
|
end
|
|
|
|
-- Interface refresh rate
|
|
print[[
|
|
<tr>
|
|
<th>]] print(i18n("if_stats_config.refresh_rate")) print[[</th>
|
|
<td>]]
|
|
local refreshrate = getInterfaceRefreshRate(ifstats.id)
|
|
inline_input_form("ifRate", "Refresh Rate",
|
|
i18n("if_stats_config.refresh_rate_popup_msg"),
|
|
refreshrate, isAdministrator(), 'type="number" min="1"')
|
|
print[[
|
|
</td>
|
|
</tr>]]
|
|
end
|
|
|
|
if not have_nedge then
|
|
-- Scaling factor
|
|
if interface.isPacketInterface() and not have_nedge then
|
|
local label = ntop.getCache(getRedisIfacePrefix(ifid)..".scaling_factor")
|
|
if((label == nil) or (label == "")) then label = "1" end
|
|
|
|
print[[
|
|
<tr>
|
|
<th>]] print(i18n("if_stats_config.scaling_factor")) print[[</th>
|
|
<td>]]
|
|
inline_input_form("scaling_factor", "Scaling Factor",
|
|
i18n("if_stats_config.scaling_factor_popup_msg"),
|
|
label, isAdministrator(), 'type="number" min="1" step="1"')
|
|
print[[
|
|
</td>
|
|
</tr>]]
|
|
end
|
|
end
|
|
|
|
local serialize_by_mac
|
|
local serialize_by_mac_key = string.format("ntopng.prefs.ifid_%u.serialize_local_broadcast_hosts_as_macs", ifId)
|
|
|
|
if(_POST["lbd_hosts_as_macs"] ~= nil) then
|
|
serialize_by_mac = _POST["lbd_hosts_as_macs"]
|
|
|
|
if ntop.getPref(serialize_by_mac_key) ~= serialize_by_mac then
|
|
ntop.setPref(serialize_by_mac_key, serialize_by_mac)
|
|
interface.updateLbdIdentifier()
|
|
end
|
|
else
|
|
serialize_by_mac = ntop.getPref(serialize_by_mac_key)
|
|
end
|
|
|
|
-- LBD identifier
|
|
print[[
|
|
<tr>
|
|
<th width="30%">]] print(i18n("prefs.toggle_host_tskey_title")) print[[ <i class="fas fa-info-circle" title="]] print(i18n("prefs.toggle_host_tskey_description")) print[["></i></th>
|
|
<td>]]
|
|
inline_select_form("lbd_hosts_as_macs", {i18n("ip_address"), i18n("mac_address")}, {"0", "1"}, serialize_by_mac)
|
|
print[[
|
|
</td>
|
|
</tr>]]
|
|
|
|
-- Hidden from top
|
|
local rv = ntop.getMembersCache(getHideFromTopSet(ifstats.id)) or {}
|
|
local members = {}
|
|
|
|
-- impose sort order
|
|
for _, net in pairsByValues(rv, asc) do
|
|
members[#members + 1] = net
|
|
end
|
|
|
|
local hide_top = table.concat(members, ",")
|
|
|
|
print[[
|
|
<tr>
|
|
<th>]] print(i18n("if_stats_config.hide_from_top_networks")) print[[</th>
|
|
<td>]]
|
|
|
|
print('<input style="width:36em;" class="form-control" name="hide_from_top" placeholder="'..i18n("if_stats_config.hide_from_top_networks_descr", {example="192.168.1.1,192.168.100.0/24"})..'" value="' .. hide_top .. '">')
|
|
|
|
print[[
|
|
</td>
|
|
</tr>]]
|
|
|
|
-- per-interface RRD generation
|
|
local interface_rrd_creation = true
|
|
local interface_rrd_creation_checked = "checked"
|
|
|
|
if _SERVER["REQUEST_METHOD"] == "POST" then
|
|
if _POST["interface_rrd_creation"] ~= "1" then
|
|
interface_rrd_creation = false
|
|
interface_rrd_creation_checked = ""
|
|
end
|
|
|
|
ntop.setPref("ntopng.prefs.ifid_"..ifId..".interface_rrd_creation", tostring(interface_rrd_creation))
|
|
else
|
|
interface_rrd_creation = ntop.getPref("ntopng.prefs.ifid_"..ifId..".interface_rrd_creation")
|
|
|
|
if interface_rrd_creation == "false" then
|
|
interface_rrd_creation = false
|
|
interface_rrd_creation_checked = ""
|
|
end
|
|
end
|
|
|
|
print [[<tr>
|
|
<th>]] print(i18n("if_stats_config.interface_rrd_creation")) print[[</th>
|
|
<td>
|
|
<input id="interface_rrd_creation" name="interface_rrd_creation" type="checkbox" value="1" ]] print(interface_rrd_creation_checked) print[[>
|
|
</td>
|
|
</tr>
|
|
|
|
<script type="text/javascript">
|
|
$("#interface_rrd_creation").change(function(){
|
|
var self = this;
|
|
$("#iface_config_table tr.rrd_creation").toggle(self.checked);
|
|
}).change();
|
|
</script>
|
|
]]
|
|
|
|
-- Skip timeseries for hosts with unidirectional traffic
|
|
local interface_one_way_hosts_rrd_creation = true
|
|
local interface_one_way_hosts_rrd_creation_checked = "checked"
|
|
|
|
if _SERVER["REQUEST_METHOD"] == "POST" then
|
|
if _POST["interface_one_way_hosts_rrd_creation"] ~= "1" then
|
|
interface_one_way_hosts_rrd_creation = false
|
|
interface_one_way_hosts_rrd_creation_checked = ""
|
|
end
|
|
|
|
ntop.setPref("ntopng.prefs.ifid_"..ifId..".interface_one_way_hosts_rrd_creation", tostring(interface_one_way_hosts_rrd_creation))
|
|
else
|
|
interface_one_way_hosts_rrd_creation = ntop.getPref("ntopng.prefs.ifid_"..ifId..".interface_one_way_hosts_rrd_creation")
|
|
|
|
if interface_one_way_hosts_rrd_creation == "false" then
|
|
interface_one_way_hosts_rrd_creation = false
|
|
interface_one_way_hosts_rrd_creation_checked = ""
|
|
end
|
|
end
|
|
|
|
print [[<tr class="rrd_creation" ]] if not interface_rrd_creation then print("style='display:none;'") end print[[>
|
|
<th>]] print(i18n("if_stats_config.interface_one_way_hosts_rrd_creation")) print[[</th>
|
|
<td>
|
|
<input name="interface_one_way_hosts_rrd_creation" type="checkbox" value="1" ]] print(interface_one_way_hosts_rrd_creation_checked) print[[>
|
|
</td>
|
|
</tr>]]
|
|
|
|
-- per-interface Top-Talkers generation
|
|
local interface_top_talkers_creation = true
|
|
local interface_top_talkers_creation_checked = "checked"
|
|
|
|
if _SERVER["REQUEST_METHOD"] == "POST" then
|
|
if _POST["interface_top_talkers_creation"] ~= "1" then
|
|
interface_top_talkers_creation = false
|
|
interface_top_talkers_creation_checked = ""
|
|
top_talkers_utils.disableTop(ifId)
|
|
else
|
|
top_talkers_utils.enableTop(ifId)
|
|
end
|
|
else
|
|
if not top_talkers_utils.areTopEnabled(ifId) then
|
|
interface_top_talkers_creation_checked = ""
|
|
end
|
|
end
|
|
|
|
print [[<tr>
|
|
<th>]] print(i18n("if_stats_config.interface_top_talkers_creation")) print[[</th>
|
|
<td>
|
|
<input name="interface_top_talkers_creation" type="checkbox" value="1" ]] print(interface_top_talkers_creation_checked) print[[>
|
|
</td>
|
|
</tr>]]
|
|
|
|
-- Flow dump
|
|
if(prefs.is_dump_flows_enabled and ifstats.isView == false) then
|
|
local interface_flow_dump_checked = ternary(interface_flow_dump, "checked", "")
|
|
|
|
print [[<tr>
|
|
<th>]] print(i18n("if_stats_config.dump_flows_to_database")) print[[</th>
|
|
<td>
|
|
<input name="interface_flow_dump" type="checkbox" value="1" ]] print(interface_flow_dump_checked) print[[>
|
|
</td>
|
|
</tr>]]
|
|
end
|
|
|
|
-- Mirrored Traffic
|
|
if not ntop.isnEdge() and interface.isPacketInterface() then
|
|
local is_mirrored_traffic = false
|
|
local is_mirrored_traffic_checked = ""
|
|
local is_mirrored_traffic_pref = string.format("ntopng.prefs.ifid_%d.is_traffic_mirrored", ifId)
|
|
|
|
if _SERVER["REQUEST_METHOD"] == "POST" then
|
|
if _POST["is_mirrored_traffic"] == "1" then
|
|
is_mirrored_traffic = true
|
|
is_mirrored_traffic_checked = "checked"
|
|
end
|
|
|
|
ntop.setPref(is_mirrored_traffic_pref,
|
|
ternary(is_mirrored_traffic == true, '1', '0'))
|
|
interface.updateTrafficMirrored()
|
|
else
|
|
is_mirrored_traffic = ternary(ntop.getPref(is_mirrored_traffic_pref) == '1', true, false)
|
|
|
|
if is_mirrored_traffic then
|
|
is_mirrored_traffic_checked = "checked"
|
|
end
|
|
end
|
|
|
|
print [[<tr>
|
|
<th>]] print(i18n("if_stats_config.is_mirrored_traffic")) print[[</th>
|
|
<td>
|
|
<input type="checkbox" name="is_mirrored_traffic" value="1" ]] print(is_mirrored_traffic_checked) print[[>
|
|
</td>
|
|
</tr>]]
|
|
end
|
|
|
|
-- Discard Probing Traffic
|
|
if not ntop.isnEdge() and not interface.isPacketInterface() then
|
|
local discard_probing_traffic = false
|
|
local discard_probing_traffic_checked = ""
|
|
local discard_probing_traffic_pref = string.format("ntopng.prefs.ifid_%d.discard_probing_traffic", ifId)
|
|
|
|
if _SERVER["REQUEST_METHOD"] == "POST" then
|
|
if _POST["discard_probing_traffic"] == "1" then
|
|
discard_probing_traffic = true
|
|
discard_probing_traffic_checked = "checked"
|
|
end
|
|
|
|
ntop.setPref(discard_probing_traffic_pref,
|
|
ternary(discard_probing_traffic == true, '1', '0'))
|
|
interface.updateDiscardProbingTraffic()
|
|
else
|
|
discard_probing_traffic = ternary(ntop.getPref(discard_probing_traffic_pref) == '1', true, false)
|
|
|
|
if discard_probing_traffic then
|
|
discard_probing_traffic_checked = "checked"
|
|
end
|
|
end
|
|
|
|
print [[<tr>
|
|
<th>]] print(i18n("if_stats_config.discard_probing_traffic")) print[[</th>
|
|
<td>
|
|
<input type="checkbox" name="discard_probing_traffic" value="1" ]] print(discard_probing_traffic_checked) print[[>
|
|
</td>
|
|
</tr>]]
|
|
end
|
|
|
|
-- per-interface Network Discovery
|
|
if interface.isDiscoverableInterface() then
|
|
local discover = require "discover_utils"
|
|
|
|
local interface_network_discovery = true
|
|
local interface_network_discovery_checked = "checked"
|
|
|
|
if _SERVER["REQUEST_METHOD"] == "POST" then
|
|
if _POST["interface_network_discovery"] ~= "1" then
|
|
interface_network_discovery = false
|
|
interface_network_discovery_checked = ""
|
|
end
|
|
|
|
ntop.setPref(discover.getInterfaceNetworkDiscoveryEnabledKey(ifId), tostring(interface_network_discovery))
|
|
else
|
|
interface_network_discovery = ntop.getPref(discover.getInterfaceNetworkDiscoveryEnabledKey(ifId))
|
|
|
|
if interface_network_discovery == "false" then
|
|
interface_network_discovery = false
|
|
interface_network_discovery_checked = ""
|
|
end
|
|
end
|
|
|
|
print [[<tr>
|
|
<th>]] print(i18n("if_stats_config.interface_network_discovery")) print[[</th>
|
|
<td>
|
|
<input type="checkbox" name="interface_network_discovery" value="1" ]] print(interface_network_discovery_checked) print[[>
|
|
</td>
|
|
</tr>]]
|
|
end
|
|
|
|
if interface.isPacketInterface() and not ifstats.isDynamic then
|
|
local cur_companion = companion_interface_utils.getCurrentCompanion(ifstats.id)
|
|
local companions = companion_interface_utils.getAvailableCompanions()
|
|
|
|
if table.len(companions) > 1 then
|
|
print [[
|
|
<tr>
|
|
<th>]] print(i18n("if_stats_config.companion_interface")) print[[</th>
|
|
<td>
|
|
<select name="companion_interface" class="form-control" style="width:36em; display:inline;">]]
|
|
|
|
for _, companion in ipairs(companions) do
|
|
local companion_id = companion["ifid"]
|
|
local companion_name = companion["ifname"]
|
|
local label = companion_name
|
|
if companion_name ~= "None" then
|
|
label = getHumanReadableInterfaceName(companion_name)
|
|
end
|
|
|
|
print[[<option value="]] print(companion_id) print[[" ]] if cur_companion == companion_id then print('selected="selected"') end print[[">]] print(label) print[[</option>]]
|
|
end
|
|
|
|
print[[
|
|
</select>
|
|
</td>
|
|
</tr>]]
|
|
end
|
|
end
|
|
|
|
if has_traffic_recording_page then
|
|
local cur_provider = recording_utils.getCurrentTrafficRecordingProvider(ifstats.id)
|
|
local providers = recording_utils.getAvailableTrafficRecordingProviders()
|
|
|
|
-- only 1 provider means there's only the default ntopng
|
|
-- so no need to show this extra menu entry
|
|
if table.len(providers) > 1 then
|
|
print [[
|
|
<tr>
|
|
<th>]] print(i18n("traffic_recording.traffic_recording_provider")) print[[</th>
|
|
<td>
|
|
<select name="traffic_recording_provider" class="form-control" style="width:36em; display:inline;">]]
|
|
|
|
for _, provider in pairs(providers) do
|
|
local label = string.format("%s", provider["name"])
|
|
if provider["conf"] then
|
|
label = string.format("%s (%s)", provider["name"], provider["conf"])
|
|
end
|
|
|
|
if provider["name"] == "ntopng" and not interface.isPacketInterface() then
|
|
-- non-packet interfaces
|
|
label = "none"
|
|
end
|
|
|
|
print[[<option value="]] print(provider["name"]) print[[" ]] if cur_provider == provider["name"] then print('selected="selected"') end print[[">]] print(label) print[[</option>]]
|
|
end
|
|
|
|
print[[
|
|
</select>
|
|
</td>
|
|
</tr>]]
|
|
end
|
|
end
|
|
|
|
if not ifstats.isDynamic then
|
|
local cur_mode = ntop.getCache(disaggregation_criterion_key)
|
|
if isEmptyString(cur_mode) then
|
|
cur_mode = "none"
|
|
end
|
|
|
|
local labels = {
|
|
i18n("prefs.none"),
|
|
i18n("prefs.vlan"),
|
|
i18n("prefs.probe_ip_address"),
|
|
i18n("prefs.flow_interface"),
|
|
i18n("prefs.ingress_flow_interface"),
|
|
i18n("prefs.ingress_vrf_id")
|
|
}
|
|
|
|
local values = {}
|
|
if is_packet_interface then
|
|
values = {
|
|
"none",
|
|
"vlan"
|
|
}
|
|
else
|
|
values = {
|
|
"none",
|
|
"vlan",
|
|
"probe_ip",
|
|
"iface_idx",
|
|
"ingress_iface_idx",
|
|
"ingress_vrf_id"
|
|
}
|
|
end
|
|
|
|
print [[
|
|
<tr>
|
|
<th>]] print(i18n("prefs.dynamic_interfaces_creation_title")) print[[</th>
|
|
<td>
|
|
<select name="disaggregation_criterion" class="form-control" style="width:36em; display:inline;">]]
|
|
|
|
for k, value in ipairs(values) do
|
|
local label = labels[k]
|
|
print[[<option value="]] print(value) print[[" ]] if cur_mode == value then print('selected="selected"') end print[[">]] print(label) print[[</option>]]
|
|
end
|
|
|
|
print[[
|
|
</select>
|
|
]]
|
|
print ("<br><br><small><p><b>"..i18n("notes").."</b><ul>"..
|
|
"<li>"..i18n("prefs.dynamic_interfaces_creation_description").."</li>"..
|
|
"<li>"..i18n("prefs.dynamic_interfaces_creation_note_0").."</li>"..
|
|
"<li>"..i18n("prefs.dynamic_interfaces_creation_note_4").."</li>"..
|
|
"<li>"..i18n("prefs.dynamic_interfaces_creation_note_1").."</li>")
|
|
if not is_packet_interface then
|
|
print("<li>"..i18n("prefs.dynamic_interfaces_creation_note_2").."</li>"..
|
|
"<li>"..i18n("prefs.dynamic_interfaces_creation_note_3").."</li>")
|
|
end
|
|
print [[
|
|
</ul></small>
|
|
</td>
|
|
</tr>]]
|
|
|
|
-- Show dynamic traffic in the master interface
|
|
local show_dyn_iface_traffic = false
|
|
local show_dyn_iface_traffic_checked = ""
|
|
local show_dyn_iface_traffic_pref = string.format("ntopng.prefs.ifid_%d.show_dynamic_interface_traffic", ifId)
|
|
|
|
if _SERVER["REQUEST_METHOD"] == "POST" then
|
|
if _POST["show_dyn_iface_traffic"] == "1" then
|
|
show_dyn_iface_traffic = true
|
|
show_dyn_iface_traffic_checked = "checked"
|
|
end
|
|
|
|
ntop.setPref(show_dyn_iface_traffic_pref,
|
|
ternary(show_dyn_iface_traffic == true, '1', '0'))
|
|
interface.updateDynIfaceTrafficPolicy()
|
|
else
|
|
show_dyn_iface_traffic = ternary(ntop.getPref(show_dyn_iface_traffic_pref) == '1', true, false)
|
|
|
|
if show_dyn_iface_traffic then
|
|
show_dyn_iface_traffic_checked = "checked"
|
|
end
|
|
end
|
|
|
|
print [[<tr>
|
|
<th>]] print(i18n("if_stats_config.show_dyn_iface_traffic")) print[[</th>
|
|
<td>
|
|
<input type="checkbox" name="show_dyn_iface_traffic" value="1" ]] print(show_dyn_iface_traffic_checked) print[[>
|
|
<br><br><small><p><b>]] print(i18n("notes")) print [[</b><ul><li>]] print(i18n("if_stats_config.show_dyn_iface_traffic_note")) print [[</li></ul></p></small>
|
|
</td>
|
|
</tr>]]
|
|
|
|
end
|
|
|
|
print[[
|
|
</table>
|
|
<button class="btn btn-primary" style="float:right; margin-right:1em; margin-left: auto" disabled="disabled" type="submit">]] print(i18n("save_settings")) print[[</button><br><br>
|
|
</form>
|
|
<script>
|
|
aysHandleForm("#iface_config");
|
|
</script>]]
|
|
|
|
elseif(page == "internals") then
|
|
internals_utils.printInternals(ifid)
|
|
print [[
|
|
</table>
|
|
]]
|
|
|
|
|
|
elseif(page == "snmp_bind") then
|
|
if ((not hasSnmpDevices(ifstats.id)) or (not is_packet_interface)) then
|
|
return
|
|
end
|
|
|
|
local snmp_host = _POST["ip"]
|
|
local snmp_interface = _POST["snmp_port_idx"] or ""
|
|
|
|
if (snmp_host ~= nil) then
|
|
-- snmp_host can be empty
|
|
set_snmp_bound_interface(ifstats.id, snmp_host, snmp_interface)
|
|
else
|
|
local value = get_snmp_bound_interface(ifstats.id)
|
|
|
|
if value ~= nil then
|
|
snmp_host = value.snmp_device
|
|
snmp_interface = value.snmp_port
|
|
end
|
|
end
|
|
|
|
local snmp_devices = get_snmp_devices(ifstats.id)
|
|
|
|
print[[
|
|
<form id="snmp_bind_form" method="post" style="margin-bottom:3em;">
|
|
<table class="table table-bordered table-striped">]]
|
|
|
|
print[[
|
|
<tr>
|
|
<th>]] print(i18n("snmp.snmp_device")) print[[</th>
|
|
<td>
|
|
<select class="form-control" style="width:30em; display:inline;" id="snmp_bind_device" name="ip">
|
|
<option]] if isEmptyString(snmp_host) then print(" selected") end print[[ value="">Not Bound</option>
|
|
]]
|
|
|
|
for _, device in pairs(snmp_devices) do
|
|
print('<option value="'..device.ip..'"')
|
|
if (snmp_host == device.ip) then
|
|
print(' selected')
|
|
end
|
|
print('>'..device.name..' ('..device.ip..')</option>')
|
|
end
|
|
|
|
print[[
|
|
</select>
|
|
<a class="btn" id="snmp_device_link" style="padding:0.2em; margin-left:0.3em;" href="#"]]
|
|
|
|
if isEmptyString(snmp_host) then
|
|
print(" disabled")
|
|
end
|
|
|
|
print[[>]] print(i18n("snmp.view_device")) print[[</i></a>
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<th>]] print(i18n("snmp.snmp_interface")) print[[</th>
|
|
<td>
|
|
<select class="form-control" style="width:30em; display:inline;" id="snmp_bind_interface" name="snmp_port_idx">]]
|
|
|
|
if not isEmptyString(snmp_interface) then
|
|
-- This is neeeded to initialized ays form fields
|
|
print('<option value="'..snmp_interface..'" selected></option>')
|
|
end
|
|
|
|
print[[
|
|
</select>
|
|
<img id="snmp_loading" style="margin-left:0.5em; visibility:hidden;" src="]] print(ntop.getHttpPrefix()) print[[/img/loading.gif"\>
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
|
|
<input type="hidden" name="csrf" value="]] print(ntop.getRandomCSRFValue()) print[[" />
|
|
<button id="snmp_bind_submit" class="btn btn-primary" style="float:right; margin-right:1em; margin-left: auto" disabled="disabled" type="submit">]] print(i18n("save_settings")) print[[</button>
|
|
</form>
|
|
|
|
<b>]] print(i18n("snmp.note") .. ":") print[[</b><br>
|
|
<small>]] print(i18n("snmp.bound_interface_description")) print[[</small>
|
|
|
|
<script>
|
|
var snmp_bind_port_ajax = null;
|
|
var snmp_bind_first_init = true;
|
|
|
|
function snmp_set_loading_status(is_loading) {
|
|
if (is_loading) {
|
|
$("#snmp_loading").css("visibility", "");
|
|
$("#snmp_bind_submit").addClass("disabled");
|
|
} else {
|
|
$("#snmp_loading").css("visibility", "hidden");
|
|
$("#snmp_bind_submit").removeClass("disabled");
|
|
}
|
|
}
|
|
|
|
function snmp_check_snmp_list() {
|
|
var iflist = $("#snmp_bind_interface");
|
|
|
|
if ($("option", iflist).length > 0)
|
|
iflist.removeAttr("disabled");
|
|
else
|
|
iflist.attr("disabled", "disabled");
|
|
|
|
aysRecheckForm('#snmp_bind_form');
|
|
}
|
|
|
|
function snmp_recheck_selection() {
|
|
var iflist = $("#snmp_bind_interface");
|
|
var selected_device = $("#snmp_bind_device option:selected").val();
|
|
|
|
// Remove existing entries
|
|
$("option", iflist).remove();
|
|
|
|
if (snmp_bind_port_ajax != null) {
|
|
snmp_bind_port_ajax.abort();
|
|
snmp_bind_port_ajax = null;
|
|
}
|
|
snmp_check_snmp_list();
|
|
|
|
if (selected_device) {
|
|
snmp_set_loading_status(true);
|
|
$("#snmp_device_link").removeAttr("disabled");
|
|
$("#snmp_device_link").attr("href", "]] print(ntop.getHttpPrefix()) print[[/lua/pro/enterprise/snmp_device_details.lua?host=" + selected_device);
|
|
|
|
snmp_bind_port_ajax = $.ajax({
|
|
type: 'GET',
|
|
url: ']]
|
|
print (ntop.getHttpPrefix())
|
|
print [[/lua/pro/enterprise/get_snmp_device_details.lua',
|
|
data: { ifid: ]] print(ifstats.id) print[[, ip: selected_device, iftype_filter:'snmp_binding' },
|
|
success: function(rsp) {
|
|
if (rsp.interfaces) {
|
|
for (var ifidx in rsp.interfaces) {
|
|
var snmp_interface = rsp.interfaces[ifidx];
|
|
var selected = snmp_interface.bound ? " selected" : "";
|
|
iflist.append('<option value="' + ifidx + '"' + selected + '>' + snmp_interface.label + '</option>');
|
|
snmp_interface.label;
|
|
}
|
|
|
|
snmp_check_snmp_list();
|
|
}
|
|
}, complete: function() {
|
|
snmp_set_loading_status(false);
|
|
}
|
|
});
|
|
} else {
|
|
snmp_set_loading_status(false);
|
|
$("#snmp_device_link").attr("disabled", "disabled");
|
|
snmp_check_snmp_list();
|
|
}
|
|
}
|
|
|
|
aysHandleForm("#snmp_bind_form");
|
|
snmp_check_snmp_list();
|
|
|
|
$("#snmp_bind_device").change(snmp_recheck_selection);
|
|
$(function() {
|
|
// let it pass some time to ays initialization
|
|
snmp_recheck_selection();
|
|
});
|
|
</script>]]
|
|
elseif(page == "sub_interfaces") then
|
|
if(isAdministrator() and ntop.isEnterprise()) then
|
|
dofile(dirs.installdir .. "/pro/scripts/lua/enterprise/sub_interfaces.lua")
|
|
end
|
|
elseif(page == "pools") then
|
|
dofile(dirs.installdir .. "/scripts/lua/admin/host_pools.lua")
|
|
elseif(page == "dhcp") then
|
|
dofile(dirs.installdir .. "/scripts/lua/admin/dhcp.lua")
|
|
elseif page == "traffic_report" then
|
|
dofile(dirs.installdir .. "/pro/scripts/lua/enterprise/traffic_report.lua")
|
|
end
|
|
|
|
print("<script>\n")
|
|
print("var last_pkts = " .. ifstats.stats.packets .. ";\n")
|
|
print("var last_in_pkts = " .. ifstats.eth.ingress.packets .. ";\n")
|
|
print("var last_out_pkts = " .. ifstats.eth.egress.packets .. ";\n")
|
|
print("var last_drops = " .. ifstats.stats.drops .. ";\n")
|
|
print("var last_engaged_alerts = " .. ifstats.num_alerts_engaged .. ";\n")
|
|
print("var last_dropped_alerts = " .. ifstats.num_dropped_alerts .. ";\n")
|
|
|
|
if(ifstats.zmqRecvStats ~= nil) then
|
|
print("var last_zmq_time = 0;\n")
|
|
print("var last_zmq_flows = ".. ifstats.zmqRecvStats.flows .. ";\n")
|
|
print("var last_zmq_events = ".. ifstats.zmqRecvStats.events .. ";\n")
|
|
print("var last_zmq_counters = ".. ifstats.zmqRecvStats.counters .. ";\n")
|
|
print("var last_zmq_msg_drops = ".. ifstats.zmqRecvStats.zmq_msg_drops .. ";\n")
|
|
print("var last_zmq_msg_rcvd = ".. ifstats.zmqRecvStats.zmq_msg_rcvd .. ";\n")
|
|
print("var last_zmq_avg_msg_flows = 1;\n")
|
|
|
|
print("var last_probe_zmq_exported_flows = ".. (ifstats["zmq.num_flow_exports"] or 0) .. ";\n")
|
|
end
|
|
|
|
if ifstats.stats.discarded_probing_packets then
|
|
print("var last_discarded_probing_pkts = " .. ifstats.stats.discarded_probing_packets .. ";\n")
|
|
end
|
|
|
|
print [[
|
|
|
|
var resetInterfaceCounters = function(drops_only) {
|
|
var action = "reset_all";
|
|
if(drops_only) action = "reset_drops";
|
|
$.ajax({ type: 'post',
|
|
url: ']]
|
|
print (ntop.getHttpPrefix())
|
|
print [[/lua/reset_stats.lua',
|
|
data: {ifid: ]] print(ifstats.id) print [[, resetstats_mode: action, csrf: "]] print(ntop.getRandomCSRFValue()) print[["},
|
|
success: function(rsp) {},
|
|
complete: function() {
|
|
/* reload the page to generate a new CSRF */
|
|
window.location.href = window.location.href;
|
|
}
|
|
});
|
|
}
|
|
|
|
setInterval(function() {
|
|
$.ajax({
|
|
type: 'GET',
|
|
url: ']]
|
|
print (ntop.getHttpPrefix())
|
|
print [[/lua/rest/get/interface/data.lua',
|
|
data: { iffilter: "]] print(tostring(interface.name2id(ifstats.name))) print [[" },
|
|
success: function(rsp) {
|
|
|
|
var v = bytesToVolume(rsp.bytes);
|
|
$('#if_bytes').html(v);
|
|
|
|
$('#if_in_bytes').html(bytesToVolume(rsp.bytes_download));
|
|
$('#if_out_bytes').html(bytesToVolume(rsp.bytes_upload));
|
|
$('#if_in_pkts').html(addCommas(rsp.packets_download) + " Pkts");
|
|
$('#if_out_pkts').html(addCommas(rsp.packets_upload) + " Pkts");
|
|
$('#pkts_in_trend').html(get_trend(last_in_pkts, rsp.bytes_download));
|
|
$('#pkts_out_trend').html(get_trend(last_out_pkts, rsp.bytes_upload));
|
|
last_in_pkts = rsp.bytes_download;
|
|
last_out_pkts = rsp.bytes_upload;
|
|
|
|
if (typeof rsp.zmqRecvStats !== 'undefined') {
|
|
var diff, time_diff, label;
|
|
var now = (new Date()).getTime();
|
|
|
|
if(last_zmq_time > 0) {
|
|
time_diff = now - last_zmq_time;
|
|
diff = rsp.zmqRecvStats.flows - last_zmq_flows;
|
|
|
|
if(diff > 0) {
|
|
rate = ((diff * 1000)/time_diff).toFixed(1);
|
|
label = " [" + fflows(rate) + "] " + get_trend(1,0);
|
|
} else {
|
|
label = " "+get_trend(0,0);
|
|
}
|
|
} else {
|
|
label = " "+get_trend(0,0);
|
|
}
|
|
$('#if_zmq_flows').html(addCommas(rsp.zmqRecvStats.flows)+label);
|
|
$('#if_zmq_events').html(addCommas(rsp.zmqRecvStats.events)+" "+get_trend(rsp.zmqRecvStats.events, last_zmq_events));
|
|
$('#if_zmq_counters').html(addCommas(rsp.zmqRecvStats.counters)+" "+get_trend(rsp.zmqRecvStats.counters, last_zmq_counters));
|
|
$('#if_zmq_msg_drops').html(addCommas(rsp.zmqRecvStats.zmq_msg_drops)+" "+get_trend(rsp.zmqRecvStats.zmq_msg_drops, last_zmq_msg_drops));
|
|
$('#if_zmq_msg_rcvd').html(addCommas(rsp.zmqRecvStats.zmq_msg_rcvd)+" "+get_trend(rsp.zmqRecvStats.zmq_msg_rcvd, last_zmq_msg_rcvd));
|
|
$('#if_zmq_avg_msg_flows').html(addCommas(formatValue(rsp.zmqRecvStats.zmq_avg_msg_flows)));
|
|
$('#if_num_remote_zmq_flow_exports').html(addCommas(rsp["zmq.num_flow_exports"])+" "+get_trend(rsp["zmq.num_flow_exports"], last_probe_zmq_exported_flows));
|
|
|
|
last_zmq_flows = rsp.zmqRecvStats.flows;
|
|
last_zmq_events = rsp.zmqRecvStats.events;
|
|
last_zmq_counters = rsp.zmqRecvStats.counters;
|
|
last_zmq_msg_drops = rsp.zmqRecvStats.zmq_msg_drops;
|
|
last_zmq_msg_rcvd = rsp.zmqRecvStats.zmq_msg_rcvd;
|
|
last_zmq_avg_msg_flows = rsp.zmqRecvStats.zmq_avg_msg_flows;
|
|
last_probe_zmq_exported_flows = rsp["zmq.num_flow_exports"];
|
|
last_zmq_time = now;
|
|
}
|
|
|
|
$('#if_pkts').html(addCommas(rsp.packets)+"]]
|
|
|
|
print(" Pkts\");")
|
|
|
|
if have_nedge and ifstats.type == "netfilter" and ifstats.netfilter then
|
|
local st = ifstats.netfilter
|
|
|
|
print("var last_nfq_queue_total = ".. st.nfq.queue_total .. ";\n")
|
|
print("var last_nfq_handling_failed = ".. st.failures.handle_packet .. ";\n")
|
|
print("var last_nfq_enobufs = ".. st.failures.no_buffers .. ";\n")
|
|
|
|
print[[
|
|
if(rsp.netfilter.nfq.queue_pct > 80) {
|
|
$('#nfq_queue_total').addClass("badge badge-danger");
|
|
} else {
|
|
$('#nfq_queue_total').removeClass("badge badge-danger");
|
|
}
|
|
$('#nfq_queue_total').html(fint(rsp.netfilter.nfq.queue_total) + " [" + fint(rsp.netfilter.nfq.queue_pct) + " %]");
|
|
$('#nfq_queue_total_trend').html(get_trend(last_nfq_queue_total, rsp.netfilter.nfq.queue_total));
|
|
$('#nfq_handling_failed').html(fint(rsp.netfilter.failures.handle_packet));
|
|
$('#nfq_handling_failed_trend').html(get_trend(last_nfq_handling_failed, rsp.netfilter.failures.handle_packet));
|
|
$('#nfq_enobufs').html(fint(rsp.netfilter.failures.no_buffers));
|
|
$('#nfq_enobufs_trend').html(get_trend(last_nfq_enobufs, rsp.netfilter.failures.no_buffers));
|
|
$('#num_conntrack_entries').html(fint(rsp.netfilter.nfq.num_conntrack_entries)+ " [" + fint((rsp.netfilter.nfq.num_conntrack_entries*100)/rsp.num_flows) + " %]");
|
|
]]
|
|
end
|
|
|
|
if ifstats.stats.discarded_probing_packets then
|
|
print[[
|
|
$('#if_discarded_probing_bytes').html(bytesToVolume(rsp.discarded_probing_bytes));
|
|
$('#if_discarded_probing_pkts').html(formatPackets(rsp.discarded_probing_packets));
|
|
$('#if_discarded_probing_trend').html(get_trend(last_discarded_probing_pkts, rsp.discarded_probing_packets));
|
|
last_discarded_probing_pkts = rsp.discarded_probing_packets;
|
|
]]
|
|
end
|
|
|
|
print [[
|
|
var pctg = 0;
|
|
var drops = "";
|
|
var last_pkt_retransmissions = ]] print(tostring(ifstats.tcpPacketStats.retransmissions)) print [[;
|
|
var last_pkt_ooo = ]] print(tostring(ifstats.tcpPacketStats.out_of_order)) print [[;
|
|
var last_pkt_lost = ]] print(tostring(ifstats.tcpPacketStats.lost)) print [[;
|
|
|
|
$('#pkt_retransmissions').html(fint(rsp.tcpPacketStats.retransmissions)+" Pkts"); $('#pkt_retransmissions_trend').html(get_trend(last_pkt_retransmissions, rsp.tcpPacketStats.retransmissions));
|
|
$('#pkt_ooo').html(fint(rsp.tcpPacketStats.out_of_order)+" Pkts"); $('#pkt_ooo_trend').html(get_trend(last_pkt_ooo, rsp.tcpPacketStats.out_of_order));
|
|
$('#pkt_lost').html(fint(rsp.tcpPacketStats.lost)+" Pkts"); $('#pkt_lost_trend').html(get_trend(last_pkt_lost, rsp.tcpPacketStats.lost));
|
|
last_pkt_retransmissions = rsp.tcpPacketStats.retransmissions;
|
|
last_pkt_ooo = rsp.tcpPacketStats.out_of_order;
|
|
last_pkt_lost = rsp.tcpPacketStats.lost;
|
|
|
|
$('#pkts_trend').html(get_trend(last_pkts, rsp.packets));
|
|
$('#drops_trend').html(get_trend(last_drops, rsp.drops));
|
|
last_pkts = rsp.packets;
|
|
last_drops = rsp.drops;
|
|
|
|
$('#engaged_alerts_trend').html(get_trend(last_engaged_alerts, rsp.engaged_alerts));
|
|
last_engaged_alerts = rsp.engaged_alerts;
|
|
$('#dropped_alerts_trend').html(get_trend(last_dropped_alerts, rsp.dropped_alerts));
|
|
last_dropped_alerts = rsp.dropped_alerts;
|
|
|
|
if((rsp.packets + rsp.drops) > 0) {
|
|
pctg = ((rsp.drops*100)/(rsp.packets+rsp.drops)).toFixed(2);
|
|
}
|
|
|
|
if(rsp.drops > 0) {
|
|
drops = '<span class="badge badge-danger">';
|
|
}
|
|
drops = drops + addCommas(rsp.drops)+" ]]
|
|
|
|
print("Pkts")
|
|
print [[";
|
|
|
|
if(pctg > 0) { drops += " [ "+pctg+" % ]"; }
|
|
if(rsp.drops > 0) { drops += '</span>'; }
|
|
$('#if_drops').html(drops);
|
|
|
|
$('#exported_flows').html(fint(rsp.flow_export_count));
|
|
$('#exported_flows_rate').html(Math.round(rsp.flow_export_rate * 100) / 100);
|
|
if(rsp.flow_export_drops > 0) {
|
|
$('#exported_flows_drops')
|
|
.addClass("badge badge-danger")
|
|
.html(fint(rsp.flow_export_drops));
|
|
if(rsp.flow_export_count > 0) {
|
|
$('#exported_flows_drops_pct')
|
|
.addClass("badge badge-danger")
|
|
.html("[" + Math.round(rsp.flow_export_drops / (rsp.flow_export_count + rsp.flow_export_count) * 100 * 1000) / 1000 + "%]");
|
|
} else {
|
|
$('#exported_flows_drops_pct').addClass("badge badge-danger").html("[100%]");
|
|
}
|
|
} else {
|
|
$('#exported_flows_drops').removeClass().html("0");
|
|
$('#exported_flows_drops_pct').removeClass().html("[0%]");
|
|
}
|
|
]]
|
|
|
|
print [[
|
|
}
|
|
});
|
|
}, ]] print(getInterfaceRefreshRate(ifstats.id).."") print[[ * 1000)
|
|
|
|
</script>
|
|
|
|
]]
|
|
|
|
print [[
|
|
<script type="text/javascript" src="]] print(ntop.getHttpPrefix()) print [[/js/jquery.tablesorter.js"></script>
|
|
<script>
|
|
$(document).ready(function()
|
|
{
|
|
$("#icmp_table_4").tablesorter();
|
|
$("#icmp_table_6").tablesorter();
|
|
$("#arp_table").tablesorter();
|
|
$("#if_stats_ndpi").tablesorter();
|
|
$("#if_stats_ndpi_categories").tablesorter();
|
|
}
|
|
);
|
|
</script>
|
|
]]
|
|
|
|
dofile(dirs.installdir .. "/scripts/lua/inc/footer.lua")
|