HttpSessionData* SetNewHttpSessionData(Packet* p, void*)
{
HttpFlowData* fd = new HttpFlowData;
- p->flow->set_application_data(fd);
+ p->flow->set_flow_data(fd);
return &fd->session;
}
static HttpSessionData* get_session_data(Flow* flow)
{
- HttpFlowData* fd = (HttpFlowData*)flow->get_application_data(
- HttpFlowData::flow_id);
-
+ HttpFlowData* fd = (HttpFlowData*)flow->get_flow_data(HttpFlowData::flow_id);
return fd ? &fd->session : NULL;
}
dnp3 = { }
dns = { }
gtp_inspect = default_gtp
+http_inspect = { }
imap = { }
smtp = { }
pop = { }
ssl = { }
telnet = { }
--- use http_inspect or new_http_inspect (incomplete)
-http_inspect = { }
---new_http_inspect = { }
-
ftp_server = default_ftp_server
ftp_client = { }
ftp_data = { }
}
if ( sfvar_ip_in(SynToMulticastDstIp, snort.ip_api.get_dst()) )
- {
codec_event(codec, DECODE_SYN_TO_MULTICAST);
- }
+
if ( (tcph->th_flags & TH_RST) )
codec_event(codec, DECODE_TCP_SYN_RST);
check_tags_flag = 1;
- /* Check for normally closed session */
+ // clear closed sessions here after inspection since non-stream
+ // inspectors may depend on flow information
+ // FIXIT-H but this result in double clearing? should normal
+ // clear_session() calls be deleted from stream? this is a
+ // performance hit on short-lived flows
stream.check_session_closed(p);
/*
FileFlows* FileFlows::get_file_flows(Flow* flow)
{
- FileFlows* fd = (FileFlows*) flow->get_application_data(FileFlows::flow_id);
+ FileFlows* fd = (FileFlows*) flow->get_flow_data(FileFlows::flow_id);
if (fd)
return fd;
if (FileService::is_file_service_enabled())
{
fd = new FileFlows(flow);
- flow->set_application_data(fd);
+ flow->set_flow_data(fd);
}
return fd;
while ((fd = head->data))
{
head->data = fd->next;
- lws->set_application_data(fd);
+ lws->set_flow_data(fd);
++realized;
fd->handle_expected(p);
}
#include "flow/ha.h"
#include "flow/session.h"
#include "ips_options/ips_flowbits.h"
-#include "utils/bitop.h"
-#include "utils/util.h"
#include "protocols/packet.h"
#include "sfip/sf_ip.h"
+#include "utils/bitop.h"
+#include "utils/util.h"
unsigned FlowData::flow_id = 0;
void Flow::init(PktType type)
{
pkt_type = type;
-
- // FIXIT-M getFlowbitSizeInBytes() should be attribute of ??? (or eliminate)
- bitop = new BitOp(getFlowbitSizeInBytes());
+ bitop = nullptr;
if ( HighAvailabilityManager::active() )
{
ha_state = new FlowHAState;
previous_ssn_state = ssn_state;
}
+ mpls_client.length = 0;
+ mpls_server.length = 0;
}
void Flow::term()
if ( session )
delete session;
- free_application_data();
+ free_flow_data();
+
+ if ( mpls_client.length )
+ delete[] mpls_client.start;
+
+ if ( mpls_server.length )
+ delete[] mpls_server.start;
+
+ if ( bitop )
+ delete bitop;
if ( ssn_client )
ssn_client->rem_ref();
if ( gadget )
gadget->rem_ref();
- if ( bitop )
- delete bitop;
-
if ( ha_state )
delete ha_state;
+}
- if ( clientMplsLyr.length )
+inline void Flow::clean()
+{
+ if ( mpls_client.length )
{
- delete[] clientMplsLyr.start;
- clientMplsLyr.length = 0;
+ delete[] mpls_client.start;
+ mpls_client.length = 0;
}
- if ( serverMplsLyr.length )
+ if ( mpls_server.length )
{
- delete[] serverMplsLyr.start;
- serverMplsLyr.length = 0;
+ delete[] mpls_server.start;
+ mpls_server.length = 0;
+ }
+ if ( bitop )
+ {
+ delete bitop;
+ bitop = nullptr;
}
}
session->clear();
}
- free_application_data();
-
- if ( clientMplsLyr.length )
- {
- delete[] clientMplsLyr.start;
- clientMplsLyr.length = 0;
- }
- if ( serverMplsLyr.length )
- {
- delete[] serverMplsLyr.start;
- serverMplsLyr.length = 0;
- }
+ free_flow_data();
+ clean();
// FIXIT-M cleanup() winds up calling clear()
if ( ssn_client )
if ( data )
clear_data();
- constexpr size_t offset = offsetof(Flow, appDataList);
- // FIXIT-L need a struct to zero here to make future proof
- memset((uint8_t*)this+offset, 0, sizeof(Flow)-offset);
-
- bitop->reset();
-
if ( ha_state )
ha_state->reset();
+
+ constexpr size_t offset = offsetof(Flow, flow_data);
+ // FIXIT-L need a struct to zero here to make future proof
+ memset((uint8_t*)this+offset, 0, sizeof(Flow)-offset);
}
-void Flow::restart(bool free_flow_data)
+void Flow::restart(bool dump_flow_data)
{
- if ( free_flow_data )
- free_application_data();
+ if ( dump_flow_data )
+ free_flow_data();
- if ( clientMplsLyr.length )
- {
- delete[] clientMplsLyr.start;
- clientMplsLyr.length = 0;
- }
- if ( serverMplsLyr.length )
- {
- delete[] serverMplsLyr.start;
- serverMplsLyr.length = 0;
- }
-
- bitop->reset();
+ clean();
ssn_state.ignore_direction = 0;
ssn_state.session_flags = SSNFLAG_NONE;
previous_ssn_state = ssn_state;
}
-void Flow::clear(bool free_flow_data)
+void Flow::clear(bool dump_flow_data)
{
- restart(free_flow_data);
+ restart(dump_flow_data);
set_state(FlowState::SETUP);
if ( ssn_client )
clear_gadget();
}
-int Flow::set_application_data(FlowData* fd)
+int Flow::set_flow_data(FlowData* fd)
{
- FlowData* appData = get_application_data(fd->get_id());
- assert(appData != fd);
+ FlowData* old = get_flow_data(fd->get_id());
+ assert(old != fd);
- if (appData)
- free_application_data(appData);
+ if (old)
+ free_flow_data(old);
fd->prev = nullptr;
- fd->next = appDataList;
+ fd->next = flow_data;
- if ( appDataList )
- appDataList->prev = fd;
+ if ( flow_data )
+ flow_data->prev = fd;
- appDataList = fd;
+ flow_data = fd;
return 0;
}
-FlowData* Flow::get_application_data(unsigned id)
+FlowData* Flow::get_flow_data(unsigned id)
{
- FlowData* appData = appDataList;
+ FlowData* fd = flow_data;
- while (appData)
+ while (fd)
{
- if (appData->get_id() == id)
- return appData;
+ if (fd->get_id() == id)
+ return fd;
- appData = appData->next;
+ fd = fd->next;
}
return nullptr;
}
-void Flow::free_application_data(FlowData* fd)
+void Flow::free_flow_data(FlowData* fd)
{
- if ( fd == appDataList )
+ if ( fd == flow_data )
{
- appDataList = fd->next;
- if ( appDataList )
- appDataList->prev = nullptr;
+ flow_data = fd->next;
+ if ( flow_data )
+ flow_data->prev = nullptr;
}
else if ( !fd->next )
{
delete fd;
}
-void Flow::free_application_data(uint32_t proto)
+void Flow::free_flow_data(uint32_t proto)
{
- FlowData* fd = get_application_data(proto);
+ FlowData* fd = get_flow_data(proto);
if ( fd )
- free_application_data(fd);
+ free_flow_data(fd);
}
-void Flow::free_application_data()
+void Flow::free_flow_data()
{
- FlowData* appData = appDataList;
+ FlowData* fd = flow_data;
- while (appData)
+ while (fd)
{
- FlowData* tmp = appData;
- appData = appData->next;
+ FlowData* tmp = fd;
+ fd = fd->next;
delete tmp;
}
- appDataList = nullptr;
+ flow_data = nullptr;
}
void Flow::call_handlers(Packet* p, bool eof)
{
- FlowData* appData = appDataList;
+ FlowData* fd = flow_data;
- while (appData)
+ while (fd)
{
if ( eof )
- appData->handle_eof(p);
+ fd->handle_eof(p);
else
- appData->handle_retransmit(p);
+ fd->handle_retransmit(p);
- appData = appData->next;
+ fd = fd->next;
}
}
}
}
-static constexpr int TCP_HZ = 100;
-
-static inline uint64_t CalcJiffies(const Packet* p)
-{
- uint64_t ret = 0;
- uint64_t sec = (uint64_t)p->pkth->ts.tv_sec * TCP_HZ;
- uint64_t usec = (p->pkth->ts.tv_usec / (1000000UL/TCP_HZ));
-
- ret = sec + usec;
-
- return ret;
-}
-
void Flow::set_expire(const Packet* p, uint32_t timeout)
{
- expire_time = CalcJiffies(p) + (timeout * TCP_HZ);
-}
-
-int Flow::get_expire(const Packet* p)
-{
- return ( CalcJiffies(p) > expire_time );
+ expire_time = (uint64_t)p->pkth->ts.tv_sec + timeout;
}
bool Flow::expired(const Packet* p)
if ( !expire_time )
return false;
- uint64_t pkttime = CalcJiffies(p);
-
- if ( (int)(pkttime - expire_time) > 0 )
+ if ( (uint64_t)p->pkth->ts.tv_sec > expire_time )
return true;
return false;
if ( p->packet_flags & PKT_FROM_CLIENT )
{
- if ( !clientMplsLyr.length )
+ if ( !mpls_client.length )
{
- clientMplsLyr.length = mpls_lyr->length;
- clientMplsLyr.prot_id = mpls_lyr->prot_id;
- clientMplsLyr.start = new uint8_t[mpls_lyr->length];
- memcpy((void *)clientMplsLyr.start, mpls_lyr->start, mpls_lyr->length);
+ mpls_client.length = mpls_lyr->length;
+ mpls_client.prot_id = mpls_lyr->prot_id;
+ mpls_client.start = new uint8_t[mpls_lyr->length];
+ memcpy((void *)mpls_client.start, mpls_lyr->start, mpls_lyr->length);
}
}
else
{
- if ( !serverMplsLyr.length )
+ if ( !mpls_server.length )
{
- serverMplsLyr.length = mpls_lyr->length;
- serverMplsLyr.prot_id = mpls_lyr->prot_id;
- serverMplsLyr.start = new uint8_t[mpls_lyr->length];
- memcpy((void *)serverMplsLyr.start, mpls_lyr->start, mpls_lyr->length);
+ mpls_server.length = mpls_lyr->length;
+ mpls_server.prot_id = mpls_lyr->prot_id;
+ mpls_server.start = new uint8_t[mpls_lyr->length];
+ memcpy((void *)mpls_server.start, mpls_lyr->start, mpls_lyr->length);
}
}
}
Layer Flow::get_mpls_layer_per_dir(bool client)
{
if ( client )
- return clientMplsLyr;
+ return mpls_client;
else
- return serverMplsLyr;
+ return mpls_server;
}
#include <assert.h>
-#include "utils/bitop.h"
#include "sfip/sfip_t.h"
#include "flow/flow_key.h"
#include "framework/inspector.h"
void term();
void reset(bool do_cleanup = true);
- void restart(bool free_flow_data = true);
- void clear(bool free_flow_data = true);
-
- int set_application_data(FlowData*);
- FlowData* get_application_data(uint32_t proto);
- void free_application_data(uint32_t proto);
- void free_application_data(FlowData*);
- void free_application_data();
- void set_application_ids(AppId serviceAppId, AppId clientAppId,
- AppId payloadAppId, AppId miscAppId);
- void get_application_ids(AppId& serviceAppId, AppId& clientAppId,
- AppId& payloadAppId, AppId& miscAppId);
+ void restart(bool dump_flow_data = true);
+ void clear(bool dump_flow_data = true);
+
+ int set_flow_data(FlowData*);
+ FlowData* get_flow_data(uint32_t proto);
+ void free_flow_data(uint32_t proto);
+ void free_flow_data(FlowData*);
+ void free_flow_data();
+
+ void set_application_ids(AppId service, AppId client, AppId payload, AppId misc);
+ void get_application_ids(AppId& service, AppId& client, AppId& payload, AppId& misc);
+
void call_handlers(Packet* p, bool eof = false);
void markup_packet_flags(Packet*);
void set_direction(Packet*);
void set_expire(const Packet*, uint32_t timeout);
- int get_expire(const Packet*);
bool expired(const Packet*);
void set_ttl(Packet*, bool client);
void set_mpls_layer_per_dir(Packet*);
}
public: // FIXIT-M privatize if possible
+ // fields are organized by initialization and size to minimize
+ // void space and allow for memset of tail end of struct
+
// these fields are const after initialization
const FlowKey* key;
class Session* session;
class BitOp* bitop;
class FlowHAState* ha_state;
+
uint8_t ip_proto; // FIXIT-M do we need both of these?
PktType pkt_type; // ^^
Flow* prev, * next;
Inspector* ssn_client;
Inspector* ssn_server;
+
long last_data_seen;
+ Layer mpls_client, mpls_server;
// everything from here down is zeroed
- FlowData* appDataList;
+ FlowData* flow_data;
Inspector* clouseau; // service identifier
Inspector* gadget; // service handler
Inspector* data;
const char* service;
- Layer clientMplsLyr, serverMplsLyr;
- unsigned policy_id;
-
- FlowState flow_state;
+ uint64_t expire_time;
sfip_t client_ip; // FIXIT-L family and bits should be changed to uint16_t
sfip_t server_ip; // or uint8_t to reduce sizeof from 24 to 20
- uint64_t expire_time;
+ LwState ssn_state;
+ LwState previous_ssn_state;
+
+ // FIXIT-L: if appid is only consumer of this move to appid
+ AppId application_ids[APP_PROTOID_MAX];
+
+ FlowState flow_state;
+ unsigned policy_id;
int32_t iface_in;
int32_t iface_out;
uint8_t response_count;
bool disable_inspect;
- // FIXIT-L: if appid is only consumer of this move to appid
- AppId application_ids[APP_PROTOID_MAX];
-
-public:
- LwState ssn_state;
- LwState previous_ssn_state;
+private:
+ void clean();
};
#endif
#include "main/snort_debug.h"
#include "packet_io/active.h"
#include "time/packet_time.h"
+#include "utils/stats.h"
#define SESSION_CACHE_FLAG_PURGING 0x01
FlowCache::FlowCache (const FlowConfig& cfg) : config(cfg)
{
- cleanup_flows = cfg.max_sessions * cfg.cleanup_pct / 100;
- if ( cleanup_flows == 0 )
- cleanup_flows = 1;
-
- assert(cleanup_flows <= cfg.max_sessions);
- assert(cleanup_flows > 0);
-
hash_table = new ZHash(config.max_sessions, sizeof(FlowKey));
hash_table->set_keyops(FlowKey::hash, FlowKey::compare);
if ( !flow )
flow = static_cast<Flow*>(hash_table->first());
- while ( flow and retired < num_flows )
+ while ( flow and (retired < num_flows) )
{
if ( flow->last_data_seen + config.nominal_timeout > thetime )
break;
while ( auto flow = static_cast<Flow*>(hash_table->first()) )
{
- flow->ssn_state.session_flags |= SSNFLAG_PRUNED;
release(flow, PruneReason::PURGE);
++retired;
}
int remove(Flow*);
private:
+ const unsigned cleanup_flows = 1;
const FlowConfig& config;
- unsigned cleanup_flows;
unsigned uni_count;
uint32_t flags;
unsigned max_sessions = 0;
unsigned pruning_timeout = 0;
unsigned nominal_timeout = 0;
- unsigned cleanup_pct = 0;
};
#endif
#include "session.h"
FlowControl::FlowControl()
-{
- ip_cache = nullptr;
- icmp_cache = nullptr;
- tcp_cache = nullptr;
- udp_cache = nullptr;
- user_cache = nullptr;
- file_cache = nullptr;
- exp_cache = nullptr;
-
- ip_mem = icmp_mem = nullptr;
- tcp_mem = udp_mem = nullptr;
- user_mem = file_mem = nullptr;
-
- get_ip = get_icmp = nullptr;
- get_tcp = get_udp = nullptr;
- get_user = get_file = nullptr;
-
- last_pkt_type = PktType::NONE;
-}
+{ }
FlowControl::~FlowControl()
{
static THREAD_LOCAL PegCount user_count = 0;
static THREAD_LOCAL PegCount file_count = 0;
-uint32_t FlowControl::max_flows(PktType type)
-{
- FlowCache* cache = get_cache(type);
-
- if ( cache )
- return cache->get_max_flows();
-
- return 0;
-}
-
PegCount FlowControl::get_flows(PktType type)
{
switch ( type )
case PktType::ICMP: return icmp_count;
case PktType::TCP: return tcp_count;
case PktType::UDP: return udp_count;
- case PktType::PDU: return user_count;
+ case PktType::PDU: return user_count;
case PktType::FILE: return file_count;
default: return 0;
}
cache->purge();
}
-void FlowControl::prune_flows(PktType type, const Packet* p)
-{
- if ( !p )
- return;
-
- FlowCache* cache = get_cache(type);
-
- if ( !cache )
- return;
-
- // smack the older timed out flows
- if ( !cache->prune_stale(p->pkth->ts.tv_sec, p->flow) )
- {
- // if no luck, try the memcap
- cache->prune_excess(p->flow);
- }
-}
-
// hole for memory manager/prune handler
bool FlowControl::prune_one(PruneReason reason, bool do_cleanup)
{
return cache ? cache->prune_one(reason, do_cleanup) : false;
}
-void FlowControl::timeout_flows(uint32_t flowCount, time_t cur_time)
+void FlowControl::timeout_flows(time_t cur_time)
{
- Active::suspend();
-
- if ( ip_cache )
- ip_cache->timeout(flowCount, cur_time);
-
- //if ( icmp_cache )
- //icmp_cache does not need cleaning
-
- if ( tcp_cache )
- tcp_cache->timeout(flowCount, cur_time);
+ if ( !types.size() )
+ return;
- if ( udp_cache )
- udp_cache->timeout(flowCount, cur_time);
+ Active::suspend();
+ FlowCache* fc = get_cache(types[next]);
- if ( user_cache )
- user_cache->timeout(flowCount, cur_time);
+ if ( ++next >= types.size() )
+ next = 0;
- if ( file_cache )
- file_cache->timeout(flowCount, cur_time);
+ if ( fc )
+ fc->timeout(1, cur_time);
Active::resume();
}
ip_cache->push(ip_mem + i);
get_ip = get_ssn;
+ types.push_back(PktType::IP);
}
void FlowControl::process_ip(Packet* p)
icmp_cache->push(icmp_mem + i);
get_icmp = get_ssn;
+ types.push_back(PktType::ICMP);
}
void FlowControl::process_icmp(Packet* p)
tcp_cache->push(tcp_mem + i);
get_tcp = get_ssn;
+ types.push_back(PktType::TCP);
}
void FlowControl::process_tcp(Packet* p)
udp_cache->push(udp_mem + i);
get_udp = get_ssn;
+ types.push_back(PktType::UDP);
}
void FlowControl::process_udp(Packet* p)
user_cache->push(user_mem + i);
get_user = get_ssn;
+ types.push_back(PktType::PDU);
}
void FlowControl::process_user(Packet* p)
file_cache->push(file_mem + i);
get_file = get_ssn;
+ types.push_back(PktType::FILE);
}
void FlowControl::process_file(Packet* p)
// processed. flows are pruned as needed to process new flows.
#include <cstdint>
+#include <vector>
#include "flow/flow_config.h"
#include "framework/counts.h"
void delete_flow(const FlowKey*);
void delete_flow(Flow*, PruneReason);
void purge_flows(PktType);
- void prune_flows(PktType, const Packet*);
bool prune_one(PruneReason, bool do_cleanup);
- void timeout_flows(uint32_t flowCount, time_t cur_time);
+
+ void timeout_flows(time_t cur_time);
char expected_flow(Flow*, Packet*);
bool is_expected(Packet*);
const sfip_t *dstIP, uint16_t dstPort,
PktType, int16_t appId, FlowData*);
- uint32_t max_flows(PktType);
-
PegCount get_flows(PktType);
PegCount get_total_prunes(PktType) const;
PegCount get_prunes(PktType, PruneReason) const;
void preemptive_cleanup();
private:
- FlowCache* ip_cache;
- FlowCache* icmp_cache;
- FlowCache* tcp_cache;
- FlowCache* udp_cache;
- FlowCache* user_cache;
- FlowCache* file_cache;
+ FlowCache* ip_cache = nullptr;
+ FlowCache* icmp_cache = nullptr;
+ FlowCache* tcp_cache = nullptr;
+ FlowCache* udp_cache = nullptr;
+ FlowCache* user_cache = nullptr;
+ FlowCache* file_cache = nullptr;
// preallocated arrays
- Flow* ip_mem;
- Flow* icmp_mem;
- Flow* tcp_mem;
- Flow* udp_mem;
- Flow* user_mem;
- Flow* file_mem;
-
- InspectSsnFunc get_ip;
- InspectSsnFunc get_icmp;
- InspectSsnFunc get_tcp;
- InspectSsnFunc get_udp;
- InspectSsnFunc get_user;
- InspectSsnFunc get_file;
-
- class ExpectCache* exp_cache;
- PktType last_pkt_type;
+ Flow* ip_mem = nullptr;
+ Flow* icmp_mem = nullptr;
+ Flow* tcp_mem = nullptr;
+ Flow* udp_mem = nullptr;
+ Flow* user_mem = nullptr;
+ Flow* file_mem = nullptr;
+
+ InspectSsnFunc get_ip = nullptr;
+ InspectSsnFunc get_icmp = nullptr;
+ InspectSsnFunc get_tcp = nullptr;
+ InspectSsnFunc get_udp = nullptr;
+ InspectSsnFunc get_user = nullptr;
+ InspectSsnFunc get_file = nullptr;
+
+ class ExpectCache* exp_cache = nullptr;
+ PktType last_pkt_type = PktType::NONE;
+
+ std::vector<PktType> types;
+ unsigned next = 0;
};
#endif
BitOp* GrpBitOp;
} FLOWBITS_GRP;
+static std::forward_list<const FLOWBITS_OP*> op_list;
+
+static SFGHASH* flowbits_hash = NULL;
static SFGHASH* flowbits_grp_hash = NULL;
+static SF_QUEUE* flowbits_bit_queue = NULL;
-static std::forward_list<const FLOWBITS_OP*> op_list;
+static unsigned flowbits_count = 0;
+static unsigned flowbits_grp_count = 0;
+static int flowbits_toggle = 1;
static int check_flowbits(
uint8_t type, uint8_t evalType, uint16_t* ids, uint16_t num_ids,
// helper methods
//-------------------------------------------------------------------------
+static inline BitOp* get_flow_bitop(const Packet* p)
+{
+ Flow* flow = p->flow;
+
+ if (!flow)
+ return NULL;
+
+ if ( !flow->bitop )
+ flow->bitop = new BitOp(flowbits_count);
+
+ return flow->bitop;
+}
+
static inline int clear_group_bit(BitOp* bitop, char* group)
{
if ( !group )
uint8_t type, uint8_t evalType, uint16_t* ids, uint16_t num_ids, char* group, Packet* p)
{
int rval = DETECTION_OPTION_NO_MATCH;
- BitOp* bitop;
Flowbits_eval eval = (Flowbits_eval)evalType;
int result = 0;
int i;
- bitop = stream.get_flow_bitop(p);
+ BitOp* bitop = get_flow_bitop(p);
+
if (!bitop)
{
- DebugMessage(DEBUG_FLOWBITS, "No FLOWBITS_DATA");
+ assert(false);
return rval;
}
// public methods
//-------------------------------------------------------------------------
-static SFGHASH* flowbits_hash = NULL;
-static SF_QUEUE* flowbits_bit_queue = NULL;
-static uint16_t flowbits_count = 0;
-static uint16_t flowbits_grp_count = 0;
-static int flowbits_toggle = 1;
-
-// FIXIT-P consider allocating flowbits on session on demand instead of
-// preallocating.
-
-unsigned int getFlowbitSize()
-{
- return flowbits_count;
-}
-
-unsigned int getFlowbitSizeInBytes()
-{
- return flowbits_count ? (flowbits_count + 7) >> 3 : 1;
-}
-
void FlowbitResetCounts()
{
SFGHASH_NODE* n;
if ( !flowbits_count )
{
ParseError("The number of flowbit IDs in the current ruleset exceeds "
- "the maximum number of IDs that are allowed (65535).");
+ "the maximum number of IDs that are allowed (%u).", flowbits_count-1);
}
}
if ( !flowbits_hash or !flowbits_grp_hash )
return;
- unsigned size = getFlowbitSizeInBytes();
-
for ( SFGHASH_NODE* n = sfghash_findfirst(flowbits_grp_hash);
n != NULL;
n= sfghash_findnext(flowbits_grp_hash) )
{
FLOWBITS_GRP* fbg = (FLOWBITS_GRP*)n->data;
- fbg->GrpBitOp = new BitOp(size);
+ fbg->GrpBitOp = new BitOp(flowbits_count);
fbg->GrpBitOp->reset();
}
void FlowbitResetCounts();
int FlowBits_SetOperation(void*);
-void setFlowbitSize(unsigned);
-unsigned int getFlowbitSize();
-unsigned int getFlowbitSizeInBytes();
-
#endif
static const PegInfo latency_pegs[] =
{
- { "total_packets", "total packets monitored" },
- { "packet_timeouts", "packets that timed out" },
- { "total_rule_evals", "total rule evals monitored" },
- { "rule_eval_timeouts", "rule evals that timed out" },
- { "rule_tree_enables", "rule tree re-enables" },
+ { "total packets", "total packets monitored" },
+ { "total usecs", "total usecs elapsed" },
+ { "max usecs", "maximum usecs elapsed" },
+ { "packet timeouts", "packets that timed out" },
+ { "total rule evals", "total rule evals monitored" },
+ { "rule eval timeouts", "rule evals that timed out" },
+ { "rule tree enables", "rule tree re-enables" },
{ nullptr, nullptr }
};
struct LatencyStats
{
PegCount total_packets;
+ PegCount total_usecs;
+ PegCount max_usecs;
PegCount packet_timeouts;
PegCount total_rule_evals;
PegCount rule_eval_timeouts;
#include "protocols/packet.h"
#include "sfip/sf_ip.h"
#include "time/clock_defs.h"
+#include "utils/stats.h"
#include "latency_config.h"
#include "latency_timer.h"
#include "catch/catch.hpp"
#endif
+static THREAD_LOCAL uint64_t elapsed = 0;
+
namespace packet_latency
{
// -----------------------------------------------------------------------------
using std::chrono::duration_cast;
using std::chrono::microseconds;
- os << "latency: packet timed out";
+ os << "latency: packet " << pc.total_from_daq << " timed out";
if ( e.fastpathed )
os << " (fastpathed)";
event_handler.handle(e);
}
+ // FIXIT-H this is fugly and inefficient
+ using std::chrono::duration_cast;
+ using std::chrono::microseconds;
+ elapsed = clock_usecs(duration_cast<microseconds>(timer.elapsed()).count());
+
timers.pop_back();
return timed_out;
}
{
if ( packet_latency::get_impl().pop(p) )
++latency_stats.packet_timeouts;
+
+ // FIXIT-L the timer is still running so this max is slightly larger than logged
+ if ( elapsed > latency_stats.max_usecs )
+ latency_stats.max_usecs = elapsed;
+
+ latency_stats.total_usecs += elapsed;
}
}
void Snort::thread_idle()
{
if ( flow_con )
- flow_con->timeout_flows(16384, time(NULL));
+ // FIXIT-M batch here or loop vs looping over idle?
+ flow_con->timeout_flows(time(NULL));
+
perf_monitor_idle_process();
aux_counts.idle++;
HighAvailabilityManager::process_receive();
PacketManager::encode_reset();
if ( flow_con ) // FIXIT-M always instantiate
- {
- flow_con->timeout_flows(4, pkthdr->ts.tv_sec);
- }
+ flow_con->timeout_flows(pkthdr->ts.tv_sec);
HighAvailabilityManager::process_receive();
AppIdSession* AppIdApi::get_appid_data(Flow* flow)
{
- AppIdSession* session = (AppIdSession*) flow->get_application_data(AppIdSession::flow_id);
+ AppIdSession* session = (AppIdSession*) flow->get_flow_data(AppIdSession::flow_id);
return (session && session->common.fsf_type.flow_type == APPID_SESSION_TYPE_NORMAL) ?
session : nullptr;
uint32_t AppIdApi::produce_ha_state(void* lwssn, uint8_t* buf)
{
AppIdSessionHA* appHA = (AppIdSessionHA*)buf;
- AppIdSession* session = (AppIdSession*)(((Flow*)lwssn)->get_application_data(AppIdSession::flow_id));
+ AppIdSession* session = (AppIdSession*)(((Flow*)lwssn)->get_flow_data(AppIdSession::flow_id));
// FIXIT - getFlowType should be a class member
if (session && get_flow_type(session) != APPID_FLOW_TYPE_NORMAL)
AppIdSessionHA* appHA = (AppIdSessionHA*)buf;
if (appHA->flags & APPID_HA_FLAGS_APP)
{
- AppIdSession* session = (AppIdSession*)(((Flow*)lwssn)->get_application_data(
+ AppIdSession* session = (AppIdSession*)(((Flow*)lwssn)->get_flow_data(
AppIdSession::flow_id));
if (!session)
{
session = new AppIdSession(proto, ip);
- ((Flow*)lwssn)->set_application_data(session);
+ ((Flow*)lwssn)->set_flow_data(session);
if (session->serviceAppId == APP_ID_FTP_CONTROL)
{
session->setAppIdFlag(APPID_SESSION_CLIENT_DETECTED |
data->flow = p->flow;
data->stats.firstPktsecond = p->pkth->ts.tv_sec;
- p->flow->set_application_data(data);
+ p->flow->set_flow_data(data);
return data;
}
if( is_packet_ignored(p) )
return;
- AppIdSession* session = (AppIdSession*) p->flow->get_application_data(AppIdSession::flow_id);
+ AppIdSession* session = (AppIdSession*) p->flow->get_flow_data(AppIdSession::flow_id);
if (session)
{
if (session->common.fsf_type.flow_type == APPID_SESSION_TYPE_IGNORE)
APPID_SESSION_BIDIRECTIONAL_CHECKED)
{
// FIXIT-M: This _dpd call needs to be convert to correct snort++ call
- // static THREAD_LOCAL APPID_SESSION_STRUCT_FLAG ignore_fsf {
- // APPID_SESSION_TYPE_IGNORE };
+ // static THREAD_LOCAL APPID_SESSION_STRUCT_FLAG ignore_fsf
+ // { APPID_SESSION_TYPE_IGNORE };
+
+ // p->flow->set_flow_data(PP_APP_ID, &ignore_fsf, nullptr);
- // _dpd.sessionAPI->set_application_data(p->flow, PP_APP_ID, &ignore_fsf,
- // nullptr);
if (app_id_debug_session_flag)
LogMessage("AppIdDbg %s not monitored\n", app_id_debug_session);
}
else
tmp_session->common.initiator_port = 0;
tmp_session->common.policyId = appIdPolicyId;
- p->flow->set_application_data(tmp_session);
+ p->flow->set_flow_data(tmp_session);
if (app_id_debug_session_flag)
LogMessage("AppIdDbg %s unknown monitoring\n", app_id_debug_session);
}
{
}
-void* get_application_data(void*, uint32_t)
+void* get_flow_data(void*, uint32_t)
{
return pAppIdData;
}
-int set_application_data(void*, uint32_t, AppIdSession* data, StreamAppDataFree)
+int set_flow_data(void*, uint32_t, AppIdSession* data, StreamAppDataFree)
{
pAppIdData = data;
// Session APIs
void enable_preproc_all_ports(SnortConfig*, uint32_t appId, uint32_t flags);
-void* get_application_data(void* stream_session, uint32_t protocol);
-int set_application_data(void* scbptr, uint32_t protocol, void* data, StreamAppDataFree);
+void* get_flow_data(void* stream_session, uint32_t protocol);
+int set_flow_data(void* scbptr, uint32_t protocol, void* data, StreamAppDataFree);
uint32_t get_packet_direction(Packet*);
uint32_t get_session_flags(void* ssnptr);
sfaddr_t* get_session_ip_address(void* scbptr, uint32_t direction);
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
-#include "bitop.h"
#include "bnfa_search.h"
#include "acsmx.h"
#include "acsmx2.h"
return retv;
}
-void mpseSetRuleMask(void* pvoid, BITOP* rm)
-{
- MPSE* p = (MPSE*)pvoid;
-
- switch ( p->method )
- {
- default:
- return;
- }
-}
-
int mpsePrintInfo(void* pvoid)
{
MPSE* p = (MPSE*)pvoid;
static void set_service(Flow* flow, const HostAttributeEntry* host)
{
- stream.set_application_protocol_id_from_host_entry(flow, host, FROM_SERVER);
+ stream.set_application_protocol_id(flow, host, FROM_SERVER);
}
static Inspector* get_gadget(Flow* flow)
void ParseError(const char*, ...) { }
void LogMessage(const char*,...) { }
-void Stream::set_application_protocol_id_from_host_entry(Flow*, HostAttributeEntry const*, int) { }
+void Stream::set_application_protocol_id(Flow*, HostAttributeEntry const*, int) { }
void Stream::set_splitter(Flow*, bool, class StreamSplitter*) { }
const char* get_protocol_name(uint16_t) { return ""; }
int16_t FindProtocolReference(const char*) { return 0; }
memset(conf,0,sizeof(SnortConfig));
snort_conf = (SnortConfig*)conf;
Flow* flow = new Flow;
- constexpr size_t offset = offsetof(Flow, appDataList);
+ constexpr size_t offset = offsetof(Flow, flow_data);
memset((uint8_t*)flow+offset, 0, sizeof(Flow)-offset);
s_inspector = new MyInspector();
static ReputationData* SetNewReputationData(Flow* flow)
{
ReputationFlowData* fd = new ReputationFlowData;
- flow->set_application_data(fd);
+ flow->set_flow_data(fd);
return &fd->session;
}
static ReputationData* get_session_data(Flow* flow)
{
- ReputationFlowData* fd = (ReputationFlowData*)flow->get_application_data(
+ ReputationFlowData* fd = (ReputationFlowData*)flow->get_flow_data(
ReputationFlowData::flow_id);
return fd ? &fd->session : nullptr;
THREAD_LOCAL Active::ActiveAction Active::delayed_active_action = Active::ACT_PASS;
THREAD_LOCAL int Active::active_tunnel_bypass = 0;
-THREAD_LOCAL bool Active::active_suspend = 0;
+THREAD_LOCAL bool Active::active_suspend = false;
THREAD_LOCAL uint8_t Active::s_attempts = 0;
THREAD_LOCAL uint64_t Active::s_injects = 0;
DCE2_SmbSsnData* get_dce2_smb_session_data(Flow* flow)
{
- Dce2SmbFlowData* fd = (Dce2SmbFlowData*)flow->get_application_data(
- Dce2SmbFlowData::flow_id);
-
+ Dce2SmbFlowData* fd = (Dce2SmbFlowData*)flow->get_flow_data(Dce2SmbFlowData::flow_id);
return fd ? &fd->dce2_smb_session : nullptr;
}
static DCE2_SmbSsnData* set_new_dce2_smb_session(Packet* p)
{
Dce2SmbFlowData* fd = new Dce2SmbFlowData;
-
memset(&fd->dce2_smb_session,0,sizeof(DCE2_SmbSsnData));
- p->flow->set_application_data(fd);
+ p->flow->set_flow_data(fd);
return(&fd->dce2_smb_session);
}
DCE2_TcpSsnData* get_dce2_tcp_session_data(Flow* flow)
{
- Dce2TcpFlowData* fd = (Dce2TcpFlowData*)flow->get_application_data(
- Dce2TcpFlowData::flow_id);
-
+ Dce2TcpFlowData* fd = (Dce2TcpFlowData*)flow->get_flow_data(Dce2TcpFlowData::flow_id);
return fd ? &fd->dce2_tcp_session : nullptr;
}
Dce2TcpFlowData* fd = new Dce2TcpFlowData;
memset(&fd->dce2_tcp_session,0,sizeof(DCE2_TcpSsnData));
- p->flow->set_application_data(fd);
+ p->flow->set_flow_data(fd);
return(&fd->dce2_tcp_session);
}
static dnp3_session_data_t* get_session_data(Flow* flow)
{
- Dnp3FlowData* fd = (Dnp3FlowData*)flow->get_application_data(
- Dnp3FlowData::flow_id);
-
+ Dnp3FlowData* fd = (Dnp3FlowData*)flow->get_flow_data(Dnp3FlowData::flow_id);
return fd ? &fd->dnp3_session : nullptr;
}
static dnp3_session_data_t* set_new_dnp3_session(Packet* p)
{
Dnp3FlowData* fd = new Dnp3FlowData;
-
- p->flow->set_application_data(fd);
+ p->flow->set_flow_data(fd);
return(&fd->dnp3_session);
}
if ((p->has_tcp_data() && !p->is_full_pdu()) || !p->flow || !p->dsize)
return DETECTION_OPTION_NO_MATCH;
- Dnp3FlowData* fd = (Dnp3FlowData*)p->flow->get_application_data(
- Dnp3FlowData::flow_id);
+ Dnp3FlowData* fd = (Dnp3FlowData*)p->flow->get_flow_data(Dnp3FlowData::flow_id);
if (!fd)
return DETECTION_OPTION_NO_MATCH;
if ((p->has_tcp_data() && !p->is_full_pdu()) || !p->flow || !p->dsize)
return DETECTION_OPTION_NO_MATCH;
- Dnp3FlowData* fd = (Dnp3FlowData*)p->flow->get_application_data(
- Dnp3FlowData::flow_id);
+ Dnp3FlowData* fd = (Dnp3FlowData*)p->flow->get_flow_data(Dnp3FlowData::flow_id);
if (!fd)
return DETECTION_OPTION_NO_MATCH;
if ((p->has_tcp_data() && !p->is_full_pdu()) || !p->flow || !p->dsize)
return DETECTION_OPTION_NO_MATCH;
- Dnp3FlowData* fd = (Dnp3FlowData*)p->flow->get_application_data(
- Dnp3FlowData::flow_id);
+ Dnp3FlowData* fd = (Dnp3FlowData*)p->flow->get_flow_data(Dnp3FlowData::flow_id);
if (!fd)
return DETECTION_OPTION_NO_MATCH;
if ((p->has_tcp_data() && !p->is_full_pdu()) || !p->flow || !p->dsize)
return DETECTION_OPTION_NO_MATCH;
- Dnp3FlowData* fd = (Dnp3FlowData*)p->flow->get_application_data(
- Dnp3FlowData::flow_id);
+ Dnp3FlowData* fd = (Dnp3FlowData*)p->flow->get_flow_data(Dnp3FlowData::flow_id);
if (!fd)
return DETECTION_OPTION_NO_MATCH;
fd = new DnsFlowData;
- p->flow->set_application_data(fd);
+ p->flow->set_flow_data(fd);
return &fd->session;
}
return &udpSessionData;
}
- fd = (DnsFlowData*)((p->flow)->get_application_data(
- DnsFlowData::flow_id));
-
+ fd = (DnsFlowData*)((p->flow)->get_flow_data(DnsFlowData::flow_id));
return fd ? &fd->session : NULL;
}
if (p->flow)
{
- FtpFlowData* fd = (FtpFlowData*)p->flow->get_application_data(FtpFlowData::flow_id);
+ FtpFlowData* fd = (FtpFlowData*)p->flow->get_flow_data(FtpFlowData::flow_id);
ft_ssn = fd ? &fd->session.ft_ssn : nullptr;
if (ft_ssn != NULL)
{
/* XXX - Not FTP or Telnet */
assert(false);
- p->flow->free_application_data(FtpFlowData::flow_id);
+ p->flow->free_flow_data(FtpFlowData::flow_id);
return 0;
}
}
return -1;
FtpDataFlowData* fd = (FtpDataFlowData*)
- p->flow->get_application_data(FtpFlowData::flow_id);
+ p->flow->get_flow_data(FtpFlowData::flow_id);
FTP_DATA_SESSION* data_ssn = fd ? &fd->session : nullptr;
/* FTP-Data session is in limbo, we need to lookup the control session
* to figure out what to do. */
- FtpFlowData* fd = (FtpFlowData*)stream.get_application_data_from_key(
+ FtpFlowData* fd = (FtpFlowData*)stream.get_flow_data(
&data_ssn->ftp_key, FtpFlowData::flow_id);
FTP_SESSION* ftp_ssn = fd ? &fd->session : NULL;
SiInput->pproto = FTPP_SI_PROTO_TELNET;
- p->flow->set_application_data(fd);
+ p->flow->set_flow_data(fd);
*Telnetsession = Newsession;
return FTPP_SUCCESS;
Newsession->client_conf = ClientConf;
Newsession->server_conf = ServerConf;
- p->flow->set_application_data(fd);
+ p->flow->set_flow_data(fd);
*Ftpsession = Newsession;
SiInput->pproto = FTPP_SI_PROTO_FTP;
if (p->flow)
{
TelnetFlowData* fd = (TelnetFlowData*)
- p->flow->get_application_data(FtpFlowData::flow_id);
+ p->flow->get_flow_data(FtpFlowData::flow_id);
ft_ssn = fd ? &fd->session.ft_ssn : nullptr;
else
{
assert(false);
- p->flow->free_application_data(FtpFlowData::flow_id);
+ p->flow->free_flow_data(FtpFlowData::flow_id);
return 0;
}
}
static GTP_Roptions* GTPGetNewSession(Packet* packetp)
{
GtpFlowData* gfd = new GtpFlowData;
- packetp->flow->set_application_data(gfd);
+ packetp->flow->set_flow_data(gfd);
GTP_Roptions* pRopts = &gfd->ropts;
gtp_stats.sessions++;
void GTPmain(Packet* packetp)
{
/* Attempt to get a previously allocated GTP block. */
- GtpFlowData* gfd = (GtpFlowData*)packetp->flow->get_application_data(GtpFlowData::flow_id);
+ GtpFlowData* gfd = (GtpFlowData*)packetp->flow->get_flow_data(GtpFlowData::flow_id);
GTP_Roptions* pRopts = gfd ? &gfd->ropts : nullptr;
if ( !pRopts )
if ( !p or !p->flow )
return DETECTION_OPTION_NO_MATCH;
- GtpFlowData* gfd = (GtpFlowData*)p->flow->get_application_data(GtpFlowData::flow_id);
+ GtpFlowData* gfd = (GtpFlowData*)p->flow->get_flow_data(GtpFlowData::flow_id);
if ( !gfd or !gfd->ropts.gtp_infoElements )
return DETECTION_OPTION_NO_MATCH;
if ( !p or !p->flow )
return DETECTION_OPTION_NO_MATCH;
- GtpFlowData* gfd = (GtpFlowData*)p->flow->get_application_data(GtpFlowData::flow_id);
+ GtpFlowData* gfd = (GtpFlowData*)p->flow->get_flow_data(GtpFlowData::flow_id);
if ( !gfd )
return DETECTION_OPTION_NO_MATCH;
if ( !p or !p->flow )
return DETECTION_OPTION_NO_MATCH;
- GtpFlowData* gfd = (GtpFlowData*)p->flow->get_application_data(GtpFlowData::flow_id);
+ GtpFlowData* gfd = (GtpFlowData*)p->flow->get_flow_data(GtpFlowData::flow_id);
if ( gfd and version == gfd->ropts.gtp_version )
return DETECTION_OPTION_MATCH;
const Field& HttpInspect::process(const uint8_t* data, const uint16_t dsize, Flow* const flow,
SourceId source_id, bool buf_owner) const
{
- HttpFlowData* session_data = (HttpFlowData*)flow->get_application_data(
- HttpFlowData::http_flow_id);
+ HttpFlowData* session_data = (HttpFlowData*)flow->get_flow_data(HttpFlowData::http_flow_id);
assert(session_data != nullptr);
HttpModule::increment_peg_counts(PEG_INSPECT);
latest_section = nullptr;
HttpFlowData* session_data =
- (HttpFlowData*)p->flow->get_application_data(HttpFlowData::http_flow_id);
+ (HttpFlowData*)p->flow->get_flow_data(HttpFlowData::http_flow_id);
if (session_data == nullptr)
return;
assert(total <= MAX_OCTETS);
- HttpFlowData* session_data = (HttpFlowData*)flow->get_application_data(
- HttpFlowData::http_flow_id);
+ HttpFlowData* session_data = (HttpFlowData*)flow->get_flow_data(HttpFlowData::http_flow_id);
assert(session_data != nullptr);
#ifdef REG_TEST
// This is the session state information we share with HttpInspect and store with stream. A
// session is defined by a TCP connection. Since scan() is the first to see a new TCP
// connection the new flow data object is created here.
- HttpFlowData* session_data = (HttpFlowData*)flow->get_application_data(
- HttpFlowData::http_flow_id);
+ HttpFlowData* session_data = (HttpFlowData*)flow->get_flow_data(HttpFlowData::http_flow_id);
+
if (session_data == nullptr)
{
- flow->set_application_data(session_data = new HttpFlowData);
+ flow->set_flow_data(session_data = new HttpFlowData);
HttpModule::increment_peg_counts(PEG_FLOW);
}
bool HttpStreamSplitter::finish(Flow* flow)
{
- HttpFlowData* session_data = (HttpFlowData*)flow->get_application_data(
- HttpFlowData::http_flow_id);
-
+ HttpFlowData* session_data = (HttpFlowData*)flow->get_flow_data(HttpFlowData::http_flow_id);
assert(session_data != nullptr);
#ifdef REG_TEST
unsigned ImapFlowData::flow_id = 0;
static IMAPData* get_session_data(Flow* flow)
{
- ImapFlowData* fd = (ImapFlowData*)flow->get_application_data(
- ImapFlowData::flow_id);
-
+ ImapFlowData* fd = (ImapFlowData*)flow->get_flow_data(ImapFlowData::flow_id);
return fd ? &fd->session : NULL;
}
IMAPData* imap_ssn;
ImapFlowData* fd = new ImapFlowData;
- p->flow->set_application_data(fd);
+ p->flow->set_flow_data(fd);
imap_ssn = &fd->session;
imapstats.sessions++;
return DETECTION_OPTION_NO_MATCH;
ModbusFlowData* mfd =
- (ModbusFlowData*)p->flow->get_application_data(ModbusFlowData::flow_id);
+ (ModbusFlowData*)p->flow->get_flow_data(ModbusFlowData::flow_id);
if ( mfd and func == mfd->ssn_data.func )
return DETECTION_OPTION_MATCH;
return DETECTION_OPTION_NO_MATCH;
ModbusFlowData* mfd =
- (ModbusFlowData*)p->flow->get_application_data(ModbusFlowData::flow_id);
+ (ModbusFlowData*)p->flow->get_flow_data(ModbusFlowData::flow_id);
if ( mfd and unit == mfd->ssn_data.unit )
return DETECTION_OPTION_MATCH;
assert(p->has_tcp_data());
ModbusFlowData* mfd =
- (ModbusFlowData*)p->flow->get_application_data(ModbusFlowData::flow_id);
+ (ModbusFlowData*)p->flow->get_flow_data(ModbusFlowData::flow_id);
if ( !p->is_full_pdu() )
{
if ( !mfd )
{
mfd = new ModbusFlowData;
- p->flow->set_application_data(mfd);
+ p->flow->set_flow_data(mfd);
modbus_stats.sessions++;
}
return false;
ModbusFlowData* mfd =
- (ModbusFlowData*)p->flow->get_application_data(ModbusFlowData::flow_id);
+ (ModbusFlowData*)p->flow->get_flow_data(ModbusFlowData::flow_id);
/* Lay the header struct over the payload */
header = (modbus_header_t*)p->data;
unsigned PopFlowData::flow_id = 0;
static POPData* get_session_data(Flow* flow)
{
- PopFlowData* fd = (PopFlowData*)flow->get_application_data(
- PopFlowData::flow_id);
-
+ PopFlowData* fd = (PopFlowData*)flow->get_flow_data(PopFlowData::flow_id);
return fd ? &fd->session : NULL;
}
POPData* pop_ssn;
PopFlowData* fd = new PopFlowData;
- p->flow->set_application_data(fd);
+ p->flow->set_flow_data(fd);
pop_ssn = &fd->session;
popstats.sessions++;
RpcSsnData* rsdata = &fd->session;
rsdata->active = 1;
- p->flow->set_application_data(fd);
+ p->flow->set_flow_data(fd);
DebugFormat(DEBUG_RPC, "STATEFUL: Created new session: " "%p\n", (void*) rsdata);
return rsdata;
if ( p->flow )
{
- RpcFlowData* fd = (RpcFlowData*)p->flow->get_application_data(
- RpcFlowData::flow_id);
+ RpcFlowData* fd = (RpcFlowData*)p->flow->get_flow_data(RpcFlowData::flow_id);
if ( fd )
rsdata = &fd->session;
MaxSessionsAlerted = 0;
}
SipFlowData* fd = new SipFlowData;
- p->flow->set_application_data(fd);
+ p->flow->set_flow_data(fd);
numSessions++;
return &fd->session;
}
SIPData* get_sip_session_data(Flow* flow)
{
- SipFlowData* fd = (SipFlowData*)flow->get_application_data(
- SipFlowData::flow_id);
-
+ SipFlowData* fd = (SipFlowData*)flow->get_flow_data(SipFlowData::flow_id);
return fd ? &fd->session : NULL;
}
sfip_to_str(&mdataB->maddress), mdataB->mport);
/* Call into Streams to mark data channel as something to ignore. */
- FlowData* fd = stream.get_application_data_from_ip_port(
+ FlowData* fd = stream.get_flow_data(
PktType::UDP, IpProtocol::UDP, &mdataA->maddress,mdataA->mport,
&mdataB->maddress, mdataB->mport, 0, 0, p->pkth->address_space_id,
SipFlowData::flow_id);
unsigned SmtpFlowData::flow_id = 0;
static SMTPData* get_session_data(Flow* flow)
{
- SmtpFlowData* fd = (SmtpFlowData*)flow->get_application_data(
- SmtpFlowData::flow_id);
-
+ SmtpFlowData* fd = (SmtpFlowData*)flow->get_flow_data(SmtpFlowData::flow_id);
return fd ? &fd->session : NULL;
}
SMTPData* smtp_ssn;
SmtpFlowData* fd = new SmtpFlowData;
- p->flow->set_application_data(fd);
+ p->flow->set_flow_data(fd);
smtp_ssn = &fd->session;
smtpstats.sessions++;
static SSHData* SetNewSSHData(Packet* p)
{
SshFlowData* fd = new SshFlowData;
- p->flow->set_application_data(fd);
+ p->flow->set_flow_data(fd);
return &fd->session;
}
static SSHData* get_session_data(Flow* flow)
{
- SshFlowData* fd = (SshFlowData*)flow->get_application_data(
- SshFlowData::flow_id);
-
+ SshFlowData* fd = (SshFlowData*)flow->get_flow_data(SshFlowData::flow_id);
return fd ? &fd->session : NULL;
}
static SSLData* SetNewSSLData(Packet* p)
{
SslFlowData* fd = new SslFlowData;
- p->flow->set_application_data(fd);
+ p->flow->set_flow_data(fd);
return &fd->session;
}
SSLData* get_ssl_session_data(Flow* flow)
{
- SslFlowData* fd = (SslFlowData*)flow->get_application_data(
- SslFlowData::flow_id);
-
+ SslFlowData* fd = (SslFlowData*)flow->get_flow_data(SslFlowData::flow_id);
return fd ? &fd->session : NULL;
}
switch ( p->type() )
{
case PktType::IP:
- if ( p->has_ip() )
+ if ( p->has_ip() and
+ ((p->ptrs.decode_flags & DECODE_FRAG) or !config->ip_frags_only) )
flow_con->process_ip(p);
break;
{ "idle_timeout", Parameter::PT_INT, "1:", idle, \
"maximum inactive time before retiring session tracker" }, \
\
- { "cleanup_pct", Parameter::PT_INT, "1:100", cleanup, \
- "percent of cache to clean when max_sessions is reached" }, \
-\
{ nullptr, Parameter::PT_MAX, nullptr, nullptr, nullptr } \
}
CACHE_PARAMS(ip_params, "16384", "30", "180", "5");
-CACHE_PARAMS(icmp_params, "32768", "30", "180", "5");
-CACHE_PARAMS(tcp_params, "131072", "30", "180", "5");
-CACHE_PARAMS(udp_params, "65536", "30", "180", "5");
+CACHE_PARAMS(icmp_params, "65536", "30", "180", "5");
+CACHE_PARAMS(tcp_params, "262144", "30", "180", "5");
+CACHE_PARAMS(udp_params, "131072", "30", "180", "5");
CACHE_PARAMS(user_params, "1024", "30", "180", "5");
CACHE_PARAMS(file_params, "128", "30", "180", "5");
static const Parameter s_params[] =
{
+ { "ip_frags_only", Parameter::PT_BOOL, nullptr, "false",
+ "don't process non-frag flows" },
+
CACHE_TABLE("ip_cache", "ip", ip_params),
CACHE_TABLE("icmp_cache", "icmp", icmp_params),
CACHE_TABLE("tcp_cache", "tcp", tcp_params),
{
FlowConfig* fc = nullptr;
- if ( strstr(fqn, "ip_cache") )
+ if ( v.is("ip_frags_only") )
+ {
+ config.ip_frags_only = v.get_bool();
+ return true;
+ }
+ else if ( strstr(fqn, "ip_cache") )
fc = &config.ip_cfg;
else if ( strstr(fqn, "icmp_cache") )
else if ( v.is("idle_timeout") )
fc->nominal_timeout = v.get_long();
- else if ( v.is("cleanup_pct") )
- fc->cleanup_pct = v.get_long();
-
else
return false;
FlowConfig udp_cfg;
FlowConfig user_cfg;
FlowConfig file_cfg;
+ bool ip_frags_only;
};
class StreamModule : public Module
{
if (ssn->ssn_state.session_flags & SSNFLAG_PRUNED)
icmpStats.prunes++;
+
else if (ssn->ssn_state.session_flags & SSNFLAG_TIMEDOUT)
icmpStats.timeouts++;
if ( lws->ssn_state.session_flags & SSNFLAG_TIMEDOUT )
ip_stats.timeouts++;
- else if ( lws->ssn_state.session_flags & SSNFLAG_PRUNED )
- ip_stats.prunes++;
- if ( lws->ssn_state.session_flags & SSNFLAG_TIMEDOUT )
- ip_stats.timeouts++;
else if ( lws->ssn_state.session_flags & SSNFLAG_PRUNED )
ip_stats.prunes++;
void SwapPacketHeaderFoo();
virtual void update_perf_base_state(char) { }
- virtual void clear_session(bool free_flow_data, bool flush_segments, bool restart, Packet* p = nullptr) = 0;
+ virtual void clear_session(
+ bool free_flow_data, bool flush_segments, bool restart, Packet* p = nullptr) = 0;
// FIXIT-L these 2 function names convey no meaning afaict... figure out
// why are they called and name appropriately...
virtual void flush() { }
- virtual TcpStreamTracker::TcpState get_talker_state() { return TcpStreamTracker::TCP_MAX_STATES; }
- virtual TcpStreamTracker::TcpState get_listener_state() { return TcpStreamTracker::TCP_MAX_STATES; }
+ virtual TcpStreamTracker::TcpState get_talker_state()
+ { return TcpStreamTracker::TCP_MAX_STATES; }
+
+ virtual TcpStreamTracker::TcpState get_listener_state()
+ { return TcpStreamTracker::TCP_MAX_STATES; }
+
virtual void init_new_tcp_session(TcpSegmentDescriptor&);
virtual void update_timestamp_tracking(TcpSegmentDescriptor&) { }
virtual void update_session_on_syn_ack();
}
void set_pkt_action_flag(uint32_t flag)
- {
- pkt_action_mask |= flag;
- }
+ { pkt_action_mask |= flag; }
virtual void update_paws_timestamps(TcpSegmentDescriptor&) { }
virtual void check_for_repeated_syn(TcpSegmentDescriptor&) { }
#include "main/snort_config.h"
#include "main/snort_debug.h"
#include "main/snort_debug.h"
-#include "utils/util.h"
#include "flow/flow_control.h"
#include "flow/flow_cache.h"
#include "flow/ha.h"
#include "protocols/vlan.h"
#include "target_based/snort_protocols.h"
#include "target_based/sftarget_hostentry.h"
+#include "utils/bitop.h"
+#include "utils/util.h"
#ifdef UNIT_TEST
#include "catch/catch.hpp"
// key foo
//-------------------------------------------------------------------------
-Flow* Stream::get_session_ptr_from_ip_port(
+Flow* Stream::get_session_ptr(
PktType type, IpProtocol proto,
const sfip_t* srcIP, uint16_t srcPort,
const sfip_t* dstIP, uint16_t dstPort,
// app data foo
//-------------------------------------------------------------------------
-FlowData* Stream::get_application_data_from_key(
+FlowData* Stream::get_flow_data(
const FlowKey* key, unsigned flow_id)
{
Flow* flow = get_session(key);
- return flow->get_application_data(flow_id);
+ return flow->get_flow_data(flow_id);
}
-FlowData* Stream::get_application_data_from_ip_port(
+FlowData* Stream::get_flow_data(
PktType type, IpProtocol proto,
const sfip_t* srcIP, uint16_t srcPort,
const sfip_t* dstIP, uint16_t dstPort,
{
Flow* flow;
- flow = get_session_ptr_from_ip_port(
+ flow = get_session_ptr(
type, proto,
srcIP, srcPort, dstIP, dstPort,
vlan, mplsId, addressSpaceID);
if (!flow)
return NULL;
- return flow->get_application_data(flow_id);
+ return flow->get_flow_data(flow_id);
}
//-------------------------------------------------------------------------
// misc support
//-------------------------------------------------------------------------
-BitOp* Stream::get_flow_bitop(const Packet* p)
-{
- Flow* flow = p->flow;
-
- if (!flow)
- return NULL;
-
- return flow->bitop;
-}
-
void Stream::init_active_response(const Packet* p, Flow* flow)
{
if ( !flow )
srcIP, srcPort, dstIP, dstPort, protocol, appId, fd);
}
-void Stream::set_application_protocol_id_from_host_entry(
+void Stream::set_application_protocol_id(
Flow* flow, const HostAttributeEntry* host_entry, int /*direction*/)
{
int16_t application_protocol;
host_entry = SFAT_LookupHostEntryByIP(&flow->server_ip);
if (host_entry)
{
- set_application_protocol_id_from_host_entry(flow, host_entry, FROM_SERVER);
+ set_application_protocol_id(flow, host_entry, FROM_SERVER);
if (flow->ssn_state.application_protocol != 0)
{
host_entry = SFAT_LookupHostEntryByIP(&flow->client_ip);
if (host_entry)
{
- set_application_protocol_id_from_host_entry(flow, host_entry, FROM_CLIENT);
+ set_application_protocol_id(flow, host_entry, FROM_CLIENT);
if (flow->ssn_state.application_protocol != 0)
{
else
lwssn->session_state |= STREAM_STATE_DROP_SERVER;
- if ( (lwssn->response_count < max) && lwssn->get_expire(p) )
+ if ( (lwssn->response_count < max) && lwssn->expired(p) )
{
uint32_t delay = snort_conf->min_interval;
EncodeFlags flags =
return false;
}
-static int StreamExpireSession(Flow* lwssn)
+static int StreamExpire(Packet* p, Flow* lwssn)
{
+ if ( !lwssn->expired(p) )
+ return 0;
+
if ( HighAvailabilityManager::in_standby(lwssn) )
return 1;
return 1;
}
-static int StreamExpire(Packet* p, Flow* lwssn)
-{
- if ( lwssn->expired(p) )
- {
- /* Expiration time has passed. */
- return StreamExpireSession(lwssn);
- }
-
- return 0;
-}
-
bool Stream::expired_session(Flow* flow, Packet* p)
{
if ( (flow->session_state & STREAM_STATE_TIMEDOUT)
Flow*, Packet* p, uint32_t gid, uint32_t sid,
uint32_t eventId, uint32_t eventSecond);
- // Get pointer to Flowbits data
- static BitOp* get_flow_bitop(const Packet*);
-
// Get reassembly direction for given session
static char get_reassembly_direction(Flow*);
// Get pointer to application data for a flow based on the lookup tuples for cases where
// Snort does not have an active packet that is relevant.
- static FlowData* get_application_data_from_ip_port(
+ static FlowData* get_flow_data(
PktType type, IpProtocol proto,
const sfip_t *a1, uint16_t p1, const sfip_t *a2, uint16_t p2,
uint16_t vlanId, uint32_t mplsId, uint16_t addrSpaceId, unsigned flow_id);
// Get pointer to application data for a flow using the FlowKey as the lookup criteria
- static FlowData* get_application_data_from_key(const FlowKey*, unsigned flow_id);
+ static FlowData* get_flow_data(const FlowKey*, unsigned flow_id);
// -- extra data methods
uint32_t reg_xtra_data_cb(LogFunction);
// Get pointer to a session flow instance for a flow based on the lookup tuples for
// cases where Snort does not have an active packet that is relevant.
- static Flow* get_session_ptr_from_ip_port(
+ static Flow* get_session_ptr(
PktType type, IpProtocol proto,
const sfip_t *a1, uint16_t p1, const sfip_t *a2, uint16_t p2,
uint16_t vlanId, uint32_t mplsId, uint16_t addrSpaceId);
void update_direction(Flow*, char dir, const sfip_t* ip, uint16_t port);
- static void set_application_protocol_id_from_host_entry(
+ static void set_application_protocol_id(
Flow*, const struct HostAttributeEntry*, int direction);
static bool is_midstream(Flow* flow)
{
if ( client->reassembler )
{
- if( flush_segments )
+ if ( flush_segments )
client->reassembler->flush_queued_segments(flow, true, p);
client->reassembler->purge_segment_list();
}
if ( server->reassembler )
{
- if( flush_segments )
+ if ( flush_segments )
server->reassembler->flush_queued_segments(flow, true, p);
server->reassembler->purge_segment_list();
}
else
return;
- if (flow->get_session_flags() & SSNFLAG_PRUNED)
+ if ( flow->get_session_flags() & SSNFLAG_PRUNED )
tcpStats.prunes++;
- else if (flow->get_session_flags() & SSNFLAG_TIMEDOUT)
+
+ else if ( flow->get_session_flags() & SSNFLAG_TIMEDOUT )
tcpStats.timeouts++;
update_perf_base_state(TcpStreamTracker::TCP_CLOSED);
- if( restart )
+ if ( restart )
{
flow->restart(free_flow_data);
paf_reset(&client->paf_state);
if ( ( session_flags & SSNFLAG_COUNTED_INITIALIZE )
&& !( session_flags & SSNFLAG_COUNTED_CLOSING ) )
{
- assert(tcpStats.sessions_initializing);
- tcpStats.sessions_initializing--;
+ //assert(tcpStats.sessions_initializing);
+ if ( tcpStats.sessions_initializing ) // FIXIT-L eliminate / fix underflow
+ tcpStats.sessions_initializing--;
}
}
break;
if ( session_flags & SSNFLAG_COUNTED_ESTABLISH )
{
- assert(tcpStats.sessions_established);
+ //assert(tcpStats.sessions_established);
tcpStats.sessions_established--;
if (perfmon_config && (perfmon_config->perf_flags & PERF_FLOWIP))
}
else if ( session_flags & SSNFLAG_COUNTED_INITIALIZE )
{
- assert(tcpStats.sessions_initializing);
- tcpStats.sessions_initializing--;
+ //assert(tcpStats.sessions_initializing);
+ if ( tcpStats.sessions_initializing ) // FIXIT-L eliminate / fix underflow
+ tcpStats.sessions_initializing--;
}
}
break;
case TcpStreamTracker::TCP_CLOSED:
if ( session_flags & SSNFLAG_COUNTED_CLOSING )
{
- assert(tcpStats.sessions_closing);
+ //assert(tcpStats.sessions_closing);
tcpStats.sessions_closing--;
}
else if ( session_flags & SSNFLAG_COUNTED_ESTABLISH )
{
- assert(tcpStats.sessions_established);
- tcpStats.sessions_established--;
+ //assert(tcpStats.sessions_established);
+ if ( tcpStats.sessions_established ) // FIXIT-L eliminate / fix underflow
+ tcpStats.sessions_established--;
if ( perfmon_config && ( perfmon_config->perf_flags & PERF_FLOWIP ) )
perf_flow_ip->update_state(&flow->client_ip,
}
else if ( session_flags & SSNFLAG_COUNTED_INITIALIZE )
{
- assert(tcpStats.sessions_initializing);
- tcpStats.sessions_initializing--;
+ //assert(tcpStats.sessions_initializing);
+ if ( tcpStats.sessions_initializing ) // FIXIT-L eliminate / fix underflow
+ tcpStats.sessions_initializing--;
}
break;
flush_talker(tsd.get_pkt());
set_splitter(true, nullptr);
set_splitter(false, nullptr);
- flow->free_application_data();
+ flow->free_flow_data();
}
talker->update_on_rst_sent( );
void TcpSession::check_for_repeated_syn(TcpSegmentDescriptor& tsd)
{
uint32_t action = ACTION_NOTHING;
- if (!SEQ_EQ(tsd.get_seg_seq(), talker->get_iss())
- && listener->normalizer->packet_dropper(tsd, NORM_TCP_BLOCK))
+
+ if ( !SEQ_EQ(tsd.get_seg_seq(), talker->get_iss()) and
+ listener->normalizer->packet_dropper(tsd, NORM_TCP_BLOCK) )
+ {
action = ACTION_BAD_PKT;
- else if (talker->get_tcp_state() >= TcpStreamTracker::TCP_ESTABLISHED)
+ }
+ else if ( talker->get_tcp_state() >= TcpStreamTracker::TCP_ESTABLISHED and
+ talker->get_tcp_state() < TcpStreamTracker::TCP_CLOSED )
+ {
action = listener->normalizer->handle_repeated_syn(tsd);
-
+ }
if (action != ACTION_NOTHING)
{
/* got a bad SYN on the session, alert! */
if ( trk.update_on_rst_recv(tsd) )
{
trk.session->update_session_on_rst(tsd, false);
- trk.session->update_perf_base_state(TcpStreamTracker::TCP_CLOSING);
+ trk.set_tcp_state(TcpStreamTracker::TCP_CLOSED);
+ trk.session->update_perf_base_state(TcpStreamTracker::TCP_CLOSED);
trk.session->set_pkt_action_flag(ACTION_RST);
+ tsd.get_pkt()->flow->session_state |= STREAM_STATE_CLOSED;
}
else
{
{
if (lwssn->ssn_state.session_flags & SSNFLAG_PRUNED)
udpStats.prunes++;
+
else if (lwssn->ssn_state.session_flags & SSNFLAG_TIMEDOUT)
udpStats.timeouts++;
UdpSessionCleanup(flow);
flow->restart();
flow->ssn_state.session_flags |= SSNFLAG_SEEN_SENDER;
- udpStats.created++; // FIXIT-M is this correct? will mess with calc of current sessions
- udpStats.timeouts++;
+ udpStats.created++;
UdpHAManager::process_deletion(flow);
}
// -----------------------------------------------------------------------------
inline BitOp::BitOp(size_t len) :
- bit_buf(new uint8_t[len]()), buf_size(len)
-{ }
+ buf_size(len ? (len + 7) >> 3 : 1)
+{
+ bit_buf = new uint8_t[len]();
+}
inline BitOp::~BitOp()
{ delete[] bit_buf; }
inline uint8_t BitOp::mask(size_t bit) const
{ return (uint8_t)(0x80 >> (bit & 7)); }
-// FIXIT-L ops that don't need to be inlined can probably be put into a .cc file
// Reset the bit buffer so that it can be reused
inline void BitOp::reset()
{ memset(bit_buf, 0, buf_size); }
TEST_CASE( "bitop", "[bitop]" )
{
- BitOp bitop(3);
+ BitOp bitop(24);
SECTION( "zero-initialized" )
{