require "lua_utils" require "flow_aggregation_utils" local json = require ("dkjson") local pcap_status_url = ntop.getHttpPrefix().."/lua/get_nbox_data.lua?nbox_action=status" local pcap_request_url = ntop.getHttpPrefix().."/lua/get_nbox_data.lua?nbox_action=schedule" local favourites_url = ntop.getHttpPrefix().."/lua/get_historical_favourites.lua" local flows_download_url = ntop.getHttpPrefix().."/lua/get_db_flows.lua" function commonJsUtils() print[[ function hideAll(cla){ $('.' + cla).hide(); } function showOne(cla, id){ $('.' + cla).not('#' + id).hide(); $('#' + id).show(); } function hostkey2hostid(host_key) { var info; var hostinfo = []; host_key = host_key.replace(/\:/g, "____"); host_key = host_key.replace(/\//g, "___"); host_key = host_key.replace(/\./g, "__"); info = host_key.split("@"); return(info); } /* * Returns a map of querystring parameters * * Keys of type [] will automatically be added to an array * * @param String url * @return Object parameters */ function getParams(url) { var regex = /([^=&?]+)=([^&#]*)/g, params = {}, parts, key, value; while((parts = regex.exec(url)) != null) { key = parts[1], value = parts[2]; var isArray = /\[\]$/.test(key); if(isArray) { params[key] = params[key] || []; params[key].push(value); } else { params[key] = value; } } return params; } /* adds a CSS style to replace the / in the breadcrumb */ var style = $(''); $('html > head').append(style); function addObservationPeriodToBreadCrumb(params_url, breadcrumb_id){ var params = getParams(params_url); var begin = params["epoch_begin"] if (typeof begin === 'undefined') { if (typeof params["epoch_begin"] !== 'undefined') begin = params["epoch_begin"] else begin = 0 } var end = params["epoch_end"] if (typeof end === undefined) end = 0 if (end < begin) end = begin var durat = moment.duration(end-begin, 'seconds') var d_d = durat.days(), d_h = durat.hours(), d_m = durat.minutes(), d_s = durat.seconds() var str = '
  • ' str += secondsToTime(end-begin) str += ' starting on ' + moment(begin*1000).format("dddd, MMMM Do YYYY, h:mm:ss a") str += '
  • ' $(breadcrumb_id).append(str); } function buildRequestData(source_div_id){ var epoch_begin = $('#' + source_div_id).attr("epoch_begin"); var epoch_end = $('#' + source_div_id).attr("epoch_end"); var ifId = "]] print(tostring(ifId)) print [["; var host = $('#' + source_div_id).attr("host"); var peer = $('#' + source_div_id).attr("peer"); var l7_proto_id = $('#' + source_div_id).attr("l7_proto_id"); var l4_proto_id = $('#' + source_div_id).attr("l4_proto_id"); var port = $('#' + source_div_id).attr("port"); var vlan = $('#' + source_div_id).attr("vlan"); var profile = $('#' + source_div_id).attr("profile"); var res = {epoch_begin: epoch_begin, epoch_end: epoch_end}; if (typeof ifId != 'undefined') res.ifid = ifId; if (typeof host != 'undefined') res.peer1 = host; if (typeof peer != 'undefined') res.peer2 = peer; if (typeof port != 'undefined') res.port = port; if (typeof vlan != 'undefined') res.vlan = vlan; if (typeof profile != 'undefined') res.profile = profile; if (typeof l7_proto_id != 'undefined'){ res.l7_proto_id = l7_proto_id; res.l7proto = l7_proto_id; }; if (typeof l4_proto_id != 'undefined'){ res.l4_proto_id = l4_proto_id; res.l4proto = l4_proto_id; }; return res; } function addToFavourites(source_div_id, stats_type, favourite_type, select_id){ $.ajax({type:'GET',url:"]]print(favourites_url)print[[?fav_action=set&stats_type=" + stats_type + "&favourite_type=" + favourite_type, data:buildRequestData(source_div_id), success:function(data){ data=jQuery.parseJSON(data); populateFavourites(source_div_id, stats_type, favourite_type, select_id); }, error:function(){ perror('An HTTP error occurred.'); } }); } function removeFromFavourites(source_div_id, stats_type, favourite_type, select_id){ $.ajax({type:'GET',url:"]]print(favourites_url)print[[?fav_action=del&stats_type=" + stats_type + "&favourite_type=" + favourite_type, data:buildRequestData(source_div_id), success:function(data){ data=jQuery.parseJSON(data); populateFavourites(source_div_id, stats_type, favourite_type, select_id); }, error:function(){ perror('An HTTP error occurred.'); } }); } var zoom_vals = { ]] if zoom_vals ~= nil then for _, zv in pairs(zoom_vals) do print('"'..zv[1]..'": '..zv[3]..', ') end end print[[ }; console.log(zoom_vals); function populateHistoricalDbExplorerLink(the_td, host, l7_proto) { var url_params = getParams(window.location.href); var mandatory_params = ["host", "l4proto", "port", "info", "protocol", "search"]; $.each(mandatory_params, function(_, p) { if(url_params[p] === undefined) { url_params[p] = ""; } }); if(host != '' && host !== undefined) { url_params["host"] = host; } if(l7_proto != '' && l7_proto !== undefined) { url_params["protocol"] = l7_proto; } if(url_params["zoom"]) { /* This is a chart url */ var zoom = url_params["zoom"]; var epoch = url_params["epoch"]; if(epoch === undefined) { url_params["epoch_end"] = Math.round(new Date() / 1000); /* now */ url_params["epoch_begin"] = url_params["epoch_end"] - zoom_vals[zoom]; } else { epoch = parseInt(epoch); url_params["epoch_end"] = epoch + zoom_vals[zoom] / 2; url_params["epoch_begin"] = epoch - zoom_vals[zoom] / 2; } } the_td.html('' + the_td.text() + ''); } function populateFavourites(source_div_id, stats_type, favourite_type, select_id){ var multival_separator = " <---> "; $('#'+select_id).find('option').remove(); $.ajax({type:'GET',url:"]]print(favourites_url)print[[?fav_action=get&stats_type=" + stats_type + "&favourite_type=" + favourite_type, data:buildRequestData(source_div_id), success:function(data){ data=jQuery.parseJSON(data); // if no favourite has been added, we hide the div that contains the dropdown if(Object.keys(data).length == 0){ $('#' + select_id).parent().closest('div').hide(); // alternatively, we ajax data to the dropdown menu } else { $('#' + select_id).parent().closest('div').show(); $('').appendTo('#' + select_id); $.each(data, function(key, value){ if (key.split(',').length == 1){ var option_data = ''; }else if (key.split(',').length == 2) { var option_data = ''; } $(option_data).appendTo('#'+select_id); }); $('#' + select_id).change(function() { if (stats_type == "top_talkers"){ var host = $(this).find(':selected').val(); if (host == "noaction"){ return; } host = host.split(','); if (host.length == 1){ populateHostTopTalkersTable(host[0]); } else if (host.length == 2){ populateAppsPerHostsPairTable(host[0], host[1]); } } else if (stats_type == "top_applications"){ var value = $(this).find(':selected').val(); var human_readable = $(this).find(':selected').text(); if (value == "noaction"){ return; } value = value.split(','); if (value.length == 1){ // only the l7 protocol id in value[0] var proto = human_readable; $('#historical-apps-container').attr("l7_proto", proto); $('#historical-apps-container').attr("l7_proto_id", value[0]); populateAppTopTalkersTable(value[0]); } else if (value.length == 2){ // both the l7 protocol id and the peer have been selected var proto = human_readable.split(multival_separator)[0]; var addr = human_readable.split(multival_separator)[1]; $('#historical-apps-container').attr("l7_proto", proto); $('#historical-apps-container').attr("l7_proto_id", value[0]); $('#historical-apps-container').attr("host", addr); populatePeersPerHostByApplication(value[1], value[0]); } } // finally, put the dropdown in the default position // after waiting a couple of seconds to give the user the feeling its // choice has had an impact setTimeout(function(){ $('#'+select_id + '>option:eq(0)').prop("selected", true); }, 2000); }); } }, error:function(){ perror('An HTTP error occurred.'); } }); } function removeAllFavourites(stats_type, favourite_type, select_id){ $.ajax({type:'GET',url:"]]print(favourites_url)print[[?fav_action=del_all&stats_type=" + stats_type + "&favourite_type=" + favourite_type, success:function(data){ // remove all the existing options... $('#'+select_id).find('option').remove(); // and hide the container div... $('#' + select_id).parent().closest('div').hide(); // refresh the right breadcrumb if (stats_type == "top_talkers"){ if(favourite_type == "talker"){ $('.bc-item-add.talker').show(); $('.bc-item-remove.talker').hide(); } else if (favourite_type == "apps_per_host_pair"){ $('.bc-item-add.host-pair').show(); $('.bc-item-remove.host-pair').hide(); } } else if (stats_type == "top_applications"){ if(favourite_type == "host_peers_by_app"){ $('.bc-app-item-add.host-peers-by-app').show(); $('.bc-app-item-remove.host-peers-by-app').hide(); } else if (favourite_type == "app"){ $('.bc-app-item-add.app').show(); $('.bc-app-item-remove.app').hide(); } } }, error:function(){ perror('An HTTP error occurred.'); } }); } ]] end function historicalDownloadButtonsBar(button_id, pcap_request_data_container_div_id, ipv4_enabled, ipv6_enabled) if not ntop.isPro() then return end -- integrate only in the Pro version -- ipv4 and ipv6 download buttons can be either disabled from lua using the parameters above. -- If download buttons are not disabled explicitly from Lua, then a javascript check will disable -- them at display time to make sure no button is shown when the number of flows equals to zero local style_ipv4 = "" local style_ipv6 = "" if ipv4_enabled == false or tonumber(ipv4_enabled) == 0 then style_ipv4 = "display:none;" end if ipv6_enabled == false or tonumber(ipv6_enabled) == 0 then style_ipv6 = "display:none;" end local displacement = "7" if not interface.isPacketInterface() then displacement = "9" end print [[
    ]] print(i18n("db_explorer.download_flows")) print[[: ]] if(ipv4_enabled) then print [[ ]] print(i18n("ipv4")) print[[ ]] else print [[]] print(i18n("ipv6")) print[[]] end print [[
    ]] if interface.isPacketInterface() and ntop.getCache("ntopng.prefs.nbox_integration") == "1" and haveAdminPrivileges() then print[[
    ]] print(i18n("db_explorer.extract_pcap")) print[[:
    ]] print[[
    ]] end print[[

    ]] end function printFlowsCountColumn() -- hides the flows count column when aggregated database flows are being used local col = '{title: "'..i18n("flows") local hide_count = "" if useAggregatedFlows() == true then hide_count = " hidden :true, " end col = col..'", field: "column_flows", '..hide_count..' sortable: true, css: {textAlign:\'right\'}}' return col end function historicalTopTalkersTable(ifid, epoch_begin, epoch_end, host, l7proto, l4proto, port, vlan, profile) local breadcrumb_root = "interface" local container_params = ' epoch_begin="" epoch_end="" host="" peer="" l7_proto_id="" l7_proto="" l4_proto_id="" l4_proto="" ' local host_talkers_url_params = "" local interface_talkers_url_params = "" local isv6 = isIPv6Address(host) interface_talkers_url_params = interface_talkers_url_params.."&epoch_begin="..epoch_begin interface_talkers_url_params = interface_talkers_url_params.."&epoch_end="..epoch_end if l7proto ~= "" and l7proto ~= nil and not string.starts(tostring(l7proto), 'all') then if not isnumber(l7proto) then local id l7proto = string.gsub(l7proto, "%.rrd", "") id = interface.getnDPIProtoId(l7proto) if id ~= -1 then l7proto = id interface_talkers_url_params = interface_talkers_url_params.."&l7_proto_id="..l7proto else l7proto = "" end elseif tonumber(l7proto) ~= nil then interface_talkers_url_params = interface_talkers_url_params.."&l7_proto_id="..tonumber(l7proto) end end if l4proto ~= "" and l4proto ~= nil and tonumber(l4proto) ~= nil then interface_talkers_url_params = interface_talkers_url_params.."&l4_proto_id="..tonumber(l4proto) end if port ~= "" and port ~= nil and tonumber(port) ~= nil then interface_talkers_url_params = interface_talkers_url_params.."&port="..tonumber(port) end if vlan ~= "" and vlan ~= nil and tonumber(vlan) ~= nil then interface_talkers_url_params = interface_talkers_url_params.."&vlan="..tostring(vlan) container_params = container_params..' vlan="'..(tostring(vlan) or '')..'"' else container_params = container_params..' vlan=0 ' end if profile ~= "" and profile ~= nil then interface_talkers_url_params = interface_talkers_url_params.."&profile="..profile container_params = container_params..' profile="'..(profile or '')..'"' end if host and host ~= "" then host_talkers_url_params = interface_talkers_url_params.."&peer1="..host breadcrumb_root = "host" else host_talkers_url_params = interface_talkers_url_params end local preference = tablePreferences("historical_rows_number",_GET["perPage"]) local sort_order = getDefaultTableSortOrder("historical_stats_top_talkers") local sort_column= getDefaultTableSort("historical_stats_top_talkers") if not sort_column or sort_column == "column_" then sort_column = "column_bytes" end print[[
     ]] print(i18n("db_explorer.app_between_talkers_pairs")) print[[ ]] print(i18n("db_explorer.all")) print[[
    ]] historicalDownloadButtonsBar("pcap-button-top-talkers", "historical-container", not(isv6), isv6) print [[ ]] end function historicalTopApplicationsTable(ifid, epoch_begin, epoch_end, host, vlan, profile) local breadcrumb_root = "interface" local container_params = ' epoch_begin="" epoch_end="" host="" peer="" l7_proto_id="" l7_proto="" l4_proto_id="" l4_proto="" ' local top_apps_url_params="" local isv6 = isIPv6Address(host) top_apps_url_params = top_apps_url_params.."&epoch_begin="..epoch_begin top_apps_url_params = top_apps_url_params.."&epoch_end="..epoch_end if vlan ~= "" and vlan ~= nil and tonumber(vlan) ~= nil then top_apps_url_params = top_apps_url_params.."&vlan="..tostring(vlan) container_params = container_params..' vlan="'..(tostring(vlan) or '')..'"' else container_params = container_params..' vlan=0 ' end if profile ~= "" and profile ~= nil then top_apps_url_params = top_apps_url_params.."&profile="..profile container_params = container_params..' profile="'..(profile or '')..'"' end if host and host ~= "" then breadcrumb_root="host" end local preference = tablePreferences("historical_rows_number",_GET["perPage"]) local sort_order = getDefaultTableSortOrder("historical_stats_top_applications") local sort_column= getDefaultTableSort("historical_stats_top_applications") if not sort_column or sort_column == "column_" then sort_column = "column_bytes" end print[[
     ]] print(i18n("protocols")) print[[ ]] print(i18n("db_explorer.all")) print[[
    ]] historicalDownloadButtonsBar("pcap-button-top-protocols", "historical-apps-container", not(isv6), isv6) print [[ ]] end function historicalPcapsTable() print[[
    ]] end -- ########################################## function historicalFlowsTab(ifId, host, epoch_begin, epoch_end, l7proto, l4proto, port, info, vlan, profile) -- prepare some attributes that will be attached to divs local div_data = "" if ifId ~= "" and ifId ~= nil then _GET["ifid"] = ifId div_data = div_data..' ifid="'..tostring(ifId)..'" ' end if epoch_begin ~= "" and epoch_begin ~= nil then _GET["epoch_begin"] = epoch_begin div_data = div_data..' epoch_begin="'..tostring(epoch_begin)..'" ' end if epoch_end ~= "" and epoch_end ~= nil then _GET["epoch_end"] = epoch_end div_data = div_data..' epoch_end="'..tostring(epoch_end)..'" ' end if host ~= "" and host ~= nil then _GET["host"] = host div_data = div_data..' host="'..tostring(host)..'" ' end if l7proto ~= "" and l7proto ~= nil and not string.starts(tostring(l7proto), 'all') then if not isnumber(l7proto) then l7proto = string.gsub(l7proto, "%.rrd", "") local id = interface.getnDPIProtoId(l7proto) if id ~= -1 then l7proto = id else l7proto = "" end end _GET["protocol"] = l7proto div_data = div_data..' l7_proto_id="'..l7proto..'" ' end if l4proto ~= "" and l4proto ~= nil then _GET["l4proto"] = l4proto div_data = div_data..' l4_proto_id="'..l4proto..'" ' end if port ~= "" and port ~= nil then _GET["port"] = port div_data = div_data..' port="'..port..'" ' end if vlan ~= "" and vlan ~= nil then _GET["vlan"] = vlan div_data = div_data..' vlan="'..vlan..'" ' end if profile ~= "" and profile ~= nil then _GET["profile"] = profile div_data = div_data..' profile="'..profile..'" ' end print[[

    ]] print(i18n("flow_search_results")) print[[ 

      ]] print(i18n("db_explorer.query_in_progress")) print[[
    ]] if useAggregatedFlows() == false then -- pointless to show counters for aggregations to the user print[[]] end print[[
    ]] print [[
    ]] historicalDownloadButtonsBar('flows_v4', 'tab-ipv4', true, false) print[[
    ]] print [[
    ]] historicalDownloadButtonsBar('flows_v6', 'tab-ipv6', false, true ) print[[
    ]] print [[
    ]] historicalFlowsTabTables(ifId, host, epoch_begin, epoch_end, l7proto, l4proto, port, info, vlan, profile) end -- ########################################## function historicalFlowsTabTables(ifId, host, epoch_begin, epoch_end, l7proto, l4proto, port, info, vlan, profile) local url_update = ntop.getHttpPrefix().."/lua/get_db_flows.lua?ifid="..ifId.. "&peer1="..(host or '') .. "&epoch_begin="..(epoch_begin or '').."&epoch_end="..(epoch_end or '').."&l4proto="..(l4proto or '').."&port="..(port or '').."&info="..(info or '').."&vlan="..(vlan or '').."&profile="..(profile or '') if(l7proto ~= "") then if(not(isnumber(l7proto))) then local id -- io.write(l7proto.."\n") l7proto = string.gsub(l7proto, "%.rrd", "") if(string.ends(l7proto, ".rrd")) then l7proto = string.sub(l7proto, 1, -5) end id = interface.getnDPIProtoId(l7proto) if(id ~= -1) then l7proto = id ipv4_title = i18n("db_explorer.top_proto_ipv4_flows", {proto=l7proto}) ipv6_title = i18n("db_explorer.top_proto_ipv6_flows", {proto=l7proto}) else l7proto = "" ipv4_title = "" ipv6_title = "" end end if(l7proto ~= "") then url_update = url_update.."&l7proto="..l7proto end end if((host == "") and (l4proto == "") and (port == "")) then ipv4_title = i18n("db_explorer.top_flows_ipv4", {date_from=formatEpoch(epoch_begin), date_to=formatEpoch(epoch_end)}) ipv6_title = i18n("db_explorer.top_flows_ipv6", {date_from=formatEpoch(epoch_begin), date_to=formatEpoch(epoch_end)}) else ipv4_title = "" ipv6_title = "" end print [[ ]] end -- ########################################## function historicalProtoHostHref(ifId, host, l4_proto, ndpi_proto_id, info) if ntop.isPro() and ntop.getPrefs().is_dump_flows_to_mysql_enabled == true then local hist_url = ntop.getHttpPrefix().."/lua/pro/db_explorer.lua?search=true&ifid="..ifId local now = os.time() local ago1h = now - 3600 hist_url = hist_url.."&epoch_end="..tostring(now) if((host ~= nil) and (host ~= "")) then hist_url = hist_url.."&"..hostinfo2url(host) end if((l4_proto ~= nil) and (l4_proto ~= "")) then hist_url = hist_url.."&l4proto="..l4_proto end if((ndpi_proto_id ~= nil) and (ndpi_proto_id ~= "")) then hist_url = hist_url.."&protocol="..ndpi_proto_id end if((info ~= nil) and (info ~= "")) then hist_url = hist_url.."&info="..info end print(' ') -- print('') print('') -- print('') end end