mirror of
https://github.com/ntop/ntopng.git
synced 2026-05-11 10:58:17 +00:00
287 lines
9.7 KiB
C++
287 lines
9.7 KiB
C++
/*
|
|
*
|
|
* (C) 2013-20 - ntop.org
|
|
*
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software Foundation,
|
|
* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
*
|
|
*/
|
|
|
|
#include "ntop_includes.h"
|
|
|
|
/* *************************************** */
|
|
|
|
LocalHostStats::LocalHostStats(Host *_host) : HostStats(_host) {
|
|
top_sites = new FrequentStringItems(HOST_SITES_TOP_NUMBER);
|
|
old_sites = strdup("{}");
|
|
dns = new (std::nothrow) DnsStats();
|
|
http = new (std::nothrow) HTTPstats(_host);
|
|
icmp = new (std::nothrow) ICMPstats();
|
|
nextSitesUpdate = 0;
|
|
|
|
if(TimeseriesRing::isRingEnabled(_host->getInterface()))
|
|
ts_ring = new TimeseriesRing(iface);
|
|
else
|
|
ts_ring = NULL;
|
|
}
|
|
|
|
/* *************************************** */
|
|
|
|
LocalHostStats::~LocalHostStats() {
|
|
if(top_sites) delete top_sites;
|
|
if(old_sites) free(old_sites);
|
|
if(dns) delete dns;
|
|
if(http) delete http;
|
|
if(icmp) delete icmp;
|
|
if(ts_ring) delete ts_ring;
|
|
}
|
|
|
|
/* *************************************** */
|
|
|
|
void LocalHostStats::incrVisitedWebSite(char *hostname) {
|
|
u_int ip4_0 = 0, ip4_1 = 0, ip4_2 = 0, ip4_3 = 0;
|
|
char *firstdot = NULL, *nextdot = NULL;
|
|
|
|
if(top_sites
|
|
&& ntop->getPrefs()->are_top_talkers_enabled()
|
|
&& (strstr(hostname, "in-addr.arpa") == NULL)
|
|
&& (sscanf(hostname, "%u.%u.%u.%u", &ip4_0, &ip4_1, &ip4_2, &ip4_3) != 4)
|
|
) {
|
|
if(ntop->isATrackerHost(hostname)) {
|
|
ntop->getTrace()->traceEvent(TRACE_INFO, "[TRACKER] %s", hostname);
|
|
return; /* Ignore trackers */
|
|
}
|
|
|
|
firstdot = strchr(hostname, '.');
|
|
|
|
if(firstdot)
|
|
nextdot = strchr(&firstdot[1], '.');
|
|
|
|
top_sites->add(nextdot ? &firstdot[1] : hostname, 1);
|
|
}
|
|
}
|
|
|
|
/* *************************************** */
|
|
|
|
void LocalHostStats::updateStats(struct timeval *tv) {
|
|
HostStats::updateStats(tv);
|
|
|
|
if(dns) dns->updateStats(tv);
|
|
if(icmp) icmp->updateStats(tv);
|
|
if(http) http->updateStats(tv);
|
|
|
|
if(top_sites && ntop->getPrefs()->are_top_talkers_enabled() && (tv->tv_sec >= nextSitesUpdate)) {
|
|
if(nextSitesUpdate > 0) {
|
|
if(old_sites)
|
|
free(old_sites);
|
|
old_sites = top_sites->json();
|
|
}
|
|
|
|
nextSitesUpdate = tv->tv_sec + HOST_SITES_REFRESH;
|
|
}
|
|
|
|
/* The ring can be enabled at runtime so we need to check for allocation */
|
|
if(!ts_ring && TimeseriesRing::isRingEnabled(getHost()->getInterface()))
|
|
ts_ring = new TimeseriesRing(iface);
|
|
|
|
if(ts_ring && ts_ring->isTimeToInsert()) {
|
|
HostTimeseriesPoint *pt = new HostTimeseriesPoint(this);
|
|
|
|
/* Ownership of the point is passed to the ring */
|
|
ts_ring->insert(pt, tv->tv_sec);
|
|
}
|
|
}
|
|
|
|
/* *************************************** */
|
|
|
|
void LocalHostStats::getJSONObject(json_object *my_object, DetailsLevel details_level) {
|
|
HostStats::getJSONObject(my_object, details_level);
|
|
|
|
if(dns) json_object_object_add(my_object, "dns", dns->getJSONObject());
|
|
if(http) json_object_object_add(my_object, "http", http->getJSONObject());
|
|
|
|
/* UDP stats */
|
|
if(udp_sent_unicast) json_object_object_add(my_object, "udpBytesSent.unicast", json_object_new_int64(udp_sent_unicast));
|
|
if(udp_sent_non_unicast) json_object_object_add(my_object, "udpBytesSent.non_unicast", json_object_new_int64(udp_sent_non_unicast));
|
|
}
|
|
|
|
/* *************************************** */
|
|
|
|
void LocalHostStats::lua(lua_State* vm, bool mask_host, DetailsLevel details_level, bool tsLua) {
|
|
HostStats::lua(vm, mask_host, details_level, tsLua);
|
|
|
|
if((!mask_host) && top_sites && ntop->getPrefs()->are_top_talkers_enabled()) {
|
|
char *cur_sites = top_sites->json();
|
|
lua_push_str_table_entry(vm, "sites", cur_sites ? cur_sites : (char*)"{}");
|
|
lua_push_str_table_entry(vm, "sites.old", old_sites ? old_sites : (char*)"{}");
|
|
if(cur_sites) free(cur_sites);
|
|
}
|
|
|
|
if(details_level >= details_high) {
|
|
luaICMP(vm,host->get_ip()->isIPv4(),true);
|
|
luaDNS(vm, true);
|
|
luaHTTP(vm);
|
|
}
|
|
}
|
|
|
|
/* *************************************** */
|
|
|
|
void LocalHostStats::deserialize(json_object *o) {
|
|
json_object *obj;
|
|
|
|
HostStats::deserialize(o);
|
|
|
|
l4stats.deserialize(o);
|
|
|
|
/* packet stats */
|
|
if(json_object_object_get_ex(o, "pktStats.sent", &obj)) sent_stats.deserialize(obj);
|
|
if(json_object_object_get_ex(o, "pktStats.recv", &obj)) recv_stats.deserialize(obj);
|
|
|
|
/* UDP stats */
|
|
if(json_object_object_get_ex(o, "udpBytesSent.unicast", &obj)) udp_sent_unicast = json_object_get_int64(obj);
|
|
if(json_object_object_get_ex(o, "udpBytesSent.non_unicast", &obj)) udp_sent_non_unicast = json_object_get_int64(obj);
|
|
|
|
/* TCP packet stats */
|
|
if(json_object_object_get_ex(o, "tcpPacketStats.sent", &obj)) tcp_packet_stats_sent.deserialize(obj);
|
|
if(json_object_object_get_ex(o, "tcpPacketStats.recv", &obj)) tcp_packet_stats_rcvd.deserialize(obj);
|
|
|
|
GenericTrafficElement::deserialize(o, iface);
|
|
|
|
if(json_object_object_get_ex(o, "total_activity_time", &obj)) total_activity_time = json_object_get_int(obj);
|
|
|
|
if(json_object_object_get_ex(o, "dns", &obj)) {
|
|
if(dns) dns->deserialize(obj);
|
|
}
|
|
|
|
if(json_object_object_get_ex(o, "http", &obj)) {
|
|
if(http) http->deserialize(obj);
|
|
}
|
|
|
|
if(json_object_object_get_ex(o, "pktStats.sent", &obj)) sent_stats.deserialize(obj);
|
|
if(json_object_object_get_ex(o, "pktStats.recv", &obj)) recv_stats.deserialize(obj);
|
|
|
|
if(json_object_object_get_ex(o, "flows.as_client", &obj)) total_num_flows_as_client = json_object_get_int(obj);
|
|
if(json_object_object_get_ex(o, "flows.as_server", &obj)) total_num_flows_as_server = json_object_get_int(obj);
|
|
if(json_object_object_get_ex(o, "misbehaving_flows.as_client", &obj)) misbehaving_flows_as_client = json_object_get_int(obj);
|
|
if(json_object_object_get_ex(o, "misbehaving_flows.as_server", &obj)) misbehaving_flows_as_server = json_object_get_int(obj);
|
|
if(json_object_object_get_ex(o, "unreachable_flows.as_client", &obj)) unreachable_flows_as_client = json_object_get_int(obj);
|
|
if(json_object_object_get_ex(o, "unreachable_flows.as_server", &obj)) unreachable_flows_as_server = json_object_get_int(obj);
|
|
if(json_object_object_get_ex(o, "host_unreachable_flows.as_client", &obj)) host_unreachable_flows_as_client = json_object_get_int(obj);
|
|
if(json_object_object_get_ex(o, "host_unreachable_flows.as_server", &obj)) host_unreachable_flows_as_server = json_object_get_int(obj);
|
|
/* NOTE: total_alerts currently not (de)serialized */
|
|
|
|
/* Restores possibly checkpointed data */
|
|
checkpoints.sent_bytes = getNumBytesSent();
|
|
checkpoints.rcvd_bytes = getNumBytesRcvd();
|
|
}
|
|
|
|
/* *************************************** */
|
|
|
|
void LocalHostStats::incNumFlows(bool as_client, Host *peer) {
|
|
HostStats::incNumFlows(as_client, peer);
|
|
|
|
map<Host*, u_int16_t> *contacts_map;
|
|
|
|
if(as_client)
|
|
contacts_map = &contacts_as_cli;
|
|
else
|
|
contacts_map = &contacts_as_srv;
|
|
|
|
if(peer) {
|
|
(*contacts_map)[peer] += 1;
|
|
|
|
#if 0
|
|
char buf1[64], buf2[64];
|
|
ntop->getTrace()->traceEvent(TRACE_NORMAL, "INC contacts: %s %s %s, now %u",
|
|
get_string_key(buf1, sizeof(buf1)), as_client ? "->" : "<-",
|
|
peer->get_string_key(buf2, sizeof(buf2)), (*contacts_map)[peer]);
|
|
#endif
|
|
}
|
|
}
|
|
|
|
/* *************************************** */
|
|
|
|
void LocalHostStats::decNumFlows(bool as_client, Host *peer) {
|
|
HostStats::decNumFlows(as_client, peer);
|
|
|
|
if(peer) {
|
|
map<Host*, u_int16_t> *contacts_map = as_client ? &contacts_as_cli : &contacts_as_srv;
|
|
map<Host*, u_int16_t>::iterator it;
|
|
|
|
if((it = contacts_map->find(peer)) != contacts_map->end()) {
|
|
if(it->second)
|
|
it->second -= 1;
|
|
|
|
#if 0
|
|
char buf1[64], buf2[64];
|
|
ntop->getTrace()->traceEvent(TRACE_NORMAL, "DEC contacts: %s %s %s, now %u",
|
|
get_string_key(buf1, sizeof(buf1)), as_client ? "->" : "<-",
|
|
peer->get_string_key(buf2, sizeof(buf2)), it->second);
|
|
#endif
|
|
|
|
if(!it->second)
|
|
contacts_map->erase(it);
|
|
}
|
|
}
|
|
}
|
|
|
|
/* *************************************** */
|
|
|
|
void LocalHostStats::tsLua(lua_State* vm) {
|
|
if(!ts_ring || !TimeseriesRing::isRingEnabled(getHost()->getInterface())) {
|
|
/* Use real time data */
|
|
HostTimeseriesPoint pt(this);
|
|
|
|
TimeseriesRing::luaSinglePoint(vm, iface, &pt);
|
|
} else
|
|
ts_ring->lua(vm);
|
|
}
|
|
/* *************************************** */
|
|
|
|
bool LocalHostStats::hasAnomalies(time_t when) {
|
|
bool ret = false;
|
|
|
|
if(dns) ret |= dns->hasAnomalies(when);
|
|
if(icmp) ret |= icmp->hasAnomalies(when);
|
|
|
|
return ret;
|
|
}
|
|
|
|
/* *************************************** */
|
|
|
|
void LocalHostStats::luaAnomalies(lua_State* vm, time_t when) {
|
|
if(dns) dns->luaAnomalies(vm, when);
|
|
if(icmp) icmp->luaAnomalies(vm, when);
|
|
}
|
|
|
|
/* *************************************** */
|
|
|
|
void LocalHostStats::incStats(time_t when, u_int8_t l4_proto,
|
|
u_int ndpi_proto, ndpi_protocol_category_t ndpi_category,
|
|
custom_app_t custom_app,
|
|
u_int64_t sent_packets, u_int64_t sent_bytes, u_int64_t sent_goodput_bytes,
|
|
u_int64_t rcvd_packets, u_int64_t rcvd_bytes, u_int64_t rcvd_goodput_bytes,
|
|
bool peer_is_unicast) {
|
|
HostStats::incStats(when, l4_proto, ndpi_proto, ndpi_category, custom_app,
|
|
sent_packets, sent_bytes, sent_goodput_bytes,
|
|
rcvd_packets, rcvd_bytes, rcvd_goodput_bytes, peer_is_unicast);
|
|
|
|
if(l4_proto == IPPROTO_UDP) {
|
|
if(peer_is_unicast)
|
|
udp_sent_unicast += sent_bytes;
|
|
else
|
|
udp_sent_non_unicast += sent_bytes;
|
|
}
|
|
}
|