-- -- (C) 2013-21 - ntop.org -- local dirs = ntop.getDirs() package.path = dirs.installdir .. "/scripts/lua/modules/?.lua;" .. package.path package.path = dirs.installdir .. "/scripts/lua/modules/pools/?.lua;" .. package.path local snmp_utils local snmp_location local host_sites_update local sites_granularities = nil if(ntop.isPro()) then package.path = dirs.installdir .. "/pro/scripts/lua/modules/?.lua;" .. package.path snmp_utils = require "snmp_utils" snmp_location = require "snmp_location" shaper_utils = require("shaper_utils") host_sites_update = require("host_sites_update") end require "lua_utils" local graph_utils = require "graph_utils" local alert_utils = require "alert_utils" require "historical_utils" local json = require ("dkjson") local discover = require "discover_utils" local ui_utils = require "ui_utils" local page_utils = require "page_utils" local template = require "template_utils" local fingerprint_utils = require "fingerprint_utils" local companion_interface_utils = require "companion_interface_utils" local flow_consts = require "flow_consts" local alert_consts = require "alert_consts" local plugins_utils = require "plugins_utils" local am_utils = plugins_utils.loadModule("active_monitoring", "am_utils") local host_pools_nedge if ntop.isnEdge() then host_pools_nedge = require "host_pools_nedge" end local host_pools = require "host_pools" -- Instantiate host pools local host_pools_instance = host_pools:create() local info = ntop.getInfo() local have_nedge = ntop.isnEdge() local debug_hosts = false local page = _GET["page"] local protocol_id = _GET["protocol"] local application = _GET["application"] local category = _GET["category"] local host_info = url2hostinfo(_GET) local host_ip = host_info["host"] local host_vlan = host_info["vlan"] or 0 local always_show_hist = _GET["always_show_hist"] local format_utils = require("format_utils") local ntopinfo = ntop.getInfo() if not isEmptyString(_GET["ifid"]) then interface.select(_GET["ifid"]) else interface.select(ifname) end local ifstats = interface.getStats() ifId = ifstats.id local charts_available = areHostTimeseriesEnabled(ifId, host_info) local is_pcap_dump = interface.isPcapDumpInterface() local host = nil local family = nil local prefs = ntop.getPrefs() local hostkey = hostinfo2hostkey(host_info, nil, true --[[ force show vlan --]]) local hostkey_compact = hostinfo2hostkey(host_info) -- do not force vlan if not host_ip then sendHTTPContentTypeHeader('text/html') page_utils.print_header() dofile(dirs.installdir .. "/scripts/lua/inc/menu.lua") print("
" .. i18n("host_details.host_parameter_missing_message") .. "
") return end -- print(">>>") print(host_info["host"]) print("<<<") if(debug_hosts) then traceError(TRACE_DEBUG,TRACE_CONSOLE, i18n("host_details.trace_debug_host_info",{hostinfo=host_info["host"],vlan=host_vlan}).."\n") end local host = interface.getHostInfo(host_info["host"], host_vlan) local tskey if _GET["tskey"] then tskey = _GET["tskey"] elseif host then tskey = host["tskey"] else tskey = host_key end local restoreFailed = false local restoreInProgress = false if((host == nil) and ((_GET["mode"] == "restore"))) then restoreFailed = not interface.restoreHost(host_info["host"], host_vlan) if(not restoreFailed) then restoreInProgress = true end end function formatContacts(v) if(v > 5) then return(""..formatValue(v).."") else return(formatValue(v)) end end local function scoreBreakdown(what) local score_category_network = what[0] local score_category_security = what[1] local tot = score_category_network + score_category_security if(tot > 0) then score_category_network = (score_category_network*100)/tot score_category_security = 100 - score_category_network print(''.. i18n("flow_details.score_category_network")) print('' .. i18n("flow_details.score_category_security") .. '\n') else print(" ") end end local function printRestoreHostBanner(hidden) print('") end local top_sites = ((host ~= nil) and host["sites"] and json.decode(host["sites"])) or {} local top_sites_old = ((host ~= nil) and host["sites.old"] and json.decode(host["sites.old"])) or {} local labelKey = host_info["host"].."@"..host_info["vlan"] local host_pool_id = nil if (host ~= nil) then charts_available = charts_available and host["localhost"] if (isAdministrator() and (_POST["pool"] ~= nil)) then host_pool_id = _POST["pool"] local prev_pool = tostring(host["host_pool_id"]) if host_pool_id ~= prev_pool then local key = host2member(host["ip"], host["vlan"]) if not host_pools_instance:bind_member(key, tonumber(host_pool_id)) then host_pool_id = nil else ntop.reloadHostPools() end end end if (host_pool_id == nil) then host_pool_id = tostring(host["host_pool_id"]) end end local only_historical = (host == nil) and ((page == "historical") or (page == "config")) local host_label if(host == nil) and (not only_historical) then -- We need to check if this is an aggregated host sendHTTPContentTypeHeader('text/html') page_utils.set_active_menu_entry(page_utils.menu_entries.hosts) if restoreInProgress then dofile(dirs.installdir .. "/scripts/lua/inc/menu.lua") print('
'.. i18n("host_details.host_restore_in_progress",{host=hostinfo2hostkey(host_info)}) .. " ") print('') print("
") print[[]] dofile(dirs.installdir .. "/scripts/lua/inc/footer.lua") else dofile(dirs.installdir .. "/scripts/lua/inc/menu.lua") if(not(restoreFailed) and (host_info ~= nil) and canRestoreHost(ifId, host_info["host"], host_vlan)) then printRestoreHostBanner() else print('
') print(i18n("host_details.host_cannot_be_found_message",{host=hostinfo2hostkey(host_info)}) .. " ") print(purgedErrorString()) print("
") end dofile(dirs.installdir .. "/scripts/lua/inc/footer.lua") return end else sendHTTPContentTypeHeader('text/html') page_utils.set_active_menu_entry(page_utils.menu_entries.hosts, nil, i18n("host", { host = host_info["host"] })) print("\n") dofile(dirs.installdir .. "/scripts/lua/inc/menu.lua") -- Added global javascript variable, in order to disable the refresh of pie chart in case -- of historical interface print('\n\n') if _POST["action"] == "reset_stats" and isAdministrator() then if _POST["resetstats_mode"] == "reset_blacklisted" then interface.resetHostStats(hostkey, true) elseif interface.resetHostStats(hostkey) then print("
") print[[]] print(i18n("host_details.reset_stats_in_progress")) print("
") end end if host == nil then -- only_historical = true here host = hostkey2hostinfo(host_info["host"] .. "@" .. host_vlan) end if(_POST["custom_name"] ~=nil) and isAdministrator() then setHostAltName(host_info, _POST["custom_name"]) end host_label = hostinfo2label(host) if canRestoreHost(ifId, host_info["host"], host_vlan) then printRestoreHostBanner(true --[[ hidden ]]) else print('
 '..i18n("details.host_purged")..'
') end local title = i18n("host_details.host")..": "..host_info["host"] if host["broadcast_domain_host"] then title = title.."  " end local url = hostinfo2detailsurl(host, {tskey = _GET["tskey"]}) if (ntop.isPro()) then sites_granularities = host_sites_update.getGranularitySites(host_ip, host_vlan, ifId, false) end local has_snmp_location = snmp_location and snmp_location.host_has_snmp_location(host["mac"]) local has_icmp = ((table.len(host["ICMPv4"]) + table.len(host["ICMPv6"])) ~= 0) local periodicity_map_available = false local service_map_available = false local num_periodicity = 0 local service_map_link = ntop.getHttpPrefix() .. "/lua/pro/enterprise/service_map.lua?host=" .. host_ip local periodicity_map_link = ntop.getHttpPrefix() .. "/lua/pro/enterprise/periodicity_map.lua?&host=" .. host_ip if(ntop.isEnterpriseL() and (ntop.getPref("ntopng.prefs.is_behaviour_analysis_enabled") == "1")) then local service_map = interface.serviceMap(_GET["host"]) if service_map and (table.len(service_map) > 0) then service_map_available = true end if host_vlan ~= 0 then service_map_link = service_map_link .. "&vlan=" .. host_vlan end end if(ntop.isEnterpriseL() and (ntop.getPref("ntopng.prefs.is_behaviour_analysis_enabled") == "1")) then local periodicity_map = interface.periodicityMap(_GET["host"]) if periodicity_map and (table.len(periodicity_map) > 0) then num_periodicity = table.len(periodicity_map) periodicity_map_available = true end if host_vlan ~= 0 then periodicity_map_link = periodicity_map_link .. "&vlan=" .. host_vlan end end page_utils.print_navbar(title, url, { { hidden = only_historical, active = page == "overview" or page == nil, page_name = "overview", label = "", }, { hidden = only_historical, active = page == "traffic", page_name = "traffic", label = i18n("traffic"), }, { hidden = have_nedge or only_historical or (host["packets.sent"] + host["packets.rcvd"] == 0), active = page == "packets", page_name = "packets", label = i18n("packets"), }, { hidden = only_historical, active = page == "DSCP", page_name = "DSCP", label = i18n("dscp"), }, { hidden = only_historical, active = page == "ports", page_name = "ports", label = i18n("ports"), }, { hidden = only_historical or interface.isLoopback(), active = page == "peers", page_name = "peers", label = i18n("peers"), }, { hidden = have_nedge or only_historical or not(has_icmp), active = page == "ICMP", page_name = "ICMP", label = i18n("icmp"), }, { hidden = only_historical, active = page == "ndpi", page_name = "ndpi", label = i18n("applications"), }, { hidden = have_nedge or only_historical or not host["localhost"], active = page == "dns", page_name = "dns", label = i18n("dns"), }, { hidden = have_nedge or only_historical or not fingerprint_utils.has_fingerprint_stats(host, "ja3"), active = page == "tls", page_name = "tls", label = i18n("tls"), }, { hidden = have_nedge or only_historical or not fingerprint_utils.has_fingerprint_stats(host, "hassh"), active = page == "ssh", page_name = "ssh", label = i18n("ssh"), }, { hidden = only_historical or have_nedge or not host["localhost"] or not host["http"] or (host["http"]["sender"]["query"]["total"] == 0 and host["http"]["receiver"]["response"]["total"] == 0 and table.len(host["http"]["virtual_hosts"] or {}) == 0), active = page == "http", page_name = "http", label = i18n("http"), badge_num = host["active_http_hosts"], }, { hidden = only_historical, active = page == "flows", page_name = "flows", label = i18n("flows"), }, { hidden = only_historical or not host["localhost"] or (table.len(sites_granularities) == 0), active = page == "sites", page_name = "sites", label = i18n("sites_page.sites"), }, { hidden = not has_snmp_location, active = page == "snmp", page_name = "snmp", label = i18n("host_details.snmp"), }, { hidden = only_historical or not host["systemhost"] or not interface.hasEBPF(), active = page == "processes", page_name = "processes", label = i18n("user_info.processes"), }, { hidden = only_historical or host["is_broadcast"] or host["is_multicast"] or not ntop.hasGeoIP(), active = page == "geomap", page_name = "geomap", label = "", }, { hidden = not areAlertsEnabled(), active = page == "alerts", page_name = "alerts", label = "", url = hostinfo2detailsurl(host, {page = ternary(host.num_alerts > 0, "engaged-alerts", "alerts")}) }, { hidden = not charts_available and not interfaceHasNindexSupport(), active = page == "historical", page_name = "historical", label = "", }, { hidden = only_historical or (not host["localhost"]) or (not hasTrafficReport()), active = page == "traffic_report", page_name = "traffic_report", label = "", }, { hidden = only_historical or not ntop.isEnterpriseM() or not ifstats.inline or not host_pool_id ~= host_pools_instance.DEFAULT_POOL_ID, active = page == "quotas", page_name = "quotas", label = i18n("quotas"), }, { hidden = not periodicity_map_available, active = page == "periodicity_map", page_name = "periodicity_map", url = periodicity_map_link, label = " "..num_periodicity.."", }, { hidden = not service_map_available, active = page == "service_map", page_name = "service_map", label = "", url = service_map_link }, { hidden = not isAdministrator() or interface.isPcapDumpInterface(), active = page == "config", page_name = "config", label = "", }, } ) -- tprint(host.bins) local macinfo = interface.getMacInfo(host["mac"]) local has_snmp_location = host['localhost'] and (host["mac"] ~= "") and snmp_location and snmp_location.host_has_snmp_location(host["mac"]) and isAllowedSystemInterface() if((page == "overview") or (page == nil)) then print("\n") if(host["ip"] ~= nil) then if(host["mac"] ~= "00:00:00:00:00:00") then print("') end if has_snmp_location then snmp_location.print_host_snmp_location(host["mac"], hostinfo2detailsurl(host, {page = "snmp"})) end print("") print("") else if(host["mac"] ~= nil) then print("\n") end end if host["vlan"] and host["vlan"] > 0 then print("\n") end if(host["os"] ~= "" and host["os"] ~= 0) then print("") if(host["os"] ~= "") then local os_detail = "" if not isEmptyString(host["os_detail"]) then os_detail = os_detail .. " [" .. host["os_detail"] .. "]" end print("\n") else print("\n") end print("") end if((host["asn"] ~= nil) and (host["asn"] > 0)) then print("") print('') print("\n") end if(host["ip"] ~= nil) then print("") if(isAdministrator()) then print("\n") end if(host["num_alerts"] > 0) then print("\n") end if isScoreEnabled() then local score_chart = "" if charts_available then score_chart = hostinfo2detailshref(host, {page = "historical", tskey = tskey, ts_schema = "host:score"}, '') end print("") print("") local c = host.score_pct and host.score_pct["score_breakdown_client"] local s = host.score_pct and host.score_pct["score_breakdown_server"] print("") print("") print("") print("\n") end -- Active monitoring if am_utils and am_utils.isMeasurementAvailable('icmp') then local icmp = isIPv6(host["ip"]) and 'icmp6' or 'icmp' print([[ ]]) if (not am_utils.hasHost(host["ip"], icmp)) then print([[ ]]) else local last_update = am_utils.getLastAmUpdate(host['ip'], icmp) local last_rtt = "" if(last_update ~= nil) then last_rtt = last_update.value .. " " .. i18n("active_monitoring_stats.msec") else last_rtt = i18n("active_monitoring_stats.no_updates_yet") end print([[ ]]) end print("") end if(host["active_alerted_flows"] > 0) then print("\n") end if(host.score_behaviour.tot_num_anomalies > 0) then -- TODO: Add JSON update print("\n") end if ntop.isPro() and ifstats.inline and (host["has_blocking_quota"] or host["has_blocking_shaper"]) then local msg = "" local target = "" local quotas_page = hostinfo2detailsurl(host, {page = "quota"}) local policies_page = "/lua/if_stats.lua?ifid="..ifId.."&page=filtering&pool="..host_pool_id if host["has_blocking_quota"] then if host["has_blocking_shaper"] then msg = i18n("host_details.host_traffic_blocked_quota_and_shaper") target = quotas_page else msg = i18n("host_details.host_traffic_blocked_quota") target = quotas_page end else msg = i18n("host_details.host_traffic_blocked_shaper") target = policies_page end print("") end print("\n") print("\n") if((host["bytes.sent"]+host["bytes.rcvd"]) > 0) then print("\n") end print("\n") local flows_th = i18n("details.flows_non_packet_iface") if interface.isPacketInterface() then flows_th = i18n("details.flows_packet_iface") end if interfaceHasNindexSupport() then flows_th = flows_th .. ' ' end print("\n") print("") print("") print("") print("") print("") print("") print("") print("") end if(host.server_contacts ~= nil) then print(""); end if host["tcp.packets.seq_problems"] == true then local tcp_seq_label = "TCP: "..i18n("details.retransmissions").." / "..i18n("details.out_of_order").." / "..i18n("details.lost").." / "..i18n("details.keep_alive") -- SENT ANALYSIS local tcp_retx_sent = ""..formatPackets(host["tcpPacketStats.sent"]["retransmissions"]).."" local tcp_ooo_sent = ""..formatPackets(host["tcpPacketStats.sent"]["out_of_order"]).."" local tcp_lost_sent = ""..formatPackets(host["tcpPacketStats.sent"]["lost"]).."" local tcp_keep_alive_sent = ""..formatPackets(host["tcpPacketStats.sent"]["keep_alive"]).."" -- RCVD ANALYSIS local tcp_retx_rcvd = ""..formatPackets(host["tcpPacketStats.rcvd"]["retransmissions"]).."" local tcp_ooo_rcvd = ""..formatPackets(host["tcpPacketStats.rcvd"]["out_of_order"]).."" local tcp_lost_rcvd = ""..formatPackets(host["tcpPacketStats.rcvd"]["lost"]).."" local tcp_keep_alive_rcvd = ""..formatPackets(host["tcpPacketStats.rcvd"]["keep_alive"]).."" print("") print("") end -- Stats reset print( template.gen("modal_confirm_dialog.html", { dialog={ id = "reset_host_stats_dialog", action = "$('#reset_host_stats_form').submit();", title = i18n("host_details.reset_host_stats"), message = i18n("host_details.reset_host_stats_confirm", {host=host_label}) .. "

" .. i18n("host_details.reset_host_stats_note"), confirm = i18n("reset"), } }) ) -- Stats reset print( template.gen("modal_confirm_dialog.html", { dialog={ id = "reset_blacklisted_stats_dialog", action = "$('#reset_blacklisted_stats_form').submit();", title = i18n("host_details.reset_blacklisted_stats"), message = i18n("host_details.reset_blacklisted_stats_confirm", {host=host_label}) .. "

" .. i18n("host_details.reset_blacklisted_stats_note"), confirm = i18n("reset"), } }) ) print[[]] local num_extra_names = 0 local extra_names = host["names"] local num_extra_names = table.len(extra_names) if num_extra_names > 0 then local name_sources = {} for source, name in pairsByKeys(extra_names, rev) do if source == "resolved" then source = "DNS Resolution" else source = source:upper() end if not name_sources[name] then name_sources[name] = source else -- Collapse multiple sources in a single row when the name is the same name_sources[name] = string.format("%s, %s", source, name_sources[name]) num_extra_names = num_extra_names - 1 end end print('') print("\n") for name, source in pairsByValues(name_sources, asc) do print("\n") end end print("JSON") print [[]] print("\n") if(host["ssdp"] ~= nil) then print("\n") end print("
"..i18n("details.router_access_point_mac_address").."" ..get_symbolic_mac(host["mac"], true).. " " .. discover.devtype2icon(host["device_type"])) print('') if(host['localhost'] and (macinfo ~= nil)) then -- This is a known device type print(discover.devtype2icon(macinfo.devtype) .. " ") if macinfo.devtype ~= 0 then print(discover.devtype2string(macinfo.devtype) .. " ") else print(i18n("host_details.unknown_device_type") .. " ") end print('\n') else print(" ") end print('
"..i18n("ip_address").."" .. host["ip"]) if(host.childSafe == true) then print(getSafeChildIcon()) end if(host.os ~= 0) then print(" "..discover.getOsIcon(host.os).." ") end historicalProtoHostHref(getInterfaceId(ifname), host["ip"], nil, nil, nil) if(host["local_network_name"] ~= nil) then print(" [ ".. host["local_network_name"].." ]") end if((host["city"] ~= nil) and (host["city"] ~= "")) then print(" [ " .. host["city"] .." "..getFlag(host["country"]).." ]") end print[[]] print(i18n(ternary(have_nedge, "nedge.user", "details.host_pool"))..": ") print[[]] print(host_pools_instance:get_pool_name(host_pool_id)) print[[]] print[[ ]] print(hostinfo2detailshref(host, {page = "config"}, '')) print("
"..i18n("mac_address").."" .. host["mac"].. "
") print(i18n("details.vlan_id")) print(""..host["vlan"].."
"..i18n("os").." ".. discover.getOsAndIcon(host["os"]) .."".. os_detail .."
"..i18n("asn").."") print(""..host.asname.." [ "..i18n("asn").." ".. host.asn.." ]'..i18n("details.whois_lookup")..'
"..i18n("name").." ") else print("") end if ntop.shouldResolveHost(host["ip"]) then print('
Loading...
') end -- tprint(host) io.write("\n") print(host_label .. " ") print(hostinfo2detailshref(host, {page = "config"}, ' ')) print(format_utils.formatAddressCategory(host)) if(host.services) then if(host.services.dhcp) then print(' '..i18n("details.label_dhcp_server")..'') end if(host.services.dns) then print(' '..i18n("details.label_dns_server")..'') end if(host.services.smtp) then print(' '..i18n("details.label_smtp_server")..'') end if(host.services.ntp) then print(' '..i18n("details.label_ntp_server")..'') end end if(host["dhcp_server"] == true) then print(' '..i18n("details.label_dhcp_server")..'') end if(host["systemhost"] == true) then print(' ') end if(host["is_blacklisted"] == true) then print(' '..i18n("details.label_blacklisted_host")..'') end if((host["privatehost"] == false) and (host["is_multicast"] == false) and (host["is_broadcast"] == false)) then print(' ') end print("
"..i18n("show_alerts.engaged_alerts")..""..hostinfo2detailshref(host, {page = "engaged-alerts"}, ""..host["num_alerts"] .. "").."
"..i18n("score").." " .. score_chart ..""..i18n("host_details.client_score")..""..i18n("host_details.server_score").."
") print("
") print("".. (host["score.as_client"] or 0) .." ") if c then scoreBreakdown(c) end print("
") print("
") print("
") print("".. (host["score.as_server"] or 0).."") if s then scoreBreakdown(s) end print("
") print("
]] .. i18n("active_monitoring_stats.active_monitoring") .. [[ ]].. i18n('active_monitoring_stats.add_icmp') ..[[ ]].. last_rtt ..[[
"..i18n("host_details.active_alerted_flows")..""..hostinfo2detailshref(host, {page = "flows", flow_status = "alerted"}, ""..formatValue(host["active_alerted_flows"]) .. "").."
"..i18n("host_details.behavioural_anomalies")..""..formatValue(host.score_behaviour.tot_num_anomalies).."
"..i18n("host_details.blocked_traffic")..""..msg) print(".") print("
"..i18n("details.first_last_seen").."" .. formatEpoch(host["seen.first"]) .. " [" .. secondsToTime(os.time()-host["seen.first"]) .. " "..i18n("details.ago").."]" .. "" .. formatEpoch(host["seen.last"]) .. " [" .. secondsToTime(os.time()-host["seen.last"]) .. " "..i18n("details.ago") .. "]" .. "
"..i18n("details.sent_vs_received_traffic_breakdown").."") graph_utils.breakdownBar(host["bytes.sent"], i18n("sent"), host["bytes.rcvd"], i18n("details.rcvd"), 0, 100) print("
"..i18n("details.traffic_sent_received").."" .. formatPackets(host["packets.sent"]) .. " / ".. bytesToSize(host["bytes.sent"]) .. " " .. formatPackets(host["packets.rcvd"]) .. " / ".. bytesToSize(host["bytes.rcvd"]) .. "
"..i18n("details.as_client")..""..i18n("details.as_server").."
"..flows_th.."" .. formatValue(host["active_flows.as_client"]) .. " \n") print("/ " .. formatValue(host["flows.as_client"]) .. " \n") print("/ " .. formatValue(host["alerted_flows.as_client"]) .. " ") print(" / " .. formatValue(host["unreachable_flows.as_client"]) .. " ") print("" .. formatValue(host["active_flows.as_server"]) .. " \n") print("/ "..formatValue(host["flows.as_server"]) .. " \n") print("/ " .. formatValue(host["alerted_flows.as_server"]) .. " ") print(" / " .. formatValue(host["unreachable_flows.as_server"]) .. " ") print("
"..i18n("details.contacts_blacklisted").."" .. formatValue(host.num_blacklisted_flows.as_client) .. " \n") print("" .. formatValue(host.num_blacklisted_flows.as_server) .. " \n") print("
"..i18n("details.peers").."" .. formatValue(host["contacts.as_client"]) .. " \n") print("" .. formatValue(host["contacts.as_server"]) .. " \n") if ntop.isnEdge() then print("
"..i18n("details.flows_dropped_by_bridge").."" .. formatValue((host["flows.dropped"] or 0)) .. " ") print("
"..i18n("details.server_contacts").."") print("DNS: "..formatContacts(host.server_contacts.dns).." / ") print("SMTP: "..formatContacts(host.server_contacts.smtp).." / "); print("NTP: "..formatContacts(host.server_contacts.ntp).."
"..tcp_seq_label..""..i18n("sent")..""..i18n("received").."
"..string.format("%s / %s / %s / %s", tcp_retx_sent, tcp_ooo_sent, tcp_lost_sent, tcp_keep_alive_sent)..""..string.format("%s / %s / %s / %s", tcp_retx_rcvd, tcp_ooo_rcvd, tcp_lost_rcvd, tcp_keep_alive_rcvd).."
]] print(i18n("host_details.reset_host_stats")) print[[
'.. i18n("details.further_host_names_information") ..' "..i18n("details.source")..""..i18n("name").."
"..source..""..name.."
"..i18n("download").." ]] if (show_live_capture and ifstats.isView == false and ifstats.isDynamic == false and interface.isPacketInterface()) then local live_traffic_utils = require("live_traffic_utils") live_traffic_utils.printLiveTrafficForm(ifId, host_info) end print[[
SSDP (UPnP) "..host["ssdp"].."
\n") elseif((page == "packets")) then print [[ ]] local tots = 0 for key, value in pairs(host["pktStats.sent"]["size"]) do tots = tots + value end local totr = 0 for key, value in pairs(host["pktStats.recv"]["size"]) do totr = totr + value end if((tots > 0) or (totr > 0)) then print('') if(tots > 0) then print('') else print('') end if(totr > 0) then print('') else print('') end print('') end local has_tcp_distro = (host["tcp.packets.rcvd"] + host["tcp.packets.sent"] > 0) local has_arp_distro = (not isEmptyString(host["mac"])) and (host["mac"] ~= "00:00:00:00:00:00") if(has_tcp_distro and has_arp_distro) then print('') else if (has_tcp_distro) then print('') end if (has_arp_distro) then if (macinfo ~= nil) and (macinfo["arp_requests.sent"] + macinfo["arp_requests.rcvd"] + macinfo["arp_replies.sent"] + macinfo["arp_replies.rcvd"] > 0) then print('') end end end hostinfo2json(host_info) print [[
'..i18n("packets_page.sent_vs_rcvd_distribution")..'
 
 
'..i18n("packets_page.tcp_flags_vs_arp_distribution")..'
'..i18n("packets_page.tcp_flags_distribution")..'
'..i18n("packets_page.arp_distribution")..'

]] elseif((page == "DSCP")) then print('\n') print('') print('') print [[
'..i18n("dscp_page.statistics_sent")..'
'..i18n("dscp_page.statistics_received")..'
]] elseif((page == "ports")) then print('\n') if(host.cardinality) then print('') print('') print('') print('') end print('') print('') print [[
'..i18n("ports_page.num_contacted_ports")..''..i18n("ports_page.num_contacted_ports_as_client")..''.. formatValue(host.cardinality.num_contacted_ports_as_client) ..' '..i18n("ports_page.num_host_contacted_ports_as_server")..''.. formatValue(host.cardinality.num_host_contacted_ports_as_server) ..'
'..i18n("ports_page.client_ports")..'
'..i18n("ports_page.server_ports")..'

]] elseif((page == "peers")) then host_info = url2hostinfo(_GET) peers = getTopFlowPeers(hostinfo2hostkey(host_info), 1 --[[exists query]]) found = 0 for key, value in pairs(peers) do found = 1 break end if(found) then print [[
]] print(i18n("peers_page.top_peers_for_host",{hostkey=hostinfo2hostkey(host_info)})) print [[
]] print(i18n("peers_page.top_peer_protocol")) print[[

]] print(i18n("peers_page.host")) print[[ ]] print(i18n("application")) print[[ ]] print(i18n("peers_page.traffic_volume")) print[[
]] else print(" "..i18n("peers_page.no_active_flows_message").."") end elseif((page == "traffic")) then total = 0 for id, _ in ipairs(l4_keys) do k = l4_keys[id][2] if(host[k..".bytes.sent"] ~= nil) then total = total + host[k..".bytes.sent"] end if(host[k..".bytes.rcvd"] ~= nil) then total = total + host[k..".bytes.rcvd"] end end if(total == 0) then print("

"..i18n("traffic_page.no_traffic_observed_message").."
") else print [[ ]] if(host.cardinality) then print('') print('') print('') print('') end print [[ ]] print("\n") for id, _ in ipairs(l4_keys) do label = l4_keys[id][1] k = l4_keys[id][2] sent = host[k..".bytes.sent"] if(sent == nil) then sent = 0 end rcvd = host[k..".bytes.rcvd"] if(rcvd == nil) then rcvd = 0 end if((sent > 0) or (rcvd > 0)) then print("\n") end end print("
'..i18n("traffic_page.hosts_contacts_cardinality")..''..i18n("traffic_page.num_contacted_hosts_as_client")..'' .. formatValue(host.cardinality.num_contacted_hosts_as_client) ..' '..i18n("traffic_page.num_host_contacts_as_server")..''.. formatValue(host.cardinality.num_host_contacts_as_server) ..'
]] print(i18n("traffic_page.l4_proto_overview")) print[[
"..i18n("protocol")..""..i18n("sent")..""..i18n("received")..""..i18n("breakdown")..""..i18n("total").."
") if(charts_available) then print(hostinfo2detailshref(host, {page = "historical", ts_schema = "host:l4protos", l4proto = k}, label)) else print(label) end t = sent+rcvd historicalProtoHostHref(ifId, host, l4_keys[id][3], nil, nil) print("" .. bytesToSize(sent) .. "" .. bytesToSize(rcvd) .. "") graph_utils.breakdownBar(sent, i18n("sent"), rcvd, i18n("traffic_page.rcvd"), 0, 100) print("" .. bytesToSize(t).. "" .. round((t * 100)/total, 2).. " %
\n") print("\n") end elseif((page == "ICMP")) then print [[
]] print(i18n("icmp_page.icmp_message")) print[[]] print(i18n("icmp_page.icmp_type")) print [[]] print(i18n("icmp_page.icmp_code")) print [[]] print(i18n("icmp_page.last_sent_peer")) print[[]] print(i18n("icmp_page.last_rcvd_peer")) print[[]] print(i18n("breakdown")) print[[]] print(i18n("icmp_page.packets_sent")) print[[]] print(i18n("icmp_page.packets_received")) print[[]] print(i18n("total")) print[[
]] elseif((page == "ndpi")) then if(host["ndpi"] ~= nil) then print [[
]] if(host.cardinality) then print('') print('') end if ntop.isPro() and host["custom_apps"] then print[[ ]] end print[[
'..i18n("ndpi_page.num_contacted_services_as_client")..''.. formatValue(host.cardinality.num_contacted_services_as_client)) print(' '..i18n("ndpi_page.num_contacted_services_as_client_descr")..'
]] print(i18n("ndpi_page.overview", {what = i18n("ndpi_page.custom_applications")})) print [[
]] print(i18n("ndpi_page.overview", {what = i18n("applications")})) print[[
]] local direction_filter = "" if(direction ~= nil) then direction_filter = '' end print('
') print('
') print [[
]] print(i18n("application")) print[[ ]] print(i18n("duration")) print[[ ]] print(i18n("sent")) print[[ ]] print(i18n("received")) print[[ ]] print(i18n("breakdown")) print[[ ]] print(i18n("total")) print[[
]] print(i18n("ndpi_page.overview", {what = i18n("categories")})) print[[
]] print(i18n("category")) print[[ ]] print(i18n("applications")) print[[ ]] print(i18n("duration")) print[[ ]] print(i18n("total")) print[[
]] print[[ ]] local host_ndpi_timeseries_creation = ntop.getCache("ntopng.prefs.host_ndpi_timeseries_creation") print(ui_utils.render_notes({ { content = i18n("ndpi_page.note_historical_per_protocol_traffic",{what=i18n("application"), url=ntop.getHttpPrefix().."/lua/admin/prefs.lua?tab=on_disk_ts",flask_icon=""}), hidden = not(host_ndpi_timeseries_creation ~= "both" and host_ndpi_timeseries_creation ~= "per_protocol") }, { content = i18n("ndpi_page.note_historical_per_protocol_traffic",{what=i18n("category"), url=ntop.getHttpPrefix().."/lua/admin/prefs.lua",flask_icon=""}), hidden = not(host_ndpi_timeseries_creation ~= "both" and host_ndpi_timeseries_creation ~= "per_category") }, { content = i18n("ndpi_page.note_possible_probing_alert",{icon="",url = hostinfo2detailsurl(host, {page = "historical"})})}, { content = i18n("ndpi_page.note_protocol_usage_time")} })) end elseif(page == "dns") then if((host.DoH_DoT ~= nil) or (host["dns"] ~= nil)) then print("\n") if(host.DoH_DoT ~= nil) then print("") for _, v in pairs(host.DoH_DoT) do print("") end print("\n") end if(host["dns"] ~= nil) then print("") print("") print("") print("") print("") print("") print("") if host["dns"]["rcvd"]["num_replies_ok"] + host["dns"]["rcvd"]["num_replies_error"] > 0 then print('') local dns_ratio = tonumber(host["dns"]["sent"]["num_queries"]) / tonumber(host["dns"]["rcvd"]["num_replies_ok"]+host["dns"]["rcvd"]["num_replies_error"]) local dns_ratio_str = string.format("%.2f", dns_ratio) if(dns_ratio < 0.9) then dns_ratio_str = "".. dns_ratio_str .."" end print(']] end -- Charts if((host["dns"]["sent"]["num_queries"] + host["dns"]["rcvd"]["num_queries"]) > 0) then print [[]] if(host["dns"]["sent"]["num_queries"] > 0) then print[[ ]] else print[[]] end if(host["dns"]["rcvd"]["num_queries"] > 0) then print [[ ]] else print [[]] end print("") end print[[
"..i18n("dns_page.doh_dot_servers")..""..i18n("dns_page.doh_dot_server_uses").."
"..buildHostHREF(v.ip, v.vlan_id, "overview")..""..formatValue(v.num_uses) .."
"..i18n("dns_page.dns_breakdown")..""..i18n("dns_page.queries")..""..i18n("dns_page.positive_replies")..""..i18n("dns_page.error_replies")..""..i18n("dns_page.reply_breakdown").."
"..i18n("sent").."".. formatValue(host["dns"]["sent"]["num_queries"]) .." ".. formatValue(host["dns"]["sent"]["num_replies_ok"]) .." ".. formatValue(host["dns"]["sent"]["num_replies_error"]) .." ") graph_utils.breakdownBar(host["dns"]["sent"]["num_replies_ok"], "OK", host["dns"]["sent"]["num_replies_error"], "Error", 0, 100) print("
"..i18n("dns_page.rcvd").."".. formatValue(host["dns"]["rcvd"]["num_queries"]) .." ".. formatValue(host["dns"]["rcvd"]["num_replies_ok"]) .." ".. formatValue(host["dns"]["rcvd"]["num_replies_error"]) .." ") graph_utils.breakdownBar(host["dns"]["rcvd"]["num_replies_ok"], "OK", host["dns"]["rcvd"]["num_replies_error"], "Error", 50, 100) print("
'..i18n("dns_page.request_vs_reply")..''.. dns_ratio_str ..'') graph_utils.breakdownBar(host["dns"]["sent"]["num_queries"], i18n("dns_page.queries"), host["dns"]["rcvd"]["num_replies_ok"]+host["dns"]["rcvd"]["num_replies_error"], i18n("dns_page.replies"), 30, 70) print [[
]] print(i18n("dns_page.dns_query_sent_vs_rcvd_distribution")) print[[
 
 
]] print(i18n("dns_page.note")) print[[:
]] print(i18n("dns_page.note_dns_ratio")) print[[
]] end end elseif(page == "tls") then local fingerprint_type = 'ja3' local endpoint = string.format(ntop.getHttpPrefix() .. "/lua/rest/v1/get/host/fingerprint/data.lua?fingerprint_type=%s&ifid=%s&host=%s", fingerprint_type, ifId, host_ip) local context = { json = json, template = template, sites = { endpoint = endpoint, } } print(template.gen("pages/ja3_fingerprint.template", context)) elseif(page == "ssh") then local fingerprint_type = 'hassh' local endpoint = string.format(ntop.getHttpPrefix() .. "/lua/rest/v1/get/host/fingerprint/data.lua?fingerprint_type=%s&ifid=%s&host=%s", fingerprint_type, ifId, host_ip) local context = { json = json, template = template, sites = { endpoint = endpoint, } } print(template.gen("pages/hassh_fingerprint.template", context)) elseif(page == "http") then local http = host["http"] if http then print("\n") if http["sender"]["query"]["total"] > 0 then print("") print("") print("") print("") print("") print("") end if http["receiver"]["response"]["total"] > 0 then print("") print("") print("") print("") print("") print("") end local vh = http["virtual_hosts"] if vh then local now = os.time() local ago1h = now - 3600 local num = table.len(vh) if(num > 0) then local ifId = getInterfaceId(ifname) print("\n") for k,v in pairsByKeys(vh, asc) do local j = string.gsub(k, "%.", "___") print("") print("") print("") print("\n") end end end print("
"..i18n("http_page.http_queries")..""..i18n("http_page.method")..""..i18n("http_page.requests")..""..i18n("http_page.distribution").."
GET".. formatValue(http["sender"]["query"]["num_get"]) .." ") print [[
]] print("
POST".. formatValue(http["sender"]["query"]["num_post"]) .."
HEAD".. formatValue(http["sender"]["query"]["num_head"]) .."
PUT".. formatValue(http["sender"]["query"]["num_put"]) .."
"..i18n("http_page.other_method").."".. formatValue(http["sender"]["query"]["num_other"]) .."
"..i18n("http_page.http_responses")..""..i18n("http_page.response_code")..""..i18n("http_page.responses")..""..i18n("http_page.distribution").."
"..i18n("http_page.response_code_1xx").."".. formatValue(http["receiver"]["response"]["num_1xx"]) .." ") print [[
]] print("
"..i18n("http_page.response_code_2xx").."".. formatValue(http["receiver"]["response"]["num_2xx"]) .."
"..i18n("http_page.response_code_3xx").."".. formatValue(http["receiver"]["response"]["num_3xx"]) .."
"..i18n("http_page.response_code_4xx").."".. formatValue(http["receiver"]["response"]["num_4xx"]) .."
"..i18n("http_page.response_code_5xx").."".. formatValue(http["receiver"]["response"]["num_5xx"]) .."
"..i18n("http_page.virtual_hosts").."Name"..i18n("http_page.traffic_sent")..""..i18n("http_page.traffic_received")..""..i18n("http_page.requests_served").."
"..k.." ") historicalProtoHostHref(ifId, host, nil, nil, k) print(""..bytesToSize(vh[k]["bytes.sent"])..""..bytesToSize(vh[k]["bytes.rcvd"])..""..formatValue(vh[k]["http.requests"]).."
\n") end elseif(page == "sites") then if not prefs.are_top_talkers_enabled then local msg = i18n("sites_page.top_sites_not_enabled_message",{url=ntop.getHttpPrefix().."/lua/admin/prefs.lua?tab=protocols"}) print("
"..msg.."
") elseif table.len(sites_granularities) > 0 then local endpoint = string.format(ntop.getHttpPrefix() .. "/lua/pro/rest/v1/get/host/top/local/sites.lua?ifid=%s&host=%s&vlan=%s", ifId, host_ip, host_vlan) local context = { json = json, template = template, sites = { endpoint = endpoint, host = host_ip, ifid = ifId, vlan = host_vlan, granularities = sites_granularities, default_granularity = "current" } } print(template.gen("pages/top_sites.template", context)) else local msg = i18n("sites_page.top_sites_not_seen") print("
"..msg.."
") end elseif(page == "flows") then require("flow_utils") print [[
]] elseif(page == "snmp" and ntop.isEnterpriseM() and isAllowedSystemInterface()) then local snmp_config = require "snmp_config" local snmp_devices = snmp_config.get_all_configured_devices() if snmp_devices[host_ip] == nil then -- host has not been configured if not has_snmp_location then local msg = i18n("snmp_page.not_configured_as_snmp_device_message",{host_ip=host_ip}) msg = msg.." "..i18n("snmp_page.guide_snmp_page_message",{url=ntop.getHttpPrefix().."/lua/pro/enterprise/snmpdevices_stats.lua"}) print("
"..msg.."
") end else local snmp_cached_dev = require "snmp_cached_dev" local snmp_ui_system = require "snmp_ui_system" local cached_device = snmp_cached_dev:create(host_ip) snmp_ui_system.print_snmp_device_system_table(cached_device) end if has_snmp_location then print[[]] snmp_location.print_host_snmp_localization_table_entry(host["mac"]) print[[
]] end elseif(page == "processes") then local ebpf_utils = require "ebpf_utils" ebpf_utils.draw_processes_graph(host_info) elseif page == "geomap" then print ([[
Loading...
]]) elseif(page == "contacts") then if(num > 0) then mode = "embed" name = host_label dofile(dirs.installdir .. "/scripts/lua/hosts_interaction.lua") print("\n") print("\n") print("") if(cnum == 0) then print("") else print("\n") end if(snum == 0) then print("") else print("\n") end print("\n") print("
"..i18n("contacts_page.client_contacts_initiator")..""..i18n("contacts_page.server_contacts_receiver").."
"..i18n("contacts_page.no_client_contacts_so_far").."\n") print("\n") -- TOFIX VLAN (We need to remove the host vlan and add the client vlan) -- Client sortTable = {} for k,v in pairs(host["contacts"]["client"]) do sortTable[v]=k end num = 0 max_num = 64 -- Do not create huge maps for _v,k in pairsByKeys(sortTable, rev) do if(num >= max_num) then break end num = num + 1 name = interface.getHostInfo(k) -- TOFIX VLAN (We need to remove the host vlan and add the client vlan) v = host["contacts"]["client"][k] info = interface.getHostInfo(k) if(info ~= nil) then if(info["name"] ~= nil) then n = info["name"] else n = hostinfo2label(info) end url = hostinfo2detailshref(info, nil, n) else url = k end if(info ~= nil) then url = url .. getFlag(info["country"]).." " end -- print(v.."
") print("\n") end print("
"..i18n("contacts_page.server_address")..""..i18n("contacts_page.contacts").."
"..url.."" .. formatValue(v) .. "
"..i18n("contacts_page.no_server_contacts_so_far").."\n") print("\n") -- Server sortTable = {} for k,v in pairs(host["contacts"]["server"]) do sortTable[v]=k end for _v,k in pairsByKeys(sortTable, rev) do v = host["contacts"]["server"][k] info = interface.getHostInfo(k) if(info ~= nil) then if(info["name"] ~= nil) then n = info["name"] else n = hostinfo2label(info) end url = hostinfo2detailshref(info, nil, n) else url = k end if(info ~= nil) then url = url ..getFlag(info["country"]).." " end print("\n") end print("
"..i18n("contacts_page.client_address")..""..i18n("contacts_page.contacts").."
"..url.."" .. formatValue(v) .. "
\n") else print(i18n("contacts_page.no_contacts_message")) end elseif (page == "quotas" and ntop.isnEdge() and ntop.isEnterpriseM() and host_pool_id ~= host_pools_instance.DEFAULT_POOL_ID and ifstats.inline) then local page_params = {ifid=ifId, pool=host_pool_id, host=hostkey, page=page} host_pools_nedge.printQuotas(host_pool_id, host, page_params) elseif (page == "periodicity_map") then dofile(dirs.installdir .. "/scripts/lua/inc/periodicity_map.lua") elseif (page == "config") then if(not isAdministrator()) then return end local top_hiddens = ntop.getMembersCache(getHideFromTopSet(ifId) or {}) local is_top_hidden = swapKeysValues(top_hiddens)[hostkey_compact] ~= nil local host_key = hostinfo2hostkey(host_info, nil, true --[[show vlan]]) if _SERVER["REQUEST_METHOD"] == "POST" then if(ifstats.inline and (host.localhost or host.systemhost)) then local drop_host_traffic = _POST["drop_host_traffic"] local host_key = hostinfo2hostkey(host_info) if(drop_host_traffic ~= "1") then ntop.delHashCache("ntopng.prefs.drop_host_traffic", host_key) else ntop.setHashCache("ntopng.prefs.drop_host_traffic", host_key, "true") end interface.updateHostTrafficPolicy(host_info["host"], host_vlan) end local new_top_hidden = (_POST["top_hidden"] == "1") if new_top_hidden ~= is_top_hidden then local set_name = getHideFromTopSet(ifId) if new_top_hidden then ntop.setMembersCache(set_name, hostkey_compact) else ntop.delMembersCache(set_name, hostkey_compact) end is_top_hidden = new_top_hidden interface.reloadHideFromTop() end end -- NOTE: this only configures the alias associated to the IP address, not to the MAC local ip_alias = getHostAltName(host_info) print[[
]] if host_pool_id ~= nil then graph_utils.printPoolChangeDropdown(ifId, host_pool_id.."", have_nedge) end print [[]] if(ifstats.inline and (host.localhost or host.systemhost)) then -- Traffic policy print("') print('') print('') end print[[
]] print(i18n("host_config.host_alias")) print[[ ]] print [[
]] print(i18n("host_config.hide_from_top")) print[[ ]] print(template.gen("on_off_switch.html", { id = "top_hidden", label = i18n("host_config.hide_host_from_top_descr", {host=host_label}), checked = is_top_hidden, })) print[[
" .. i18n("host_config.host_traffic_policy") .. "") if(host["localhost"] == true) then local host_key = hostinfo2hostkey(host_info) drop_traffic = ntop.getHashCache("ntopng.prefs.drop_host_traffic", host_key) if(drop_traffic == "true") then drop_traffic_checked = 'checked="checked"' drop_traffic_value = "false" -- Opposite else drop_traffic_checked = "" drop_traffic_value = "true" -- Opposite end print(template.gen("on_off_switch.html", { id = "drop_host_traffic", label = i18n("host_config.drop_all_host_traffic"), checked = drop_traffic == "true", })) end print('


]] elseif(page == "historical") then host_url = "host="..host_ip host_key = host_ip if(host_vlan and (host_vlan > 0)) then host_url = host_url.."&vlan="..host_vlan host_key = host_key.."@"..host_vlan end local schema = _GET["ts_schema"] or "host:traffic" local selected_epoch = _GET["epoch"] or "" local tags = { ifid = ifId, host = host_key, protocol = _GET["protocol"], category = _GET["category"], l4proto = _GET["l4proto"], dscp_class = _GET["dscp_class"], } local url = hostinfo2detailsurl(host, {page = "historical"}) graph_utils.drawGraphs(ifId, schema, tags, _GET["zoom"], url, selected_epoch, { top_protocols = "top:host:ndpi", top_categories = "top:host:ndpi_categories", l4_protocols = "host:l4protos", dscp_classes = "iface:dscp", show_historical = true, tskey = tskey, timeseries = table.merge({ {schema="host:traffic", label=i18n("traffic"), split_directions = true --[[ split RX and TX directions ]]}, {schema="host:score", label=i18n("score"), metrics_labels = { i18n("graphs.cli_score"), i18n("graphs.srv_score")}}, {schema="host:active_flows", label=i18n("graphs.active_flows")}, {schema="host:total_flows", label=i18n("db_explorer.total_flows")}, {schema="host:num_blacklisted_flows", label=i18n("graphs.num_blacklisted_flows")}, {schema="host:alerted_flows", label=i18n("graphs.total_alerted_flows")}, {schema="host:unreachable_flows", label=i18n("graphs.total_unreachable_flows")}, {schema="host:contacts", label=i18n("graphs.active_host_contacts")}, {schema="host:contacts_behaviour", label=i18n("graphs.host_contacts_behaviour"), split_directions = true}, {schema="host:total_alerts", label=i18n("details.alerts")}, {schema="host:engaged_alerts", label=i18n("show_alerts.engaged_alerts")}, {schema="host:host_unreachable_flows", label=i18n("graphs.host_unreachable_flows")}, {schema="host:dns_qry_sent_rsp_rcvd", label=i18n("graphs.dns_qry_sent_rsp_rcvd")}, {schema="host:dns_qry_rcvd_rsp_sent", label=i18n("graphs.dns_qry_rcvd_rsp_sent")}, {schema="host:udp_pkts", label=i18n("graphs.udp_packets")}, {schema="host:tcp_rx_stats", label=i18n("graphs.tcp_rx_stats")}, {schema="host:tcp_tx_stats", label=i18n("graphs.tcp_tx_stats")}, {schema="host:echo_reply_packets", label=i18n("graphs.echo_reply_packets")}, {schema="host:echo_packets", label=i18n("graphs.echo_request_packets")}, {schema="host:tcp_packets", label=i18n("graphs.tcp_packets")}, {schema="host:udp_sent_unicast", label=i18n("graphs.udp_sent_unicast_vs_non_unicast")}, {schema="host:dscp", label=i18n("graphs.dscp_classes")}, {schema="host:srv_score_behaviour", label=i18n("graphs.srv_score_behaviour"), split_directions = true}, {schema="host:cli_score_behaviour", label=i18n("graphs.cli_score_behaviour"), split_directions = true}, {schema="host:srv_active_flows_behaviour", label=i18n("graphs.srv_active_flows_behaviour"), split_directions = true}, {schema="host:cli_active_flows_behaviour", label=i18n("graphs.cli_active_flows_behaviour"), split_directions = true}, {schema="host:srv_score_anomalies", label=i18n("graphs.srv_score_anomalies")}, {schema="host:cli_score_anomalies", label=i18n("graphs.cli_score_anomalies")}, {schema="host:srv_active_flows_anomalies", label=i18n("graphs.srv_active_flows_anomalies")}, {schema="host:cli_active_flows_anomalies", label=i18n("graphs.cli_active_flows_anomalies")}, }, graph_utils.getDeviceCommonTimeseries()), device_timeseries_mac = host["mac"], }) elseif(page == "traffic_report") then dofile(dirs.installdir .. "/pro/scripts/lua/enterprise/traffic_report.lua") end end if(not only_historical) and (host ~= nil) then print[[]] print [[ ]] end dofile(dirs.installdir .. "/scripts/lua/inc/footer.lua")