"Fossies" - the Fresh Open Source Software Archive  

Source code changes of the file "src/service_inspectors/netflow/netflow.cc" between
snort3-3.1.31.0.tar.gz and snort3-3.1.32.0.tar.gz

About: Snort 3 is a network intrusion prevention and detection system (IDS/IPS) combining the benefits of signature, protocol and anomaly-based inspection.

netflow.cc  (snort3-3.1.31.0):netflow.cc  (snort3-3.1.32.0)
skipping to change at line 33 skipping to change at line 33
#include "config.h" #include "config.h"
#endif #endif
#include <fstream> #include <fstream>
#include <mutex> #include <mutex>
#include <sys/stat.h> #include <sys/stat.h>
#include <unordered_map> #include <unordered_map>
#include <vector> #include <vector>
#include "log/messages.h" #include "log/messages.h"
#include "managers/module_manager.h"
#include "main/reload_tuner.h"
#include "profiler/profiler.h" #include "profiler/profiler.h"
#include "protocols/packet.h" #include "protocols/packet.h"
#include "pub_sub/netflow_event.h" #include "pub_sub/netflow_event.h"
#include "src/utils/endian.h" #include "src/utils/endian.h"
#include "utils/util.h" #include "utils/util.h"
#include "netflow_cache.cc" #include "netflow_cache.cc"
using namespace snort; using namespace snort;
skipping to change at line 75 skipping to change at line 77
typedef std::vector<IpRecord> DumpCache; typedef std::vector<IpRecord> DumpCache;
static DumpCache* dump_cache = nullptr; static DumpCache* dump_cache = nullptr;
// compare struct to use with ip sort // compare struct to use with ip sort
struct IpCompare struct IpCompare
{ {
bool operator()(const IpRecord& a, const IpRecord& b) bool operator()(const IpRecord& a, const IpRecord& b)
{ return a.first.less_than(b.first); } { return a.first.less_than(b.first); }
}; };
static std::unordered_map<int, int>* udp_srv_map = nullptr;
static std::unordered_map<int, int>* tcp_srv_map = nullptr;
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// static functions // static functions
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
static const NetflowRule* filter_record(const NetflowRules* rules, const int zon
static bool filter_record(const NetflowRules* rules, const int zone, e,
const SfIp* src, const SfIp* dst) const SfIp* src, const SfIp* dst)
{ {
const SfIp* addr[2] = {src, dst}; const SfIp* addr[2] = {src, dst};
for( auto const & address : addr ) for( auto const & address : addr )
{ {
for( auto const& rule : rules->exclude ) for( auto const& rule : rules->exclude )
{ {
if ( rule.filter_match(address, zone) ) if ( rule.filter_match(address, zone) )
return false; return nullptr;
} }
} }
for( auto const & address : addr ) for( auto const & address : addr )
{ {
for( auto const& rule : rules->include ) for( auto const& rule : rules->include )
{ {
if ( rule.filter_match(address, zone) ) if ( rule.filter_match(address, zone) )
return true; return &rule;
} }
} }
return false; return nullptr;
}
static void publish_service_event(const Packet* p, const NetflowRule* match, Net
flowSessionRecord& record)
{
uint32_t serviceID = 0;
if (record.proto == (int) ProtocolId::TCP and tcp_srv_map)
serviceID = (*tcp_srv_map)[record.responder_port];
else if (record.proto == (int) ProtocolId::UDP and udp_srv_map)
serviceID = (*udp_srv_map)[record.responder_port];
NetflowEvent event(p, &record, match->create_host, match->create_service, se
rviceID);
DataBus::publish(NETFLOW_EVENT, event);
} }
static bool version_9_record_update(const unsigned char* data, uint32_t unix_sec s, static bool version_9_record_update(const unsigned char* data, uint32_t unix_sec s,
uint16_t field_type, uint16_t field_length, NetflowSessionRecord &record, uint16_t field_type, uint16_t field_length, NetflowSessionRecord &record,
RecordStatus& record_status) RecordStatus& record_status)
{ {
switch ( field_type ) switch ( field_type )
{ {
case NETFLOW_PROTOCOL: case NETFLOW_PROTOCOL:
skipping to change at line 442 skipping to change at line 459
} }
if ( bad_field ) if ( bad_field )
{ {
++netflow_stats.invalid_netflow_record; ++netflow_stats.invalid_netflow_record;
records--; records--;
continue; continue;
} }
// filter based on configuration // filter based on configuration
if ( !filter_record(p_rules, zone, &record.initiator_ip, &record const NetflowRule* match = filter_record(p_rules, zone, &record.
.responder_ip) ) initiator_ip, &record.responder_ip);
if ( !match )
{ {
records--; records--;
continue; continue;
} }
if ( record_status.bytes_sent and record_status.packets_sent and if ( record_status.bytes_sent and record_status.packets_sent and
record_status.src and record_status.dst and record_status.fi rst and record_status.src and record_status.dst and record_status.fi rst and
record_status.last and record.first_pkt_second <= record.las t_pkt_second ) record_status.last and record.first_pkt_second <= record.las t_pkt_second )
{ {
if ( record_status.src_tos ) if ( record_status.src_tos )
{ {
if ( !record_status.dst_tos ) if ( !record_status.dst_tos )
record.nf_dst_tos = record.nf_src_tos; record.nf_dst_tos = record.nf_src_tos;
} }
else if ( record_status.dst_tos ) else if ( record_status.dst_tos )
{ {
if ( !record_status.src_tos ) if ( !record_status.src_tos )
record.nf_src_tos = record.nf_dst_tos; record.nf_src_tos = record.nf_dst_tos;
} }
// send create_host and create_service flags too so that rna
event handler can log those if (match->create_service)
NetflowEvent event(p, &record); publish_service_event(p, match, record);
DataBus::publish(NETFLOW_EVENT, event);
} }
if ( netflow_cache->add(record.initiator_ip, record, true) ) if ( netflow_cache->add(record.initiator_ip, record, true) )
++netflow_stats.unique_flows; ++netflow_stats.unique_flows;
records--; records--;
} }
} }
// template flowset // template flowset
else if ( f_id == 0 ) else if ( f_id == 0 )
skipping to change at line 608 skipping to change at line 627
// Invalid source IP address provided // Invalid source IP address provided
if ( record.initiator_ip.set(&precord->flow_src_addr, AF_INET) != SFIP_S UCCESS ) if ( record.initiator_ip.set(&precord->flow_src_addr, AF_INET) != SFIP_S UCCESS )
return false; return false;
if ( record.responder_ip.set(&precord->flow_dst_addr, AF_INET) != SFIP_S UCCESS ) if ( record.responder_ip.set(&precord->flow_dst_addr, AF_INET) != SFIP_S UCCESS )
return false; return false;
if ( record.next_hop_ip.set(&precord->next_hop_addr, AF_INET) != SFIP_SU CCESS ) if ( record.next_hop_ip.set(&precord->next_hop_addr, AF_INET) != SFIP_SU CCESS )
return false; return false;
if ( !filter_record(p_rules, zone, &record.initiator_ip, &record.respond const NetflowRule* match = filter_record(p_rules, zone, &record.initiato
er_ip) ) r_ip, &record.responder_ip);
if ( !match )
continue; continue;
record.initiator_port = ntohs(precord->src_port); record.initiator_port = ntohs(precord->src_port);
record.responder_port = ntohs(precord->dst_port); record.responder_port = ntohs(precord->dst_port);
record.proto = precord->flow_protocol; record.proto = precord->flow_protocol;
record.first_pkt_second = first_packet; record.first_pkt_second = first_packet;
record.last_pkt_second = last_packet; record.last_pkt_second = last_packet;
record.initiator_pkts = ntohl(precord->pkt_count); record.initiator_pkts = ntohl(precord->pkt_count);
record.responder_pkts = 0; record.responder_pkts = 0;
record.initiator_bytes = ntohl(precord->bytes_sent); record.initiator_bytes = ntohl(precord->bytes_sent);
skipping to change at line 633 skipping to change at line 653
record.nf_snmp_in = ntohs(precord->snmp_if_in); record.nf_snmp_in = ntohs(precord->snmp_if_in);
record.nf_snmp_out = ntohs(precord->snmp_if_out); record.nf_snmp_out = ntohs(precord->snmp_if_out);
record.nf_src_as = (uint32_t)ntohs(precord->src_as); record.nf_src_as = (uint32_t)ntohs(precord->src_as);
record.nf_dst_as = (uint32_t)ntohs(precord->dst_as); record.nf_dst_as = (uint32_t)ntohs(precord->dst_as);
record.nf_src_mask = precord->src_mask; record.nf_src_mask = precord->src_mask;
record.nf_dst_mask = precord->dst_mask; record.nf_dst_mask = precord->dst_mask;
if ( netflow_cache->add(record.initiator_ip, record, false) ) if ( netflow_cache->add(record.initiator_ip, record, false) )
++netflow_stats.unique_flows; ++netflow_stats.unique_flows;
// send create_host and create_service flags too so that rna event handl if (match->create_service)
er can log those publish_service_event(p, match, record);
NetflowEvent event(p, &record);
DataBus::publish(NETFLOW_EVENT, event);
} }
return true; return true;
} }
static bool validate_netflow(const Packet* p, const NetflowRules* p_rules) static bool validate_netflow(const Packet* p, const NetflowRules* p_rules)
{ {
uint16_t size = p->dsize; uint16_t size = p->dsize;
const unsigned char* data = p->data; const unsigned char* data = p->data;
uint16_t version; uint16_t version;
bool retval = false; bool retval = false;
skipping to change at line 674 skipping to change at line 693
retval = decode_netflow_v9(data, size, p, p_rules); retval = decode_netflow_v9(data, size, p, p_rules);
if ( retval ) if ( retval )
{ {
++netflow_stats.packets; ++netflow_stats.packets;
++netflow_stats.version_9; ++netflow_stats.version_9;
} }
} }
return retval; return retval;
} }
//------------------------------------------------------------------------- //-------------------------------------------------------------------------
// inspector stuff // inspector stuff
//------------------------------------------------------------------------- //-------------------------------------------------------------------------
class NetflowInspector : public snort::Inspector class NetflowInspector : public snort::Inspector
{ {
public: public:
NetflowInspector(const NetflowConfig*); NetflowInspector(const NetflowConfig*);
~NetflowInspector() override; ~NetflowInspector() override;
void tinit() override; void tinit() override;
void tterm() override; void tterm() override;
void eval(snort::Packet*) override; void eval(snort::Packet*) override;
void show(const snort::SnortConfig*) const override; void show(const snort::SnortConfig*) const override;
void install_reload_handler(snort::SnortConfig*) override;
private: private:
const NetflowConfig *config; const NetflowConfig *config;
bool log_netflow_cache(); bool log_netflow_cache();
void stringify(std::ofstream&); void stringify(std::ofstream&);
}; };
class NetflowReloadSwapper : public snort::ReloadSwapper
{
public:
explicit NetflowReloadSwapper(NetflowInspector& ins) : inspector(ins) { }
void tswap() override;
private:
NetflowInspector& inspector;
};
static std::string to_string(const std::vector <snort::SfCidr>& networks) static std::string to_string(const std::vector <snort::SfCidr>& networks)
{ {
std::string nets; std::string nets;
if ( networks.empty() ) if ( networks.empty() )
{ {
nets = "any"; nets = "any";
} }
else else
{ {
for( auto const& n : networks ) for( auto const& n : networks )
skipping to change at line 755 skipping to change at line 784
{ {
ConfigLogger::log_flag("exclude", is_exclude, true); ConfigLogger::log_flag("exclude", is_exclude, true);
ConfigLogger::log_flag("create_host", d.create_host, true); ConfigLogger::log_flag("create_host", d.create_host, true);
ConfigLogger::log_flag("create_service", d.create_service, true); ConfigLogger::log_flag("create_service", d.create_service, true);
ConfigLogger::log_value("networks", to_string(d.networks).c_str(), true); ConfigLogger::log_value("networks", to_string(d.networks).c_str(), true);
ConfigLogger::log_value("zones", to_string(d.zones).c_str(), true); ConfigLogger::log_value("zones", to_string(d.zones).c_str(), true);
} }
void NetflowInspector::show(const SnortConfig*) const void NetflowInspector::show(const SnortConfig*) const
{ {
ConfigLogger::log_value("flow_memcap", config->flow_memcap); ConfigLogger::log_value("flow_memcap", (uint64_t)config->flow_memcap);
ConfigLogger::log_value("template_memcap", config->template_memcap); ConfigLogger::log_value("template_memcap", (uint64_t)config->template_memcap
);
ConfigLogger::log_value("dump_file", config->dump_file); ConfigLogger::log_value("dump_file", config->dump_file);
ConfigLogger::log_value("update_timeout", config->update_timeout); ConfigLogger::log_value("update_timeout", config->update_timeout);
bool log_header = true; bool log_header = true;
for ( auto const& d : config->device_rule_map ) for ( auto const& d : config->device_rule_map )
{ {
if (log_header) if (log_header)
{ {
ConfigLogger::log_option("rules"); ConfigLogger::log_option("rules");
log_header = false; log_header = false;
} }
skipping to change at line 873 skipping to change at line 902
NetflowInspector::NetflowInspector(const NetflowConfig* pc) NetflowInspector::NetflowInspector(const NetflowConfig* pc)
{ {
config = pc; config = pc;
if ( config->dump_file ) if ( config->dump_file )
{ {
// create dump cache // create dump cache
if ( ! dump_cache ) if ( ! dump_cache )
dump_cache = new DumpCache; dump_cache = new DumpCache;
} }
NetflowModule* mod = (NetflowModule*) ModuleManager::get_module(NETFLOW_NAME
);
if (mod)
{
udp_srv_map = &mod->udp_service_mappings;
tcp_srv_map = &mod->tcp_service_mappings;
}
} }
NetflowInspector::~NetflowInspector() NetflowInspector::~NetflowInspector()
{ {
// config and cache removal // config and cache removal
if ( config ) if ( config )
{ {
if ( config->dump_file ) if ( config->dump_file )
{ {
// log the cache and delete it // log the cache and delete it
skipping to change at line 917 skipping to change at line 954
{ {
const NetflowRules* p_rules = &(d->second); const NetflowRules* p_rules = &(d->second);
if ( ! validate_netflow(p, p_rules) ) if ( ! validate_netflow(p, p_rules) )
++netflow_stats.invalid_netflow_record; ++netflow_stats.invalid_netflow_record;
} }
} }
void NetflowInspector::tinit() void NetflowInspector::tinit()
{ {
if ( !netflow_cache ) delete netflow_cache;
netflow_cache = new NetflowCache(config->flow_memcap, netflow_stats); netflow_cache = new NetflowCache(config->flow_memcap, netflow_stats);
if ( !template_cache ) delete template_cache;
template_cache = new TemplateFieldCache(config->template_memcap, netflow template_cache = new TemplateFieldCache(config->template_memcap, netflow_sta
_stats); ts);
} }
void NetflowInspector::tterm() void NetflowInspector::tterm()
{ {
if ( config->dump_file and dump_cache ) if ( config->dump_file and dump_cache )
{ {
static std::mutex stats_mutex; static std::mutex stats_mutex;
std::lock_guard<std::mutex> lock(stats_mutex); std::lock_guard<std::mutex> lock(stats_mutex);
netflow_cache->get_all_values(*dump_cache); netflow_cache->get_all_values(*dump_cache);
} }
delete netflow_cache; delete netflow_cache;
delete template_cache; delete template_cache;
} }
void NetflowInspector::install_reload_handler(SnortConfig* sc)
{
sc->register_reload_handler(new NetflowReloadSwapper(*this));
}
void NetflowReloadSwapper::tswap()
{
inspector.tinit();
}
//------------------------------------------------------------------------- //-------------------------------------------------------------------------
// api stuff // api stuff
//------------------------------------------------------------------------- //-------------------------------------------------------------------------
static Module* netflow_mod_ctor() static Module* netflow_mod_ctor()
{ return new NetflowModule; } { return new NetflowModule; }
static void netflow_mod_dtor(Module* m) static void netflow_mod_dtor(Module* m)
{ delete m; } { delete m; }
 End of changes. 18 change blocks. 
25 lines changed or deleted 75 lines changed or added

Home  |  About  |  Features  |  All  |  Newest  |  Dox  |  Diffs  |  RSS Feeds  |  Screenshots  |  Comments  |  Imprint  |  Privacy  |  HTTP(S)