mirror of
https://github.com/ntop/ntopng.git
synced 2026-04-28 06:59:33 +00:00
1763 lines
65 KiB
C++
1763 lines
65 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 {
|
|
u_int32_t exporter_ipv4;
|
|
IpAddress next_hop;
|
|
u_int32_t in_index, out_index;
|
|
FlowSource source; /* sFlow / NetFlow */
|
|
bool return_path;
|
|
} ExporterFlowInfo;
|
|
|
|
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;
|
|
SNMPInterfaceRole flowExporterInterfaceRole;
|
|
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;
|
|
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;
|
|
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];
|
|
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::vector<ExporterFlowInfo> exporterStats;
|
|
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 */
|
|
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, *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;
|
|
} 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;
|
|
|
|
struct {
|
|
u_int32_t device_ip;
|
|
IpAddress next_hop;
|
|
u_int32_t in_index, out_index;
|
|
u_int16_t observation_point_id;
|
|
u_int16_t site_id;
|
|
} flow_device;
|
|
|
|
/* 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 */
|
|
} 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;
|
|
|
|
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 computeKey();
|
|
void accountBidirectionalTCPProtocolServices();
|
|
void accountBidirectionalUDPProtocolServices();
|
|
void setServerName(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; };
|
|
const char* getDomainName();
|
|
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 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(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; };
|
|
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 getLabels();
|
|
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();
|
|
};
|
|
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 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) const;
|
|
|
|
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(u_int32_t 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) {
|
|
srcPeerAS = v;
|
|
} /* Used when collecting flows via ZMQ (usually it contains the peer AS) */
|
|
inline void setDstPeerAS(u_int32_t v) {
|
|
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);
|
|
}
|
|
#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 void setFlowDevice(u_int32_t device_ip, u_int16_t observation_point_id,
|
|
u_int32_t inidx, u_int32_t outidx) {
|
|
ObservationPoint* obs_point;
|
|
|
|
flow_device.device_ip = device_ip,
|
|
flow_device.observation_point_id = observation_point_id;
|
|
flow_device.in_index = inidx, flow_device.out_index = outidx;
|
|
if (cli_host) cli_host->setLastDeviceIp(device_ip);
|
|
if (srv_host) srv_host->setLastDeviceIp(device_ip);
|
|
|
|
if ((obs_point = iface->getObsPoint(observation_point_id, true, true)) !=
|
|
NULL)
|
|
obs_point->addProbeIp(device_ip);
|
|
}
|
|
inline u_int32_t getFlowDeviceIP() { return flow_device.device_ip; };
|
|
inline u_int16_t getFlowObservationPointId() {
|
|
return flow_device.observation_point_id;
|
|
};
|
|
inline u_int16_t get_observation_point_id() {
|
|
return (getFlowObservationPointId());
|
|
};
|
|
inline u_int32_t getFlowDeviceInIndex() { return flow_device.in_index; };
|
|
inline u_int32_t getFlowDeviceOutIndex() { return flow_device.out_index; };
|
|
|
|
inline void setFlowDeviceInIndex(u_int32_t idx) {
|
|
if (idx != 0) flow_device.in_index = idx;
|
|
};
|
|
inline void setFlowDeviceOutIndex(u_int32_t idx) {
|
|
if (idx != 0) flow_device.out_index = idx;
|
|
};
|
|
|
|
inline void setFlowDeviceNextHop(IpAddress* nh) {
|
|
flow_device.next_hop.set(nh);
|
|
}
|
|
inline IpAddress* getFlowDeviceNextHop() { return (&flow_device.next_hop); }
|
|
|
|
inline void setFlowExporterSiteId(u_int16_t id) { flow_device.site_id = id; }
|
|
inline u_int16_t getFlowExporterSiteId() { return (flow_device.site_id); }
|
|
|
|
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);
|
|
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*)""); }
|
|
inline void setHRSrc2DstBytes(const std::vector<uint64_t>& v) { hr_src2dst_bytes = v; }
|
|
inline void setHRDst2SrcBytes(const std::vector<uint64_t>& v) { hr_dst2src_bytes = v; }
|
|
inline const std::vector<uint64_t>& getHRSrc2DstBytes() const { return hr_src2dst_bytes; }
|
|
inline const std::vector<uint64_t>& getHRDst2SrcBytes() const { return hr_dst2src_bytes; }
|
|
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) {
|
|
ndpiAddressFamilyProtocol = strdup(proto);
|
|
}
|
|
|
|
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);
|
|
|
|
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(int service_enum);
|
|
void setSrvService(int service_enum);
|
|
inline void setIGMPType(u_int8_t t) { protos.igmp.igmp_type = t; }
|
|
void addExporterInfo(u_int32_t exporter_ipv4, IpAddress* next_hop,
|
|
u_int32_t in_index, u_int32_t out_index,
|
|
FlowSource source, bool src2dst_direction);
|
|
|
|
inline SNMPInterfaceRole getSNMPExporterInterfaceRole() {
|
|
return (flowExporterInterfaceRole);
|
|
}
|
|
inline void setSNMPExporterInterfaceRole(SNMPInterfaceRole r) {
|
|
flowExporterInterfaceRole = r;
|
|
}
|
|
};
|
|
|
|
#endif /* _FLOW_H_ */
|