-- -- (C) 2013-22 - ntop.org -- dirs = ntop.getDirs() package.path = dirs.installdir .. "/scripts/lua/modules/?.lua;" .. package.path require "template" require "voip_utils" require "lua_utils" local graph_utils = require "graph_utils" local tcp_flow_state_utils = require("tcp_flow_state_utils") local format_utils = require("format_utils") local flow_consts = require "flow_consts" local alert_consts = require "alert_consts" local json = require("dkjson") if ntop.isPro() then package.path = dirs.installdir .. "/scripts/lua/pro/modules/?.lua;" .. package.path shaper_utils = require("shaper_utils") end -- ####################### local flow_verdict_mapping = { "Unknown", -- 0 "Pass", -- 1 "Drop", -- 2 } local flow_verdict_icon = { '', '', '', } -- ####################### function parseFlowVerdict(flow_verdict, minimal) if flow_verdict_mapping[flow_verdict + 1] then if minimal then return flow_verdict_mapping[flow_verdict + 1] .. " " .. flow_verdict_icon[flow_verdict + 1] else return (flow_verdict .. " (" .. flow_verdict_mapping[flow_verdict + 1] .. " " .. flow_verdict_icon[flow_verdict + 1] .. ")") end end return flow_verdict end -- ####################### function addFlowVerdictBadge(flow_verdict, minimal) local flow_verdict_class = "badge bg-secondary" if tonumber(flow_verdict) == 1 then flow_verdict_class = "badge bg-success" elseif tonumber(flow_verdict) == 2 then flow_verdict_class = "badge bg-danger" end local flow_verdict_formatted = parseFlowVerdict(flow["flow_verdict"], minimal) return '' .. flow_verdict_formatted .. '' end -- ####################### function formatInterfaceId(id, idx, snmpdevice) if(id == 65535) then return("Unknown") else if(snmpdevice ~= nil) then return(''..id..'') else return(id) end end end -- ####################### function formatTrafficProfile(profile) local res = "" if not isEmptyString(profile) then res = ""..profile.." " end return res end -- ####################### -- Extracts the information serialized into alert_info from the flow -- checks function flow2alertinfo(flow) local alert_info = flow["alert_info"] if(alert_info and (string.sub(alert_info, 1, 1) == "{")) then local res = json.decode(alert_info) if(res ~= nil) then return(res) end end return(alert_info) end -- ####################### function getFlowsFilter() -- Pagination local sortColumn = _GET["sortColumn"] local sortOrder = _GET["sortOrder"] local currentPage = _GET["currentPage"] local perPage = _GET["perPage"] -- Other Filters local port = _GET["port"] local application = _GET["application"] local category = _GET["category"] local network_id = _GET["network"] local traffic_profile = _GET["traffic_profile"] local traffic_type = _GET["traffic_type"] local flowhosts_type = _GET["flowhosts_type"] local ipversion = _GET["version"] local l4proto = _GET["l4proto"] local vlan = _GET["vlan"] local username = _GET["username"] local host = _GET["host"] local pid_name = _GET["pid_name"] local container = _GET["container"] local pod = _GET["pod"] local icmp_type = _GET["icmp_type"] local icmp_code = _GET["icmp_cod"] local dscp_filter = _GET["dscp"] local host_pool = _GET["host_pool_id"] local flow_status = _GET["flow_status"] local flow_status_severity = _GET["flow_status_severity"] local alert_type = _GET["alert_type"] local alert_type_severity = _GET["alert_type_severity"] local deviceIP = _GET["deviceIP"] local inIfIdx = _GET["inIfIdx"] local outIfIdx = _GET["outIfIdx"] local asn = _GET["asn"] local tcp_state = _GET["tcp_flow_state"] local talking_with = _GET["talking_with"] if sortColumn == nil or sortColumn == "column_" or sortColumn == "" then sortColumn = getDefaultTableSort("flows") elseif sortColumn ~= "column_" and sortColumn ~= "" then tablePreferences("sort_flows", sortColumn) else sortColumn = "column_client" end if sortOrder == nil then sortOrder = getDefaultTableSortOrder("flows") elseif sortColumn ~= "column_" and sortColumn ~= "" then tablePreferences("sort_order_flows", sortOrder) end if currentPage == nil then currentPage = 1 else currentPage = tonumber(currentPage) end if perPage == nil then perPage = getDefaultTableSize() else perPage = tonumber(perPage) tablePreferences("rows_number",perPage) end if port ~= nil then port = tonumber(port) end if network_id ~= nil then network_id = tonumber(network_id) end local to_skip = (currentPage - 1) * perPage local a2z = false if sortOrder == "desc" then a2z = false else a2z = true end local pageinfo = { ["perPage"] = perPage, ["currentPage"] = currentPage, ["sortOrder"] = sortOrder or "", ["sortColumn"] = sortColumn or "", ["toSkip"] = to_skip, ["maxHits"] = perPage, ["a2zSortOrder"] = a2z, ["hostFilter"] = host, ["portFilter"] = port, ["LocalNetworkFilter"] = network_id, } if application ~= nil and application ~= "" then pageinfo["l7protoFilter"] = interface.getnDPIProtoId(application) end if category ~= nil and category ~= "" then pageinfo["l7categoryFilter"] = interface.getnDPICategoryId(category) end if traffic_profile ~= nil then pageinfo["trafficProfileFilter"] = traffic_profile end if not isEmptyString(flowhosts_type) then if flowhosts_type == "local_origin_remote_target" then pageinfo["clientMode"] = "local" pageinfo["serverMode"] = "remote" elseif flowhosts_type == "local_only" then pageinfo["clientMode"] = "local" pageinfo["serverMode"] = "local" elseif flowhosts_type == "remote_origin_local_target" then pageinfo["clientMode"] = "remote" pageinfo["serverMode"] = "local" elseif flowhosts_type == "remote_only" then pageinfo["clientMode"] = "remote" pageinfo["serverMode"] = "remote" end end if not isEmptyString(traffic_type) then if traffic_type:contains("unicast") then pageinfo["unicast"] = true else pageinfo["unicast"] = false end if traffic_type:contains("one_way") then pageinfo["unidirectional"] = true end end if not isEmptyString(alert_type) then if alert_type == "normal" then pageinfo["alertedFlows"] = false pageinfo["filteredFlows"] = false elseif alert_type == "alerted" then pageinfo["alertedFlows"] = true elseif alert_type == "filtered" then pageinfo["filteredFlows"] = true else pageinfo["statusFilter"] = tonumber(alert_type) end end if not isEmptyString(alert_type_severity) then local s = alert_consts.severity_groups[alert_type_severity] if s then pageinfo["statusSeverityFilter"] = s.severity_group_id end end if not isEmptyString(ipversion) then pageinfo["ipVersion"] = tonumber(ipversion) end if not isEmptyString(l4proto) then pageinfo["L4Protocol"] = tonumber(l4proto) end if not isEmptyString(vlan) then pageinfo["vlanIdFilter"] = tonumber(vlan) end if not isEmptyString(username) then pageinfo["usernameFilter"] = username end if not isEmptyString(pid_name) then pageinfo["pidnameFilter"] = pid_name end if not isEmptyString(container) then pageinfo["container"] = container end if not isEmptyString(pod) then pageinfo["pod"] = pod end if not isEmptyString(deviceIP) then pageinfo["deviceIpFilter"] = deviceIP if not isEmptyString(inIfIdx) then pageinfo["inIndexFilter"] = tonumber(inIfIdx) end if not isEmptyString(outIfIdx) then pageinfo["outIndexFilter"] = tonumber(outIfIdx) end end if not isEmptyString(asn) then pageinfo["asnFilter"] = tonumber(asn) end pageinfo["icmp_type"] = tonumber(icmp_type) pageinfo["icmp_code"] = tonumber(icmp_code) if not isEmptyString(dscp_filter) then pageinfo["dscpFilter"] = tonumber(dscp_filter) end if not isEmptyString(talking_with) then pageinfo["talkingWith"] = talking_with end if not isEmptyString(host_pool) then pageinfo["poolFilter"] = tonumber(host_pool) end if not isEmptyString(tcp_state) then pageinfo["tcpFlowStateFilter"] = tcp_state end return pageinfo end -- ####################### function handleCustomFlowField(key, value, snmpdevice) if key == 'TCP_FLAGS' then return(formatTcpFlags(value)) elseif key == 'INPUT_SNMP' then return(formatInterfaceId(value, "inIfIdx", snmpdevice)) elseif key == 'OUTPUT_SNMP' then return(formatInterfaceId(value, "outIfIdx", snmpdevice)) elseif key == 'TOTAL_FLOWS_EXP' then return(format_utils.formatValue(value)) elseif key == 'EXPORTER_IPV4_ADDRESS' or key == 'NPROBE_IPV4_ADDRESS' then if ntop.isPro() then return(""..value.."") else return(value) end elseif key == 'FLOW_USER_NAME' then elems = string.split(value, ';') if((elems ~= nil) and (#elems == 6)) then r = '' imsi = elems[1] mcc = string.sub(imsi, 1, 3) if(flow_consts.mobile_country_code[mcc] ~= nil) then mcc_name = " ["..flow_consts.mobile_country_code[mcc].."]" else mcc_name = "" end r = r .. "" r = r .. "" r = r .. "" r = r .. "" r = r .. "" r = r .. "" r = r .. "
"..i18n("flow_details.imsi")..""..elems[1]..mcc_name r = r .. "
"..i18n("flow_details.nsapi").."".. elems[2].."
"..i18n("flow_details.gsm_cell_lac").."".. elems[3].."
"..i18n("flow_details.gsm_cell_identifier").."".. elems[4].."
"..i18n("flow_details.sac_service_area_code").."".. elems[5].."
"..i18n("ip_address").."".. ntop.inet_ntoa(elems[6]).."
" return(r) else return(value) end elseif key == 'SIP_TRYING_TIME' or key == 'SIP_RINGING_TIME' or key == 'SIP_INVITE_TIME' or key == 'SIP_INVITE_OK_TIME' or key == 'SIP_INVITE_FAILURE_TIME' or key == 'SIP_BYE_TIME' or key == 'SIP_BYE_OK_TIME' or key == 'SIP_CANCEL_TIME' or key == 'SIP_CANCEL_OK_TIME' then if(value ~= '0') then return(formatEpoch(value)) else return "0" end elseif key == 'RTP_IN_JITTER' or key == 'RTP_OUT_JITTER' then if(value ~= nil and value ~= '0') then return(value/1000) else return 0 end elseif key == 'RTP_IN_MAX_DELTA' or key == 'RTP_OUT_MAX_DELTA' or key == 'RTP_MOS' or key == 'RTP_R_FACTOR' or key == 'RTP_IN_MOS' or key == 'RTP_OUT_MOS' or key == 'RTP_IN_R_FACTOR' or key == 'RTP_OUT_R_FACTOR' or key == 'RTP_IN_TRANSIT' or key == 'RTP_OUT_TRANSIT' then if(value ~= nil and value ~= '0') then return(value/100) else return 0 end end -- Unformatted value if (type(value) == "boolean") then if (value) then value = i18n("yes") else value = i18n("no") end end return value end -- ####################### function formatTcpFlags(flags) if(flags == 0) then return("") end rsp = "" if((flags & 1) == 2) then rsp = rsp .. " SYN " end if((flags & 16) == 16) then rsp = rsp .. " ACK " end if((flags & 1) == 1) then rsp = rsp .. " FIN " end if((flags & 4) == 4) then rsp = rsp .. " RST " end if((flags & 8) == 8 ) then rsp = rsp .. " PUSH " end return(rsp .. "") end -- ####################### local dns_types = { ['A'] = 1, ['NS'] = 2, ['MD'] = 3, ['MF'] = 4, ['CNAME'] = 5, ['SOA'] = 6, ['MB'] = 7, ['MG'] = 8, ['MR'] = 9, ['NULL'] = 10, ['WKS'] = 11, ['PTR'] = 12, ['HINFO'] = 13, ['MINFO'] = 14, ['MX'] = 15, ['TXT'] = 16, ['AAAA'] = 28, ['A6'] = 38, ['SPF'] = 99, ['AXFR'] = 252, ['MAILB'] = 253, ['MAILA'] = 254, ['ANY'] = 255, } -- ####################### function get_dns_type(dns_type_name) if dns_types[dns_type_name] then return dns_types[dns_type_name] else return 0 end end -- ####################### function get_dns_type_label(dns_type) dns_type = tonumber(dns_type) if dns_type then for k, v in pairs(dns_types) do if v == dns_type then return k end end end return string.format("%u", dns_type) end -- ####################### function extractSIPCaller(caller) local i local j -- find string between \" and \" i = string.find(caller, "\\\"") if(i ~= nil) then j = string.find(caller, "\\\"",i+2) if(j ~= nil) then return string.sub(caller, i+2, j-1) end end -- find string between " and " i = string.find(caller, "\"") if(i ~= nil) then j = string.find(caller, "\"",i+1) if(j ~= nil) then return string.sub(caller, i+1, j-1) end end -- find string between : and @ i = string.find(caller, ":") if(i ~= nil) then j = string.find(caller, "@",i+1) if(j ~= nil) then return string.sub(caller, i+1, j-1) end end return caller end -- ####################### function map_failure_resp_code(fail_resp_code_string) if (fail_resp_code_string ~= nil) then if(fail_resp_code_string == "200") then return "OK" end if(fail_resp_code_string == "100") then return "TRYING" end if(fail_resp_code_string == "180") then return "RINGING" end if(tonumber(fail_resp_code_string) > 399) then return "FAILURE" end end return fail_resp_code_string end -- ####################### function getAlertTimeBounds(alert, engaged) local epoch_begin local epoch_end local half_interval = 1800 local alert_tstamp = alert.alert_tstamp if alert.first_switched and alert.last_switched then -- Flow alert epoch_begin = alert.first_switched - half_interval epoch_end = alert.last_switched + half_interval else local tend = ternary(engaged, os.time(), alert.alert_tstamp_end) or alert_tstamp -- tprint(debug.traceback()) half_interval = math.max(half_interval, (tend - alert_tstamp) / 2) -- at least 1 hour interval local middle_time = (tend + alert_tstamp) / 2 epoch_begin = middle_time - half_interval epoch_end = middle_time + half_interval end return math.floor(epoch_begin), math.floor(epoch_end) end -- ####################### local function formatFlowHost(flow, cli_or_srv, historical_bounds, hyperlink_suffix) local hyperlink_params if historical_bounds then hyperlink_params = {page = "historical", epoch_begin = historical_bounds[1], epoch_end = historical_bounds[2], detail_view = "top_l7_contacts"} elseif type(hyperlink_suffix) == "table" then hyperlink_params = hyperlink_suffix end local host if(cli_or_srv) then host = interface.getHostMinInfo(flow[cli_or_srv .. ".ip"], flow[cli_or_srv .. ".vlan"]) else host = interface.getHostMinInfo(flow[cli_or_srv .. ".ip"], flow[cli_or_srv .. ".vlan"]) end local host_name if(host ~= nil) then host_name = host["name"] if isEmptyString(host_name) then host_name = host["ip"] end end if(host_name == nil) then host_name = "" end host_name = host_name .. format_utils.formatFullAddressCategory(host) local mac if(host == nil) then mac = nil else mac = host["mac"] end return hostinfo2detailshref(flow2hostinfo(flow, cli_or_srv), hyperlink_params, host_name, nil, true --[[ perform link existance checks --]]), mac end local function formatFlowPort(flow, cli_or_srv, port, historical_bounds) if not historical_bounds then return ""..port.."" end -- TODO port filter return hostinfo2detailshref(flow2hostinfo(flow, cli_or_srv), {page = "historical", epoch_begin = historical_bounds[1], epoch_end = historical_bounds[2], detail_view = "flows", port = port}, port, port, true --[[ check href existance --]]) end function getFlowLabel(flow, show_macs, add_hyperlinks, historical_bounds, hyperlink_suffix, add_flag, add_hostnames) if flow == nil then return "" end local cli_name = flowinfo2hostname(flow, "cli", nil, add_hostnames) local srv_name = flowinfo2hostname(flow, "srv", nil, add_hostnames) local cli_mac = flow["cli.mac"] local srv_mac = flow["srv.mac"] local cli_as = nil local srv_as = nil if((not isIPv4(cli_name)) and (not isIPv6(cli_name))) then cli_name = shortenString(cli_name) end if((not isIPv4(srv_name)) and (not isIPv6(srv_name))) then srv_name = shortenString(srv_name) end local cli_port local srv_port if flow["cli.port"] and (flow["cli.port"] > 0 or flow["proto.l4"] == "TCP" or flow["proto.l4"] == "UDP") then cli_port = flow["cli.port"] end if flow["srv.port"] and (flow["srv.port"] > 0 or flow["proto.l4"] == "TCP" or flow["proto.l4"] == "UDP") then srv_port = flow["srv.port"] end if add_hyperlinks then cli_name, cli_mac = formatFlowHost(flow, "cli", historical_bounds, hyperlink_suffix) srv_name, srv_mac = formatFlowHost(flow, "srv", historical_bounds, hyperlink_suffix) if cli_port then cli_port = formatFlowPort(flow, "cli", cli_port, historical_bounds) end if srv_port then srv_port = formatFlowPort(flow, "srv", srv_port, historical_bounds) end if((flow.cli_as ~= nil) and (flow.cli_as ~= 0)) then cli_as = "" .. shortenString( flow.cli_as_name or "", 14 ) .."" cli_mac = "" else if cli_mac and (cli_mac ~= "00:00:00:00:00:00") and not interface.isView() then cli_mac = "" ..cli_mac.."" elseif interface.isView() and (cli_mac ~= "00:00:00:00:00:00") then cli_mac = cli_mac or "" else cli_mac = "" end end if((flow.dst_as ~= nil) and (flow.dst_as ~= 0)) then dst_as = "" .. shortenString( flow.dst_as_name or "", 14 ) .."" srv_mac = "" else if srv_mac and (srv_mac ~= "00:00:00:00:00:00") and not interface.isView() then srv_mac = "" ..srv_mac.."" elseif interface.isView() and (srv_mac ~= "00:00:00:00:00:00") then srv_mac = srv_mac or "" else srv_mac = "" end end end local label = "" if not isEmptyString(cli_name) then label = label..cli_name end if add_flag then local info = interface.getHostInfo(flow["cli.ip"], flow["cli.vlan"]) if(info ~= nil) then label = label .. getFlag(info["country"]) end end if cli_port then label = label..":"..cli_port end if(cli_as ~= nil) then label = label.." [ "..cli_as.." ]" else if show_macs and not isEmptyString(cli_mac) then label = label.." [ "..cli_mac.." ]" end end label = label.."   " if not isEmptyString(srv_name) then label = label..srv_name end if add_flag then local info = interface.getHostInfo(flow["srv.ip"], flow["srv.vlan"]) if(info ~= nil) then label = label .. getFlag(info["country"]) end end if srv_port then label = label..":"..srv_port end if(dst_as ~= nil) then label = label.." [ "..dst_as.." ]" else if show_macs and not isEmptyString(srv_mac) then label = label.." [ "..srv_mac.." ]" end end local s_info = flow2alertinfo(flow) if(s_info ~= nil) then if(not isEmptyString(s_info.info)) then label = label.." [".. s_info.info .."]" end end return label end -- ####################### function getFlowKey(name) local s = flow_consts.flow_fields_description[name] if(s == nil) then -- Try to decode the name as . -- then try to look up the name or directly the field -- in the rtemplate (pen is ignored). -- TODO: currently rtemplate is flat and PENs are ignored, we should add PEN there local pen, field = name:match("^(%d+)%.(%d+)$") local v = (rtemplate[tonumber(name)] or rtemplate[tonumber(field)]) if(v == nil) then return(name) end s = flow_consts.flow_fields_description[v] end if(s ~= nil) then s = string.gsub(s, "<", "<") s = string.gsub(s, ">", ">") return(s) else return(name) end end -- ####################### function fieldIDToFieldName(id) local id_num local name local pen_id = string.split(id, "%.") if pen_id then id_num = tonumber(pen_id[2]) else id_num = tonumber(id) end if id_num then name = rtemplate[id_num] else name = id end return name end -- ####################### function isFieldProtocol(protocol, field) if not field or not protocol then return false end local key_name = fieldIDToFieldName(field) if not key_name then return false end if starts(key_name, protocol) then return true end return false end -- ####################### function removeProtocolFields(protocol, array) elements_to_remove = {} n = 0 for key,value in pairs(array) do if(isFieldProtocol(protocol,key)) then elements_to_remove[n] = key n=n+1 end end for key,value in pairs(elements_to_remove) do if(value ~= nil) then array[value] = nil end end return array end -- ####################### function isFlowValueDefined(info, field) if(info[field] ~= nil) then return true else for key,value in pairs(info) do local key_name = fieldIDToFieldName(key) if(key_name == field) then return true end end end return false end -- ####################### function getFlowValue(info, field) local return_value = "0" local value_original = "0" if((info == nil) or (table.len(info) == 0)) then return("") end if(info[field] ~= nil) then return_value = handleCustomFlowField(field, info[field]) value_original = info[field] else for key,value in pairs(info) do local key_name = fieldIDToFieldName(key) if(key_name == field) then return_value = handleCustomFlowField(key_name, value) value_original = value end end end return_value = string.gsub(return_value, "<", "<") return_value = string.gsub(return_value, ">", ">") return_value = string.gsub(return_value, "\"", "\\\"") -- io.write(field.." = ["..return_value..","..value_original.."]\n") return return_value , value_original end -- ####################### function mapCallState(call_state) -- return call_state if(call_state == "CALL_STARTED") then return(i18n("flow_details.call_started")) elseif(call_state == "CALL_IN_PROGRESS") then return(i18n("flow_details.ongoing_call")) elseif(call_state == "CALL_COMPLETED") then return(""..i18n("flow_details.call_completed").."") elseif(call_state == "CALL_ERROR") then return(""..i18n("flow_details.call_error").."") elseif(call_state == "CALL_CANCELED") then return(""..i18n("flow_details.call_canceled").."") else return(call_state) end end -- ####################### function isThereProtocol(protocol, info) local found = 0 for key,value in pairs(info) do if isFieldProtocol(protocol, key) then found = 1 break end end return found end -- ####################### function isThereSIPCall(info) local retVal = 0 local call_state = getFlowValue(info, "SIP_CALL_STATE") if((call_state ~= nil) and (call_state ~= "")) then retVal = 1 end return retVal end -- ####################### function getSIPInfo(infoPar) local called_party = "" local calling_party = "" local sip_found_flow local returnString = "" local infoFlow, posFlow, errFlow = json.decode(infoPar["moreinfo.json"], 1, nil) if (infoFlow ~= nil) then sip_found_flow = isThereSIPCall(infoFlow) if(sip_found_flow == 1) then called_party = getFlowValue(infoFlow, "SIP_CALLED_PARTY") calling_party = getFlowValue(infoFlow, "SIP_CALLING_PARTY") called_party = string.gsub(called_party, "\\\"","\"") calling_party = string.gsub(calling_party, "\\\"","\"") called_party = extractSIPCaller(called_party) calling_party = extractSIPCaller(calling_party) if(((called_party == nil) or (called_party == "")) and ((calling_party == nil) or (calling_party == ""))) then returnString = "" else returnString = calling_party .. " " .. called_party end end end return returnString end -- ####################### function getRTPInfo(infoPar) local call_id local returnString = "" local infoFlow, posFlow, errFlow = json.decode(infoPar["moreinfo.json"], 1, nil) if infoFlow ~= nil then call_id = getFlowValue(infoFlow, "RTP_SIP_CALL_ID") if tostring(call_id) ~= "" then call_id = " "..call_id else call_id = "" end returnString = call_id end if(infoPar.rtp_stream_type ~= nil) then if(infoPar.rtp_stream_type == "screen_share") then str = "Screen Sharing" else str = capitalize(infoPar.rtp_stream_type) end returnString = returnString .. '' .. str .. '' end return returnString end -- ####################### function getSIPTableRows(info) local string_table = "" local call_id = "" local call_id_ico = " " local called_party = "" local calling_party = "" local rtp_codecs = "" local sip_rtp_src_addr = 0 local sip_rtp_dst_addr = 0 local print_second = 0 local print_second_2 = 0 -- check if there is a SIP field sip_found = isThereProtocol("SIP", info) if(sip_found == 1) then sip_found = isThereSIPCall(info) end if(sip_found == 1) then string_table = string_table..""..i18n("flow_details.sip_protocol_information").."\n" call_id = getFlowValue(info, "SIP_CALL_ID") if((call_id == nil) or (call_id == "")) then string_table = string_table.." "..i18n("flow_details.call_id").." "..call_id_ico.."
\n" else string_table = string_table.." "..i18n("flow_details.call_id").." "..call_id_ico.."
" .. call_id .. "
\n" end called_party = getFlowValue(info, "SIP_CALLED_PARTY") calling_party = getFlowValue(info, "SIP_CALLING_PARTY") called_party = string.gsub(called_party, "\\\"","\"") calling_party = string.gsub(calling_party, "\\\"","\"") called_party = extractSIPCaller(called_party) calling_party = extractSIPCaller(calling_party) if(((called_party == nil) or (called_party == "")) and ((calling_party == nil) or (calling_party == ""))) then string_table = string_table..""..i18n("flow_details.call_initiator").." "..i18n("flow_details.called_party").."
\n" else string_table = string_table..""..i18n("flow_details.call_initiator").." "..i18n("flow_details.called_party").."
" .. calling_party .. " " .. called_party .. "
\n" end rtp_codecs = getFlowValue(info, "SIP_RTP_CODECS") if((rtp_codecs == nil) or (rtp_codecs == "")) then string_table = string_table..""..i18n("flow_details.rtp_codecs").."
\n" else string_table = string_table..""..i18n("flow_details.rtp_codecs").."
" .. rtp_codecs .. "\n" end local string_table_1 = "" local string_table_2 = "" local string_table_3 = "" local string_table_4 = "" local string_table_5 = "" local show_rtp_stream = 0 if((getFlowValue(info, "SIP_RTP_IPV4_SRC_ADDR")~=nil) and (getFlowValue(info, "SIP_RTP_IPV4_SRC_ADDR")~="")) then sip_rtp_src_addr = 1 string_table_1 = getFlowValue(info, "SIP_RTP_IPV4_SRC_ADDR") if (string_table_1 ~= "0.0.0.0") then sip_rtp_src_address_ip = string_table_1 interface.select(ifname) rtp_host = interface.getHostInfo(string_table_1) if(rtp_host ~= nil) then string_table_1 = hostinfo2detailshref(rtp_host, nil, sip_rtp_src_address_ip) end end show_rtp_stream = 1 end if((getFlowValue(info, "SIP_RTP_L4_SRC_PORT")~=nil) and (getFlowValue(info, "SIP_RTP_L4_SRC_PORT")~="") and (sip_rtp_src_addr == 1)) then --string_table = string_table ..":"..getFlowValue(info, "SIP_RTP_L4_SRC_PORT") --string_table_2 = ":"..getFlowValue(info, "SIP_RTP_L4_SRC_PORT") sip_rtp_src_port = getFlowValue(info, "SIP_RTP_L4_SRC_PORT") string_table_2 = ":" string_table_2 = string_table_2..sip_rtp_src_port string_table_2 = string_table_2.."" show_rtp_stream = 1 end if((sip_rtp_src_addr == 1) or ((getFlowValue(info, "SIP_RTP_IPV4_DST_ADDR")~=nil) and (getFlowValue(info, "SIP_RTP_IPV4_DST_ADDR")~=""))) then --string_table = string_table.." " string_table_3 = " " show_rtp_stream = 1 end if((getFlowValue(info, "SIP_RTP_IPV4_DST_ADDR")~=nil) and (getFlowValue(info, "SIP_RTP_IPV4_DST_ADDR")~="")) then sip_rtp_dst_addr = 1 string_table_4 = getFlowValue(info, "SIP_RTP_IPV4_DST_ADDR") if (string_table_4 ~= "0.0.0.0") then sip_rtp_dst_address_ip = string_table_4 interface.select(ifname) rtp_host = interface.getHostInfo(string_table_4) if(rtp_host ~= nil) then string_table_4 = hostinfo2detailshref(rtp_host, nil, sip_rtp_dst_address_ip) end end show_rtp_stream = 1 end if((getFlowValue(info, "SIP_RTP_L4_DST_PORT")~=nil) and (getFlowValue(info, "SIP_RTP_L4_DST_PORT")~="") and (sip_rtp_dst_addr == 1)) then --string_table = string_table ..":"..getFlowValue(info, "SIP_RTP_L4_DST_PORT") --string_table_5 = ":"..getFlowValue(info, "SIP_RTP_L4_DST_PORT") sip_rtp_dst_port = getFlowValue(info, "SIP_RTP_L4_DST_PORT") string_table_5 = ":" string_table_5 = string_table_5..sip_rtp_dst_port string_table_5 = string_table_5.."" show_rtp_stream = 1 end if (show_rtp_stream == 1) then string_table = string_table..""..i18n("flow_details.rtp_stream_peers").." (src dst)
" else string_table = string_table..""..i18n("flow_details.rtp_stream_peers").." (src dst)
" end string_table = string_table..string_table_1..string_table_2..string_table_3..string_table_4..string_table_5 local rtp_flow_key = interface.getFlowKey(sip_rtp_src_address_ip or "", tonumber(sip_rtp_src_port) or 0, sip_rtp_dst_address_ip or "", tonumber(sip_rtp_dst_port) or 0, 17 --[[ UDP --]]) -- TODO: fix if tonumber(rtp_flow_key) ~= nil and interface.findFlowByKeyAndHashId(tonumber(rtp_flow_key), 0) ~= nil then string_table = string_table..' ' string_table = string_table.." " string_table = string_table..sip_rtp_dst_address_ip..":"..sip_rtp_dst_port.."\">" string_table = string_table..'' end string_table = string_table.."
\n" val, val_original = getFlowValue(info, "SIP_REASON_CAUSE") if(val_original ~= "0") then string_table = string_table.." "..i18n("flow_details.cancel_bye_failure_reason_cause").."
" string_table = string_table..val else string_table = string_table.." "..i18n("flow_details.cancel_bye_failure_reason_cause").."
" end string_table = string_table.."
\n" if isFlowValueDefined(info, "SIP_C_IP") then string_table = string_table.." "..i18n("flow_details.c_ip_addresses").."
" .. getFlowValue(info, "SIP_C_IP") .. "
\n" end if((getFlowValue(info, "SIP_CALL_STATE") == nil) or (getFlowValue(info, "SIP_CALL_STATE") == "")) then string_table = string_table.." "..i18n("flow_details.call_state").."
\n" else string_table = string_table.." "..i18n("flow_details.call_state").."
" .. mapCallState(getFlowValue(info, "SIP_CALL_STATE")) .. "
\n" end end return string_table end -- ####################### function getRTPTableRows(info) local string_table = "" -- check if there is a RTP field local rtp_found = isThereProtocol("RTP", info) if(rtp_found == 1) then -- SSRC string_table = string_table..""..i18n("flow_details.rtp_protocol_information").."\n" if isFlowValueDefined(info, "RTP_SSRC") then sync_source_var = getFlowValue(info, "RTP_SSRC") if((sync_source_var == nil) or (sync_source_var == "")) then sync_source_hide = "style=\"display: none;\"" else sync_source_hide = "style=\"display: table-row;\"" end string_table = string_table.." "..i18n("flow_details.sync_source_id").."
" .. sync_source_var .. "\n" end -- ROUND-TRIP-TIME if isFlowValueDefined(info, "RTP_RTT") then local rtp_rtt_var = getFlowValue(info, "RTP_RTT") if((rtp_rtt_var == nil) or (rtp_rtt_var == "")) then rtp_rtt_hide = "style=\"display: none;\"" else rtp_rtt_hide = "style=\"display: table-row;\"" end string_table = string_table .. ""..i18n("flow_details.round_trip_time").."" if((rtp_rtt_var ~= nil) and (rtp_rtt_var ~= "")) then string_table = string_table .. rtp_rtt_var .. " ms " end string_table = string_table .. " \n" end -- RTP-IN-TRASIT if isFlowValueDefined(info, "RTP_IN_TRANSIT") then local rtp_in_transit = getFlowValue(info, "RTP_IN_TRANSIT")/100 local rtp_out_transit = getFlowValue(info, "RTP_OUT_TRANSIT")/100 if(((rtp_in_transit == nil) or (rtp_in_transit == "")) and ((rtp_out_transit == nil) or (rtp_out_transit == ""))) then rtp_transit_hide = "style=\"display: none;\"" else rtp_transit_hide = "style=\"display: table-row;\"" end string_table = string_table .. ""..i18n("flow_details.rtp_transit_in_out").."
"..getFlowValue(info, "RTP_IN_TRANSIT").."
"..getFlowValue(info, "RTP_OUT_TRANSIT").."
\n" end -- TONES if isFlowValueDefined(info, "RTP_DTMF_TONES") then local rtp_dtmf_var = getFlowValue(info, "RTP_DTMF_TONES") if((rtp_dtmf_var == nil) or (rtp_dtmf_var == "")) then rtp_dtmf_hide = "style=\"display: none;\"" else rtp_dtmf_hide = "style=\"display: table-row;\"" end string_table = string_table .. ""..i18n("flow_details.dtmf_tones_sent")..""..rtp_dtmf_var.."\n" end -- FIRST REQUEST if isFlowValueDefined(info, "RTP_FIRST_SEQ") then local first_flow_sequence_var = getFlowValue(info, "RTP_FIRST_SEQ") local last_flow_sequence_var = getFlowValue(info, "RTP_FIRST_SEQ") if(((first_flow_sequence_var == nil) or (first_flow_sequence_var == "")) and ((last_flow_sequence_var == nil) or (last_flow_sequence_var == ""))) then first_last_flow_sequence_hide = "style=\"display: none;\"" else first_last_flow_sequence_hide = "style=\"display: table-row;\"" end string_table = string_table .. ""..i18n("flow_details.first_last_flow_sequence").."
"..first_flow_sequence_var.."
"..last_flow_sequence_var.."
\n" end -- CALL-ID if isFlowValueDefined(info, "RTP_SIP_CALL_ID") then local sip_call_id_var = getFlowValue(info, "RTP_SIP_CALL_ID") if((sip_call_id_var == nil) or (sip_call_id_var == "")) then sip_call_id_hide = "style=\"display: none;\"" else sip_call_id_hide = "style=\"display: table-row;\"" end string_table = string_table .. " "..i18n("flow_details.sip_call_id").."  
" .. sip_call_id_var .. "
\n" end -- TWO-WAY CALL-QUALITY INDICATORS string_table = string_table..""..i18n("flow_details.call_quality_indicators")..""..i18n("flow_details.forward")..""..i18n("flow_details.reverse").."" -- JITTER if isFlowValueDefined(info, "RTP_IN_JITTER") then local rtp_in_jitter = getFlowValue(info, "RTP_IN_JITTER")/100 local rtp_out_jitter = getFlowValue(info, "RTP_OUT_JITTER")/100 if(((rtp_in_jitter == nil) or (rtp_in_jitter == "")) and ((rtp_out_jitter == nil) or (rtp_out_jitter == ""))) then rtp_out_jitter_hide = "style=\"display: none;\"" else rtp_out_jitter_hide = "style=\"display: table-row;\"" end string_table = string_table .. ""..i18n("flow_details.jitter").."" if((rtp_in_jitter ~= nil) and (rtp_in_jitter ~= "")) then string_table = string_table .. rtp_in_jitter.." ms " end string_table = string_table .. " " if((rtp_out_jitter ~= nil) and (rtp_out_jitter ~= "")) then string_table = string_table .. rtp_out_jitter.." ms " end string_table = string_table .. " \n" end -- PACKET LOSS if isFlowValueDefined(info, "RTP_IN_PKT_LOST") then local rtp_in_pkt_lost = getFlowValue(info, "RTP_IN_PKT_LOST") local rtp_out_pkt_lost = getFlowValue(info, "RTP_OUT_PKT_LOST") if(((rtp_in_pkt_lost == nil) or (rtp_in_pkt_lost == "")) and ((rtp_out_pkt_lost == nil) or (rtp_out_pkt_lost == ""))) then rtp_packet_loss_hide = "style=\"display: none;\"" else rtp_packet_loss_hide = "style=\"display: table-row;\"" end string_table = string_table .. ""..i18n("flow_details.lost_packets").."" if((rtp_in_pkt_lost ~= nil) and (rtp_in_pkt_lost ~= "")) then string_table = string_table .. formatPackets(rtp_in_pkt_lost) end string_table = string_table .. " " if((rtp_out_pkt_lost ~= nil) and (rtp_out_pkt_lost ~= "")) then string_table = string_table .. formatPackets(rtp_out_pkt_lost) end string_table = string_table .. " \n" end -- PACKET DROPS if isFlowValueDefined(info, "RTP_IN_PKT_DROP") then local rtp_in_pkt_drop = getFlowValue(info, "RTP_IN_PKT_DROP") local rtp_out_pkt_drop = getFlowValue(info, "RTP_OUT_PKT_DROP") if(((rtp_in_pkt_drop == nil) or (rtp_in_pkt_drop == "")) and ((rtp_out_pkt_drop == nil) or (rtp_out_pkt_drop == ""))) then rtp_pkt_drop_hide = "style=\"display: none;\"" else rtp_pkt_drop_hide = "style=\"display: table-row;\"" end string_table = string_table .. ""..i18n("flow_details.dropped_packets").."" if((rtp_in_pkt_drop ~= nil) and (rtp_in_pkt_drop ~= "")) then string_table = string_table .. formatPackets(rtp_in_pkt_drop) end string_table = string_table .. " " if((rtp_out_pkt_drop ~= nil) and (rtp_out_pkt_drop ~= "")) then string_table = string_table .. formatPackets(rtp_out_pkt_drop) end string_table = string_table .. " \n" end -- MAXIMUM DELTA BETWEEN CONSECUTIVE PACKETS if isFlowValueDefined(info, "RTP_IN_MAX_DELTA") then local rtp_in_max_delta = getFlowValue(info, "RTP_IN_MAX_DELTA") local rtp_out_max_delta = getFlowValue(info, "RTP_OUT_MAX_DELTA") if(((rtp_in_max_delta == nil) or (rtp_in_max_delta == "")) and ((rtp_out_max_delta == nil) or (rtp_out_max_delta == ""))) then rtp_max_delta_hide = "style=\"display: none;\"" else rtp_max_delta_hide = "style=\"display: table-row;\"" end string_table = string_table .. ""..i18n("flow_details.max_packet_interarrival_time").."" if((rtp_in_max_delta ~= nil) and (rtp_in_max_delta ~= "")) then string_table = string_table .. rtp_in_max_delta .. " ms " end string_table = string_table .. " " if((rtp_out_max_delta ~= nil) and (rtp_out_max_delta ~= "")) then string_table = string_table .. rtp_out_max_delta .. " ms " end string_table = string_table .. " \n" end -- PAYLOAD TYPE if isFlowValueDefined(info, "RTP_IN_PAYLOAD_TYPE") then local rtp_payload_in_var = formatRtpPayloadType(getFlowValue(info, "RTP_IN_PAYLOAD_TYPE")) local rtp_payload_out_var = formatRtpPayloadType(getFlowValue(info, "RTP_OUT_PAYLOAD_TYPE")) if(((rtp_payload_in_var == nil) or (rtp_payload_in_var == "")) and ((rtp_payload_out_var == nil) or (rtp_payload_out_var == ""))) then rtp_payload_hide = "style=\"display: none;\"" else rtp_payload_hide = "style=\"display: table-row;\"" end string_table = string_table .. ""..i18n("flow_details.payload_type").."
"..rtp_payload_in_var.."
"..rtp_payload_out_var.."
\n" end -- MOS if isFlowValueDefined(info, "RTP_IN_MOS") then local rtp_in_mos = getFlowValue(info, "RTP_IN_MOS") local rtp_out_mos = getFlowValue(info, "RTP_OUT_MOS") if(rtp_in_mos == nil or rtp_in_mos == "") and (rtp_out_mos == nil or rtp_out_mos == "") then quality_mos_hide = "style=\"display: none;\"" else quality_mos_hide = "style=\"display: table-row;\"" end string_table = string_table.. "".. ""..i18n("flow_details.pseudo_mos").."".. "" if((rtp_in_mos ~= nil) and (rtp_in_mos ~= "")) then string_table = string_table .. MosPercentageBar(rtp_in_mos) end string_table = string_table .. " " string_table = string_table .. "" if((rtp_out_mos ~= nil) and (rtp_out_mos ~= "")) then string_table = string_table .. MosPercentageBar(rtp_out_mos) end string_table = string_table.." ".. "" end -- R_FACTOR if isFlowValueDefined(info, "RTP_IN_R_FACTOR") then local rtp_in_r_factor = getFlowValue(info, "RTP_IN_R_FACTOR")/100 local rtp_out_r_factor = getFlowValue(info, "RTP_OUT_R_FACTOR")/100 if(rtp_in_r_factor == nil or rtp_in_r_factor == "" or rtp_in_r_factor == "0") and (rtp_out_r_factor == nil or rtp_out_r_factor == "" or rtp_out_r_factor == "0") then quality_r_factor_hide = "style=\"display: none;\"" else quality_r_factor_hide = "style=\"display: table-row;\"" end string_table = string_table .. ""..i18n("flow_details.r_factor").."" if((rtp_in_r_factor ~= nil) and (rtp_in_r_factor ~= "")) then string_table = string_table .. RFactorPercentageBar(rtp_in_r_factor) end string_table = string_table .. " " string_table = string_table .. "" if((rtp_out_r_factor ~= nil) and (rtp_out_r_factor ~= "")) then string_table = string_table .. RFactorPercentageBar(rtp_out_r_factor) end string_table = string_table .. " " end end return string_table end -- ####################### function getFlowQuota(ifid, info, as_client) local pool_id, quota_source if as_client then pool_id = info["cli.pool_id"] quota_source = info["cli.quota_source"] else pool_id = info["srv.pool_id"] quota_source = info["srv.quota_source"] end local master_proto, app_proto = splitProtocol(info["proto.ndpi"]) app_proto = app_proto or master_proto local pools_stats = interface.getHostPoolsStats() local pool_stats = pools_stats and pools_stats[tonumber(pool_id)] local quota_and_protos = shaper_utils.getPoolProtoShapers(ifid, pool_id) if pool_stats ~= nil then local key = nil if quota_source == "policy_source_protocol" then proto_stats = pool_stats.ndpi -- determine if the quota is on the app or master proto if(quota_and_protos[master_proto] ~= nil) then key = master_proto else key = app_proto end elseif quota_source == "policy_source_category" then key = flow["proto.ndpi_cat"] proto_stats = nil category_stats = pool_stats.ndpi_categories elseif quota_source == "policy_source_pool" then key = "Default" proto_stats = nil category_stats = {default = pool_stats.cross_application} end if key ~= nil then local proto_info = nil if key ~= "Default" then proto_info = quota_and_protos[key] else proto_info = shaper_utils.getCrossApplicationShaper(ifid, pool_id) end if proto_info ~= nil then return proto_info, proto_stats, category_stats end end end return nil end -- ####################### function printFlowQuota(ifid, info, as_client) local flow_quota, proto_stats, category_stats = getFlowQuota(ifid, info, as_client) if flow_quota ~= nil then print("") print(string.gsub(graph_utils.printProtocolQuota(flow_quota, proto_stats, category_stats, {traffic=true, time=true}, true), "\n", "")) print("
") else print(i18n("shaping.no_quota_applied")) end end -- ####################### function printFlowSNMPInfo(snmpdevice, input_idx, output_idx) local inputidx_name = format_portidx_name(snmpdevice, tostring(input_idx)) local outputidx_name = format_portidx_name(snmpdevice, tostring(output_idx)) print(""..i18n("details.flow_snmp_localization")..""..i18n("flows_page.inIfIdx")..""..(inputidx_name or "").."") print(""..i18n("flows_page.outIfIdx")..""..(outputidx_name or "").."") end -- ####################### function printBlockFlowJs() print[[ var block_flow_csrf = "]] print(ntop.getRandomCSRFValue()) print[["; function block_flow(flow_key, flow_hash_id) { var url = "]] print(ntop.getHttpPrefix()) print[[/lua/pro/nedge/block_flow.lua"; $.ajax({ type: 'GET', url: url, cache: false, data: { csrf: block_flow_csrf, flow_key: flow_key, flow_hash_id: flow_hash_id, }, success: function(content) { var data = jQuery.parseJSON(content); var row_id = flow_key + "_" + flow_hash_id; if (data.status == "BLOCKED") { $('#'+row_id+'_block') .removeClass('bg-secondary') .addClass('bg-danger') .attr('title', ']] print(i18n("flow_details.flow_traffic_is_dropped")) print[['); } }, error: function(content) { console.log("error"); } }); } ]] end -- ####################### function printL4ProtoDropdown(base_url, page_params, l4_proto) local l4proto = _GET["l4proto"] local l4proto_filter if not isEmptyString(l4proto) then l4proto_filter = '' else l4proto_filter = '' end -- table.clone needed to modify some parameters while keeping the original unchanged local l4proto_params = table.clone(page_params) l4proto_params["l4proto"] = nil -- Used to possibly remove tcp state filters when selecting a non-TCP l4 protocol local l4proto_params_non_tcp = table.clone(l4proto_params) if l4proto_params_non_tcp["tcp_flow_state"] then l4proto_params_non_tcp["tcp_flow_state"] = nil end print[[\ \ ]] end -- ####################### local function printFlowDevicesFilterDropdown(base_url, page_params) local snmp_cached_dev = require "snmp_cached_dev" local flowdevs = interface.getFlowDevices() local ordering_fun = pairsByKeys if flowdevs == nil then flowdevs = {} end local devips = getProbesName(flowdevs, false, false) local devips_order = ntop.getPref("ntopng.prefs.flow_table_probe_order") == "1" -- Order by Probe Name if devips_order then ordering_fun = pairsByValues end local cur_dev = _GET["deviceIP"] local cur_dev_filter = '' local snmp_community = '' if not isEmptyString(cur_dev) then cur_dev_filter = '' end -- table.clone needed to modify some parameters while keeping the original unchanged local dev_params = table.clone(page_params) for _, p in pairs({"deviceIP", "outIfIdx", "inIfIdx"}) do dev_params[p] = nil end print[[, '
\ \ \
']] if cur_dev ~= nil then -- also print dropddowns for input and output interface index local ports = interface.getFlowDeviceInfo(cur_dev) for _, direction in pairs({"outIfIdx", "inIfIdx"}) do local cur_if = _GET[direction] local cur_if_filter = '' if not isEmptyString(cur_if) then cur_if_filter = '' end -- table.clone needed to modify some parameters while keeping the original unchanged local if_params = table.clone(page_params) if_params[direction] = nil print[[, '
\ \ \
']] end end end -- ####################### local function printDropdownEntries(entries, base_url, param_arr, param_filter, curr_filter) for _, htype in ipairs(entries) do if type(htype) == "string" then -- plain html print(htype) goto continue end param_arr[param_filter] = htype[1] print[[]] print(htype[2]) print[[]] ::continue:: end end local function getParamFilter(page_params, param_name) if page_params[param_name] then return '' end return '' end function printActiveFlowsDropdown(base_url, page_params, ifstats, flowstats, is_ebpf_flows) -- Local / Remote hosts selector -- table.clone needed to modify some parameters while keeping the original unchanged local flowhosts_type_params = table.clone(page_params) print[['\
\ \ \
\ ']] local talking_with_params = table.clone(page_params) talking_with_params["talking_with"] = nil if talking_with_params["host"] then local talking_with_list = {} for host, num_flows in pairs(flowstats["talking_with"] or {}) do if talking_with_params["host"] ~= host then local hinfo = hostkey2hostinfo(host) talking_with_list[#talking_with_list + 1] = { host, hostinfo2label(hinfo) .. " (" .. tostring(num_flows) .. ")" } end end print[[, '\
\ \ \
\ ']] end -- Status selector -- table.clone needed to modify some parameters while keeping the original unchanged local alert_type_params = table.clone(page_params) alert_type_params["alert_type"] = nil print[[, '\
\ \ \
\ ']] -- Flow Status Severity local alert_type_severity_params = table.clone(page_params) alert_type_severity_params["alert_type_severity"] = nil print[[, '\
\ \ \
\ ']] if not is_ebpf_flows then if page_params["l4proto"] and page_params["l4proto"] == "6" then -- TCP flow state filter -- table.clone needed to modify some parameters while keeping the original unchanged local tcp_state_params = table.clone(page_params) tcp_state_params["tcp_flow_state"] = nil print[[, '\
\ \ \
\ ']] end -- Unidirectional flows selector -- table.clone needed to modify some parameters while keeping the original unchanged local traffic_type_params = table.clone(page_params) traffic_type_params["traffic_type"] = nil print[[, '\
\ \ \
\ ']] else -- is_ebpf_flows if not page_params.container then -- POD filter local pods = interface.getPodsStats() -- table.clone needed to modify some parameters while keeping the original unchanged local pods_params = table.clone(page_params) pods_params["pod"] = nil if not table.empty(pods) then print[[, '\
\ \ \
\ ']] end end if not page_params.pod then -- Container filter local containers = interface.getContainersStats() -- table.clone needed to modify some parameters while keeping the original unchanged local container_params = table.clone(page_params) container_params["container"] = nil if not table.empty(containers) then print[[, '\
\ \ \
\ ']] end end end -- L7 Application print(', \'
'") -- L7 Application Category print(', \'
'") -- DSCP selector -- table.clone needed to modify some parameters while keeping the original unchanged local dscp_params = table.clone(page_params) dscp_params["dscp"] = nil print[[, '
]] printDSCPDropdown(base_url, dscp_params, flowstats["dscps"] or {}) print [[
']] -- Host Pool selector -- table.clone needed to modify some parameters while keeping the original unchanged local host_pool_params = table.clone(page_params) host_pool_params["host_pool"] = nil print[[, '
]] printHostPoolDropdown(base_url, host_pool_params, flowstats["host_pool_id"] or {}) print [[
']] -- Host Pool selector -- table.clone needed to modify some parameters while keeping the original unchanged local local_network_params = table.clone(page_params) local_network_params["network"] = nil print[[, '
]] printLocalNetworksDropdown(base_url, local_network_params) print [[
']] -- IP version selector -- table.clone needed to modify some parameters while keeping the original unchanged local ipversion_params = table.clone(page_params) ipversion_params["version"] = nil print[[, '
]] printIpVersionDropdown(base_url, ipversion_params) print [[
']] -- L4 protocol selector -- table.clone needed to modify some parameters while keeping the original unchanged local l4proto_params = table.clone(page_params) l4proto_params["l4proto"] = nil print[[, '
]] printL4ProtoDropdown(base_url, l4proto_params, flowstats["l4_protocols"]) print [[
']] -- VLAN selector -- table.clone needed to modify some parameters while keeping the original unchanged local vlan_params = table.clone(page_params) if ifstats.vlan then print[[, '
]] printVLANFilterDropdown(base_url, vlan_params) print[[
']] end if ntop.isPro() then local hashname = "ntopng.prefs.profiles" local profiles = ntop.getHashKeysCache(hashname) or {} local profiles_defined = false for k,_ in pairsByKeys(profiles) do profiles_defined = true break end if profiles_defined then -- Traffic Profiles print(', \'
'") end end if ntop.isPro() and interface.isPacketInterface() == false then printFlowDevicesFilterDropdown(base_url, vlan_params) end end -- ####################### function getFlowsTableTitle() local active_msg = "" local status_type if _GET["alert_type"] then local alert_type_id = tonumber(_GET["alert_type"]) if(alert_type_id ~= nil) then status_type = alert_consts.alertTypeLabel(tonumber(_GET["alert_type"]), true) else status_type = firstToUpper(_GET["alert_type"]) end end if _GET["alert_type_severity"] then local alert_type_severity = _GET["alert_type_severity"] local s = alert_consts.severity_groups[alert_type_severity] active_msg = active_msg .. " ".. i18n(s.i18n_title) end if _GET["application"] then local application = _GET["application"] if tonumber(application) then application = interface.getnDPIProtoName(tonumber(application)) end active_msg = active_msg .. " ".. application end if _GET["category"] then active_msg = active_msg .. " " .. _GET["category"] end if _GET["vhost"] then active_msg = active_msg .. " " .. _GET["vhost"] end if status_type then active_msg = active_msg .. " " .. status_type end if(_GET["network_name"] ~= nil) then active_msg = active_msg .. i18n("network", {network=_GET["network_name"]}) end if(_GET["host"] ~= nil) then active_msg = active_msg .. i18n("flows_page.host", {host=_GET["host"]}) end if(_GET["port"] ~= nil) then active_msg = active_msg .. i18n("flows_page.port", {port=_GET["port"]}) end if(_GET["inIfIdx"] ~= nil) then active_msg = active_msg .. " ["..i18n("flows_page.inIfIdx").." ".._GET["inIfIdx"].."]" end if(_GET["outIfIdx"] ~= nil) then active_msg = active_msg .. " ["..i18n("flows_page.outIfIdx").." ".._GET["outIfIdx"].."]" end if(_GET["deviceIP"] ~= nil) then active_msg = active_msg .. " ["..i18n("flows_page.device_ip").." ".._GET["deviceIP"].."]" end if(_GET["container"] ~= nil) then active_msg = active_msg .. " ["..i18n("containers_stats.container").." ".. format_utils.formatContainerFromId(_GET["container"]).."]" end if(_GET["pod"] ~= nil) then active_msg = active_msg .. " ["..i18n("containers_stats.pod").." ".. shortenString(_GET["pod"]) .."]" end if((_GET["icmp_type"] ~= nil) and (_GET["icmp_cod"] ~= nil)) then local is_v4 = true if(_GET["version"] ~= nil) then is_v4 = (_GET["version"] == "4") end local icmp_utils = require "icmp_utils" local icmp_label = icmp_utils.get_icmp_label(ternary(is_v4, 4, 6), _GET["icmp_type"], _GET["icmp_cod"]) active_msg = active_msg .. " ["..icmp_label.."]" end if(_GET["tcp_flow_state"] ~= nil) then active_msg = active_msg .. " ["..tcp_flow_state_utils.state2i18n(_GET["tcp_flow_state"]).."]" end if not interface.isPacketInterface() then active_msg = i18n("flows_page.recently_active_flows", {filter = active_msg}) elseif interface.isPcapDumpInterface() then active_msg = i18n("flows_page.flows", {filter = active_msg}) else active_msg = i18n("flows_page.active_flows", {filter = active_msg}) end return active_msg end -- ####################### -- A one line flow description -- This uses the information from flow.getInfo() function shortFlowLabel(flow) local info = "" if not isEmptyString(flow["info"]) then info = " [" .. flow["info"] .. "]" end return(string.format("[%s] %s %s:%d -> %s:%s%s", flow["proto.ndpi"], flow["proto.l4"], flow["cli.ip"], flow["cli.port"], flow["srv.ip"], flow["srv.port"], info )) end -- #######################