-- -- (C) 2013-20 - 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 local snmp_utils 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 snmp_utils = require "snmp_utils" end local json = require "dkjson" 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" local graph_utils = require "graph_utils" local alert_utils = require "alert_utils" require "db_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"] -- 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) ifname_clean = "iface_"..tostring(ifid) msg = "" local is_packet_interface = interface.isPacketInterface() local is_pcap_dump = interface.isPcapDumpInterface() local periodicity_stats = interface.periodicityStats() local periodic_info_available = false local num_periodicity = 0 if(periodicity_stats) then num_periodicity = table.len(periodicity_stats) if(num_periodicity > 0) then periodic_info_available = true end end local ifstats = interface.getStats() if page == "syslog_producers" and not ifstats.isSyslog then page = "overview" end local disaggregation_criterion_key = "ntopng.prefs.dynamic_sub_interfaces.ifid_"..tostring(ifid)..".mode" local charts_available = areInterfaceTimeseriesEnabled(ifid) function inline_input_form(name, placeholder, tooltip, value, can_edit, input_opts, input_class, measure_unit) if(can_edit) then print(']] if (measure_unit) then print([[]].. i18n(measure_unit) ..[[]]) end else if(value ~= nil) then print(value) end end end function inline_select_form(name, keys, values, curval) print[[]] end -- 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("ntopng.prefs.iface_" .. tostring(ifid)..'.scaling_factor',tostring(sf)) interface.loadScalingFactorPrefs() end end page_utils.set_active_menu_entry(page_utils.menu_entries.interface, { ifname=getHumanReadableInterfaceName(if_name) }) print("") 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 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\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 = "", }, { hidden = not interface.isPacketInterface() or ntop.isnEdge() or interface.isView(), active = page == "networks", page_name = "networks", label = i18n("networks"), }, { hidden = have_nedge or not ifstats or ifstats.stats.packets == 0 or ntop.isnEdge(), active = page == "packets", page_name = "packets", label = i18n("packets"), }, { hidden = not ifstats or not ifstats["has_macs"] or ntop.isnEdge(), active = page == "DSCP", page_name = "DSCP", label = i18n("dscp"), }, { active = page == "ndpi", page_name = "ndpi", label = i18n("applications"), }, { hidden = have_nedge, 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 charts_available, active = page == "historical", page_name = "historical", label = "", }, { hidden = have_nedge or not ifstats or table.empty(ifstats.profiles), active = page == "trafficprofiles", page_name = "trafficprofiles", label = "", }, { hidden = not has_traffic_recording_page, active = page == "traffic_recording", page_name = "traffic_recording", label = "", }, { hidden = not isAdministrator() or not areAlertsEnabled(), active = page == "alerts", page_name = "alerts", label = "", }, { hidden = not hasTrafficReport(), active = page == "traffic_report", page_name = "traffic_report", label = "", }, { hidden = not isAdministrator() or is_pcap_dump, active = page == "config", page_name = "config", label = "", }, { active = page == "internals", page_name = "internals", label = "", }, { hidden = have_nedge or not isAdministrator() or not ntop.isEnterpriseM() or ifstats.isDynamic or ifstats.isView, active = page == "sub_interfaces", page_name = "sub_interfaces", label = "", }, { hidden = have_nedge or not isAdministrator() or not ifstats.isSyslog, active = page == "syslog_producers", page_name = "syslog_producers", label = "", }, { hidden = not isAdministrator() or not ifstats.has_macs or have_nedge, active = page == "unassigned_pool_devices", page_name = "unassigned_pool_devices", label = "", }, { hidden = not isAdministrator() or is_pcap_dump, active = page == "dhcp", page_name = "dhcp", label = "", }, { hidden = not periodic_info_available, active = page == "periodicity_stats", page_name = "periodicity_stats", label = " "..num_periodicity.."", }, } ) if((page == "overview") or (page == nil)) then local tags = {ifid = ifstats.id} print("\n") print("\n") if not is_pcap_dump and ifstats["type"] ~= "netfilter" then print("\n") end if(ifstats["remote.name"] ~= nil) then local max_items_per_row = 3 local cur_i = 0 local title = i18n("if_stats_overview.remote_probe") if ifstats["remote.name"] == "none" then title = title .. " [" .. i18n("if_stats_overview.remote_probe_collector_mode") .. "]" end print("") if(ifstats["remote.name"] ~= "none") then if cur_i >= max_items_per_row then print(""); cur_i = 0 end print("") cur_i = cur_i + 1 end if not isEmptyString(ifstats["probe.probe_version"]) then if cur_i >= max_items_per_row then print(""); cur_i = 0 end print("") cur_i = cur_i + 1 end if not isEmptyString(ifstats["probe.ip"]) then if cur_i >= max_items_per_row then print(""); cur_i = 0 end print("") cur_i = cur_i + 1 end if ifstats["timeout.lifetime"] > 0 then if cur_i >= max_items_per_row then print(""); cur_i = 0 end print("") cur_i = cur_i + 1 end if ifstats["timeout.idle"] > 0 then if cur_i >= max_items_per_row then print(""); cur_i = 0 end print("") cur_i = cur_i + 1 end if not isEmptyString(ifstats["probe.remote_time"]) then local tdiff = math.abs(os.time()-ifstats["probe.remote_time"]) if cur_i >= max_items_per_row then print(""); cur_i = 0 end print("") cur_i = cur_i + 1 end 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 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 if cur_i >= max_items_per_row then print(""); cur_i = 0 end print("") print("") cur_i = cur_i + 1 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 if cur_i >= max_items_per_row then print(""); cur_i = 0 end print("") print("") cur_i = cur_i + 1 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 if cur_i >= max_items_per_row then print(""); cur_i = 0 end print("") print("") cur_i = cur_i + 1 end print("") 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 .. " " end print('\n') print("") if ifstats.encryption and ifstats.encryption.public_key then print("\n") end if is_physical_iface then print("") print("\n") local speed_key = 'ntopng.prefs.'..ifname..'.speed' local speed = ntop.getCache(speed_key) if (tonumber(speed) == nil) then speed = ifstats.speed end print("") print("") end if (not hasAllowedNetworksSet()) and ((ifstats.num_alerts_engaged > 0) or (ifstats.num_dropped_alerts > 0)) then print("") local warning = " " print("\n") print("\n") end label = i18n("pkts") print[[ ]] if(ifstats.type ~= "zmq") then print [[ ]] else print [[ ]] end print [[ \n") if(ifstats.zmqRecvStats ~= nil) then print("\n") print("") print("") print("") print("") print("") print("") print("") print("") print("") print("") print("") print("") print("") print("") print("") end print("\n") print("") if not ifstats.isDynamic then print("") print("") else print("") end print("") if(ifstats.has_traffic_directions) then print("") print("") end if not interface.isPacketInterface() then local external_json_stats = ntop.getCache("ntopng.prefs.ifid_"..tostring(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("\n") for key, value in pairsByKeys(external_stats, asc) do print("") print("") print("") print("") end end end end if prefs.is_dump_flows_enabled and not ifstats.isViewed 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("\n") print("") print("") print("") print("") local span_danger = "" if export_drops == nil then elseif(export_drops > 0) then span_danger = ' class="badge badge-danger"' end print("") if not interface.isPacketInterface() then print("") print("") else print("") end print("") end if ifstats.stats.discarded_probing_packets then print("\n") end if isAdministrator() and ifstats.isView == false then local ts_utils = require "ts_utils_core" local storage_info = storage_utils.interfaceStorageInfo(ifid) local storage_items = {} if storage_info then 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("\n") end end end if (ntop.isPcapDownloadAllowed() and ifstats.isView == false and ifstats.isDynamic == false and interface.isPacketInterface()) then print("\n") end if isAdministrator() then print("") print("") print("\n") end if have_nedge and ifstats.type == "netfilter" and ifstats.netfilter then local st = ifstats.netfilter print("") local span_class = '' if st.nfq.queue_pct > 80 then span_class = "class='badge badge-danger'" end print("") print("") print("") print("") print("") print("") print("") print("") end print [[ ]] print("
"..i18n("if_stats_overview.id").."" .. ifstats.id .. " ") if(ifstats.description ~= ifstats.name) then print(" ("..ifstats.description..")") end print("
"..i18n("if_stats_overview.state").."") 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("
".. title .."
".. i18n("if_stats_overview.interface_name") .."".. string.format("%s [%s]", ifstats["remote.name"], bitsToSize(ifstats.speed*1000000)) .."
".. i18n("if_stats_overview.remote_probe") .."" .. ifstats["probe.probe_version"]) if not isEmptyString(ifstats["probe.probe_os"]) then print(" ("..ifstats["probe.probe_os"]..")") end print("
".. i18n("if_stats_overview.probe_ip")) if not isEmptyString(ifstats["probe.public_ip"]) then print(" / ".. i18n("if_stats_overview.public_probe_ip")) end print("" .. ifstats["probe.ip"]) if not isEmptyString(ifstats["probe.public_ip"]) then print(" / "..ifstats["probe.public_ip"].." ") end print("
"..i18n("if_stats_overview.probe_timeout_lifetime").. " ") if((ifstats["timeout.collected_lifetime"] ~= nil) and (ifstats["timeout.collected_lifetime"] > 0)) then -- We're in collector mode on the nProbe side print(" "..secondsToTime(ifstats["timeout.lifetime"]).." [".. i18n("if_stats_overview.remote_flow_lifetime")..": "..secondsToTime(ifstats["timeout.collected_lifetime"]).."]") else -- Modern nProbe in non-flow collector mode or old nProbe print(secondsToTime(ifstats["timeout.lifetime"])) end print("
"..i18n("if_stats_overview.probe_timeout_idle")..""..secondsToTime(ifstats["timeout.idle"]).."
"..i18n("if_stats_overview.remote_probe_time").. " " .. "") if(tdiff > 10) then print("") end print(formatValue(tdiff).." sec") if(tdiff > 10) then print("") end print("
"..i18n("if_stats_overview.probe_zmq_drops_export_queue_full").." "..formatValue(ifstats["zmq.drops.export_queue_full"]).."
"..i18n("if_stats_overview.probe_zmq_drops_flow_collection_drops").." "..formatValue(ifstats["zmq.drops.flow_collection_drops"]).."
"..i18n("if_stats_overview.probe_zmq_drops_flow_collection_udp_socket_drops").." "..formatValue(ifstats["zmq.drops.flow_collection_udp_socket_drops"]).."
'..i18n("name")..'

' .. s ..'

"..i18n("if_stats_overview.family").."") if(ifstats.type == "zmq") then print("ZMQ") else print(ifstats.type) end 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("
"..i18n("if_stats_overview.zmq_encryption_public_key").."") print(ifstats.encryption.public_key) print("
"..i18n("if_stats_overview.note")..":
  • ".. i18n("if_stats_overview.zmq_encryption_public_key_note", {key="<key>"}).."") print("
  • nprobe --zmq "..ifstats.name.." --zmq-encryption-key '"..ifstats.encryption.public_key.."' ...") print("
"..i18n("mtu")..""..ifstats.mtu.." "..i18n("bytes")..""..i18n("speed").."" .. bitsToSize(speed * 1000000) .. "
".. ternary(ifstats.num_alerts_engaged > 0, warning, "") ..i18n("show_alerts.engaged_alerts").. ternary(charts_available, " ", "").."".. formatValue(ifstats.num_alerts_engaged) .." ".. ternary(ifstats.num_dropped_alerts > 0, warning, "")..i18n("show_alerts.dropped_alerts").. " ".. ternary(charts_available, " ", "") .."" .. formatValue(ifstats.num_dropped_alerts) .. "
]] print(i18n("if_stats_overview.traffic_breakdown")) print[[
"..i18n("if_stats_overview.zmq_rx_statistics").."
"..i18n("if_stats_overview.collected_flows")..ternary(charts_available, " ", "")..""..formatValue(ifstats.zmqRecvStats.flows).." "..i18n("if_stats_overview.unhandled_flows")..""..formatValue(ifstats.zmqRecvStats.dropped_flows).."
"..i18n("if_stats_overview.zmq_message_rcvd")..ternary(charts_available, " ", "")..""..formatValue(ifstats.zmqRecvStats.zmq_msg_rcvd).." "..i18n("if_stats_overview.zmq_message_drops")..ternary(charts_available, " ", "")..""..formatValue(ifstats.zmqRecvStats.zmq_msg_drops).." "..i18n("if_stats_overview.zmq_avg_msg_flows").."
"..i18n("if_stats_overview.interface_rx_updates")..""..formatValue(ifstats.zmqRecvStats.events)..""..i18n("if_stats_overview.sflow_counter_updates")..""..formatValue(ifstats.zmqRecvStats.counters).."
"..i18n("if_stats_overview.traffic_statistics").."
"..i18n("report.total_traffic")..ternary(charts_available, " ", "")..""..bytesToSize(ifstats.stats.bytes).." [".. formatValue(ifstats.stats.packets) .. " ".. label .."] ") print(" ") print(i18n("if_stats_overview.dropped_packets")..ternary(charts_available, " ", "").."") if(ifstats.stats.drops > 0) then print('') 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('') end print(" ") if(ifstats.zmqRecvStats ~= nil) then print("

"..i18n("if_stats_overview.note")..":
".. i18n("if_stats_overview.note_drops_sflow").."
") end print("

") print(""..i18n("if_stats_overview.note")..": "..i18n("if_stats_overview.note_drop_ifstats_dynamic").."") print("
"..i18n("http_page.traffic_sent")..ternary(charts_available, " ", "")..""..bytesToSize(ifstats.eth.egress.bytes).." [".. formatValue(ifstats.eth.egress.packets) .. " ".. label .."] "..i18n("http_page.traffic_received")..ternary(charts_available, " ", "")..""..bytesToSize(ifstats.eth.ingress.bytes).." [".. formatValue(ifstats.eth.ingress.packets) .. " ".. label .."]
"..external_stats_title.."
"..ternary(i18n("external_stats."..key), i18n("external_stats."..key), key)..""..ternary(type(value) == "number", formatValue(value), value).."
") if prefs.is_dump_flows_runtime_enabled then print(dump_to.." "..i18n("if_stats_overview.flows_export_statistics")) else print(i18n("if_stats_overview.export_disabled")) end print("
"..i18n("if_stats_overview.exported_flows")..ternary(charts_available, " ", "")..""..formatValue(export_count).."") if export_rate == nil then export_rate = 0 end print(" ["..formatValue(round(export_rate, 2)).." fps] ") print(i18n("if_stats_overview.dropped_flows")..ternary(charts_available, " ", "")..""..formatValue(export_drops).." ") print("[" ..formatValue(round(export_drops_pct, 2)).."%]"..i18n("if_stats_overview.direct_mode")..""..ternary(prefs.is_dump_flows_direct_enabled, i18n("enabled"), i18n("disabled")).."
"..i18n("if_stats_overview.discarded_probing_traffic")..ternary(charts_available, " ", "")..""..bytesToSize(ifstats.stats.discarded_probing_bytes).." [".. formatPackets(ifstats.stats.discarded_probing_packets) .."] ") print("
"..i18n("traffic_recording.storage_utilization").."") print(graph_utils.stackedProgressBars(storage_info.total, storage_items, nil, bytesToSize)) print("
"..i18n("download").." ") local live_traffic_utils = require("live_traffic_utils") live_traffic_utils.printLiveTrafficForm(ifId) print("
"..i18n("if_stats_overview.reset_counters").."") 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(' ') print('') print("
"..i18n("if_stats_overview.nf_queue_total")..""..string.format("%s [%s %%]", formatValue(st.nfq.queue_total), formatValue(st.nfq.queue_pct)).." "..i18n("if_stats_overview.nf_handle_packet_failed")..""..formatValue(st.failures.handle_packet).." "..i18n("if_stats_overview.nf_enobufs")..""..formatValue(st.failures.no_buffers).."
") print(i18n("if_stats_overview.conntrack_flow_entries")) print("") print(""..formatValue(st.nfq.num_conntrack_entries).."
]] print(i18n("if_stats_overview.note")..":

"..i18n("if_stats_overview.note_packets")) print[[

\n") elseif page == "networks" and interface.isPacketInterface() then print("") if(ifstats.ip_addresses ~= "") then local tokens = split(ifstats.ip_addresses, ",") if(tokens ~= nil) then print("") end end local has_ghost_networks = false local ghost_icon = '' if ifstats.bcast_domains and table.len(ifstats.bcast_domains) > 0 then print("") end print("
"..i18n("ip_address").."
  • ") local addresses = {} for _,s in pairs(tokens) do t = string.split(s, "/") host = interface.getHostInfo(t[1]) if(host ~= nil) then addresses[#addresses+1] = hostinfo2detailshref(host, nil, t[1]).."/"..t[2] else addresses[#addresses+1] = s end end print(table.concat(addresses, "\n
  • ")) print("
"..i18n("broadcast_domain").."") local bcast_domains = {} for bcast_domain, domain_info in pairsByKeys(ifstats.bcast_domains) do bcast_domain = string.format("%s", 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("
    ") for _, bcast_domain in ipairs(bcast_domains) do print("
  • "..bcast_domain.."
  • ") end print("
") end print("
") print("

"..i18n("if_stats_overview.note")..":

") elseif((page == "packets")) then local nedge_hidden = ternary(have_nedge, 'class="hidden"', '') print [[ ]] print("\n") print("\n") print("\n") if(ifstats.type ~= "zmq") then print [[]] end print[[
" .. i18n("packets_page.tcp_packets_analysis") .. "" .. i18n("packets_page.retransmissions") .."".. formatPackets(ifstats.tcpPacketStats.retransmissions) .."
" .. i18n("packets_page.out_of_order") .. "".. formatPackets(ifstats.tcpPacketStats.out_of_order) .."
" .. i18n("packets_page.lost") .. "".. formatPackets(ifstats.tcpPacketStats.lost) .."
]] print(i18n("packets_page.size_distribution")) print [[
]] print(i18n("packets_page.version_vs_flags_distribution")) print[[

]] elseif(page == "DSCP") then print [[
]] print(i18n("dscp_page.statistics")) print [[
]] elseif(page == "ndpi") then print[[


]] if ntop.isPro() and ifstats["custom_apps"] then print[[ ]] end print[[
]] print(i18n("ndpi_page.overview", {what = i18n("ndpi_page.custom_applications")})) print [[
]] print(i18n("ndpi_page.overview", {what = i18n("applications")})) print [[
]] print(i18n("ndpi_page.live_flows_count")) print [[

]] print(i18n("ndpi_page.note")) print [[ :]] print(i18n("ndpi_page.note_live_flows_chart")) print [[
]] print(i18n("application")) print[[ ]] print(i18n("ndpi_page.total_since_startup")) print[[ ]] print(i18n("percentage")) print[[

]] print(i18n("ndpi_page.overview", {what = i18n("categories")})) print [[
]] print(i18n("category")) print[[ ]] print(i18n("applications")) print[[ ]] print(i18n("ndpi_page.total_since_startup")) print[[ ]] print(i18n("percentage")) print[[
]] print [[ ]] 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("packets")) print[[

]] print(i18n("icmp_page.icmp_message")) print [[]] print(i18n("icmp_page.icmp_type")) print [[]] print(i18n("icmp_page.icmp_code")) print [[]] print(i18n("packets")) print[[
]] elseif(page == "ARP") then print [[
]] print(i18n("arp_page.arp_type")) print [[]] print(i18n("packets")) print[[
]] 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"], dscp_class = _GET["dscp_class"], } url = url.."&page=historical" local top_enabled = top_talkers_utils.areTopEnabled(ifid) graph_utils.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", dscp_classes = "iface:dscp", show_historical = not ifstats.isViewed, timeseries = graph_utils.get_default_timeseries() }) elseif(page == "trafficprofiles") then print("\n") print("\n") for pname,pbytes in pairs(ifstats.profiles) do local trimmed = trimSpace(pname) local statschart_icon = '' if areInterfaceTimeseriesEnabled(ifid) then statschart_icon = '' end print("\n") end print [[
" .. i18n("traffic_profiles.profile_name") .. "" .. i18n("chart") .. "" .. i18n("traffic") .. "
"..pname..""..statschart_icon..""..bytesToSize(pbytes).."
]] elseif(page == "traffic_recording" and has_traffic_recording_page) then if not dismiss_recording_providers_reminder then print('
'..i18n('traffic_recording.msg_external_providers_detected', {url = ntop.getHttpPrefix().."/lua/if_stats.lua?page=config"})..'
') print [[ ]] 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('') print('
') if recording_enabled and tab == "status" then dofile(dirs.installdir .. "/scripts/lua/inc/traffic_recording_status.lua") elseif recording_enabled and ntop.isEnterpriseM() 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('
') elseif(page == "alerts") then alert_utils.printAlertTables("interface", ifid, "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 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("
") end print[[
]] if ((not is_pcap_dump) and (ifstats.name ~= nil) and (ifstats.name ~= "dummy")) then -- Custom name print[[ ]] -- Interface speed if not have_nedge then print[[ ]] end -- Interface refresh rate print[[ ]] end if not have_nedge then -- Scaling factor if interface.isPacketInterface() and not have_nedge then local label = ntop.getCache("ntopng.prefs.iface_"..tostring(ifid)..".scaling_factor") if((label == nil) or (label == "")) then label = "1" end print[[ ]] 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[[ ]] -- 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[[ ]] -- per-interface Top-Talkers generation local interface_top_talkers_creation = true if _SERVER["REQUEST_METHOD"] == "POST" then if _POST["interface_top_talkers_creation"] ~= "1" then interface_top_talkers_creation = false 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 = false end end print [[]] -- Flow dump if prefs.is_dump_flows_enabled then print [[]] end -- Mirrored Traffic if not ntop.isnEdge() and interface.isPacketInterface() then local is_mirrored_traffic = false 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 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) end print [[]] end -- Flows-Only Interface if not ntop.isnEdge() and not interface.isView() and not interface.isViewed() then local flows_only_interface = false local flows_only_interface_pref = string.format("ntopng.prefs.ifid_%d.flows_only_interface", ifId) if _SERVER["REQUEST_METHOD"] == "POST" then if _POST["flows_only_interface"] == "1" then flows_only_interface = true end ntop.setPref(flows_only_interface_pref, ternary(flows_only_interface == true, '1', '0')) interface.updateDiscardProbingTraffic() else flows_only_interface = ternary(ntop.getPref(flows_only_interface_pref) == '1', true, false) end print [[]] end -- Discard Probing Traffic if not ntop.isnEdge() and not interface.isPacketInterface() then local discard_probing_traffic = false 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 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) end print [[]] end -- per-interface Network Discovery if interface.isDiscoverableInterface() then local discover = require "discover_utils" local interface_network_discovery = true if _SERVER["REQUEST_METHOD"] == "POST" then if _POST["interface_network_discovery"] ~= "1" then interface_network_discovery = false 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 end end print [[]] end if 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 [[ ]] 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 [[ ]] end end if not ifstats.isDynamic and not have_nedge 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"), i18n("prefs.probe_ip_and_ingress_iface_idx") } local values = {} if is_packet_interface then values = { "none", "vlan" } else values = { "none", "vlan", "probe_ip", "iface_idx", "ingress_iface_idx", "ingress_vrf_id", "probe_ip_and_ingress_iface_idx", } end print [[ ]] -- Show dynamic traffic in the master interface local show_dyn_iface_traffic = false 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 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) end print [[]] end print[[
]] print(i18n("if_stats_config.custom_name")) print[[ ]] 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[[
]] print(i18n("if_stats_config.interface_speed")) print[[ ]] 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"', "d-inline-block", "if_stats_config.interface_speed_measure_unit") print[[
]] print(i18n("if_stats_config.refresh_rate")) print[[ ]] 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"', "d-inline-block", "if_stats_config.referesh_rate_measure_unit") print[[
]] print(i18n("if_stats_config.scaling_factor")) print[[ ]] inline_input_form("scaling_factor", "Scaling Factor", i18n("if_stats_config.scaling_factor_popup_msg"), label, isAdministrator(), 'type="number" min="1" step="1"') print[[
]] print(i18n("prefs.toggle_host_tskey_title")) print[[ ]] inline_select_form("lbd_hosts_as_macs", {i18n("ip_address"), i18n("mac_address")}, {"0", "1"}, serialize_by_mac) print[[
]] print(i18n("if_stats_config.hide_from_top_networks")) print[[ ]] print('') print[[
]] print(i18n("if_stats_config.interface_top_talkers_creation")) print[[ ]] print(template.gen("on_off_switch.html", { id = "interface_top_talkers_creation", checked = interface_top_talkers_creation, })) print[[
]] print(i18n("if_stats_config.dump_flows_to_database")) print[[ ]] print(template.gen("on_off_switch.html", { id = "interface_flow_dump", checked = interface_flow_dump, })) print[[
]] print(i18n("if_stats_config.is_mirrored_traffic")) print[[ ]] print(template.gen("on_off_switch.html", { id = "is_mirrored_traffic", checked = is_mirrored_traffic, })) print[[
]] print(i18n("if_stats_config.flows_only_interface")) print[[ ]] print(template.gen("on_off_switch.html", { id = "flows_only_interface", checked = flows_only_interface, })) print[[
]] print(i18n("if_stats_config.discard_probing_traffic")) print[[ ]] print(template.gen("on_off_switch.html", { id = "discard_probing_traffic", checked = discard_probing_traffic, })) print[[
]] print(i18n("if_stats_config.interface_network_discovery")) print[[ ]] print(template.gen("on_off_switch.html", { id = "interface_network_discovery", checked = interface_network_discovery, })) print[[
]] print(i18n("if_stats_config.companion_interface")) print[[
]] print(i18n("traffic_recording.traffic_recording_provider")) print[[
]] print(i18n("prefs.dynamic_interfaces_creation_title")) print[[ ]] print ("

"..i18n("notes").."

    ".. "
  • "..i18n("prefs.dynamic_interfaces_creation_description").."
  • ".. "
  • "..i18n("prefs.dynamic_interfaces_creation_note_0").."
  • ".. "
  • "..i18n("prefs.dynamic_interfaces_creation_note_4").."
  • ".. "
  • "..i18n("prefs.dynamic_interfaces_creation_note_1").."
  • ") if not is_packet_interface then print("
  • "..i18n("prefs.dynamic_interfaces_creation_note_2").."
  • ".. "
  • "..i18n("prefs.dynamic_interfaces_creation_note_3").."
  • ") end print [[
]] print(i18n("if_stats_config.show_dyn_iface_traffic")) print[[ ]] print(template.gen("on_off_switch.html", { id = "show_dyn_iface_traffic", checked = show_dyn_iface_traffic, })) print[[

]] print(i18n("notes")) print [[

  • ]] print(i18n("if_stats_config.show_dyn_iface_traffic_note")) print [[



]] elseif(page == "internals") then internals_utils.printInternals(ifid, true --[[ hash tables ]], true --[[ periodic activities ]], true --[[ user scripts]]) print [[ ]] 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 snmp_utils.set_snmp_bound_interface(ifstats.id, snmp_host, snmp_interface) else local value = snmp_utils.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 = snmp_utils.get_snmp_devices(ifstats.id) print[[
]] print[[
]] print(i18n("snmp.snmp_device")) print[[ ]] print(i18n("snmp.view_device")) print[[
]] print(i18n("snmp.snmp_interface")) print[[
]] print(i18n("snmp.note") .. ":") print[[
]] print(i18n("snmp.bound_interface_description")) print[[ ]] elseif(page == "sub_interfaces") then if(isAdministrator() and ntop.isEnterpriseM()) then dofile(dirs.installdir .. "/pro/scripts/lua/enterprise/sub_interfaces.lua") end elseif(page == "syslog_producers") then if(isAdministrator()) then dofile(dirs.installdir .. "/scripts/lua/syslog_producers.lua") end elseif(page == "unassigned_pool_devices") then dofile(dirs.installdir .. "/scripts/lua/unknown_devices.lua") elseif(page == "dhcp") then dofile(dirs.installdir .. "/scripts/lua/admin/dhcp.lua") elseif page == "periodicity_stats" then dofile(dirs.installdir .. "/scripts/lua/inc/periodicity_stats.lua") elseif page == "traffic_report" then dofile(dirs.installdir .. "/pro/scripts/lua/enterprise/traffic_report.lua") end print(" ]] print [[ ]] dofile(dirs.installdir .. "/scripts/lua/inc/footer.lua")