mirror of
https://github.com/ntop/ntopng.git
synced 2026-10-21 22:10:23 +00:00
With a view interface, a host could be marked with a service or a tag that belongs to its peer. The visible case is DNS: a DNS client was marked as a DNS server (host service "DNS", "DNS Server" tag, and from there the matching asset) when the first packet seen on its flow is a reply, i.e. when the query has not been captured (capture started in the middle of the exchange, packet lost, asymmetric traffic). When the first packet of a flow is sent by the server, the flow is recorded "reversed" (the server looks like the client) and a swap of its peers is requested. Until the swap is performed, the services and the tags have to be set on the peers as they will be after the swap. On a regular interface this is what happens, as the hosts of the flow are taken honouring the swap request. The flows of a viewed interface have no hosts: services and tags are stored in the IP addresses of the flow and moved to the hosts of the view later on. There the swap request was ignored, so they ended up on the other peer. Fix: take the IP addresses of the flow honouring the swap request, exactly as it is done with the hosts, when a service or a tag is set on a peer of a flow with no hosts. Impact: * View interfaces only. Nothing changes on the other interfaces, where flows have hosts. * Only flows with a pending swap request, that is flows seen "reversed": they are uncommon. With DNS it takes a flow starting with a reply. * It applies to all the services and tags set on the peers of a flow, not only to DNS, as the change is in the common code. Only the DNS case has been tested. * This is unrelated to the DNS replies with no records fixed in #11079: that issue never showed up on view interfaces.
1829 lines
68 KiB
C++
1829 lines
68 KiB
C++
/*
|
|
*
|
|
* (C) 2013-26 - 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.
|
|
*
|
|
*/
|
|
|
|
#ifndef _FLOW_H_
|
|
#define _FLOW_H_
|
|
|
|
#include "ntop_includes.h"
|
|
|
|
typedef struct {
|
|
u_int32_t pktFrag;
|
|
} IPPacketStats;
|
|
|
|
typedef struct {
|
|
u_int64_t last, next;
|
|
} TCPSeqNum;
|
|
|
|
typedef struct {
|
|
/* 0...254, 255 means more events */
|
|
u_int8_t num_syn, num_rst, num_fin, num_zero_window;
|
|
} TCPStats;
|
|
|
|
typedef struct {
|
|
/* TCP stats */
|
|
TCPSeqNum tcp_seq_s2d, tcp_seq_d2s;
|
|
u_int16_t cli2srv_window, srv2cli_window;
|
|
struct timeval synTime, synAckTime,
|
|
ackTime; /* network Latency (3-way handshake) */
|
|
float clientRTT3WH, serverRTT3WH; /* Computed at 3WH (msec) */
|
|
time_t last_network_issues; /* last time retr/ooo/lost has been observed */
|
|
struct {
|
|
struct ndpi_analyze_struct cli_to_srv, srv_to_cli;
|
|
u_int8_t cli_to_srv_winscale, srv_to_cli_winscale;
|
|
} tcpWin;
|
|
|
|
struct {
|
|
u_int32_t last_cli_ack, last_srv_ack;
|
|
struct bpf_timeval last_cli_ts, last_srv_ts;
|
|
struct ndpi_analyze_struct cli_to_srv, srv_to_cli;
|
|
} rtt; /* Computed continuously */
|
|
} FlowTCP;
|
|
|
|
typedef struct {
|
|
struct timeval first_cli_to_srv, first_srv_to_cli,
|
|
second_cli_to_srv; /* Time of the first packet in each direction */
|
|
float clientRTT3WH, serverRTT3WH; /* Computed at 3WH (msec) */
|
|
struct {
|
|
bool last_spin_set;
|
|
struct timeval last_ts;
|
|
struct ndpi_analyze_struct cli_min_rtt /* cli <-> ntopng RTT */,
|
|
srv_min_rtt /* ntopng <-> dst RTT */;
|
|
} rtt;
|
|
} FlowUDP;
|
|
|
|
typedef struct {
|
|
struct ndpi_in6_addr exporter_ip; /* IPv4 stored as IPv4-mapped IPv6 (original IP) */
|
|
struct ndpi_in6_addr mapped_exporter_ip; /* IPv4 stored as IPv4-mapped IPv6 (after SNMP mapping) */
|
|
struct ndpi_in6_addr next_hop, mapped_next_hop; /* Same as for exporter_ip */
|
|
u_int16_t exporter_site_id, next_hop_site_id;
|
|
u_int32_t in_index, out_index;
|
|
SNMPInterfaceRole in_role, out_role;
|
|
FlowSource source; /* sFlow / NetFlow */
|
|
bool return_path;
|
|
} ExporterFlowInfo;
|
|
|
|
typedef struct {
|
|
struct ndpi_in6_addr exporter_ip, next_hop;
|
|
} ExporterFlowInfoKey;
|
|
|
|
|
|
// Define the equality operator
|
|
inline bool operator==(const ExporterFlowInfoKey& lhs, const ExporterFlowInfoKey& rhs) {
|
|
return std::memcmp(&lhs.exporter_ip, &rhs.exporter_ip, sizeof(ndpi_in6_addr)) == 0 &&
|
|
std::memcmp(&lhs.next_hop, &rhs.next_hop, sizeof(ndpi_in6_addr)) == 0;
|
|
}
|
|
|
|
// Hash functor
|
|
struct ExporterFlowInfoKeyHash {
|
|
std::size_t operator()(const ExporterFlowInfoKey &k) const noexcept {
|
|
// FNV-1a over the raw bytes of both addresses
|
|
const unsigned char *p = reinterpret_cast<const unsigned char *>(&k);
|
|
std::size_t h = 1469598103934665603ULL; // FNV offset basis
|
|
for (size_t i = 0; i < sizeof(ExporterFlowInfoKey); i++) {
|
|
h ^= p[i];
|
|
h *= 1099511628211ULL; // FNV prime
|
|
}
|
|
return h;
|
|
}
|
|
};
|
|
|
|
typedef struct {
|
|
u_int32_t prevAdjacentAS, nextAdjacentAS;
|
|
u_int32_t vrfId;
|
|
|
|
struct {
|
|
char *src, *dst;
|
|
} bgp;
|
|
|
|
struct {
|
|
char* wlan_ssid;
|
|
u_int8_t wtp_mac_address[6];
|
|
} wifi;
|
|
|
|
struct {
|
|
/* IPv4 only, so a int32 bit is only needed */
|
|
u_int32_t src_ip_addr_post_nat, dst_ip_addr_post_nat;
|
|
u_int16_t src_port_post_nat, dst_port_post_nat;
|
|
} nat;
|
|
} FlowCollectionInfo;
|
|
|
|
/* ******************************************************** */
|
|
|
|
class FlowAlert;
|
|
class FlowCheck;
|
|
|
|
class Flow : public GenericHashEntry {
|
|
private:
|
|
time_t creation_time; /*** Epoch of the flow creation */
|
|
int32_t iface_index; /* Interface index on which this flow has been first
|
|
observed */
|
|
Host *cli_host, *srv_host; /* They are ALWAYS NULL on ViewInterfaces. For
|
|
shared hosts see below viewFlowStats */
|
|
IpAddress *cli_ip_addr, *srv_ip_addr;
|
|
u_int8_t src2dst_tcp_flags, dst2src_tcp_flags;
|
|
FlowTCP* tcp;
|
|
#ifdef NTOPNG_PRO
|
|
FlowUDP* udp;
|
|
FlowRTP* rtp;
|
|
#endif
|
|
u_int32_t flow_key;
|
|
FlowCollectionInfo* collection;
|
|
|
|
/* Data collected from nProbe */
|
|
std::string l7_json;
|
|
std::vector<uint64_t> hr_src2dst_bytes, hr_dst2src_bytes;
|
|
/* Time (wall-clock) of slot 0 of HR counters (hr_src2dst_bytes, etc)
|
|
set by the first HR merge after a reset */
|
|
time_t hr_base_first_seen = 0;
|
|
ICMPinfo* icmp_info;
|
|
char* category_list_name_shared_pointer; /* NOTE: this is a pointer handled by
|
|
Ntop::getPersistentCustomListNameById()
|
|
and it MUST NOT BE FREED */
|
|
ndpi_confidence_t ndpi_confidence;
|
|
ndpi_protocol_category_t flow_category;
|
|
ndpi_protocol_breed_t flow_breed;
|
|
u_int32_t privateFlowId; /* Used to store specific flow info such as DNS
|
|
TransactionId or SIP CallId */
|
|
u_int8_t cli2srv_tos, srv2cli_tos; /* RFC 2474, 3168 */
|
|
u_int16_t cli_port, srv_port;
|
|
u_int16_t vlanId;
|
|
u_int32_t srcAS, dstAS; /* Calculated via GeoIP */
|
|
u_int32_t transitAS;
|
|
u_int16_t observation_point_id;
|
|
char *srcASName, *dstASName, *_srcASNameBuf, *_dstASNameBuf;
|
|
char searched_field[64];
|
|
u_int32_t srcPeerAS, dstPeerAS; /* Collected via NetFLow/IPFIX */
|
|
u_int32_t protocolErrorCode;
|
|
u_int8_t protocol, flow_verdict;
|
|
u_int16_t flow_score;
|
|
bool twh_over_view : 1 /* This flag is used for view interfaces */,
|
|
shapers_profile_set : 1, iface_flow_accounted : 1, _notused : 5;
|
|
u_int8_t cli_mac[6], srv_mac[6];
|
|
/* Viewed flows have no hosts: the OS of the client learnt from this flow is
|
|
* parked here, and it is set on the host of the view by the view itself (see
|
|
* updateViewClientOS). The flags are written by the view only, the other
|
|
* two when the flow is processed.
|
|
* NOTE: the flags come first, as they fit in the padding after the MACs */
|
|
u_int8_t view_cli_os_applied;
|
|
ndpi_os view_cli_os_hint, view_cli_fingerprint_os;
|
|
Mac *c_mac, *s_mac; /* Real flow MACs (hosts can have floating MACs when
|
|
load-balancers are in use) Calculated using cli_mac and
|
|
srv_mac[6] */
|
|
bool c_mac_updated, s_mac_updated;
|
|
struct ndpi_flow_struct* ndpiFlow;
|
|
ndpi_risk ndpi_flow_risk_bitmap;
|
|
/* The bitmap of all possible flow alerts set by FlowCheck subclasses.
|
|
When no alert is set, the flow is in flow_alert_normal.
|
|
|
|
A flow can have multiple alerts but at most ONE of its alerts is
|
|
predominant of a flow, which is written into `predominant_alert`.
|
|
*/
|
|
Bitmap128 alerts_map;
|
|
|
|
std::unordered_map<ExporterFlowInfoKey, ExporterFlowInfo, ExporterFlowInfoKeyHash> exporterStats;
|
|
ExporterFlowInfo *primary_exporter; /* First exporter in exporterStats (do not use begin() as it is not ordered) */
|
|
std::map<FlowAlertTypeEnum, FlowAlert*> triggered_alerts;
|
|
FlowAlertType predominant_alert; /* This is the predominant alert */
|
|
u_int16_t predominant_alert_score; /* The score associated to the predominant
|
|
alert */
|
|
bool pending_alerts; /* alerts triggered with triggerAlert but waiting to be
|
|
enqueued */
|
|
bool refresh_triggered_alerts; /* updated alerts previously triggered */
|
|
bool flow_end_housekeeping_done; /* used by pcap file processing to run flow-end housekeeping
|
|
(including flow-end checks) before shutting down and purging */
|
|
FlowSource flow_source;
|
|
|
|
struct {
|
|
u_int8_t is_cli_attacker : 1, is_cli_victim : 1, is_srv_attacker : 1,
|
|
is_srv_victim : 1, auto_acknowledge : 1;
|
|
} alert_info;
|
|
|
|
char *json_protocol_info, *alerts_json, *alerts_json_shadow, *riskInfo,
|
|
*end_reason;
|
|
|
|
u_int32_t hash_entry_id; /* Uniquely identify this flow inside the flows_hash
|
|
hash table */
|
|
u_int32_t periodicity; /* When is_periodic_flow is set, specifies how periodic
|
|
(seconds) is this flow */
|
|
u_int16_t detection_completed : 1, extra_dissection_completed : 1,
|
|
twh_over : 1, dissect_next_http_packet : 1, passVerdict : 1,
|
|
flow_dropped_counts_increased : 1, quota_exceeded : 1, swap_done : 1,
|
|
swap_requested : 1, has_malicious_cli_signature : 1,
|
|
has_malicious_srv_signature : 1, src2dst_tcp_zero_window : 1,
|
|
dst2src_tcp_zero_window : 1, non_zero_payload_observed : 1,
|
|
is_periodic_flow : 1, has_collected_qoe : 1;
|
|
|
|
struct {
|
|
u_int8_t src_to_dst, dst_to_src;
|
|
} collected_qoe;
|
|
|
|
DropReason dropVerdictReason;
|
|
|
|
u_int8_t rtp_stream_type;
|
|
#ifdef ALERTED_FLOWS_DEBUG
|
|
bool iface_alert_inc, iface_alert_dec;
|
|
#endif
|
|
#ifdef NTOPNG_PRO
|
|
bool ingress2egress_direction;
|
|
bool lateral_movement;
|
|
PeriodicityStatus periodicity_status;
|
|
#ifndef HAVE_NEDGE
|
|
#ifdef HAVE_NBPF
|
|
FlowProfile* trafficProfile;
|
|
#endif
|
|
#else
|
|
u_int32_t numFlowProcessedPkts, numPktsMarkerSet;
|
|
u_int8_t routing_table_id;
|
|
L7PolicySource_t cli_quota_source, srv_quota_source;
|
|
#endif
|
|
CounterTrend throughputTrend, goodputTrend, thptRatioTrend;
|
|
#endif
|
|
char* ndpiAddressFamilyProtocol;
|
|
ndpi_protocol ndpiDetectedProtocol;
|
|
char* ndpiFlowRiskName;
|
|
custom_app_t custom_app;
|
|
|
|
struct {
|
|
bool alertTriggered;
|
|
u_int8_t score;
|
|
char* msg;
|
|
} customFlowAlert;
|
|
json_object* json_info;
|
|
ndpi_serializer* tlv_info;
|
|
ndpi_confidence_t confidence;
|
|
char *host_server_name, *client_info, *bt_hash, *stun_mapped_address;
|
|
IEC104Stats* iec104;
|
|
#ifdef NTOPNG_PRO
|
|
ModbusStats* modbus;
|
|
S7CommStats* s7comm;
|
|
ProfinetStats* profinet;
|
|
#endif
|
|
char* suspicious_dga_domain; /* Stores the suspicious DGA domain for flows
|
|
with NDPI_SUSPICIOUS_DGA_DOMAIN */
|
|
ndpi_os operating_system;
|
|
#ifdef HAVE_NEDGE
|
|
u_int32_t last_conntrack_update;
|
|
u_int32_t marker;
|
|
#endif
|
|
struct {
|
|
char* source;
|
|
json_object* json;
|
|
} external_alert;
|
|
|
|
char *tcp_fingerprint, *ndpi_fingerprint, *tls_blocks;
|
|
struct {
|
|
TCPStats cli2srv, srv2cli;
|
|
} tcp_stats;
|
|
|
|
bool
|
|
trigger_immediate_periodic_update; /* needed to process external alerts */
|
|
time_t next_call_periodic_update; /* The time at which the periodic lua script
|
|
on this flow shall be called */
|
|
|
|
/* Flow payload */
|
|
u_int16_t flow_payload_len;
|
|
char* flow_payload;
|
|
|
|
union {
|
|
struct {
|
|
char *last_url, *last_user_agent, *last_server;
|
|
ndpi_http_method last_method;
|
|
u_int16_t last_return_code;
|
|
} http;
|
|
|
|
struct {
|
|
char *last_query, *last_query_shadow;
|
|
char *last_rsp, *last_rsp_shadow;
|
|
time_t
|
|
last_query_update_time; /* The time when the last query was updated */
|
|
u_int16_t last_query_type;
|
|
u_int16_t last_return_code;
|
|
bool last_pkt_src2dst; /* Direction of the last packet dissected by nDPI */
|
|
} dns;
|
|
|
|
struct {
|
|
char *name, *name_txt, *ssid;
|
|
char* answer;
|
|
} mdns;
|
|
|
|
struct {
|
|
char* location;
|
|
} ssdp;
|
|
|
|
struct {
|
|
char* name;
|
|
} netbios;
|
|
|
|
struct {
|
|
char* name;
|
|
} dhcp;
|
|
|
|
struct {
|
|
char* call_id;
|
|
} sip;
|
|
|
|
struct {
|
|
char *client_signature, *server_signature;
|
|
struct {
|
|
/* https://engineering.salesforce.com/open-sourcing-hassh-abed3ae5044c
|
|
*/
|
|
char *client_hash, *server_hash;
|
|
} hassh;
|
|
} ssh;
|
|
|
|
struct {
|
|
u_int16_t tls_version;
|
|
u_int32_t notBefore, notAfter;
|
|
char *client_alpn, *client_tls_supported_versions, *issuerDN, *subjectDN;
|
|
char *client_requested_server_name, *server_names;
|
|
/* Certificate dissection */
|
|
struct {
|
|
char* client_hash;
|
|
} ja4;
|
|
} tls;
|
|
|
|
struct {
|
|
u_int8_t igmp_type;
|
|
} igmp;
|
|
|
|
struct {
|
|
struct {
|
|
u_int8_t icmp_type, icmp_code;
|
|
} cli2srv, srv2cli;
|
|
u_int16_t max_icmp_payload_size;
|
|
|
|
struct {
|
|
float min_entropy, max_entropy;
|
|
} client_to_server;
|
|
} icmp;
|
|
|
|
struct {
|
|
char* currency;
|
|
} mining;
|
|
|
|
struct {
|
|
char* mail_from;
|
|
char* rcpt_to;
|
|
} smtp;
|
|
} protos;
|
|
|
|
/* eBPF Information */
|
|
ParsedeBPF* ebpf;
|
|
|
|
/* Stats */
|
|
FlowTrafficStats stats;
|
|
|
|
/* IP stats */
|
|
IPPacketStats ip_stats_s2d, ip_stats_d2s;
|
|
|
|
struct timeval c2sFirstGoodputTime;
|
|
float rttSec, applLatencyMsec;
|
|
|
|
InterarrivalStats *cli2srvPktTime, *srv2cliPktTime;
|
|
|
|
/* Counter values at last host update */
|
|
struct {
|
|
PartializableFlowTrafficStats* partial;
|
|
PartializableFlowTrafficStats delta;
|
|
time_t first_seen, last_seen;
|
|
bool in_progress, /* Set to true when the flow is enqueued to be dumped */
|
|
is_first_dump;
|
|
} last_db_dump;
|
|
|
|
#ifdef NTOPNG_PRO
|
|
/* Lazily initialized and used by a possible view interface */
|
|
ViewInterfaceFlowStats* viewFlowStats;
|
|
#endif
|
|
|
|
/* Stats base updated periodically (get_partial_traffic_stats)
|
|
* used to compute partial stats */
|
|
PartializableFlowTrafficStats* periodic_stats_base;
|
|
|
|
#ifdef HAVE_NEDGE
|
|
struct {
|
|
TrafficShaper* cli;
|
|
TrafficShaper* srv;
|
|
} flowShapers;
|
|
u_int16_t cli_shaper_id, srv_shaper_id;
|
|
#endif
|
|
struct timeval last_update_time;
|
|
|
|
float top_bytes_thpt, top_goodput_bytes_thpt, top_pkts_thpt;
|
|
float bytes_thpt, goodput_bytes_thpt;
|
|
float pkts_thpt;
|
|
ValueTrend bytes_thpt_trend, goodput_bytes_thpt_trend, pkts_thpt_trend;
|
|
|
|
/* 64-bit tag bitmap: bits 0-31 reserved for ntop, bits 32-63 user-defined */
|
|
u_int64_t user_tags_bitmap; /* user-defined */
|
|
|
|
MinorConnectionStates current_c_state;
|
|
u_int counter = 0;
|
|
/*
|
|
IMPORTANT NOTE
|
|
|
|
if you add a new 'directional' field such as cliX and serverX
|
|
you need to handle it in the Flow::swap() method
|
|
*/
|
|
|
|
void deferredInitialization();
|
|
char* intoaV4(unsigned int addr, char* buf, u_short bufLen);
|
|
void allocDPIMemory();
|
|
bool checkTor(char* hostname);
|
|
void updateThroughputStats(float tdiff_msec, u_int32_t diff_sent_packets,
|
|
u_int64_t diff_sent_bytes,
|
|
u_int64_t diff_sent_goodput_bytes,
|
|
u_int32_t diff_rcvd_packets,
|
|
u_int64_t diff_rcvd_bytes,
|
|
u_int64_t diff_rcvd_goodput_bytes);
|
|
void updatePacketStats(InterarrivalStats* stats, const struct timeval* when,
|
|
bool update_iat);
|
|
char* printTCPState(char* const buf, u_int buf_len) const;
|
|
void update_pools_stats(NetworkInterface* iface, Host* cli_host,
|
|
Host* srv_host, const struct timeval* tv,
|
|
u_int64_t diff_sent_packets,
|
|
u_int64_t diff_sent_bytes,
|
|
u_int64_t diff_rcvd_packets,
|
|
u_int64_t diff_rcvd_bytes) const;
|
|
/*
|
|
Check (and possibly enqueues) the flow for dump
|
|
*/
|
|
void dumpCheck(time_t t, bool last_dump_before_free);
|
|
void updateCliJA4();
|
|
void updateHASSH(bool as_client);
|
|
void processExtraDissectedInformation();
|
|
void processDetectedProtocol(
|
|
u_int8_t* payload, u_int16_t payload_len); /* nDPI detected protocol */
|
|
void processDetectedProtocolData(); /* nDPI detected protocol data (e.g.,
|
|
ndpiFlow->host_server_name) */
|
|
void setExtraDissectionCompleted(bool src2dst_direction);
|
|
void setProtocolDetectionCompleted(u_int8_t* payload, u_int16_t payload_len,
|
|
time_t when_seen);
|
|
void updateProtocol(ndpi_protocol proto_id);
|
|
const char* cipher_weakness2str(ndpi_cipher_weakness w) const;
|
|
bool get_partial_traffic_stats(PartializableFlowTrafficStats** dst,
|
|
PartializableFlowTrafficStats* delta,
|
|
bool* first_partial) const;
|
|
void lua_tos(lua_State* vm);
|
|
void lua_confidence(lua_State* vm);
|
|
void luaScore(lua_State* vm);
|
|
void luaIEC104(lua_State* vm);
|
|
bool setAlertsMap(FlowAlert* alert);
|
|
void setNormalToAlertedCounters();
|
|
/* Decreases scores on both client and server hosts when the flow is being
|
|
* destructed */
|
|
void decAllFlowScores();
|
|
void updateServerPortsStats(Host* server_host, ndpi_protocol* proto,
|
|
time_t when_seen);
|
|
void updateClientContactedPorts(Host* client, ndpi_protocol* proto);
|
|
void updateTCPHostServices(Host* cli_h, Host* srv_h);
|
|
void updateUDPHostServices(bool src2dst_direction);
|
|
void updateServerName(Host* h);
|
|
void allocateCollection();
|
|
void mergeHRCounters(std::vector<uint64_t>& flow_counters,
|
|
const std::vector<uint64_t>& update_counters,
|
|
time_t update_first_seen);
|
|
void computeKey();
|
|
void accountBidirectionalTCPProtocolServices();
|
|
void accountBidirectionalUDPProtocolServices();
|
|
void setServerName(char* value);
|
|
void setClientInfo(char* value);
|
|
#ifdef NTOPNG_PRO
|
|
void processHostName(char* host_name);
|
|
#endif
|
|
void updateMac();
|
|
void decodeTCPstats(u_int32_t v, TCPStats* stats);
|
|
void serializeTCPFlagsJSON(ndpi_serializer* serializer, TCPStats* stats,
|
|
const char* label);
|
|
void allocTCPStats();
|
|
void allocUDPStats();
|
|
|
|
public:
|
|
Flow(NetworkInterface* _iface, int32_t iface_idx, u_int16_t _vlanId,
|
|
u_int16_t _observation_point_id, u_int32_t _private_flow_id,
|
|
u_int8_t _protocol, Mac* _cli_mac, IpAddress* _cli_ip,
|
|
u_int16_t _cli_port, Mac* _srv_mac, IpAddress* _srv_ip,
|
|
u_int16_t _srv_port, const ICMPinfo* const icmp_info, time_t _first_seen,
|
|
time_t _last_seen, u_int8_t* _view_cli_mac, u_int8_t* _view_srv_mac);
|
|
~Flow();
|
|
|
|
virtual bool is_active_entry_now_idle(u_int max_idleness) const;
|
|
inline Bitmap128 getAlertsBitmap() const { return (alerts_map); }
|
|
|
|
/* Enqueues an alert to all available flow recipients. */
|
|
bool enqueueAlertToRecipients(FlowAlert* alert);
|
|
|
|
/*
|
|
Called by FlowCheck subclasses to trigger a flow alert. Setting sync
|
|
will causes the alert (FlowAlert) to be immediatly enqueued to recipients.
|
|
*/
|
|
bool triggerAlert(FlowAlert* alert, bool sync = false);
|
|
|
|
inline FlowAlert* getTriggeredAlert(FlowAlertTypeEnum alert_type) const {
|
|
std::map<FlowAlertTypeEnum, FlowAlert*>::const_iterator it;
|
|
it = triggered_alerts.find(alert_type);
|
|
return (it != triggered_alerts.end()) ? it->second : NULL;
|
|
}
|
|
|
|
/*
|
|
Alerts are not flushed immediatly as optimization (unless sync is set in
|
|
triggerAlert). If pending_alerts, they are enqueued to recipients, in a
|
|
single notification for the predominant one.
|
|
*/
|
|
void flushAlerts();
|
|
|
|
/*
|
|
Refresh alert stored in flows (rebuild JSON) as the content of some
|
|
of them have been updated (e.g. re-triggered) and the value may be changed
|
|
(e.g. the value that exceeded a threshold has increased further)
|
|
*/
|
|
void refreshAlert(FlowAlertTypeEnum alert_type);
|
|
|
|
/*
|
|
Enqueues the predominant alert of the flow to all available flow recipients.
|
|
*/
|
|
void enqueuePredominantAlert();
|
|
|
|
inline void setFlowVerdict(u_int8_t _flow_verdict) {
|
|
flow_verdict = _flow_verdict;
|
|
};
|
|
|
|
inline void setPredominantAlert(FlowAlertType alert_type, u_int16_t score);
|
|
inline FlowAlertType getPredominantAlert() const {
|
|
return predominant_alert;
|
|
};
|
|
inline u_int16_t getPredominantAlertScore() const {
|
|
return predominant_alert_score;
|
|
};
|
|
inline AlertLevel getPredominantAlertSeverity() const {
|
|
return Utils::mapScoreToSeverity(predominant_alert_score);
|
|
};
|
|
inline bool isFlowAlerted() const {
|
|
return (predominant_alert.id != flow_alert_normal);
|
|
};
|
|
|
|
#if defined(NTOPNG_PRO)
|
|
bool isFlowAllowed(bool* is_allowed);
|
|
|
|
#endif
|
|
inline u_int32_t getSrcPeerAS() const { return srcPeerAS; }
|
|
inline u_int32_t getDstPeerAS() const { return dstPeerAS; }
|
|
inline u_int32_t getNextAdjacentAS() const { return (collection ? collection->nextAdjacentAS : 0); }
|
|
|
|
void setAlertInfo(FlowAlert* alert);
|
|
inline bool isAlertAutoAck() { return !!alert_info.auto_acknowledge; };
|
|
inline u_int8_t isClientAttacker() { return alert_info.is_cli_attacker; };
|
|
inline u_int8_t isClientVictim() { return alert_info.is_cli_victim; };
|
|
inline u_int8_t isServerAttacker() { return alert_info.is_srv_attacker; };
|
|
inline u_int8_t isServerVictim() { return alert_info.is_srv_victim; };
|
|
inline char* getProtocolInfo() { return json_protocol_info; };
|
|
void updateAlertsJSON();
|
|
inline char* getAlertJSON() { return alerts_json; };
|
|
char *getRequestedServerName();
|
|
const char *getDomainName(char *buf, u_int buf_len);
|
|
static bool isValidDomainName(const char *domain);
|
|
void callFlowUpdate(time_t t);
|
|
void setProtocolJSONInfo();
|
|
void serializeProtocolJSONInfo(ndpi_serializer* serializer);
|
|
void serializeCustomFieldsInfo(ndpi_serializer* serializer);
|
|
|
|
inline char* getJa4CliHash() { return (protos.tls.ja4.client_hash); }
|
|
|
|
char* getCliCountry(char* buf, u_int buf_len);
|
|
char* getSrvCountry(char* buf, u_int buf_len);
|
|
bool isBlacklistedFlow() const;
|
|
bool isBlacklistedClient() const;
|
|
bool isBlacklistedServer() const;
|
|
struct site_categories* getFlowCategory(bool force_categorization);
|
|
void freeDPIMemory();
|
|
bool isTiny() const;
|
|
inline bool isProto(u_int16_t p) const {
|
|
return (((ndpiDetectedProtocol.proto.master_protocol == p) ||
|
|
(ndpiDetectedProtocol.proto.app_protocol == p))
|
|
? true
|
|
: false);
|
|
}
|
|
bool isTLS() const;
|
|
inline bool isEncryptedProto() const {
|
|
return (ndpi_is_encrypted_proto(iface->get_ndpi_struct(),
|
|
ndpiDetectedProtocol.proto));
|
|
}
|
|
inline bool isSSH() const { return (isProto(NDPI_PROTOCOL_SSH)); }
|
|
inline bool isMining() const { return (isProto(NDPI_PROTOCOL_MINING)); }
|
|
inline bool isDNS() const { return (isProto(NDPI_PROTOCOL_DNS)); }
|
|
inline bool isSTUN() const { return (isProto(NDPI_PROTOCOL_STUN)); }
|
|
inline bool isQUIC() const { return (isProto(NDPI_PROTOCOL_QUIC)); }
|
|
inline bool isZoomRTP() const {
|
|
return (isProto(NDPI_PROTOCOL_ZOOM) &&
|
|
(isProto(NDPI_PROTOCOL_RTP) || isProto(NDPI_PROTOCOL_SRTP)));
|
|
}
|
|
inline bool isIEC60870() const { return (isProto(NDPI_PROTOCOL_IEC60870)); }
|
|
inline bool isModbus() const { return (isProto(NDPI_PROTOCOL_MODBUS)); }
|
|
inline bool isS7Comm() const { return (isProto(NDPI_PROTOCOL_S7COMM)); }
|
|
inline bool isProfinet() const {
|
|
return (isProto(NDPI_PROTOCOL_PROFINET_IO));
|
|
}
|
|
inline bool isMDNS() const { return (isProto(NDPI_PROTOCOL_MDNS)); }
|
|
inline bool isSSDP() const { return (isProto(NDPI_PROTOCOL_SSDP)); }
|
|
inline bool isNetBIOS() const { return (isProto(NDPI_PROTOCOL_NETBIOS)); }
|
|
inline bool isSIP() const { return (isProto(NDPI_PROTOCOL_SIP)); }
|
|
inline bool isDHCP() const { return (isProto(NDPI_PROTOCOL_DHCP)); }
|
|
inline bool isNTP() const { return (isProto(NDPI_PROTOCOL_NTP)); }
|
|
inline bool isSMTPorSMTPS() const { return (isSMTP() || isSMTPS()); }
|
|
inline bool isSMTP() const { return (isProto(NDPI_PROTOCOL_MAIL_SMTP)); }
|
|
inline bool isSMTPS() const { return (isProto(NDPI_PROTOCOL_MAIL_SMTPS)); }
|
|
inline bool isHTTP() const { return (isProto(NDPI_PROTOCOL_HTTP)); }
|
|
inline bool isHTTP_PROXY() const {
|
|
return (isProto(NDPI_PROTOCOL_HTTP_PROXY));
|
|
}
|
|
inline bool isHTTP_CONNECT() const {
|
|
return (isProto(NDPI_PROTOCOL_HTTP_CONNECT));
|
|
}
|
|
inline bool isIGMP() const { return (isProto(NDPI_PROTOCOL_IP_IGMP)); }
|
|
inline bool isICMP() const {
|
|
return (isProto(NDPI_PROTOCOL_IP_ICMP) || isProto(NDPI_PROTOCOL_IP_ICMPV6));
|
|
}
|
|
inline bool isBittorrent() const {
|
|
return (isProto(NDPI_PROTOCOL_BITTORRENT));
|
|
}
|
|
|
|
inline bool isTwhOverForViewInterface() {
|
|
return ((twh_over_view == 1) ? true : false);
|
|
}
|
|
inline void setTwhOverForViewInterface() { twh_over_view = 1; }
|
|
#if defined(NTOPNG_PRO)
|
|
inline bool isLateralMovement() const { return (lateral_movement); }
|
|
inline void setLateralMovement(bool change) { lateral_movement = change; }
|
|
PeriodicityStatus getPeriodicity() const { return (periodicity_status); }
|
|
inline void setPeriodicity(PeriodicityStatus _periodicity_status) {
|
|
periodicity_status = _periodicity_status;
|
|
}
|
|
#endif
|
|
|
|
inline bool isCliDeviceAllowedProtocol() const {
|
|
return !cli_host ||
|
|
cli_host->getDeviceAllowedProtocolStatus(
|
|
get_detected_protocol(), true) == device_proto_allowed;
|
|
}
|
|
inline bool isSrvDeviceAllowedProtocol() const {
|
|
return !srv_host ||
|
|
get_bytes_srv2cli() ==
|
|
0 /* Server must respond to be considered NOT allowed */
|
|
|| srv_host->getDeviceAllowedProtocolStatus(
|
|
get_detected_protocol(), false) == device_proto_allowed;
|
|
}
|
|
inline bool isDeviceAllowedProtocol() const {
|
|
return isCliDeviceAllowedProtocol() && isSrvDeviceAllowedProtocol();
|
|
}
|
|
inline u_int16_t getCliDeviceDisallowedProtocol() const {
|
|
DeviceProtoStatus cli_ps =
|
|
cli_host->getDeviceAllowedProtocolStatus(get_detected_protocol(), true);
|
|
|
|
return (cli_ps == device_proto_forbidden_app)
|
|
? ndpiDetectedProtocol.proto.app_protocol
|
|
: ndpiDetectedProtocol.proto.master_protocol;
|
|
}
|
|
inline u_int16_t getSrvDeviceDisallowedProtocol() const {
|
|
DeviceProtoStatus srv_ps = srv_host->getDeviceAllowedProtocolStatus(
|
|
get_detected_protocol(), false);
|
|
|
|
return (srv_ps == device_proto_forbidden_app)
|
|
? ndpiDetectedProtocol.proto.app_protocol
|
|
: ndpiDetectedProtocol.proto.master_protocol;
|
|
}
|
|
inline bool isMaskedFlow() const {
|
|
return ((get_cli_ip_addr() &&
|
|
Utils::maskHost(get_cli_ip_addr()->isLocalHost())) ||
|
|
(get_srv_ip_addr() &&
|
|
Utils::maskHost(get_srv_ip_addr()->isLocalHost())));
|
|
};
|
|
char* serialize(ExportFormat format = export_format_GENERIC);
|
|
/* Prepares an alert JSON and puts int in the resulting `serializer`. */
|
|
void alert2JSON(FlowAlert* alert, ndpi_serializer* serializer);
|
|
json_object* flow2JSON(ExportFormat format);
|
|
json_object* flow2es(json_object* flow_object);
|
|
void formatECSInterface(json_object* my_object);
|
|
void formatECSNetwork(json_object* my_object, const IpAddress* addr);
|
|
void formatECSHost(json_object* my_object, bool is_client,
|
|
const IpAddress* addr, Host* host);
|
|
void formatECSEvent(json_object* my_object);
|
|
void formatECSFlow(json_object* my_object);
|
|
void formatSyslogFlow(json_object* my_object);
|
|
void formatGenericFlow(json_object* my_object);
|
|
void formatECSExtraInfo(json_object* my_object);
|
|
void formatECSAppProto(json_object* my_object);
|
|
void formatECSObserver(json_object* my_object);
|
|
|
|
inline u_int16_t getLowerProtocol() {
|
|
return (ndpi_get_lower_proto(ndpiDetectedProtocol.proto));
|
|
}
|
|
inline u_int16_t getUpperProtocol() {
|
|
return (ndpi_get_upper_proto(ndpiDetectedProtocol.proto));
|
|
}
|
|
|
|
inline void updateJA4C(char* j) {
|
|
if (j && (j[0] != '\0') && (protos.tls.ja4.client_hash == NULL))
|
|
protos.tls.ja4.client_hash = strdup(j);
|
|
updateCliJA4();
|
|
}
|
|
|
|
inline u_int8_t getTcpFlags() const {
|
|
return (src2dst_tcp_flags | dst2src_tcp_flags);
|
|
};
|
|
inline u_int8_t getTcpFlagsCli2Srv() const { return (src2dst_tcp_flags); };
|
|
inline u_int8_t getTcpFlagsSrv2Cli() const { return (dst2src_tcp_flags); };
|
|
#ifdef HAVE_NEDGE
|
|
bool checkPassVerdict(const struct tm* now);
|
|
bool isPassVerdict();
|
|
inline void setConntrackMarker(u_int32_t marker) { this->marker = marker; }
|
|
inline u_int32_t getConntrackMarker() { return (marker); }
|
|
void incFlowDroppedCounters();
|
|
#endif
|
|
void setDropVerdict(DropReason reason);
|
|
inline bool getVerdict() { return passVerdict; };
|
|
inline DropReason getDropReason() { return dropVerdictReason; };
|
|
u_int32_t getPid(bool client);
|
|
u_int32_t getFatherPid(bool client);
|
|
u_int32_t get_uid(bool client) const;
|
|
char* get_proc_name(bool client);
|
|
char* get_user_name(bool client);
|
|
u_int32_t getNextTcpSeq(u_int8_t tcpFlags, u_int32_t tcpSeqNum,
|
|
u_int32_t payloadLen);
|
|
static double toMs(const struct timeval* t);
|
|
void timeval_diff(struct timeval* begin, const struct timeval* end,
|
|
struct timeval* result, bool divide_by_two);
|
|
std::string getFlowInfo(bool isLuaRequest);
|
|
inline std::string getL7JSON() { return (l7_json); }
|
|
inline void setL7JSON(const std::string &j) { l7_json = j; }
|
|
inline char* getFlowServerInfo() {
|
|
return (isTLS() && protos.tls.client_requested_server_name)
|
|
? protos.tls.client_requested_server_name
|
|
: host_server_name;
|
|
}
|
|
inline char* getBitTorrentHash() { return (bt_hash); };
|
|
inline void setBTHash(char* h) {
|
|
if (!h) return;
|
|
if (bt_hash) free(bt_hash);
|
|
bt_hash = h;
|
|
}
|
|
void updateICMPFlood(const struct bpf_timeval* when, bool src2dst_direction);
|
|
void updateDNSFlood(const struct bpf_timeval* when, bool src2dst_direction);
|
|
void updateSNMPFlood(const struct bpf_timeval* when, bool src2dst_direction);
|
|
void updateTcpFlags(const struct bpf_timeval* when, u_int8_t flags,
|
|
bool src2dst_direction, bool new_flow);
|
|
void updateTcpWindow(u_int16_t window, bool src2dst_direction);
|
|
void updateTcpSeqIssues(const ParsedFlow* pf);
|
|
void updateTLS(ParsedFlow* zflow);
|
|
void updateDNS(ParsedFlow* zflow);
|
|
void updateHTTP(ParsedFlow* zflow);
|
|
void updateSuspiciousDGADomain();
|
|
void incTcpBadStats(bool src2dst_direction, Host* cli, Host* srv,
|
|
NetworkInterface* iface, u_int32_t ooo_pkts,
|
|
u_int32_t retr_pkts, u_int32_t lost_pkts,
|
|
u_int32_t keep_alive_pkts);
|
|
|
|
void updateTcpSeqNum(const struct bpf_timeval* when, u_int32_t seq_num,
|
|
u_int32_t ack_seq_num, u_int16_t window, u_int8_t flags,
|
|
u_int16_t payload_len, bool src2dst_direction);
|
|
|
|
void updateSeqNum(time_t when, u_int32_t sN, u_int32_t aN);
|
|
void setDetectedProtocol(ndpi_protocol proto_id, bool src2dst_direction);
|
|
void processPacket(bool src2dst_direction, const struct pcap_pkthdr* h,
|
|
const u_char* ip_packet, u_int16_t ip_len,
|
|
u_int64_t packet_time, u_int8_t* payload,
|
|
u_int16_t payload_len, u_int16_t src_port);
|
|
void processDNSPacket(const u_char* ip_packet, u_int16_t ip_len,
|
|
u_int64_t packet_time);
|
|
void processIEC60870Packet(bool tx_direction, const u_char* payload,
|
|
u_int16_t payload_len,
|
|
const struct pcap_pkthdr* h);
|
|
#ifdef NTOPNG_PRO
|
|
void updateOTStats(ParsedFlow* zflow);
|
|
void processModbusPacket(bool is_query, const u_char* payload,
|
|
u_int16_t payload_len, const struct pcap_pkthdr* h);
|
|
void processRTPPacket(const u_char* payload, u_int16_t payload_len,
|
|
const struct pcap_pkthdr* h, bool src2dst_direction);
|
|
void updateQUICStats(bool src2dst_direction, const struct timeval* tv,
|
|
u_int8_t* payload, u_int16_t payload_len);
|
|
void updateUDPTimestamp(bool src2dst_direction, const struct timeval* tv);
|
|
void computeQoEscore(u_int8_t* cli_to_srv_qoe,
|
|
std::vector<std::string>* cli_to_srv_qoe_issues,
|
|
u_int8_t* srv_to_cli_qoe,
|
|
std::vector<std::string>* srv_to_cli_qoe_issues);
|
|
u_int8_t computeQoETCPscore(QoELimits* l, bool cli_to_srv,
|
|
std::vector<std::string>* issues);
|
|
u_int8_t computeQoEUDPscore(QoELimits* l, bool cli_to_srv,
|
|
std::vector<std::string>* issues);
|
|
u_int8_t computeQoEMOSscore(bool cli_to_srv);
|
|
u_int8_t getQoEScore();
|
|
void serializeQoEInfo(ndpi_serializer* serializer);
|
|
QoEType getQoEType();
|
|
#endif
|
|
void endProtocolDissection(bool src2dst_direction);
|
|
inline void setCustomApp(custom_app_t ca) {
|
|
memcpy(&custom_app, &ca, sizeof(custom_app));
|
|
};
|
|
inline custom_app_t getCustomApp() const { return custom_app; };
|
|
u_int16_t getStatsProtocol() const;
|
|
void setJSONInfo(json_object* json);
|
|
void setTLVInfo(ndpi_serializer* tlv);
|
|
void incStats(bool cli2srv_direction, u_int pkt_len, u_int8_t* payload,
|
|
u_int payload_len, u_int8_t l4_proto, u_int8_t is_fragment,
|
|
u_int16_t tcp_flags, const struct timeval* when,
|
|
u_int16_t fragment_extra_overhead);
|
|
bool addFlowStats(bool new_flow, bool cli2srv_direction, u_int in_pkts,
|
|
u_int in_bytes, u_int in_goodput_bytes, u_int out_pkts,
|
|
u_int out_bytes, u_int out_goodput_bytes,
|
|
u_int in_fragments, u_int out_fragments, time_t first_seen,
|
|
time_t last_seen);
|
|
|
|
void addPostNATIPv4(u_int32_t _src_ip_addr_post_nat,
|
|
u_int32_t _dst_ip_addr_post_nat);
|
|
|
|
void addPostNATPort(u_int32_t _src_port_post_nat,
|
|
u_int32_t _dst_port_post_nat);
|
|
void check_swap();
|
|
|
|
bool isThreeWayHandshakeOK() const;
|
|
|
|
inline ndpi_classification_state getDetectionState() {
|
|
return (ndpiDetectedProtocol.state);
|
|
}
|
|
inline bool isDetectionCompleted() const {
|
|
return (detection_completed ? true : false);
|
|
};
|
|
inline bool isOneWay() const {
|
|
return (get_packets() &&
|
|
(!get_packets_cli2srv() || !get_packets_srv2cli()));
|
|
};
|
|
inline bool isBidirectional() const {
|
|
return (get_packets_cli2srv() && get_packets_srv2cli());
|
|
};
|
|
|
|
/*
|
|
Find a simple criteria to ignore probing attempts selecting
|
|
only flows with real data exchanged both ways
|
|
*/
|
|
inline bool isTCPReallyBidirectional() const {
|
|
return ((get_packets_cli2srv() > NUM_MIN_TCP_PKTS_PER_DIRECTION) &&
|
|
(src2dst_tcp_flags & TH_PUSH) &&
|
|
(get_packets_srv2cli() > NUM_MIN_TCP_PKTS_PER_DIRECTION) &&
|
|
(dst2src_tcp_flags & TH_PUSH));
|
|
};
|
|
|
|
inline bool isRemoteToRemote() const {
|
|
return (cli_host && srv_host && !cli_host->isLocalHost() &&
|
|
!srv_host->isLocalHost());
|
|
};
|
|
|
|
inline bool isLocalToRemote() const {
|
|
return get_cli_ip_addr()->isLocalHost() &&
|
|
!get_srv_ip_addr()->isLocalHost();
|
|
};
|
|
|
|
inline bool isRemoteToLocal() const {
|
|
return !get_cli_ip_addr()->isLocalHost() &&
|
|
get_srv_ip_addr()->isLocalHost();
|
|
};
|
|
|
|
inline bool isLocalToLocal() const {
|
|
return get_cli_ip_addr()->isLocalHost() && get_srv_ip_addr()->isLocalHost();
|
|
};
|
|
|
|
inline bool isUnicast() const {
|
|
return (cli_ip_addr && srv_ip_addr &&
|
|
!cli_ip_addr->isBroadMulticastAddress() &&
|
|
!srv_ip_addr->isBroadMulticastAddress());
|
|
};
|
|
|
|
inline u_int32_t get_cli_ipv4() const {
|
|
return (cli_host->get_ip()->get_ipv4());
|
|
};
|
|
|
|
inline u_int32_t get_srv_ipv4() const {
|
|
return (srv_host->get_ip()->get_ipv4());
|
|
};
|
|
inline ndpi_protocol get_detected_protocol() const {
|
|
return (ndpiDetectedProtocol);
|
|
}
|
|
|
|
inline struct ndpi_flow_struct* get_ndpi_flow() const { return (ndpiFlow); };
|
|
inline const struct ndpi_in6_addr* get_cli_ipv6() const {
|
|
return (cli_host->get_ip()->get_ipv6());
|
|
};
|
|
|
|
inline const struct ndpi_in6_addr* get_srv_ipv6() const {
|
|
return (srv_host->get_ip()->get_ipv6());
|
|
};
|
|
|
|
inline u_int16_t get_cli_port() const { return (ntohs(cli_port)); };
|
|
inline u_int16_t get_srv_port() const { return (ntohs(srv_port)); };
|
|
inline u_int16_t get_vlan_id() const { return (vlanId); };
|
|
inline u_int8_t get_protocol() const { return (protocol); };
|
|
inline u_int64_t get_bytes() const {
|
|
return (stats.get_cli2srv_bytes() + stats.get_srv2cli_bytes());
|
|
};
|
|
inline u_int64_t get_bytes_cli2srv() const {
|
|
return (stats.get_cli2srv_bytes());
|
|
};
|
|
inline u_int64_t get_bytes_srv2cli() const {
|
|
return (stats.get_srv2cli_bytes());
|
|
};
|
|
inline u_int64_t get_goodput_bytes() const {
|
|
return (stats.get_cli2srv_goodput_bytes() +
|
|
stats.get_srv2cli_goodput_bytes());
|
|
};
|
|
inline u_int64_t get_goodput_bytes_cli2srv() const {
|
|
return (stats.get_cli2srv_goodput_bytes());
|
|
};
|
|
inline u_int64_t get_goodput_bytes_srv2cli() const {
|
|
return (stats.get_srv2cli_goodput_bytes());
|
|
};
|
|
inline u_int64_t get_packets() const {
|
|
return (stats.get_cli2srv_packets() + stats.get_srv2cli_packets());
|
|
};
|
|
inline u_int32_t get_packets_cli2srv() const {
|
|
return (stats.get_cli2srv_packets());
|
|
};
|
|
inline u_int32_t get_packets_srv2cli() const {
|
|
return (stats.get_srv2cli_packets());
|
|
};
|
|
inline u_int64_t get_partial_bytes() const {
|
|
return get_partial_bytes_cli2srv() + get_partial_bytes_srv2cli();
|
|
};
|
|
inline u_int64_t get_partial_packets() const {
|
|
return get_partial_packets_cli2srv() + get_partial_packets_srv2cli();
|
|
};
|
|
inline u_int64_t get_partial_goodput_bytes() const {
|
|
return last_db_dump.delta.get_cli2srv_goodput_bytes() +
|
|
last_db_dump.delta.get_srv2cli_goodput_bytes();
|
|
};
|
|
inline u_int64_t get_partial_bytes_cli2srv() const {
|
|
return last_db_dump.delta.get_cli2srv_bytes();
|
|
};
|
|
inline u_int64_t get_partial_bytes_srv2cli() const {
|
|
return last_db_dump.delta.get_srv2cli_bytes();
|
|
};
|
|
inline u_int64_t get_partial_packets_cli2srv() const {
|
|
return last_db_dump.delta.get_cli2srv_packets();
|
|
};
|
|
inline u_int64_t get_partial_packets_srv2cli() const {
|
|
return last_db_dump.delta.get_srv2cli_packets();
|
|
};
|
|
inline void set_dump_in_progress() { last_db_dump.in_progress = true; };
|
|
inline void set_dump_done() { last_db_dump.in_progress = false, last_db_dump.is_first_dump = false; };
|
|
bool needsExtraDissection();
|
|
bool hasDissectedTooManyPackets();
|
|
#ifdef NTOPNG_PRO
|
|
bool get_partial_traffic_stats_view(PartializableFlowTrafficStats* delta,
|
|
bool* first_partial);
|
|
#endif
|
|
bool update_partial_traffic_stats_db_dump();
|
|
inline float get_pkts_thpt() const { return (pkts_thpt); };
|
|
inline float get_bytes_thpt() const { return (bytes_thpt); };
|
|
inline float get_goodput_bytes_thpt() const { return (goodput_bytes_thpt); };
|
|
inline float get_goodput_ratio() const {
|
|
return ((float)(100 * get_goodput_bytes()) / ((float)get_bytes() + 1));
|
|
};
|
|
inline time_t get_partial_first_seen() const {
|
|
return (last_db_dump.first_seen);
|
|
};
|
|
inline time_t get_partial_last_seen() const {
|
|
return (last_db_dump.last_seen);
|
|
};
|
|
inline char* get_protocol_name() const {
|
|
return (Utils::l4proto2name(protocol));
|
|
};
|
|
|
|
inline Host* get_cli_host() const { return (cli_host); };
|
|
inline Host* get_srv_host() const { return (srv_host); };
|
|
u_int64_t getTags();
|
|
inline IpAddress* get_cli_ip_addr() const { return (cli_ip_addr); };
|
|
inline IpAddress* get_srv_ip_addr() const { return (srv_ip_addr); };
|
|
inline IpAddress* get_dns_srv_ip_addr() const {
|
|
return ((get_cli_port() == 53) ? get_cli_ip_addr() : get_srv_ip_addr());
|
|
};
|
|
inline IpAddress* get_dhcp_srv_ip_addr() const {
|
|
return ((get_cli_port() == 67) ? get_cli_ip_addr() : get_srv_ip_addr());
|
|
};
|
|
|
|
inline json_object* get_json_info() const { return (json_info); };
|
|
inline ndpi_serializer* get_tlv_info() const { return (tlv_info); };
|
|
inline void setICMPPayloadSize(u_int16_t size) {
|
|
if (isICMP())
|
|
protos.icmp.max_icmp_payload_size =
|
|
max(protos.icmp.max_icmp_payload_size, size);
|
|
};
|
|
inline u_int16_t getICMPPayloadSize() const {
|
|
return (isICMP() ? protos.icmp.max_icmp_payload_size : 0);
|
|
};
|
|
inline ICMPinfo* getICMPInfo() const { return (isICMP() ? icmp_info : NULL); }
|
|
inline ndpi_protocol_breed_t get_protocol_breed() const {
|
|
return (flow_breed);
|
|
}
|
|
inline const char* get_protocol_breed_name() const {
|
|
return (ndpi_get_proto_breed_name(get_protocol_breed()));
|
|
};
|
|
inline ndpi_protocol_category_t get_protocol_category() const {
|
|
return (flow_category);
|
|
};
|
|
|
|
inline const char* get_protocol_category_name() const {
|
|
return (ndpi_category_get_name(iface->get_ndpi_struct(),
|
|
get_protocol_category()));
|
|
};
|
|
char* get_detected_protocol_name(char* buf, u_int buf_len) const {
|
|
return (iface->get_ndpi_full_proto_name(isDetectionCompleted()
|
|
? ndpiDetectedProtocol
|
|
: getConstNdpiUnknownProtocol(),
|
|
buf, buf_len));
|
|
}
|
|
static inline ndpi_protocol get_ndpi_unknown_protocol() {
|
|
return getConstNdpiUnknownProtocol();
|
|
};
|
|
|
|
#ifdef NTOPNG_PRO
|
|
/* NOTE: the caller must ensure that the hosts returned by these methods are
|
|
* not used concurrently by subinterfaces since hosts are shared between all
|
|
* the subinterfaces of the same ViewInterface. */
|
|
inline Host* getViewSharedClient() {
|
|
return (viewFlowStats ? viewFlowStats->getViewSharedClient()
|
|
: get_cli_host());
|
|
};
|
|
inline Host* getViewSharedServer() {
|
|
return (viewFlowStats ? viewFlowStats->getViewSharedServer()
|
|
: get_srv_host());
|
|
};
|
|
#else
|
|
inline Host* getViewSharedClient() { return (get_cli_host()); }
|
|
inline Host* getViewSharedServer() { return (get_srv_host()); }
|
|
#endif
|
|
|
|
u_int32_t get_packetsLost();
|
|
u_int32_t get_packetsRetr();
|
|
u_int32_t get_packetsOOO();
|
|
inline bool isUnderNetworkIssues(time_t now) {
|
|
return tcp && tcp->last_network_issues >= now - 1;
|
|
};
|
|
|
|
inline const struct timeval* get_current_update_time() const {
|
|
return &last_update_time;
|
|
};
|
|
u_int64_t get_current_bytes_cli2srv() const;
|
|
u_int64_t get_current_bytes_srv2cli() const;
|
|
u_int64_t get_current_goodput_bytes_cli2srv() const;
|
|
u_int64_t get_current_goodput_bytes_srv2cli() const;
|
|
u_int64_t get_current_packets_cli2srv() const;
|
|
u_int64_t get_current_packets_srv2cli() const;
|
|
void request_swap();
|
|
inline bool is_swap_requested() const {
|
|
return (swap_requested ? true : false);
|
|
};
|
|
inline bool is_swap_done() const { return (swap_done ? true : false); };
|
|
inline void set_swap_done() { swap_done = 1; };
|
|
/*
|
|
Returns actual client and server, that is the client and server as
|
|
determined after the swap heuristic that has taken place.
|
|
*/
|
|
inline void get_actual_peers(Host** actual_client,
|
|
Host** actual_server) const {
|
|
if (is_swap_requested())
|
|
*actual_client = get_srv_host(), *actual_server = get_cli_host();
|
|
else
|
|
*actual_client = get_cli_host(), *actual_server = get_srv_host();
|
|
};
|
|
/*
|
|
Same as above, for the IP addresses of the peers: they are used in place of
|
|
the hosts with viewed interfaces, where flows have no hosts.
|
|
*/
|
|
inline void get_actual_peers_ip(IpAddress** actual_client,
|
|
IpAddress** actual_server) const {
|
|
if (is_swap_requested())
|
|
*actual_client = srv_ip_addr, *actual_server = cli_ip_addr;
|
|
else
|
|
*actual_client = cli_ip_addr, *actual_server = srv_ip_addr;
|
|
};
|
|
bool is_hash_entry_state_idle_transition_ready();
|
|
void hosts_periodic_stats_update(NetworkInterface* iface, Host* cli_host,
|
|
Host* srv_host,
|
|
PartializableFlowTrafficStats* partial,
|
|
bool first_partial,
|
|
const struct timeval* tv);
|
|
void periodic_stats_update(const struct timeval* tv, bool force_update);
|
|
void flow_end_stats_update();
|
|
void flow_end_housekeeping();
|
|
void set_hash_entry_id(u_int32_t assigned_hash_entry_id);
|
|
u_int32_t get_hash_entry_id() const;
|
|
|
|
static char* printTCPflags(u_int8_t flags, char* const buf, u_int buf_len);
|
|
char* print(char* buf, u_int buf_len, bool full_report = true);
|
|
|
|
inline u_int32_t key() { return (flow_key); }
|
|
static u_int32_t key(Host* cli, u_int16_t cli_port, Host* srv,
|
|
u_int16_t srv_port, u_int16_t vlan_id,
|
|
u_int16_t _observation_point_id, u_int16_t protocol);
|
|
void lua(lua_State* vm, AddressTree* allowed_nets, DetailsLevel details_level,
|
|
bool asListElement);
|
|
void lua_get_min_info(lua_State* vm);
|
|
void lua_duration_info(lua_State* vm);
|
|
void lua_dump_tcp_stats(lua_State* vm, const TCPStats* s,
|
|
const char* label) const;
|
|
void lua_snmp_info(lua_State* vm);
|
|
void lua_device_protocol_allowed_info(lua_State* vm);
|
|
void lua_get_flow_connection_state(lua_State* vm);
|
|
void lua_get_unicast_info(lua_State* vm) const;
|
|
void lua_get_status(lua_State* vm) const;
|
|
void lua_get_protocols(lua_State* vm) const;
|
|
void lua_get_bytes(lua_State* vm) const;
|
|
void lua_get_dir_traffic(lua_State* vm, bool cli2srv) const;
|
|
void lua_get_dir_iat(lua_State* vm, bool cli2srv) const;
|
|
void lua_get_packets(lua_State* vm) const;
|
|
void lua_get_throughput(lua_State* vm) const;
|
|
void lua_get_time(lua_State* vm) const;
|
|
void lua_get_ip(lua_State* vm, bool client) const;
|
|
void lua_get_mac(lua_State* vm, bool client) const;
|
|
void lua_get_info(lua_State* vm, bool client) const;
|
|
void lua_get_sip_info(lua_State* vm) const;
|
|
void lua_get_tls_info(lua_State* vm) const;
|
|
void lua_get_ssh_info(lua_State* vm) const;
|
|
void lua_get_http_info(lua_State* vm) const;
|
|
void lua_get_dns_info(lua_State* vm) const;
|
|
void lua_get_tcp_info(lua_State* vm) const;
|
|
void lua_get_port(lua_State* vm, bool client) const;
|
|
void lua_get_geoloc(lua_State* vm, bool client, bool coords,
|
|
bool country_city) const;
|
|
#if defined(NTOPNG_PRO)
|
|
void lua_get_qoe_score(lua_State* vm);
|
|
#endif
|
|
void lua_get_risk_info(lua_State* vm);
|
|
|
|
void getInfo(ndpi_serializer* serializer);
|
|
void getHTTPInfo(ndpi_serializer* serializer) const;
|
|
void getDNSInfo(ndpi_serializer* serializer) const;
|
|
void getICMPInfo(ndpi_serializer* serializer) const;
|
|
void getTLSInfo(ndpi_serializer* serializer) const;
|
|
void getMDNSInfo(ndpi_serializer* serializer) const;
|
|
void getNetBiosInfo(ndpi_serializer* serializer) const;
|
|
void getSIPInfo(ndpi_serializer* serializer) const;
|
|
void getSSHInfo(ndpi_serializer* serializer) const;
|
|
|
|
bool equal(const Mac* src_mac, const Mac* dst_mac, const IpAddress* _cli_ip,
|
|
const IpAddress* _srv_ip, u_int16_t _cli_port, u_int16_t _srv_port,
|
|
u_int16_t _u_int16_t, u_int16_t _observation_point_id,
|
|
u_int32_t _private_flow_id, u_int8_t _protocol,
|
|
const ICMPinfo* const icmp_info, bool* src2srv_direction) const;
|
|
void getFingerprintInfo(ndpi_serializer* serializer);
|
|
void serializeExporters(ndpi_serializer* serializer);
|
|
void sumStats(nDPIStats* ndpi_stats, FlowStats* stats);
|
|
bool dump(time_t t, bool last_dump_before_free);
|
|
bool match(AddressTree* ptree);
|
|
bool matchFlowIP(IpAddress* ip, u_int16_t vlan_id);
|
|
bool matchFlowVLAN(u_int16_t vlan_id);
|
|
bool matchFlowDeviceIP(struct ndpi_in6_addr *flow_device_ip);
|
|
bool matchInIfIdx(u_int32_t in_if_idx);
|
|
bool matchOutIfIdx(u_int32_t out_if_idx);
|
|
bool matchAlertsStatus(u_int32_t out_if_idx);
|
|
void dissectHTTP(bool src2dst_direction, char* payload,
|
|
u_int16_t payload_len);
|
|
void dissectDNS(bool src2dst_direction, char* payload, u_int16_t payload_len);
|
|
void dissectTLS(char* payload, u_int16_t payload_len);
|
|
void dissectSSDP(bool src2dst_direction, char* payload,
|
|
u_int16_t payload_len);
|
|
void dissectMDNS(u_int8_t* payload, u_int16_t payload_len);
|
|
void dissectNetBIOS(u_int8_t* payload, u_int16_t payload_len);
|
|
void dissectBittorrent(char* payload, u_int16_t payload_len);
|
|
void fillZMQFlowCategory(ndpi_protocol* res);
|
|
void setDHCPHostName(const char* name);
|
|
void setSIPCallId(const char* name);
|
|
inline void setICMP(bool src2dst_direction, u_int8_t icmp_type,
|
|
u_int8_t icmp_code, u_int8_t* icmpdata) {
|
|
if (isICMP()) {
|
|
if (src2dst_direction)
|
|
protos.icmp.cli2srv.icmp_type = icmp_type,
|
|
protos.icmp.cli2srv.icmp_code = icmp_code;
|
|
else
|
|
protos.icmp.srv2cli.icmp_type = icmp_type,
|
|
protos.icmp.srv2cli.icmp_code = icmp_code;
|
|
// if(get_cli_host()) get_cli_host()->incICMP(icmp_type, icmp_code,
|
|
// src2dst_direction ? true : false, get_srv_host()); if(get_srv_host())
|
|
// get_srv_host()->incICMP(icmp_type, icmp_code, src2dst_direction ? false
|
|
// : true, get_cli_host());
|
|
}
|
|
}
|
|
inline void getICMP(u_int8_t* _icmp_type, u_int8_t* _icmp_code) {
|
|
if (isBidirectional())
|
|
*_icmp_type = protos.icmp.srv2cli.icmp_type,
|
|
*_icmp_code = protos.icmp.srv2cli.icmp_code;
|
|
else
|
|
*_icmp_type = protos.icmp.cli2srv.icmp_type,
|
|
*_icmp_code = protos.icmp.cli2srv.icmp_code;
|
|
}
|
|
inline u_int8_t getICMPType() {
|
|
if (isICMP()) {
|
|
return isBidirectional() ? protos.icmp.srv2cli.icmp_type
|
|
: protos.icmp.cli2srv.icmp_type;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
inline bool hasInvalidDNSQueryChars() const {
|
|
return (isDNS() && hasRisk(NDPI_INVALID_CHARACTERS));
|
|
}
|
|
inline bool hasMaliciousSignature(bool as_client) const {
|
|
return as_client ? has_malicious_cli_signature
|
|
: has_malicious_srv_signature;
|
|
}
|
|
|
|
void setRisk(ndpi_risk r);
|
|
void addRisk(ndpi_risk r);
|
|
inline ndpi_risk getRiskBitmap() const { return ndpi_flow_risk_bitmap; }
|
|
bool hasRisk(ndpi_risk_enum r) const;
|
|
bool hasRisks() const;
|
|
void clearRisks();
|
|
inline void setDGADomain(char* name) {
|
|
if (name) {
|
|
if (suspicious_dga_domain) free(suspicious_dga_domain);
|
|
suspicious_dga_domain = strdup(name);
|
|
}
|
|
}
|
|
inline char* getDGADomain() const {
|
|
return (hasRisk(NDPI_SUSPICIOUS_DGA_DOMAIN) && suspicious_dga_domain
|
|
? suspicious_dga_domain
|
|
: (char*)"");
|
|
}
|
|
inline char* getDNSQuery() const {
|
|
return (isDNS() ? protos.dns.last_query : (char*)"");
|
|
}
|
|
bool setDNSQuery(char* value, char* rsp_addresses, bool copy_memory);
|
|
inline void setDNSQueryType(u_int16_t t) {
|
|
if (isDNS()) {
|
|
protos.dns.last_query_type = t;
|
|
}
|
|
}
|
|
inline void setDNSRetCode(u_int16_t c) {
|
|
if (isDNS()) {
|
|
protos.dns.last_return_code = c;
|
|
}
|
|
}
|
|
inline u_int16_t getLastQueryType() {
|
|
return (isDNS() ? protos.dns.last_query_type : 0);
|
|
}
|
|
inline u_int16_t getDNSRetCode() {
|
|
return (isDNS() ? protos.dns.last_return_code : 0);
|
|
}
|
|
inline char* getHTTPURL() {
|
|
return (isHTTP() ? protos.http.last_url : (char*)"");
|
|
}
|
|
inline void setHTTPURL(char* v) {
|
|
if (isHTTP()) {
|
|
if (!protos.http.last_url)
|
|
protos.http.last_url = v;
|
|
else
|
|
free(v);
|
|
} else {
|
|
if (v) free(v);
|
|
}
|
|
}
|
|
inline char* getHTTPUserAgent() {
|
|
return (isHTTP() ? protos.http.last_user_agent : (char*)"");
|
|
}
|
|
inline void setHTTPUserAgent(char* v) {
|
|
if (isHTTP()) {
|
|
if (!protos.http.last_user_agent)
|
|
protos.http.last_user_agent = v;
|
|
else
|
|
free(v);
|
|
} else {
|
|
if (v) free(v);
|
|
}
|
|
}
|
|
void setHTTPMethod(const char* method, ssize_t method_len);
|
|
void setHTTPMethod(ndpi_http_method m);
|
|
inline void setHTTPRetCode(u_int16_t c) {
|
|
if (isHTTP()) {
|
|
protos.http.last_return_code = c;
|
|
}
|
|
}
|
|
inline u_int16_t getHTTPRetCode() const {
|
|
return isHTTP() ? protos.http.last_return_code : 0;
|
|
};
|
|
inline const char* getHTTPMethod() const {
|
|
return isHTTP() ? ndpi_http_method2str(protos.http.last_method) : (char*)"";
|
|
};
|
|
|
|
void setExternalAlert(json_object* a);
|
|
inline bool hasExternalAlert() const { return external_alert.json != NULL; };
|
|
inline json_object* getExternalAlert() { return external_alert.json; };
|
|
inline char* getExternalSource() { return external_alert.source; };
|
|
void luaRetrieveExternalAlert(lua_State* vm);
|
|
|
|
u_int32_t getSrvTcpIssues();
|
|
u_int32_t getCliTcpIssues();
|
|
double getCliRetrPercentage();
|
|
double getSrvRetrPercentage();
|
|
|
|
#if defined(NTOPNG_PRO)
|
|
void updateTCPAck(const struct bpf_timeval* when, bool src2dst_direction,
|
|
u_int32_t ack_id);
|
|
void updateTCPWinScale(bool src2dst_direction, u_int8_t winscale);
|
|
void updateTCPWin(bool src2dst_direction, u_int16_t win);
|
|
void getModbusInfo(ndpi_serializer* serializer);
|
|
void getS7CommInfo(ndpi_serializer* serializer);
|
|
void getProfinetInfo(ndpi_serializer* serializer);
|
|
|
|
#if !defined(HAVE_NEDGE)
|
|
#ifdef HAVE_NBPF
|
|
inline void updateProfile() { trafficProfile = iface->getFlowProfile(this); }
|
|
#endif
|
|
#endif
|
|
inline char* get_profile_name() {
|
|
return (
|
|
#if !defined(HAVE_NEDGE)
|
|
#ifdef HAVE_NBPF
|
|
trafficProfile ? trafficProfile->getName() :
|
|
#endif
|
|
#endif
|
|
(char*)"");
|
|
}
|
|
#endif
|
|
/* http://bradhedlund.com/2008/12/19/how-to-calculate-tcp-throughput-for-long-distance-links/
|
|
*/
|
|
inline float getCli2SrvMaxThpt() const {
|
|
if (tcp == NULL)
|
|
return (0);
|
|
else
|
|
return (rttSec ? ((float)(tcp->cli2srv_window * 8) / rttSec) : 0);
|
|
}
|
|
inline float getSrv2CliMaxThpt() const {
|
|
if (tcp == NULL)
|
|
return (0);
|
|
else
|
|
return (rttSec ? ((float)(tcp->srv2cli_window * 8) / rttSec) : 0);
|
|
}
|
|
|
|
inline InterarrivalStats* getCli2SrvIATStats() const {
|
|
return cli2srvPktTime;
|
|
}
|
|
inline InterarrivalStats* getSrv2CliIATStats() const {
|
|
return srv2cliPktTime;
|
|
}
|
|
|
|
inline bool isTCP() const { return protocol == IPPROTO_TCP; };
|
|
inline bool isUDP() const { return protocol == IPPROTO_UDP; };
|
|
inline bool isTCPEstablished() const {
|
|
return (!isTCPClosed() && !isTCPReset() && isThreeWayHandshakeOK());
|
|
}
|
|
inline bool isTCPConnecting() const {
|
|
if (tcp == NULL)
|
|
return (false);
|
|
else
|
|
return (src2dst_tcp_flags == TH_SYN &&
|
|
(!dst2src_tcp_flags || (dst2src_tcp_flags == (TH_SYN | TH_ACK))));
|
|
}
|
|
inline bool isTCPClosed() const {
|
|
if (tcp == NULL)
|
|
return (false);
|
|
else
|
|
return (((src2dst_tcp_flags & (TH_SYN | TH_ACK | TH_FIN)) ==
|
|
(TH_SYN | TH_ACK | TH_FIN)) &&
|
|
((dst2src_tcp_flags & (TH_SYN | TH_ACK | TH_FIN)) ==
|
|
(TH_SYN | TH_ACK | TH_FIN)));
|
|
}
|
|
inline bool isTCPReset() const {
|
|
if (tcp == NULL)
|
|
return (false);
|
|
else
|
|
return (!isTCPClosed() &&
|
|
((src2dst_tcp_flags & TH_RST) || (dst2src_tcp_flags & TH_RST)));
|
|
};
|
|
inline bool isOnlyTCPReset() const {
|
|
if (tcp == NULL)
|
|
return (false);
|
|
else
|
|
return ((src2dst_tcp_flags & TH_RST) || (dst2src_tcp_flags & TH_RST));
|
|
}
|
|
inline bool isTCPRefused() const {
|
|
if (tcp == NULL)
|
|
return (false);
|
|
else
|
|
return (!isThreeWayHandshakeOK() &&
|
|
(dst2src_tcp_flags & TH_RST) == TH_RST);
|
|
};
|
|
inline bool isTCPZeroWindow() const {
|
|
return (src2dst_tcp_zero_window || dst2src_tcp_zero_window);
|
|
};
|
|
inline void setVRFid(u_int32_t v) {
|
|
allocateCollection();
|
|
if (collection) collection->vrfId = v;
|
|
}
|
|
inline void setSrcPeerAS(u_int32_t v) {
|
|
if(v != srcAS) srcPeerAS = v;
|
|
} /* Used when collecting flows via ZMQ (usually it contains the peer AS) */
|
|
inline void setDstPeerAS(u_int32_t v) {
|
|
if(v != dstAS) dstPeerAS = v;
|
|
} /* Used when collecting flows via ZMQ (usually it contains the peer AS) */
|
|
inline void setPrevAdjacentAS(u_int32_t v) {
|
|
allocateCollection();
|
|
if (collection) collection->prevAdjacentAS = v;
|
|
}
|
|
inline void setNextAdjacentAS(u_int32_t v) {
|
|
allocateCollection();
|
|
if (collection) collection->nextAdjacentAS = v;
|
|
}
|
|
|
|
#ifdef NTOPNG_PRO
|
|
inline ViewInterfaceFlowStats* getViewInterfaceFlowStats() {
|
|
return (viewFlowStats);
|
|
}
|
|
|
|
void postDetectionCallback();
|
|
#endif
|
|
|
|
inline double getFlowRTT(bool client) const {
|
|
if (tcp == NULL)
|
|
return (0.0);
|
|
else
|
|
return client ? tcp->clientRTT3WH : tcp->serverRTT3WH;
|
|
};
|
|
|
|
inline void setFlowRTT(const struct timeval* const tv, bool client) {
|
|
allocTCPStats();
|
|
|
|
if (tcp != NULL) {
|
|
if (client) {
|
|
tcp->clientRTT3WH = Utils::timeval2ms(tv);
|
|
|
|
if (cli_host) cli_host->updateNetworkRTT(tcp->clientRTT3WH);
|
|
} else {
|
|
tcp->serverRTT3WH = Utils::timeval2ms(tv);
|
|
|
|
if (srv_host) srv_host->updateNetworkRTT(tcp->serverRTT3WH);
|
|
}
|
|
}
|
|
}
|
|
|
|
inline void setFlowTcpWindow(u_int16_t window_val, bool client) {
|
|
allocTCPStats();
|
|
if (tcp != NULL) {
|
|
if (client)
|
|
tcp->cli2srv_window = window_val;
|
|
else
|
|
tcp->srv2cli_window = window_val;
|
|
}
|
|
}
|
|
inline void setRTT() {
|
|
allocTCPStats();
|
|
|
|
if (tcp != NULL) rttSec = (tcp->serverRTT3WH + tcp->clientRTT3WH) / 1000.;
|
|
}
|
|
inline void setFlowApplLatency(float latency_msecs) {
|
|
applLatencyMsec = latency_msecs;
|
|
}
|
|
inline float getFlowApplLatency() const { return (applLatencyMsec); }
|
|
|
|
struct ndpi_in6_addr getExporterIP();
|
|
struct ndpi_in6_addr getOriginalExporterIP();
|
|
struct ndpi_in6_addr getNextHopIP();
|
|
struct ndpi_in6_addr getOriginalNextHopIP();
|
|
u_int32_t getInIndex();
|
|
u_int32_t getOutIndex();
|
|
SNMPInterfaceRole getInRole();
|
|
SNMPInterfaceRole getOutRole();
|
|
SNMPInterfaceRole getMainRole();
|
|
|
|
inline u_int16_t getObservationPointId() { return (observation_point_id); };
|
|
|
|
u_int16_t getExporterSiteId();
|
|
u_int16_t getNextHopSiteId();
|
|
u_int16_t getSrcNetworkSiteId();
|
|
u_int16_t getDstNetworkSiteId();
|
|
|
|
void setUserTags(u_int64_t bitmap);
|
|
|
|
inline const u_int16_t getScore() const { return (flow_score); };
|
|
|
|
#ifdef HAVE_NEDGE
|
|
inline void setLastConntrackUpdate(u_int32_t when) {
|
|
last_conntrack_update = when;
|
|
}
|
|
inline u_int32_t getLastConntrackUpdate() { return (last_conntrack_update); }
|
|
bool isNetfilterIdleFlow() const;
|
|
|
|
void setPacketsBytes(time_t now, u_int32_t s2d_pkts, u_int32_t d2s_pkts,
|
|
u_int64_t s2d_bytes, u_int64_t d2s_bytes,
|
|
u_int32_t *delta_pkts /* out */,
|
|
u_int64_t *delta_bytes /* out */);
|
|
void getFlowShapers(TrafficShaper** shaper_cli, TrafficShaper** shaper_srv) {
|
|
*shaper_cli = flowShapers.cli;
|
|
*shaper_srv = flowShapers.srv;
|
|
}
|
|
bool updateCliSrvShapers(TrafficShaper** ingress_shaper,
|
|
TrafficShaper** egress_shaper);
|
|
void updateFlowShapers(bool first_update = false);
|
|
void recheckQuota(const struct tm* now);
|
|
inline u_int8_t getFlowRoutingTableId() { return (routing_table_id); }
|
|
inline void setIngress2EgressDirection(bool _ingress2egress) {
|
|
ingress2egress_direction = _ingress2egress;
|
|
}
|
|
inline bool isIngress2EgressDirection() { return (ingress2egress_direction); }
|
|
void fillDynamicPoolBlacklist();
|
|
#endif
|
|
void housekeep(time_t t);
|
|
void setParsedeBPFInfo(const ParsedeBPF* const _ebpf, bool swap_directions);
|
|
inline const ContainerInfo* getClientContainerInfo() const {
|
|
return ebpf && ebpf->container_info_set ? &ebpf->src_container_info : NULL;
|
|
}
|
|
inline const ContainerInfo* getServerContainerInfo() const {
|
|
return ebpf && ebpf->container_info_set ? &ebpf->dst_container_info : NULL;
|
|
}
|
|
inline const ProcessInfo* getClientProcessInfo() const {
|
|
return ebpf && ebpf->process_info_set ? &ebpf->src_process_info : NULL;
|
|
}
|
|
inline const ProcessInfo* getServerProcessInfo() const {
|
|
return ebpf && ebpf->process_info_set ? &ebpf->dst_process_info : NULL;
|
|
}
|
|
inline const TcpInfo* getClientTcpInfo() const {
|
|
return ebpf && ebpf->tcp_info_set ? &ebpf->src_tcp_info : NULL;
|
|
}
|
|
inline const TcpInfo* getServerTcpInfo() const {
|
|
return ebpf && ebpf->tcp_info_set ? &ebpf->dst_tcp_info : NULL;
|
|
}
|
|
|
|
inline bool isNotPurged() {
|
|
return (getInterface()->isPacketInterface() &&
|
|
getInterface()->is_purge_idle_interface() && (!idle()) &&
|
|
is_active_entry_now_idle(10 * getInterface()->getFlowMaxIdle()));
|
|
}
|
|
|
|
inline u_int16_t getTLSVersion() {
|
|
return (isTLS() ? protos.tls.tls_version : 0);
|
|
}
|
|
inline u_int32_t getTLSNotBefore() {
|
|
return (isTLS() ? protos.tls.notBefore : 0);
|
|
};
|
|
inline u_int32_t getTLSNotAfter() {
|
|
return (isTLS() ? protos.tls.notAfter : 0);
|
|
};
|
|
inline char* getTLSCertificateIssuerDN() {
|
|
return (isTLS() ? protos.tls.issuerDN : NULL);
|
|
}
|
|
inline char* getTLSCertificateSubjectDN() {
|
|
return (isTLS() ? protos.tls.subjectDN : NULL);
|
|
}
|
|
void setTLSCertificateIssuerDN(char* issuer);
|
|
void setTCPFingerprint(char* fp);
|
|
void setnDPIFingerprint(char* fp);
|
|
inline char* getTCPFingerprint() { return (tcp_fingerprint); }
|
|
inline char* getnDPIFingerprint() { return (ndpi_fingerprint); }
|
|
|
|
/* For now, the check is only on the nDPI fingerprint, but it will
|
|
need to be extended to the TCP fingerprint and JA4 when they are
|
|
merged into the fingerprints block of proto_json_info.*/
|
|
inline bool isFingerprintAvailable() {
|
|
return getnDPIFingerprint() != nullptr;
|
|
}
|
|
|
|
inline void setSearchedField(const char* field) {
|
|
snprintf(searched_field, sizeof(searched_field), "%s", field);
|
|
}
|
|
inline void resetSearchedField() { searched_field[0] = '\0'; }
|
|
|
|
inline void setTOS(u_int8_t tos, bool is_cli_tos) {
|
|
if (is_cli_tos)
|
|
cli2srv_tos = tos;
|
|
else
|
|
srv2cli_tos = tos;
|
|
}
|
|
inline u_int8_t getTOS(bool is_cli_tos) const {
|
|
return (is_cli_tos ? cli2srv_tos : srv2cli_tos);
|
|
}
|
|
|
|
inline u_int8_t getCli2SrvDSCP() const { return (cli2srv_tos & 0xFC) >> 2; }
|
|
inline u_int8_t getSrv2CliDSCP() const { return (srv2cli_tos & 0xFC) >> 2; }
|
|
|
|
inline u_int8_t getCli2SrvECN() { return (cli2srv_tos & 0x3); }
|
|
inline u_int8_t getSrv2CliECN() { return (srv2cli_tos & 0x3); }
|
|
|
|
inline float getICMPPacketsEntropy() {
|
|
return (protos.icmp.client_to_server.max_entropy -
|
|
protos.icmp.client_to_server.min_entropy);
|
|
}
|
|
|
|
inline bool timeToPeriodicDump(u_int sec) {
|
|
return ((sec - get_first_seen() >= CONST_DB_DUMP_FREQUENCY) &&
|
|
(sec - get_partial_last_seen() >= CONST_DB_DUMP_FREQUENCY));
|
|
}
|
|
|
|
u_char* getCommunityId(u_char* community_id, u_int community_id_len);
|
|
void setJSONRiskInfo(char* r);
|
|
void setEndReason(char* r);
|
|
char* getEndReason();
|
|
void setSMTPMailFrom(char* r);
|
|
char* getSMTPMailFrom();
|
|
void setSMTPRcptTo(char* r);
|
|
char* getSMTPRcptTo();
|
|
void setFlowRiskName(char* r);
|
|
char* getFlowRiskName();
|
|
void serializeJSONRiskInfo(ndpi_serializer* serializer);
|
|
void serializeVerdictInfo(ndpi_serializer* serializer);
|
|
void serializeTCPFlagsAnalysis(ndpi_serializer* serializer);
|
|
void serializeBGPInfo(ndpi_serializer* serializer);
|
|
void setWLANInfo(char* wlan_ssid, u_int8_t* wtp_mac_address);
|
|
void setClientBGPInfo(char* bgp_info);
|
|
void setServerBGPInfo(char* bgp_info);
|
|
inline char* getClientBGPInfo() { return((collection && collection->bgp.src) ? collection->bgp.src : (char*)""); }
|
|
inline char* getServerBGPInfo() { return((collection && collection->bgp.dst) ? collection->bgp.dst : (char*)""); }
|
|
void updateHRSrc2DstBytes(const std::vector<uint64_t>& v, time_t update_first_seen) {
|
|
mergeHRCounters(hr_src2dst_bytes, v, update_first_seen);
|
|
}
|
|
void updateHRDst2SrcBytes(const std::vector<uint64_t>& v, time_t update_first_seen) {
|
|
mergeHRCounters(hr_dst2src_bytes, v, update_first_seen);
|
|
}
|
|
inline const std::vector<uint64_t>& getHRSrc2DstBytes() const { return hr_src2dst_bytes; }
|
|
inline const std::vector<uint64_t>& getHRDst2SrcBytes() const { return hr_dst2src_bytes; }
|
|
inline void resetHRCounters() { hr_src2dst_bytes.clear(); hr_dst2src_bytes.clear(); hr_base_first_seen = 0; }
|
|
char* getWLANSSID() {
|
|
return (collection ? collection->wifi.wlan_ssid : NULL);
|
|
};
|
|
u_int8_t* getWTPMACAddress() {
|
|
return (collection ? collection->wifi.wtp_mac_address : NULL);
|
|
};
|
|
|
|
inline FlowTrafficStats* getTrafficStats() { return (&stats); };
|
|
inline char* get_custom_category_file() const {
|
|
if (category_list_name_shared_pointer)
|
|
return (category_list_name_shared_pointer);
|
|
else
|
|
return ((char*)ndpiDetectedProtocol.custom_category_userdata);
|
|
}
|
|
|
|
inline u_int32_t getErrorCode() { return (protocolErrorCode); }
|
|
inline void setErrorCode(u_int32_t rc) { protocolErrorCode = rc; }
|
|
|
|
inline char* getAddressFamilyProtocol() const {
|
|
return (ndpiAddressFamilyProtocol);
|
|
}
|
|
inline void setAddressFamilyProtocol(char* proto) {
|
|
if (ndpiAddressFamilyProtocol) free(ndpiAddressFamilyProtocol);
|
|
ndpiAddressFamilyProtocol = proto ? strdup(proto) : NULL;
|
|
}
|
|
|
|
inline ndpi_confidence_t getConfidence() { return (confidence); }
|
|
inline void setConfidence(ndpi_confidence_t rc) { confidence = rc; }
|
|
inline void setNdpiConfidence(ndpi_confidence_t rc) { ndpi_confidence = rc; }
|
|
|
|
inline u_int8_t getCliLocation() {
|
|
if ((cli_host && cli_host->isMulticastHost()) ||
|
|
(cli_ip_addr && cli_ip_addr->isMulticastAddress()))
|
|
return 2; // Multicast host
|
|
else if ((cli_host && cli_host->isLocalHost()) ||
|
|
(cli_ip_addr && cli_ip_addr->isLocalHost()))
|
|
return 1; // Local host
|
|
else
|
|
return 0; // Remote host
|
|
}
|
|
inline u_int8_t getSrvLocation() {
|
|
if ((srv_host && srv_host->isMulticastHost()) ||
|
|
(srv_ip_addr && srv_ip_addr->isMulticastAddress()))
|
|
return 2; // Multicast host
|
|
else if ((srv_host && srv_host->isLocalHost()) ||
|
|
(srv_ip_addr && srv_ip_addr->isLocalHost()))
|
|
return 1; // Local host
|
|
else
|
|
return 0; // Remote host
|
|
}
|
|
|
|
inline u_int32_t getPrivateFlowId() const { return (privateFlowId); }
|
|
|
|
inline bool isCustomFlowAlertTriggered() {
|
|
return (customFlowAlert.alertTriggered);
|
|
}
|
|
inline u_int8_t getCustomFlowAlertScore() { return (customFlowAlert.score); }
|
|
inline char* getCustomFlowAlertMessage() { return (customFlowAlert.msg); }
|
|
void triggerCustomFlowAlert(u_int8_t score, char* msg);
|
|
inline void setRTPStreamType(u_int8_t s) { rtp_stream_type = s; }
|
|
inline u_int8_t getRTPStreamType() { return (rtp_stream_type); }
|
|
inline void setPeriodicFlow(u_int32_t _periodicity) {
|
|
is_periodic_flow = 1, periodicity = _periodicity;
|
|
}
|
|
inline bool isPeriodicFlow() { return (is_periodic_flow ? true : false); }
|
|
void swap();
|
|
bool isDPIDetectedFlow();
|
|
void updateHostBlacklists();
|
|
int32_t getInterfaceIndex() { return (iface_index); };
|
|
inline void setFlowSource(FlowSource n) { flow_source = n; }
|
|
inline FlowSource getFlowSource() { return (flow_source); }
|
|
inline MinorConnectionStates setCurrentConnectionState(u_int8_t new_state) {
|
|
current_c_state = static_cast<MinorConnectionStates>(new_state);
|
|
return (current_c_state);
|
|
};
|
|
inline MinorConnectionStates getCurrentConnectionState() {
|
|
return (current_c_state);
|
|
};
|
|
bool checkS1ConnState();
|
|
bool isTCPFlagSet(u_int8_t flags, int flag_to_check);
|
|
MinorConnectionStates calculateConnectionState(bool is_cumulative);
|
|
MajorConnectionStates getMajorConnState();
|
|
inline u_int32_t getPostNATSrcIp() {
|
|
return (collection ? ntohl(collection->nat.src_ip_addr_post_nat) : 0);
|
|
};
|
|
inline u_int32_t getPostNATDstIp() {
|
|
return (collection ? ntohl(collection->nat.dst_ip_addr_post_nat) : 0);
|
|
};
|
|
inline u_int16_t getPostNATSrcPort() {
|
|
return (collection ? ntohs(collection->nat.src_port_post_nat) : 0);
|
|
};
|
|
inline u_int16_t getPostNATDstPort() {
|
|
return (collection ? ntohs(collection->nat.dst_port_post_nat) : 0);
|
|
};
|
|
|
|
void getSrcAS(u_int32_t* as, char** as_name);
|
|
void getDstAS(u_int32_t* as, char** as_name);
|
|
void getTransitAS(u_int32_t* as, char** as_nam);
|
|
|
|
TransitAS getTransitASType();
|
|
void setBittorrentHash(char* hash, u_int len);
|
|
inline bool isFlowAccounted() { return iface_flow_accounted; };
|
|
inline void setFlowAccounted() { iface_flow_accounted = 1; };
|
|
void accountFlowTraffic(bool src2dst_direction);
|
|
void setICMPTypeCode(u_int16_t icmp_type_code);
|
|
inline void setQoE(u_int8_t c2s, u_int8_t s2c) {
|
|
if ((c2s != NTOP_QOE_UNKNOWN) || (s2c != NTOP_QOE_UNKNOWN))
|
|
collected_qoe.src_to_dst = c2s, collected_qoe.dst_to_src = s2c,
|
|
has_collected_qoe = 1;
|
|
}
|
|
void setHostTCPFingerprint(char* fp, ndpi_os os_hint);
|
|
void setClientOSHint(ndpi_os os_hint);
|
|
void updateViewClientOS(Host* view_cli_host);
|
|
|
|
u_int32_t getSrcAS() { return (srcAS); }
|
|
u_int32_t getDstAS() { return (dstAS); }
|
|
u_int32_t getSrcPeerAS() { return (srcPeerAS); }
|
|
u_int32_t getDstPeerAS() { return (dstPeerAS); }
|
|
|
|
inline Mac* getCliMac() { return (c_mac); }
|
|
inline Mac* getSrvMac() { return (s_mac); }
|
|
|
|
inline u_int8_t* getCliMacRaw() { return (cli_mac); }
|
|
inline u_int8_t* getSrvMacRaw() { return (srv_mac); }
|
|
inline void setCliMacRaw(u_int8_t* m) {
|
|
memcpy(cli_mac, m, 6);
|
|
updateMac();
|
|
};
|
|
inline void setSrvMacRaw(u_int8_t* m) {
|
|
memcpy(srv_mac, m, 6);
|
|
updateMac();
|
|
};
|
|
|
|
#ifdef HAVE_NEDGE
|
|
inline void incNumProcessedPkts() { numFlowProcessedPkts++; }
|
|
inline void setNumPktsMarker() { numPktsMarkerSet = numFlowProcessedPkts; }
|
|
#endif
|
|
|
|
void updateTCPStats(u_int32_t cli_stats, u_int32_t srv_stats);
|
|
|
|
void setCliService(HostService service_enum);
|
|
void setSrvService(HostService service_enum);
|
|
void setCliTag(int tag_idx);
|
|
void setSrvTag(int tag_idx);
|
|
#ifdef NTOPNG_PRO
|
|
void refreshHostsTags();
|
|
#endif
|
|
inline void setIGMPType(u_int8_t t) { protos.igmp.igmp_type = t; }
|
|
void addExporterInfo(struct ndpi_in6_addr *exporter_ip,
|
|
struct ndpi_in6_addr *next_hop,
|
|
struct ndpi_in6_addr *mapped_exporter_ip,
|
|
struct ndpi_in6_addr *mapped_next_hop,
|
|
u_int16_t exporter_site_id,
|
|
u_int16_t next_hop_site_id,
|
|
u_int32_t in_index, u_int32_t out_index,
|
|
SNMPInterfaceRole in_role,
|
|
SNMPInterfaceRole out_role,
|
|
FlowSource source, bool src2dst_direction);
|
|
|
|
inline bool isFirstFlowDump() { return(last_db_dump.is_first_dump); }
|
|
|
|
u_int64_t get_transit_bytes();
|
|
u_int64_t get_peering_bytes();
|
|
u_int64_t get_ix_bytes();
|
|
};
|
|
|
|
#endif /* _FLOW_H_ */
|