From 1e18b7b693573f763b18c5e053b7f22675dc0d57 Mon Sep 17 00:00:00 2001 From: Matteo Biscosi Date: Tue, 14 Jan 2025 10:37:28 +0100 Subject: [PATCH] Added Assets to hosts dump (#6794) --- http_src/vue/page-inactive-hosts.vue | 15 + .../tables_config/inactive_hosts_list.json | 22 +- include/Host.h | 4 + include/LocalHost.h | 9 +- include/Mac.h | 3 +- include/Ntop.h | 4 - include/ntop_defines.h | 1 - scripts/locales/en.lua | 10 +- .../lua/modules/asset_management_utils.lua | 7 +- .../lua/rest/v2/get/host/inactive_host.lua | 16 ++ src/Flow.cpp | 35 +-- src/LocalHost.cpp | 267 +++++------------- src/LuaEngineInterface.cpp | 93 ++++++ src/Mac.cpp | 51 +--- src/Ntop.cpp | 2 - 15 files changed, 235 insertions(+), 304 deletions(-) diff --git a/http_src/vue/page-inactive-hosts.vue b/http_src/vue/page-inactive-hosts.vue index 70e6da13cd..45427d47c9 100644 --- a/http_src/vue/page-inactive-hosts.vue +++ b/http_src/vue/page-inactive-hosts.vue @@ -156,6 +156,7 @@ const map_table_def_columns = (columns) => { if (c.id == "actions") { const visible_dict = { historical_flows: props.context.historical_available, + details: true, }; c.button_def_array.forEach((b) => { if (!visible_dict[b.id]) { @@ -241,6 +242,12 @@ function create_historical_flows_url_link(row) { /* ************************************** */ +function create_button_host_details(row) { + return `${http_prefix}/lua/inactive_host_details.lua?ifid=${props.context.ifid}&serial_key=${row.key}` +} + +/* ************************************** */ + function click_button_historical_flows(event) { const row = event.row; window.open(create_historical_flows_url_link(row)); @@ -248,9 +255,17 @@ function click_button_historical_flows(event) { /* ************************************** */ +function click_button_host_details(event) { + const row = event.row; + window.open(create_button_host_details(row)); +} + +/* ************************************** */ + function on_table_custom_event(event) { let events_managed = { "click_button_historical_flows": click_button_historical_flows, + "click_button_host_details": click_button_host_details, }; if (events_managed[event.event_id] == null) { return; diff --git a/httpdocs/tables_config/inactive_hosts_list.json b/httpdocs/tables_config/inactive_hosts_list.json index e9547b3c03..03dbe4eeff 100644 --- a/httpdocs/tables_config/inactive_hosts_list.json +++ b/httpdocs/tables_config/inactive_hosts_list.json @@ -21,6 +21,16 @@ ], "render_v_node_type": "button_list", "button_def_array": [ + { + "id": "details", + "icon": "fa-solid fa-magnifying-glass-plus", + "title_i18n": "host_details_tooltip", + "class": [ + "link-button", + "btn-info" + ], + "event_id": "click_button_host_details" + }, { "id": "historical_flows", "icon": "fas fa-stream", @@ -37,7 +47,7 @@ "title_i18n": "ip_address", "data_field": "ip_address", "sortable": true, - "min-width" : "180px", + "min-width": "180px", "class": [ "text-nowrap" ] @@ -46,7 +56,7 @@ "title_i18n": "name", "data_field": "host_name", "sortable": true, - "min-width" : "120px", + "min-width": "120px", "class": [ "text-nowrap" ] @@ -54,7 +64,7 @@ { "title_i18n": "mac_address", "data_field": "mac", - "min-width" : "120px", + "min-width": "120px", "sortable": true, "class": [ "text-nowrap" @@ -64,7 +74,7 @@ "title_i18n": "manufacturer", "data_field": "manufacturer", "sortable": true, - "min-width" : "120px", + "min-width": "120px", "class": [ "text-nowrap" ] @@ -73,7 +83,7 @@ "title_i18n": "first_seen", "data_field": "first_seen", "sortable": true, - "min-width" : "120px", + "min-width": "120px", "class": [ "text-nowrap", "text-center" @@ -83,7 +93,7 @@ "title_i18n": "last_seen", "data_field": "last_seen", "sortable": true, - "min-width" : "120px", + "min-width": "120px", "class": [ "text-nowrap", "text-center" diff --git a/include/Host.h b/include/Host.h index 43a7014f46..16220e6ff6 100644 --- a/include/Host.h +++ b/include/Host.h @@ -955,6 +955,10 @@ class Host : public GenericHashEntry, void setUnidirectionalTCPUDPNoTXEgressFlow(IpAddress *ip, u_int16_t port); void setUnidirectionalTCPUDPNoTXIngressFlow(IpAddress *ip, u_int16_t port); + /* Currently used only by LocalHost */ + bool addDataToAssets(char *field, char *value) { return false; }; + bool removeDataFromAssets(char *field) { return false; }; + u_int32_t getNumContactedPeersAsClientTCPUDPNoTX(); u_int32_t getNumContactsFromPeersAsServerTCPUDPNoTX(); diff --git a/include/LocalHost.h b/include/LocalHost.h index 9fda18b59a..dda6573675 100644 --- a/include/LocalHost.h +++ b/include/LocalHost.h @@ -42,20 +42,19 @@ class LocalHost : public Host { /* LocalHost data: update LocalHost::deleteHostData when adding new fields */ char *os_detail, *tcp_fingerprint; std::map os_learning; /* How OS info has been learnt */ + std::map asset_map; /* For generic purposes, a pair is done */ /* END Host data: */ void initialize(); void deferredInitialization(); void freeLocalHostData(); - void addInactiveData(); + void dumpAssetInfo(); virtual void deleteHostData(); + void dumpAssetJson(ndpi_serializer *serializer); char *getMacBasedSerializationKey(char *redis_key, size_t size, char *mac_key, bool short_format); char *getIPBasedSerializationKey(char *redis_key, size_t size, bool short_format); void luaDoHDot(lua_State *vm); -#ifdef NTOPNG_PRO - void dumpAssetInfo(); -#endif public: LocalHost(NetworkInterface *_iface, int32_t _iface_idx, @@ -225,6 +224,8 @@ class LocalHost : public Host { void offlineSetHTTPName(const char *n); void setServerName(const char *n); void setResolvedName(const char *resolved_name); + bool addDataToAssets(char *field, char *value); + bool removeDataFromAssets(char *field); virtual void setOS(OSType _os, OSLearningMode mode); void setTCPfingerprint(char *tcp_fingerprint, enum operating_system_hint os); diff --git a/include/Mac.h b/include/Mac.h index 8aa0968402..afab84638d 100644 --- a/include/Mac.h +++ b/include/Mac.h @@ -53,8 +53,7 @@ class Mac : public GenericHashEntry { /* END Mac data: */ #ifdef NTOPNG_PRO - void dumpAssetInfo(); - void dumpAssetInfoToRedis(bool dump_last_seen); + void dumpAssetInfo(bool dump_last_seen); #endif void checkDeviceTypeFromManufacturer(); void readDHCPCache(); diff --git a/include/Ntop.h b/include/Ntop.h index 8ebaeae522..0858852495 100644 --- a/include/Ntop.h +++ b/include/Ntop.h @@ -111,7 +111,6 @@ class Ntop { std::atomic num_flow_exporters; std::atomic num_flow_interfaces; #ifdef NTOPNG_PRO - AssetManagement am; #ifdef HAVE_KAFKA KafkaClient kafkaClient; #endif @@ -803,9 +802,6 @@ class Ntop { inline ClickHouseImport *getClickHouseImport() { return (clickhouseImport); } #endif inline char *getTZname() { return (myTZname); } -#ifdef NTOPNG_PRO - inline AssetManagement *get_am() { return (&am); } -#endif inline Mutex *get_pools_lock() { return (&pools_lock); }; inline u_int32_t get_current_time() { return(current_time); }; diff --git a/include/ntop_defines.h b/include/ntop_defines.h index f4329d318a..0615a35038 100644 --- a/include/ntop_defines.h +++ b/include/ntop_defines.h @@ -239,7 +239,6 @@ #define DHCP_CACHE "ntopng.dhcp.%d.cache.%s" #define DHCP_STORM_QUEUE_NAME "ntopng.dhcp.storm.%d" #define ASSET_SERVICE_KEY "ntopng.asset.%d.%s" /* ifId.host */ -#define ASSET_LIST_INSERTION_KEY "ntopng.asset.device_queue.%d" /* take in sync with lua code */ #define ASSET_HASH_CACHE_KEY "ntopng.asset.hash.cache.%d" /* take in sync with lua code */ #define DHCP_STORM_PPS_THSHOLD 2048 #define NTOPNG_TRACE "ntopng.trace" diff --git a/scripts/locales/en.lua b/scripts/locales/en.lua index fd5d01187d..34506af5bd 100644 --- a/scripts/locales/en.lua +++ b/scripts/locales/en.lua @@ -364,6 +364,10 @@ local lang = { ["inactivity_period"] = "Inactive Since", ["incomingflows"] = "Active Incoming Flows", ["increase_num_flows_hosts"] = "Increase Number", + ["inactive_host_details"] = { + ["dns"] = "DNS Resolved Name", + ["dhcp"] = "DHCP Resolved Name", + }, ["info"] = "Info", ["information"] = "Information", ["ingress"] = "Ingress", @@ -3086,10 +3090,8 @@ local lang = { ["long_lived_description"] = "Trigger an alert when a flow lasts more than the configured duration", ["malicious_fingerprint"] = "Malicious Fingerprint", ["malicious_fingerprint_description"] = "Trigger an alert when a fingerprint of the TLS connection is considered suspicious", - ["malicious_sha1_certificate"] = "Malicious JA3 SHA1 Cert.", + ["malicious_sha1_certificate"] = "Malicious SHA1 TLS Cert.", ["malicious_sha1_certificate_description"] = "Trigger an alert when a SHA1 certificate of the TLS connection is found on a blacklist", - ["malicious_signature"] = "Malicious JA3 Signature", - ["malicious_signature_description"] = "Trigger an alert when a blacklisted JA3 signature is detected", ["ndpi_malware_host_contacted"] = "Malware Host Contacted", ["ndpi_malware_host_contacted_alert_descr"] = "Client or server contacted a malware host", ["ndpi_malware_host_contacted_description"] = "Trigger an alert when nDPI detects a contact towards a malware host", @@ -3947,7 +3949,7 @@ local lang = { }, }, ["flow_risk"] = { - ["malicious_signature_detected"] = "Possibly Client Malicious JA3 Signature", + ["malicious_signature_detected"] = "Possibly Client Malicious JA4 Signature", ["ndpi_anonymous_subscriber"] = "Anonymous Subscriber", ["ndpi_anonymous_subscriber_descr"] = "Trigger an alert whenever the (source) IP address has been anonymized and it can’t be used to identify the subscriber (e.g. iCloud-private-relay)", ["ndpi_binary_application_transfer"] = "Binary App/.exe Transfer", diff --git a/scripts/lua/modules/asset_management_utils.lua b/scripts/lua/modules/asset_management_utils.lua index 9be4681616..34e2300768 100644 --- a/scripts/lua/modules/asset_management_utils.lua +++ b/scripts/lua/modules/asset_management_utils.lua @@ -44,8 +44,9 @@ local function updateData(entry, ifid, type) data = data[1] entry.first_seen = data.first_seen -- Keep the old first_seen local data_json_info = json.decode(data.json_info or "") or {} - local entry_json_info = json.decode(entry.json_info or "") or {} - entry.json_info = json.encode(table.merge(data_json_info, entry_json_info)) -- Merge the json_info field + -- Merge the json_info field, note, that in case of duplicates, the data from + -- entry table are used. + entry.json_info = json.encode(table.merge(data_json_info, entry.json_info)) end return entry end @@ -199,7 +200,7 @@ end function asset_management_utils.insertHost(entry, version, ifid) local query = nil entry = updateData(entry, ifid, "host") - + if hasClickHouseSupport() then query = string.format( "INSERT INTO %s " .. diff --git a/scripts/lua/rest/v2/get/host/inactive_host.lua b/scripts/lua/rest/v2/get/host/inactive_host.lua index 24b03a51ae..e8b7b4dd56 100644 --- a/scripts/lua/rest/v2/get/host/inactive_host.lua +++ b/scripts/lua/rest/v2/get/host/inactive_host.lua @@ -6,6 +6,7 @@ package.path = dirs.installdir .. "/scripts/lua/modules/?.lua;" .. package.path require "lua_utils" require "mac_utils" +local json = require "dkjson" local rest_utils = require "rest_utils" local asset_management_utils = require "asset_management_utils" @@ -101,6 +102,21 @@ for _, host_details in pairs(list or {}) do name = name }} } + + -- Now add the info inside the json_info + local json_info = json.decode(host_details.json_info) or {} + for name, value in pairs(json_info or {}) do + local formatted_name = i18n('inactive_host_details.' .. name) + if isEmptyString(formatted_name) then + formatted_name = name + end + rsp["host_info"][#rsp["host_info"] + 1] = { + name = formatted_name, + values = {{ + name = value + }} + } + end end rest_utils.answer(rest_utils.consts.success.ok, rsp) diff --git a/src/Flow.cpp b/src/Flow.cpp index 22b04c926f..08eb29d49d 100644 --- a/src/Flow.cpp +++ b/src/Flow.cpp @@ -2197,12 +2197,7 @@ void Flow::hosts_periodic_stats_update(NetworkInterface *iface, Host *cli_host, srv_host->getDNSstats()->incStats(false /* Server */, partial->get_flow_dns_stats()); if(cli_host && srv_host) { - if(cli_host->incDNSContactCardinality(srv_host)) { -#ifdef NTOPNG_PRO - ntop->get_am()->addClientServerUsage(cli_host, srv_host, dns_server, - NULL /* no DNS server name */, get_first_seen()); -#endif - } + cli_host->incDNSContactCardinality(srv_host); } break; @@ -2238,12 +2233,7 @@ void Flow::hosts_periodic_stats_update(NetworkInterface *iface, Host *cli_host, case NDPI_PROTOCOL_NTP: if(cli_host && srv_host) { - if(cli_host->incNTPContactCardinality(srv_host)) { -#ifdef NTOPNG_PRO - ntop->get_am()->addClientServerUsage(cli_host, srv_host, ntp_server, - NULL /* no NTP server name */, get_first_seen()); -#endif - } + cli_host->incNTPContactCardinality(srv_host); } break; @@ -2289,36 +2279,21 @@ void Flow::hosts_periodic_stats_update(NetworkInterface *iface, Host *cli_host, case NDPI_PROTOCOL_MAIL_SMTPS: case NDPI_PROTOCOL_MAIL_SMTP: if(cli_host && srv_host) { - if(cli_host->incSMTPContactCardinality(srv_host)) { -#ifdef NTOPNG_PRO - ntop->get_am()->addClientServerUsage(cli_host, srv_host, smtp_server, - getFlowServerInfo(), get_first_seen()); -#endif - } + cli_host->incSMTPContactCardinality(srv_host); } break; case NDPI_PROTOCOL_MAIL_IMAPS: case NDPI_PROTOCOL_MAIL_IMAP: if(cli_host && srv_host) { - if(cli_host->incIMAPContactCardinality(srv_host)) { -#ifdef NTOPNG_PRO - ntop->get_am()->addClientServerUsage(cli_host, srv_host, imap_server, - getFlowServerInfo(), get_first_seen()); -#endif - } + cli_host->incIMAPContactCardinality(srv_host); } break; case NDPI_PROTOCOL_MAIL_POPS: case NDPI_PROTOCOL_MAIL_POP: if(cli_host && srv_host) { - if(cli_host->incPOPContactCardinality(srv_host)) { -#ifdef NTOPNG_PRO - ntop->get_am()->addClientServerUsage(cli_host, srv_host, pop_server, - getFlowServerInfo(), get_first_seen()); -#endif - } + cli_host->incPOPContactCardinality(srv_host); } break; diff --git a/src/LocalHost.cpp b/src/LocalHost.cpp index f257152138..b0f0b2d566 100644 --- a/src/LocalHost.cpp +++ b/src/LocalHost.cpp @@ -63,17 +63,14 @@ LocalHost::~LocalHost() { if (trace_new_delete) ntop->getTrace()->traceEvent(TRACE_NORMAL, "[delete] %s", __FILE__); - addInactiveData(); + dumpAssetInfo(); if (initial_ts_point) delete (initial_ts_point); freeLocalHostData(); /* Decrease number of active hosts */ iface->decNumHosts(this, is_rx_only); - -#ifdef NTOPNG_PRO - ntop->get_am()->deleteHost(this, get_first_seen(), time(NULL)); -#endif + asset_map.clear(); } /* *************************************** */ @@ -179,17 +176,6 @@ void LocalHost::initialize() { fingerprints = NULL; tcp_fingerprint_host_os = os_hint_unknown; - -#ifdef NTOPNG_PRO - if ((!(isBroadcastHost() || isMulticastHost())) && - ntop->getPrefs()->is_enterprise_xl_edition() && - (ntop->getPrefs()->isAssetInventoryEnabled() || - ntop->getPrefs()->isNetBoxEnabled())) - dumpAssetInfo(); - - if(!(isBroadcastHost() || isMulticastHost())) - ntop->get_am()->createHost(this); -#endif } /* *************************************** */ @@ -200,7 +186,7 @@ void LocalHost::deferredInitialization() { /* *************************************** */ -void LocalHost::addInactiveData() { +void LocalHost::dumpAssetInfo() { Mac *cur_mac = getMac(); /* Remove the key from the hash, used to get the offline hosts */ /* Exclude the multicast/broadcast addresses */ @@ -247,6 +233,9 @@ void LocalHost::addInactiveData() { ndpi_serialize_string_string(&host_json, "key", serialization_key); + /* Now dump the json_info field */ + dumpAssetJson(&host_json); + json_str = ndpi_serializer_get_buffer(&host_json, &json_str_len); if ((json_str != NULL) && (json_str_len > 0)) { char redis_key[64]; @@ -676,10 +665,6 @@ void LocalHost::luaDoHDot(lua_State *vm) { void LocalHost::setRouterMac(Mac *gw) { if (!router_mac_set) { memcpy(router_mac, gw->get_mac(), 6), router_mac_set = true; - -#ifdef NTOPNG_PRO - ntop->get_am()->addClientGateway(this, gw, get_first_seen()); -#endif } } @@ -747,209 +732,56 @@ void LocalHost::lua_get_fingerprints(lua_State *vm) { /* *************************************** */ -#ifdef NTOPNG_PRO -void LocalHost::dumpAssetInfo() { - char buf[64], mac_buf[32], *json_str = NULL, - *ip = printMask(buf, sizeof(buf)), *mac_ptr; - ndpi_serializer device_json; - u_int32_t json_str_len = 0; - - ndpi_init_serializer(&device_json, ndpi_serialization_format_json); - - mac_ptr = Utils::formatMac(getMac()->get_mac(), mac_buf, sizeof(mac_buf)); - - if (getMac() && serializeByMac()) { - /* DHCP */ - ndpi_serialize_string_string(&device_json, "key", mac_ptr); - - ndpi_serialize_string_uint32(&device_json, "role", mac->getDeviceType()); - } else { - /* IP */ - ndpi_serialize_string_string(&device_json, "key", ip); - ndpi_serialize_string_uint32(&device_json, "role", getDeviceType()); - } - - ndpi_serialize_string_string(&device_json, "mac", mac_ptr); - if (mac->get_manufacturer()) - ndpi_serialize_string_string(&device_json, "manufacturer", mac->get_manufacturer()); - - if (isIPv6()) - ndpi_serialize_string_string(&device_json, "ipv6", ip); - else - ndpi_serialize_string_string(&device_json, "ipv4", ip); - - ndpi_serialize_string_string(&device_json, "source", "traffic"); - ndpi_serialize_string_uint32(&device_json, "first_seen", first_seen); - ndpi_serialize_string_uint32(&device_json, "last_seen", last_seen); - - json_str = ndpi_serializer_get_buffer(&device_json, &json_str_len); - - if ((json_str != NULL) && (json_str_len > 0)) { - char key[64]; - - snprintf(key, sizeof(key), ASSET_LIST_INSERTION_KEY, iface->get_id()); - ntop->getRedis()->rpush(key, json_str, 1024); - } - - ndpi_term_serializer(&device_json); -} -#endif - -/* *************************************** */ - -void LocalHost::setDhcpServer(char *name) { - Host::setDhcpServer(name); -#ifdef NTOPNG_PRO - bool previousDhcpServer = isDhcpServer(); - if (!previousDhcpServer && isDhcpServer()) - ntop->get_am()->setServerInfo(this, dhcp_server, name); -#endif -} - -/* *************************************** */ - -void LocalHost::setDnsServer(char *name) { - Host::setDnsServer(name); -#ifdef NTOPNG_PRO - bool previous_DnsServer = isDnsServer(); - if (!previous_DnsServer && isDnsServer()) - ntop->get_am()->setServerInfo(this, dns_server, name); -#endif -} - -/* *************************************** */ - -void LocalHost::setSmtpServer(char *name) { - Host::setSmtpServer(name); -#ifdef NTOPNG_PRO - bool previous_SmtpServer = isSmtpServer(); - if (!previous_SmtpServer && isSmtpServer()) - ntop->get_am()->setServerInfo(this, smtp_server, name); -#endif -} - -/* *************************************** */ - -void LocalHost::setNtpServer(char *name) { - Host::setNtpServer(name); -#ifdef NTOPNG_PRO - bool previous_NtpServer = isNtpServer(); - if (!previous_NtpServer && isNtpServer()) - ntop->get_am()->setServerInfo(this, ntp_server, name); -#endif -} - -/* *************************************** */ - -void LocalHost::setImapServer(char *name) { - Host::setImapServer(name); -#ifdef NTOPNG_PRO - bool previous_ImapServer = isImapServer(); - if (!previous_ImapServer && isImapServer()) - ntop->get_am()->setServerInfo(this, imap_server, name); -#endif -} - -/* *************************************** */ - -void LocalHost::setPopServer(char *name) { - Host::setPopServer(name); -#ifdef NTOPNG_PRO - bool previous_popServer = isPopServer(); - if (!previous_popServer && isPopServer()) - ntop->get_am()->setServerInfo(this, pop_server, name); -#endif -} - -/* *************************************** */ - void LocalHost::offlineSetMDNSInfo(char *const str) { -#ifdef NTOPNG_PRO - bool previous_mdns_info = names.mdns_info ? true : false; -#endif Host::offlineSetMDNSInfo(str); -#ifdef NTOPNG_PRO - if (names.mdns_info && !previous_mdns_info) - ntop->get_am()->setResolvedName(this, label_mdns_info, names.mdns_info); -#endif } /* *************************************** */ void LocalHost::offlineSetMDNSName(const char *mdns_n) { -#ifdef NTOPNG_PRO - bool previous_mdns = names.mdns ? true : false; -#endif Host::offlineSetMDNSName(mdns_n); -#ifdef NTOPNG_PRO - if (names.mdns && !previous_mdns) - ntop->get_am()->setResolvedName(this, label_mdns, names.mdns); -#endif + addDataToAssets((char *) "mdns_name", (char *) mdns_n); } /* *************************************** */ void LocalHost::offlineSetDHCPName(const char *dhcp_n) { -#ifdef NTOPNG_PRO - bool previous_dhcp = names.dhcp ? true : false; -#endif Host::offlineSetDHCPName(dhcp_n); -#ifdef NTOPNG_PRO - if (names.dhcp && !previous_dhcp) - ntop->get_am()->setResolvedName(this, label_dhcp, names.dhcp); -#endif + addDataToAssets((char *) "dhcp_name", (char *) dhcp_n); } /* *************************************** */ void LocalHost::offlineSetMDNSTXTName(const char *mdns_n_txt) { -#ifdef NTOPNG_PRO - bool previous_mdns_txt = names.mdns_txt ? true : false; -#endif Host::offlineSetMDNSTXTName(mdns_n_txt); -#ifdef NTOPNG_PRO - if (names.mdns_txt && !previous_mdns_txt) - ntop->get_am()->setResolvedName(this, label_mdns_txt, names.mdns_txt); -#endif + addDataToAssets((char *) "mdns_txt_name", (char *) mdns_n_txt); } /* *************************************** */ void LocalHost::offlineSetNetbiosName(const char *netbios_n) { -#ifdef NTOPNG_PRO - bool previous_netbios = names.netbios ? true : false; -#endif Host::offlineSetNetbiosName(netbios_n); -#ifdef NTOPNG_PRO - if (names.netbios && !previous_netbios) - ntop->get_am()->setResolvedName(this, label_netbios, names.netbios); -#endif + addDataToAssets((char *) "netbios_name", (char *) netbios_n); +} + +/* *************************************** */ + +void LocalHost::offlineSetTLSName(const char *tls_n) { + Host::offlineSetHTTPName(tls_n); + addDataToAssets((char *) "tls_name", (char *) tls_n); } /* *************************************** */ void LocalHost::offlineSetHTTPName(const char *http_n) { -#ifdef NTOPNG_PRO - bool previous_http = names.http ? true : false; -#endif Host::offlineSetHTTPName(http_n); -#ifdef NTOPNG_PRO - if(names.http && !previous_http) - ntop->get_am()->setResolvedName(this, label_http, names.http); -#endif + addDataToAssets((char *) "http_name", (char *) http_n); } /* *************************************** */ void LocalHost::setServerName(const char *server_n) { -#ifdef NTOPNG_PRO - bool previous_server_name = names.server_name ? true : false; -#endif Host::setServerName(server_n); -#ifdef NTOPNG_PRO - if(names.server_name && !previous_server_name) - ntop->get_am()->setResolvedName(this, label_server_name, names.server_name); -#endif } /* *************************************** */ @@ -958,15 +790,8 @@ void LocalHost::setResolvedName(const char *resolved_name) { char buf[64]; if(strcmp(get_ip()->print(buf, sizeof(buf)), resolved_name)) { -#ifdef NTOPNG_PRO - bool previous_resolved = names.resolved ? true : false; -#endif Host::setResolvedName(resolved_name); - -#ifdef NTOPNG_PRO - if(names.resolved && !previous_resolved) - ntop->get_am()->setResolvedName(this, label_resolver, names.resolved); -#endif + addDataToAssets((char *) "resolved_name", (char *) resolved_name); } } @@ -974,7 +799,8 @@ void LocalHost::setResolvedName(const char *resolved_name) { void LocalHost::setTCPfingerprint(char *_tcp_fingerprint, enum operating_system_hint os) { - + if (_tcp_fingerprint && _tcp_fingerprint[0] != '\0') + addDataToAssets((char *) "tcp_fingerprint", (char *) _tcp_fingerprint); if(tcp_fingerprint_host_os == os_hint_unknown) { /* Not yet set the host fingerprint */ OSType os_type = Utils::OShint2OSType(os); @@ -1006,11 +832,52 @@ void LocalHost::setOS(OSType _os, OSLearningMode mode) { if((_os != os_unknown) && (getOS() != _os)) { os_learning[mode] = _os; + char buf[8]; + snprintf(buf, sizeof(buf), "%d", _os) + addDataToAssets((char *) "os_type", buf); + Host::setOS(_os, mode); - -#ifdef NTOPNG_PRO - if(ntop->get_am() != NULL) - ntop->get_am()->setHostOS(this, _os, mode); -#endif } } + +/* *************************************** */ + +/* This function is used to add a new field to the asset map; + * this field is going to be automatically added to the json, when dumped to redis + * Note: the function overwrite the old values if already present + */ +bool LocalHost::addDataToAssets(char *_field, char *_value) { + /* Check for incorrect values */ + if (_field && _field[0] != '\0' && _value && _value[0] != '\0') { + std::string field = _field; + std::string value = _value; + asset_map[field] = value; + return true; + } + return false; +} + +/* *************************************** */ + +/* This function instead remove a field from the asset map */ +bool LocalHost::removeDataFromAssets(char *field) { + if (asset_map.size() > 0 && field && field[0] != '\0') { + asset_map.erase(field); + return true; + } + return false; +} + +/* *************************************** */ + +void LocalHost::dumpAssetJson(ndpi_serializer *serializer) { + /* Check for the map size */ + if (asset_map.size() == 0) + return; + + ndpi_serialize_start_of_block(serializer, "json_info"); /* Custom fields block */ + for(std::map::iterator it = asset_map.begin(); it != asset_map.end(); it++) { + ndpi_serialize_string_string(serializer, it->first.c_str(), it->second.c_str()); + } + ndpi_serialize_end_of_block(serializer); +} diff --git a/src/LuaEngineInterface.cpp b/src/LuaEngineInterface.cpp index f78318e7fc..2e8d4c93f4 100644 --- a/src/LuaEngineInterface.cpp +++ b/src/LuaEngineInterface.cpp @@ -606,6 +606,96 @@ AddressTree *get_allowed_nets(lua_State *vm) { /* ****************************************** */ +static int ntop_add_data_to_assets(lua_State *vm) { + NetworkInterface *iface = getCurrentInterface(vm); + char *host = NULL, *field = NULL, *value = NULL; + + ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__); + if (!iface) return (ntop_lua_return_value(vm, __FUNCTION__, CONST_LUA_ERROR)); + + if (lua_type(vm, 1) == LUA_TSTRING) /* Host provided in IP@VLAN format */ + host = (char *)lua_tostring(vm, 1); + + if (host != NULL && strlen(host) > 0) { + Host *h; + char host_ip[64]; + char *key; + u_int16_t vlan_id = 0; + + get_host_vlan_info(host, &key, &vlan_id, host_ip, sizeof(host_ip)); + + if ((!iface) || + ((h = iface->findHostByIP(get_allowed_nets(vm), host_ip, vlan_id, getLuaVMUservalue(vm, observationPointId))) == NULL)) { + ntop->getTrace()->traceEvent(TRACE_WARNING, "Unable to locate host %s", + host_ip); + return (ntop_lua_return_value(vm, __FUNCTION__, CONST_LUA_ERROR)); + } + + if (h->isLocalHost()) { + /* Available only for local hosts */ + if (lua_type(vm, 2) == LUA_TSTRING) /* Field provided */ + field = (char *)lua_tostring(vm, 2); + + if (lua_type(vm, 3) == LUA_TSTRING) /* Value provided */ + value = (char *)lua_tostring(vm, 3); + + if (!h->addDataToAssets(field, value)) { + ntop->getTrace()->traceEvent(TRACE_WARNING, "Error while updating [%s] Asset Map [field: %s][value :%s]", + host ? host : "NULL", + field ? field : "NULL", + value ? value : "NULL"); + return (ntop_lua_return_value(vm, __FUNCTION__, CONST_LUA_ERROR)); + } + } + } + return (ntop_lua_return_value(vm, __FUNCTION__, CONST_LUA_OK)); +} + +/* ****************************************** */ + +static int ntop_remove_data_from_assets(lua_State *vm) { + NetworkInterface *iface = getCurrentInterface(vm); + char *host = NULL, *field = NULL; + + ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__); + if (!iface) return (ntop_lua_return_value(vm, __FUNCTION__, CONST_LUA_ERROR)); + + if (lua_type(vm, 1) == LUA_TSTRING) /* Host provided in IP@VLAN format */ + host = (char *)lua_tostring(vm, 1); + + if (host != NULL && strlen(host) > 0) { + Host *h; + char host_ip[64]; + char *key; + u_int16_t vlan_id = 0; + + get_host_vlan_info(host, &key, &vlan_id, host_ip, sizeof(host_ip)); + + if ((!iface) || + ((h = iface->findHostByIP(get_allowed_nets(vm), host_ip, vlan_id, getLuaVMUservalue(vm, observationPointId))) == NULL)) { + ntop->getTrace()->traceEvent(TRACE_WARNING, "Unable to locate host %s", + host_ip); + return (ntop_lua_return_value(vm, __FUNCTION__, CONST_LUA_ERROR)); + } + + if (h->isLocalHost()) { + /* Available only for local hosts */ + if (lua_type(vm, 2) == LUA_TSTRING) /* Field provided */ + field = (char *)lua_tostring(vm, 2); + + if (!h->removeDataFromAssets(field)) { + ntop->getTrace()->traceEvent(TRACE_WARNING, "Error while updating [%s] Asset Map [field: %s]", + host ? host : "NULL", + field ? field : "NULL"); + return (ntop_lua_return_value(vm, __FUNCTION__, CONST_LUA_ERROR)); + } + } + } + return (ntop_lua_return_value(vm, __FUNCTION__, CONST_LUA_OK)); +} + +/* ****************************************** */ + static int ntop_interface_live_capture(lua_State *vm) { NetworkInterface *curr_iface = getCurrentInterface(vm); NtopngLuaContext *c; @@ -5726,6 +5816,9 @@ static luaL_Reg _ntop_interface_reg[] = { {"updateIPReassignment", ntop_interface_update_ip_reassignment}, {"triggerTrafficAlert", ntop_interface_trigger_traffic_alert}, + {"addDataToLocalHostAssets", ntop_add_data_to_assets }, + {"removeDataFromLocalHostAssets", ntop_remove_data_from_assets }, + /* eBPF, Containers and Companion Interfaces */ {"getPodsStats", ntop_interface_get_pods_stats}, {"getContainersStats", ntop_interface_get_containers_stats}, diff --git a/src/Mac.cpp b/src/Mac.cpp index fa59e53725..65533750a1 100644 --- a/src/Mac.cpp +++ b/src/Mac.cpp @@ -70,17 +70,8 @@ Mac::Mac(NetworkInterface *_iface, u_int8_t _mac[6]) #endif #ifdef NTOPNG_PRO - if ((!special_mac) && (!broadcast_mac) && - ntop->getPrefs()->is_enterprise_xl_edition() && - (ntop->getPrefs()->isAssetInventoryEnabled() || - ntop->getPrefs()->isNetBoxEnabled())) - dumpAssetInfo(); - if ((!special_mac) && ntop->getRedis() && ntop->getPrefs()->is_enterprise_m_edition()) - dumpAssetInfoToRedis(false); - - if((!special_mac) && (!broadcast_mac)) - ntop->get_am()->createMac(this); + dumpAssetInfo(false); #endif updateHostPool(true /* inline with packet processing */, @@ -98,7 +89,7 @@ Mac::~Mac() { #ifdef NTOPNG_PRO if (!special_mac && ntop->getRedis() && ntop->getPrefs()->is_enterprise_m_edition()) - dumpAssetInfoToRedis(true); + dumpAssetInfo(true); #endif if (model) free(model); @@ -108,10 +99,6 @@ Mac::~Mac() { if (stats) delete (stats); if (stats_shadow) delete (stats_shadow); -#ifdef NTOPNG_PRO - ntop->get_am()->deleteMac(this, get_first_seen(), time(NULL)); -#endif - #ifdef DEBUG ntop->getTrace()->traceEvent(TRACE_NORMAL, "Deleted %s [total %u][%s]", Utils::formatMac(mac, buf, sizeof(buf)), @@ -506,38 +493,7 @@ void Mac::dumpToRedis() { /* *************************************** */ #ifdef NTOPNG_PRO -/* This is used for netbox */ -void Mac::dumpAssetInfo() { - char buf[32], *json_str = NULL; - ndpi_serializer device_json; - u_int32_t json_str_len = 0; - char *mac_ptr = Utils::formatMac(get_mac(), buf, sizeof(buf)); - - ndpi_init_serializer(&device_json, ndpi_serialization_format_json); - - ndpi_serialize_string_string(&device_json, "key", mac_ptr); - ndpi_serialize_string_string(&device_json, "mac", mac_ptr); - ndpi_serialize_string_string(&device_json, "source", "traffic"); - ndpi_serialize_string_uint32(&device_json, "first_seen", first_seen); - ndpi_serialize_string_uint32(&device_json, "last_seen", last_seen); - ndpi_serialize_string_string(&device_json, "manufacturer", - manuf ? manuf : "n/a"); - ndpi_serialize_string_uint32(&device_json, "role", device_type); - - json_str = ndpi_serializer_get_buffer(&device_json, &json_str_len); - - if ((json_str != NULL) && (json_str_len > 0)) { - char key[64]; - snprintf(key, sizeof(key), ASSET_LIST_INSERTION_KEY, iface->get_id()); - ntop->getRedis()->rpush(key, json_str, 1024); - } - - ndpi_term_serializer(&device_json); -} - -/* *************************************** */ - -void Mac::dumpAssetInfoToRedis(bool dump_last_seen) { +void Mac::dumpAssetInfo(bool dump_last_seen) { char mac_addr[64], *mac, *json_str; ndpi_serializer device_json; u_int32_t json_str_len = 0; @@ -562,7 +518,6 @@ void Mac::dumpAssetInfoToRedis(bool dump_last_seen) { ndpi_term_serializer(&device_json); } - #endif /* *************************************** */ diff --git a/src/Ntop.cpp b/src/Ntop.cpp index 6297e1c378..38aaf175fe 100644 --- a/src/Ntop.cpp +++ b/src/Ntop.cpp @@ -588,8 +588,6 @@ void Ntop::start() { #ifdef NTOPNG_PRO if (!pro->forced_community_edition()) pro->printLicenseInfo(); - - am.init(); #endif FlowRiskAlerts::checkUndefinedRisks();