const auto& src_ip = nfe->get_record()->initiator_ip;
const auto& src_ip_ptr = (const struct in6_addr*) src_ip.get_ip6_ptr();
- auto ht = find_or_create_host_tracker(src_ip, new_host);
-
- if ( !new_host )
- ht->update_last_seen();
-
- const uint8_t src_mac[6] = {0};
-
+ // This case must be handled first before adding the host to the
+ // host cache. Otherwise, new rules evals with create_host = true
+ // will fail since the host will already exist.
if (!nfe->get_create_host() and !nfe->get_create_service())
{
uint32_t service = nfe->get_service_id();
return;
}
+ auto ht = find_or_create_host_tracker(src_ip, new_host);
+
+ if ( !new_host )
+ ht->update_last_seen();
+
+ const uint8_t src_mac[6] = {0};
+
if ( new_host )
{
if ( nfe->get_create_host() )
// -----------------------------------------------------------------------------
// static functions
// -----------------------------------------------------------------------------
-static const NetFlowRule* filter_record(const NetFlowRules* rules, const int zone,
+static std::vector<const NetFlowRule*> filter_record(const NetFlowRules* rules, const int zone,
const SfIp* src, const SfIp* dst)
{
+ std::vector<const NetFlowRule*> match_vec;
+
const SfIp* addr[2] = {src, dst};
for( auto const & address : addr )
for( auto const& rule : rules->exclude )
{
if ( rule.filter_match(address, zone) )
- return nullptr;
+ return match_vec;
}
}
for( auto const& rule : rules->include )
{
if ( rule.filter_match(address, zone) )
- return &rule;
+ match_vec.emplace_back(&rule);
}
}
- return nullptr;
+
+ return match_vec;
}
static void publish_netflow_event(const Packet* p, const NetFlowRule* match, NetFlowSessionRecord& record)
}
// filter based on configuration
- const NetFlowRule* match = filter_record(p_rules, zone, &record.initiator_ip, &record.responder_ip);
- if ( !match )
+ std::vector<const NetFlowRule*> match_vec = filter_record(p_rules, zone, &record.initiator_ip, &record.responder_ip);
+ if ( !match_vec.size() )
{
records--;
continue;
}
record.netflow_initiator_ip.set(p->ptrs.ip_api.get_src()->get_ip6_ptr(), AF_INET6);
- publish_netflow_event(p, match, record);
+ bool alerted_conn = false;
+ bool alerted_host = false;
+
+ for (const NetFlowRule* nr: match_vec)
+ {
+ if ((!alerted_conn and !nr->create_host) or (!alerted_host and nr->create_host) )
+ publish_netflow_event(p, nr, record);
+
+ if (nr->create_host or nr->create_service)
+ alerted_host = true;
+ else
+ alerted_conn = true;
+ }
}
if ( netflow_cache->add(record.initiator_ip, record, true) )
if ( record.next_hop_ip.set(&precord->next_hop_addr, AF_INET) != SFIP_SUCCESS )
return false;
- const NetFlowRule* match = filter_record(p_rules, zone, &record.initiator_ip, &record.responder_ip);
- if ( !match )
+ std::vector<const NetFlowRule*> match_vec = filter_record(p_rules, zone, &record.initiator_ip, &record.responder_ip);
+ if ( !match_vec.size() )
continue;
record.initiator_port = ntohs(precord->src_port);
++netflow_stats.unique_flows;
record.netflow_initiator_ip.set(p->ptrs.ip_api.get_src()->get_ip6_ptr(), AF_INET6);
- publish_netflow_event(p, match, record);
+
+ bool alerted_conn = false;
+ bool alerted_host = false;
+
+ for (const NetFlowRule* nr: match_vec)
+ {
+ if ( (!alerted_conn and !nr->create_host) or (!alerted_host and nr->create_host) )
+ publish_netflow_event(p, nr, record);
+
+ if (nr->create_host or nr->create_service)
+ alerted_host = true;
+ else
+ alerted_conn = true;
+ }
}
return true;
}