// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
//--------------------------------------------------------------------------
-// cisco_meta_data_test.cc author Sunirmal Mukherjee <sunimukh@cisco.com>
+// cisco_meta_data_test.cc author Sunirmal Mukherjee <sunimukh@cisco.com>
// unit test main
#ifdef HAVE_CONFIG_H
lyr.start = hdr_start;
lyr.length = (uint16_t)len;
}
-
+
TEST_GROUP(cisco_meta_data_test)
{
};
uint8_t * cmd_data;
int len;
int sgt;
-
+
pkt.num_layers = 0;
pkt.layers = &layers;
- cmd_data = new uint8_t[sizeof(cisco_meta_data::CiscoMetaDataHdr) + sizeof(cisco_meta_data::CiscoMetaDataOpt)];
+ cmd_data = new uint8_t[sizeof(cisco_meta_data::CiscoMetaDataHdr) +
+ sizeof(cisco_meta_data::CiscoMetaDataOpt)];
cisco_meta_data::CiscoMetaDataOpt* cmd_options =
- reinterpret_cast<cisco_meta_data::CiscoMetaDataOpt*>(cmd_data + sizeof(cisco_meta_data::CiscoMetaDataHdr));
+ reinterpret_cast<cisco_meta_data::CiscoMetaDataOpt*>(cmd_data +
+ sizeof(cisco_meta_data::CiscoMetaDataHdr));
+
cmd_options->sgt = 512;
len = (sizeof(cisco_meta_data::CiscoMetaDataHdr) + sizeof(cisco_meta_data::CiscoMetaDataOpt));
pc.log_pkts++;
OutputSet* idx = head ? head->LogList : nullptr;
- EventManager::call_loggers(idx, p, otn->sigInfo.message, &event);
+ EventManager::call_loggers(idx, p, otn->sigInfo.message.c_str(), &event);
}
void CallAlertFuncs(Packet* p, const OptTreeNode* otn, ListHead* head)
#endif
OutputSet* idx = head ? head->AlertList : nullptr;
- EventManager::call_alerters(idx, p, otn->sigInfo.message, event);
+ EventManager::call_alerters(idx, p, otn->sigInfo.message.c_str(), event);
}
/*
if ( snort_protocol_id != UNKNOWN_PROTOCOL_ID )
{
- auto sig_info = otn->sigInfo;
+ const auto& sig_info = otn->sigInfo;
- for ( unsigned svc_idx = 0; svc_idx < sig_info.num_services; ++svc_idx )
+ for ( const auto& svc : sig_info.services )
{
- if ( snort_protocol_id == sig_info.services[svc_idx].snort_protocol_id )
+ if ( snort_protocol_id == svc.snort_protocol_id )
{
check_ports = 0;
break; // out of for
}
}
- if ( sig_info.num_services and check_ports )
+ if ( !sig_info.services.empty() and check_ports )
{
- // none of the services match
trace_logf(detection, TRACE_RULE_EVAL,
- "SID %u not matched because of service mismatch %d!=%d \n",
- sig_info.sid, snort_protocol_id, sig_info.services[0].snort_protocol_id);
+ "SID %u not matched because of service mismatch %d\n",
+ sig_info.sid, snort_protocol_id);
break; // out of case
}
}
}
}
- if ( best.pmd and best.cat != CAT_SET_RAW and !srvc and otn->sigInfo.num_services > 0 )
+ if ( best.pmd and best.cat != CAT_SET_RAW and !srvc and !otn->sigInfo.services.empty() )
{
pmds.clear(); // just include in service group
exclude = true;
if ( !rtn->enabled() )
continue;
- for (unsigned svc_idx = 0; svc_idx < otn->sigInfo.num_services; svc_idx++)
+ for ( const auto& svc : otn->sigInfo.services )
{
- const char* svc = otn->sigInfo.services[svc_idx].service;
- ServiceMapAddOtn(sc->srmmTable, rtn->snort_protocol_id, svc, otn);
+ const char* s = svc.service.c_str();
+ ServiceMapAddOtn(sc->srmmTable, rtn->snort_protocol_id, s, otn);
}
}
}
#endif
#include <cassert>
+#include <iostream>
#include "signature.h"
using namespace snort;
-/********************** Reference System Implementation ***********************/
+//--------------------------------------------------------------------------
+// reference systems
+//--------------------------------------------------------------------------
-ReferenceSystemNode* ReferenceSystemAdd(
- SnortConfig* sc, const char* name, const char* url)
+const ReferenceSystem* reference_system_add(
+ SnortConfig* sc, const std::string& name, const char* url)
{
if ( !sc->alert_refs() )
return nullptr;
- assert(name);
-
- ReferenceSystemNode* node = (ReferenceSystemNode*)snort_calloc(sizeof(*node));
- node->name = snort_strdup(name);
+ assert(!name.empty());
- if ( url )
- node->url = snort_strdup(url);
+ ReferenceSystem* sys = new ReferenceSystem(name, url);
+ sc->references[sys->name] = sys;
- ReferenceSystemNode** head = &sc->references;
- node->next = *head;
- *head = node;
-
- return node;
+ return sys;
}
-static ReferenceSystemNode* ReferenceSystemLookup(
- ReferenceSystemNode* head, const char* name)
+static const ReferenceSystem* reference_system_lookup(SnortConfig* sc, const std::string& key)
{
- assert(name);
+ const auto it = sc->references.find(key);
- while ( head )
- {
- if ( !strcasecmp(name, head->name) )
- break;
+ if ( it != sc->references.end() )
+ return it->second;
- head = head->next;
- }
- return head;
+ return nullptr;
}
-/********************* Reference Implementation *******************************/
+//--------------------------------------------------------------------------
+// references
+//--------------------------------------------------------------------------
-void AddReference(
- SnortConfig* sc, ReferenceNode** head, const char* system, const char* id)
+void add_reference(
+ SnortConfig* sc, OptTreeNode* otn, const std::string& system, const std::string& id)
{
if ( !sc->alert_refs() )
return;
- assert(sc and head and system and id);
-
- /* create the new node */
- ReferenceNode* node = (ReferenceNode*)snort_calloc(sizeof(ReferenceNode));
+ assert(sc and otn and !system.empty() and !id.empty());
- node->system = ReferenceSystemLookup(sc->references, system);
+ const ReferenceSystem* sys = reference_system_lookup(sc, system);
- if ( !node->system )
- node->system = ReferenceSystemAdd(sc, system);
+ if ( !sys )
+ sys = reference_system_add(sc, system);
- node->id = snort_strdup(id);
-
- node->next = *head;
- *head = node;
+ ReferenceNode* node = new ReferenceNode(sys, id);
+ otn->sigInfo.refs.push_back(node);
}
-/************************ Class/Priority Implementation ***********************/
+//--------------------------------------------------------------------------
+// classifications
+//--------------------------------------------------------------------------
-void AddClassification(
- SnortConfig* sc, const char* type, const char* name, unsigned priority)
+void add_classification(
+ SnortConfig* sc, const char* name, const char* text, unsigned priority)
{
- int max_id = 0;
- ClassType* current = sc->classifications;
-
- while (current != nullptr)
+ if ( get_classification(sc, name) )
{
- /* dup check */
- if (strcasecmp(current->type, type) == 0)
- {
- ParseWarning(WARN_CONF,
- "Duplicate classification \"%s\""
- "found, ignoring this line", type);
- return;
- }
-
- if (current->id > max_id)
- max_id = current->id;
-
- current = current->next;
+ ParseWarning(WARN_CONF, "Duplicate classification '%s' found, ignoring this line", name);
+ return;
}
- ClassType* new_node = (ClassType*)snort_calloc(sizeof(ClassType));
-
- new_node->type = snort_strdup(type);
- new_node->name = snort_strdup(name);
- new_node->priority = priority;
- new_node->id = max_id + 1;
-
- /* insert node */
- new_node->next = sc->classifications;
- sc->classifications = new_node;
+ ClassType* ct = new ClassType(name, text, priority, sc->classifications.size() + 1);
+ sc->classifications[ct->name] = ct;
}
-/* NOTE: This lookup can only be done during parse time */
-ClassType* ClassTypeLookupByType(SnortConfig* sc, const char* type)
+const ClassType* get_classification(SnortConfig* sc, const char* type)
{
- assert(sc and type);
- ClassType* node = sc->classifications;
+ std::string key = type;
+ const auto it = sc->classifications.find(key);
- while ( node )
- {
- if ( !strcasecmp(type, node->type) )
- break;
+ if ( it != sc->classifications.end() )
+ return it->second;
- node = node->next;
- }
- return node;
+ return nullptr;
}
-/***************** Otn Utilities ***********************/
+//--------------------------------------------------------------------------
+// otn utilities
+//--------------------------------------------------------------------------
void OtnRemove(GHash* otn_map, OptTreeNode* otn)
{
otn_map->remove(&key);
}
-void OtnFree(void* data)
+OptTreeNode::~OptTreeNode()
{
- if ( !data )
- return;
-
- OptTreeNode* otn = (OptTreeNode*)data;
- OptFpList* opt_func = otn->opt_func;
-
- while ( opt_func )
- {
- OptFpList* tmp = opt_func;
- opt_func = opt_func->next;
- snort_free(tmp); // FIXIT-L use c++ operators for all of this
- }
+ OptFpList* opt = opt_func;
- if ( otn->sigInfo.message )
- {
- snort_free(otn->sigInfo.message);
- }
- for (unsigned svc_idx = 0; svc_idx < otn->sigInfo.num_services; svc_idx++)
+ while ( opt )
{
- if (otn->sigInfo.services[svc_idx].service)
- snort_free(otn->sigInfo.services[svc_idx].service);
+ OptFpList* tmp = opt;
+ opt = opt->next;
+ snort_free(tmp);
}
- if (otn->sigInfo.services)
- snort_free(otn->sigInfo.services);
- ReferenceNode* ref_node = otn->sigInfo.refs;
+ for ( auto& ref : sigInfo.refs )
+ delete ref;
- while ( ref_node )
- {
- ReferenceNode* tmp = ref_node;
- ref_node = ref_node->next;
- snort_free(tmp->id);
- snort_free(tmp);
- }
+ if ( tag )
+ snort_free(tag);
- if ( otn->tag )
- snort_free(otn->tag);
+ if ( soid )
+ snort_free(soid);
- if ( otn->soid )
- snort_free(otn->soid);
+ if (proto_nodes)
+ snort_free(proto_nodes);
- if (otn->proto_nodes)
- snort_free(otn->proto_nodes);
+ if (detection_filter)
+ snort_free(detection_filter);
- if (otn->detection_filter)
- snort_free(otn->detection_filter);
+ delete[] state;
+}
- delete[] otn->state;
+static void OtnFree(void* data)
+{
+ OptTreeNode* otn = (OptTreeNode*)data;
delete otn;
}
delete otn_map;
}
+void dump_msg_map(SnortConfig* sc)
+{
+ GHashNode* ghn = sc->otn_map->find_first();
+
+ while ( ghn )
+ {
+ const OptTreeNode* otn = (OptTreeNode*)ghn->data;
+ const SigInfo& si = otn->sigInfo;
+
+ std::cout << si.gid << " || ";
+ std::cout << si.sid << " || ";
+ std::cout << si.rev << " || ";
+ std::cout << si.message;
+
+ for ( const auto& rn : si.refs )
+ std::cout << " || " << rn->system->name << "," << rn->id;
+
+ std::cout << std::endl;
+ ghn = sc->otn_map->find_next();
+ }
+}
+
#include <cstdint>
#include <cstdio>
+#include <string>
#include "target_based/snort_protocols.h"
struct OptTreeNode;
-/* this contains a list of the URLs for various reference systems */
-struct ReferenceSystemNode
+struct ReferenceSystem
{
- char* name;
- char* url;
- ReferenceSystemNode* next;
+ ReferenceSystem(const std::string& n, const char* u) : name(n), url(u) { }
+ std::string name;
+ std::string url;
};
-ReferenceSystemNode* ReferenceSystemAdd(snort::SnortConfig*, const char*, const char* = nullptr);
+const ReferenceSystem* reference_system_add(snort::SnortConfig*, const std::string&, const char* = "");
struct ReferenceNode
{
- char* id;
- ReferenceSystemNode* system;
- ReferenceNode* next;
+ ReferenceNode(const ReferenceSystem* sys, const std::string& id) : system(sys), id(id) { }
+ const ReferenceSystem* system;
+ std::string id;
};
-void AddReference(snort::SnortConfig*, ReferenceNode**, const char*, const char*);
+void add_reference(snort::SnortConfig*, OptTreeNode*, const std::string& sys, const std::string& id);
-/* struct for rule classification */
struct ClassType
{
- // FIXIT-L type and name are backwards (name -> text, type -> name)
- char* type;
- int id;
- char* name; // "pretty" name
+ ClassType(const char* s, const char* txt, unsigned pri, int id) :
+ name(s), text(txt), priority(pri), id(id) { }
+
+ std::string name;
+ std::string text;
unsigned priority;
- ClassType* next;
+ int id;
};
-/* NOTE: These methods can only be used during parse time */
-void AddClassification(snort::SnortConfig*, const char* type, const char* name, unsigned priority);
+void add_classification(snort::SnortConfig*, const char* name, const char* text, unsigned priority);
-ClassType* ClassTypeLookupByType(snort::SnortConfig*, const char*);
+const ClassType* get_classification(snort::SnortConfig*, const char*);
struct SignatureServiceInfo
{
- char* service;
+ SignatureServiceInfo(const char* s, SnortProtocolId proto) :
+ service(s), snort_protocol_id(proto) { }
+ std::string service;
SnortProtocolId snort_protocol_id;
};
struct SigInfo
{
- char* message = nullptr;
- ClassType* class_type = nullptr;
- ReferenceNode* refs = nullptr;
- SignatureServiceInfo* services = nullptr;
+ std::string message;
+ std::vector<const ReferenceNode*> refs;
+ std::vector<SignatureServiceInfo> services;
+
+ const ClassType* class_type = nullptr;
uint32_t gid = 0;
uint32_t sid = 0;
uint32_t class_id = 0;
uint32_t priority = 0;
- uint32_t num_services = 0;
bool builtin = false;
Target target = TARGET_NONE;
void OtnLookupFree(snort::GHash*);
void OtnRemove(snort::GHash*, OptTreeNode*);
-void OtnDeleteData(void* data);
-void OtnFree(void* data);
-
OptTreeNode* GetOTN(uint32_t gid, uint32_t sid);
+void dump_msg_map(snort::SnortConfig*);
+
#endif
// represents body part of rule
struct OptTreeNode
{
+ ~OptTreeNode();
+
using Flag = uint8_t;
static constexpr Flag WARNED_FP = 0x01;
static constexpr Flag STATELESS = 0x02;
// ptr to list of RTNs (head part); indexed by policyId
RuleTreeNode** proto_nodes = nullptr;
OtnState* state = nullptr;
- int chain_node_number = 0;
+
unsigned evalIndex = 0; /* where this rule sits in the evaluation sets */
unsigned ruleIndex = 0; // unique index
uint32_t num_detection_opts = 0;
#include <cassert>
#include <string>
-#include <unordered_map>
-#include <vector>
#include "framework/base_api.h"
#include "main/snort_types.h"
#ifndef MPSE_BATCH_H
#define MPSE_BATCH_H
+#include <unordered_map>
+#include <vector>
+
#include "framework/mpse.h"
#include "main/snort_types.h"
// it should not be found
CHECK(t->find(str) == nullptr);
-
+
// try to remove a node that is not in the table
CHECK(t->remove( str) == HASH_NOT_FOUND);
{ return DETECT; }
public:
- ClassType* type;
+ const ClassType* type;
};
bool ClassTypeModule::set(const char*, Value& v, SnortConfig* sc)
if ( !v.is("~") )
return false;
- type = ClassTypeLookupByType(sc, v.get_string());
+ type = get_classification(sc, v.get_string());
return type != nullptr;
}
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
//--------------------------------------------------------------------------
-/*
- ** Major rewrite: Hui Cao <hcao@sourcefire.com>
- **
- ** Add flowbits OR support
- **
- ** sp_flowbits
- **
- ** Purpose:
- **
- ** Wouldn't it be nice if we could do some simple state tracking
- ** across multiple packets? Well, this allows you to do just that.
- **
- ** Effect:
- **
- ** - [Un]set a bitmask stored with the session
- ** - Check the value of the bitmask
- */
+// Major rewrite: Hui Cao <hcao@sourcefire.com>
#ifdef HAVE_CONFIG_H
#include "config.h"
#include "ips_flowbits.h"
#include <forward_list>
+#include <sstream>
+#include <string>
#include "framework/ips_option.h"
#include "framework/module.h"
#include "hash/hash_defs.h"
#include "hash/hash_key_operations.h"
#include "log/messages.h"
-#include "parser/mstring.h"
#include "protocols/packet.h"
#include "profiler/profiler.h"
#include "utils/bitop.h"
#include "utils/util.h"
using namespace snort;
-using namespace std;
#define s_name "flowbits"
static THREAD_LOCAL ProfileStats flowBitsPerfStats;
-#define DEFAULT_FLOWBIT_GROUP "default"
#define ALLOWED_SPECIAL_CHARS ".-_"
-#define DEFAULT_FLOWBIT_SIZE 1024
-#define MAX_FLOWBIT_SIZE 2048
-
#define FLOWBITS_SET 0x01
#define FLOWBITS_UNSET 0x02
#define FLOWBITS_TOGGLE 0x04
*/
struct FLOWBITS_OBJECT
{
- uint16_t id;
- uint8_t types;
- int toggle;
- int set;
- int isset;
+ uint16_t id = 0;
+ uint8_t types = 0;
+ int toggle = 0;
+ int set = 0;
+ int isset = 0;
};
typedef enum
class FLOWBITS_OP
{
public:
- uint16_t* ids = nullptr;
- uint8_t num_ids = 0;
- uint8_t type = 0; /* Set, Unset, Invert, IsSet, IsNotSet, Reset */
- Flowbits_eval eval = FLOWBITS_AND; /* and , or, all, any*/
- char* name = nullptr;
- char* group = nullptr;
+ std::string name;
+ std::string group;
+
+ std::vector<uint16_t> ids;
+ Flowbits_eval eval = FLOWBITS_AND;
+
uint32_t group_id = 0;
- ~FLOWBITS_OP();
+ uint8_t type = 0; /* Set, Unset, Invert, IsSet, IsNotSet, Reset */
};
-FLOWBITS_OP::~FLOWBITS_OP()
-{
- if (ids != nullptr)
- snort_free(ids);
- if (name != nullptr)
- snort_free(name);
- if (group != nullptr)
- snort_free(group);
-}
-
struct FLOWBITS_GRP
{
- uint16_t count;
- uint16_t max_id;
- char* name;
- uint32_t group_id;
- BitOp* GrpBitOp;
+ std::string name;
+ BitOp* GrpBitOp = nullptr;
+
+ uint32_t group_id = 0;
+
+ uint16_t count = 0;
+ uint16_t max_id = 0;
};
struct FlowBitState
};
// Forward declarations
-static void FlowItemFree(void* d);
-static void FlowBitsGrpFree(void* d);
-static IpsOption::EvalStatus check_flowbits(
- uint8_t type, uint8_t evalType, uint16_t* ids, uint16_t num_ids,
- char* group, Packet* p);
+static void free_item(void*);
+static void free_group(void*);
+
+static IpsOption::EvalStatus check_flowbits(FLOWBITS_OP*, Packet*);
class FlowBitsOption : public IpsOption
{
{
uint32_t a,b,c;
const FLOWBITS_OP* data = config;
- int i;
- int j = 0;
+ unsigned i;
+ unsigned j = 0;
a = data->eval;
b = data->type;
mix(a,b,c);
mix_str(a,b,c,get_name());
- for (i = 0, j = 0; i < data->num_ids; i++, j++)
+ for (i = 0, j = 0; i < data->ids.size(); i++, j++)
{
if (j >= 3)
{
}
if (1 == j)
{
- a += data->ids[data->num_ids - 1];
- b += data->num_ids;
+ a += data->ids[data->ids.size() - 1];
+ b += data->ids.size();
}
else if (2 == j)
{
- a += data->ids[data->num_ids - 2];
- b += data->ids[data->num_ids - 1]|data->num_ids << 16;
+ a += data->ids[data->ids.size() - 2];
+ b += data->ids[data->ids.size() - 1]|data->ids.size() << 16;
}
c += data->group_id;
const FlowBitsOption& rhs = (const FlowBitsOption&)ips;
- if ( (config->num_ids != rhs.config->num_ids)or
+ if ( (config->ids.size() != rhs.config->ids.size()) or
(config->eval != rhs.config->eval) or
(config->type != rhs.config->type) or
(config->group_id != rhs.config->group_id) )
return false;
- for ( int i = 0; i < config->num_ids; i++ )
+ for ( unsigned i = 0; i < config->ids.size(); i++ )
{
if (config->ids[i] != rhs.config->ids[i])
return false;
IpsOption::EvalStatus FlowBitsOption::eval(Cursor&, Packet* p)
{
RuleProfile profile(flowBitsPerfStats);
-
- FLOWBITS_OP* flowbits = config;
-
- if (!flowbits)
- return NO_MATCH;
-
- return check_flowbits(flowbits->type, (uint8_t)flowbits->eval,
- flowbits->ids, flowbits->num_ids, flowbits->group, p);
+ return check_flowbits(config, p);
}
//-------------------------------------------------------------------------
return flow->bitop;
}
-static inline int clear_group_bit(BitOp* bitop, char* group, FlowBitState* flowbit_state)
+static inline int clear_group_bit(
+ BitOp* bitop, const std::string& group, FlowBitState* flowbit_state)
{
- if ( !group )
+ if ( group.empty() )
return 0;
// FIXIT-M why is the hash lookup done at runtime for flowbits groups?
- // a pointer to flowbis_grp should be in flowbits config data
+ // a pointer to flowbits_grp should be in flowbits config data
// this *should* be safe but iff splay mode is disabled
- auto flowbits_grp = (FLOWBITS_GRP*)flowbit_state->flowbits_grp_hash->find(group);
+ auto flowbits_grp = (FLOWBITS_GRP*)flowbit_state->flowbits_grp_hash->find(group.c_str());
if ( !flowbits_grp )
return 0;
- if ( !bitop || (bitop->size() <= flowbits_grp->max_id) || !flowbits_grp->count )
+ if ( !bitop or (bitop->size() <= flowbits_grp->max_id) or !flowbits_grp->count )
return 0;
auto GrpBitOp = flowbits_grp->GrpBitOp;
/* note, max_id is an index, not a count.
* Calculate max_bytes by adding 8 to max_id, then dividing by 8. */
unsigned int max_bytes = (flowbits_grp->max_id + 8) >> 3;
+
for ( unsigned int i = 0; i < max_bytes; i++ )
bitop->get_buf_element(i) &= ~GrpBitOp->get_buf_element(i);
return 1;
}
-static inline int toggle_group_bit(BitOp* bitop, char* group, FlowBitState* flowbit_state)
+static inline int toggle_group_bit(
+ BitOp* bitop, const std::string& group, FlowBitState* flowbit_state)
{
- if ( !group )
+ if ( group.empty() )
return 0;
- auto flowbits_grp = (FLOWBITS_GRP*)flowbit_state->flowbits_grp_hash->find(group);
+ auto flowbits_grp = (FLOWBITS_GRP*)flowbit_state->flowbits_grp_hash->find(group.c_str());
if ( !flowbits_grp )
return 0;
- if ( !bitop || (bitop->size() <= flowbits_grp->max_id) || !flowbits_grp->count )
+ if ( !bitop or (bitop->size() <= flowbits_grp->max_id) or !flowbits_grp->count )
return 0;
auto GrpBitOp = flowbits_grp->GrpBitOp;
}
static inline int set_xbits_to_group(
- BitOp* bitop, uint16_t* ids, uint16_t num_ids, char* group, FlowBitState* flowbit_state)
+ BitOp* bitop, FLOWBITS_OP* fb, FlowBitState* flowbit_state)
{
- unsigned int i;
- if (!clear_group_bit(bitop, group, flowbit_state))
+ if ( !clear_group_bit(bitop, fb->group, flowbit_state) )
return 0;
- for (i = 0; i < num_ids; i++)
- bitop->set(ids[i]);
+
+ for ( auto id : fb->ids )
+ bitop->set(id);
+
return 1;
}
static inline int is_set_flowbits(
- BitOp* bitop, uint8_t eval, uint16_t* ids,
- uint16_t num_ids, char* group, FlowBitState* flowbit_state)
+ BitOp* bitop, FLOWBITS_OP* fb, FlowBitState* flowbit_state)
{
- unsigned int i;
FLOWBITS_GRP* flowbits_grp;
- Flowbits_eval evalType = (Flowbits_eval)eval;
- switch (evalType)
+ switch ( fb->eval )
{
case FLOWBITS_AND:
- for (i = 0; i < num_ids; i++)
+ for ( auto id : fb->ids )
{
- if (!bitop->is_set(ids[i]))
+ if ( !bitop->is_set(id) )
return 0;
}
return 1;
case FLOWBITS_OR:
- for (i = 0; i < num_ids; i++)
+ for ( auto id : fb->ids )
{
- if (bitop->is_set(ids[i]))
+ if ( bitop->is_set(id) )
return 1;
}
return 0;
case FLOWBITS_ALL:
- flowbits_grp = (FLOWBITS_GRP*)flowbit_state->flowbits_grp_hash->find(group);
- if ( flowbits_grp == nullptr )
+ flowbits_grp = (FLOWBITS_GRP*)flowbit_state->flowbits_grp_hash->find(fb->group.c_str());
+
+ if ( !flowbits_grp )
return 0;
- for ( i = 0; i <= (unsigned int)(flowbits_grp->max_id >>3); i++ )
+
+ for ( unsigned i = 0; i <= (unsigned int)(flowbits_grp->max_id >>3); i++ )
{
uint8_t val = bitop->get_buf_element(i) & flowbits_grp->GrpBitOp->get_buf_element(i);
return 1;
case FLOWBITS_ANY:
- flowbits_grp = (FLOWBITS_GRP*)flowbit_state->flowbits_grp_hash->find(group);
- if ( flowbits_grp == nullptr )
+ flowbits_grp = (FLOWBITS_GRP*)flowbit_state->flowbits_grp_hash->find(fb->group.c_str());
+
+ if ( !flowbits_grp )
return 0;
- for ( i = 0; i <= (unsigned int)(flowbits_grp->max_id >>3); i++ )
+
+ for ( unsigned i = 0; i <= (unsigned int)(flowbits_grp->max_id >>3); i++ )
{
uint8_t val = bitop->get_buf_element(i) & flowbits_grp->GrpBitOp->get_buf_element(i);
if ( val )
}
}
-static IpsOption::EvalStatus check_flowbits(
- uint8_t type, uint8_t evalType, uint16_t* ids, uint16_t num_ids, char* group, Packet* p)
+static IpsOption::EvalStatus check_flowbits(FLOWBITS_OP* fb, Packet* p)
{
- Flowbits_eval eval = (Flowbits_eval)evalType;
int result = 0;
- int i;
FlowBitState* flowbit_state = SnortConfig::get_conf()->flowbit_state;
assert(flowbit_state != nullptr);
if (!bitop)
return IpsOption::NO_MATCH;
- switch (type)
+ switch (fb->type)
{
case FLOWBITS_SET:
- for (i = 0; i < num_ids; i++)
- bitop->set(ids[i]);
+ for ( auto id : fb->ids )
+ bitop->set(id);
result = 1;
break;
case FLOWBITS_SETX:
- result = set_xbits_to_group(bitop, ids, num_ids, group, flowbit_state);
+ result = set_xbits_to_group(bitop, fb, flowbit_state);
break;
case FLOWBITS_UNSET:
- if (eval == FLOWBITS_ALL )
- clear_group_bit(bitop, group, flowbit_state);
+ if (fb->eval == FLOWBITS_ALL )
+ clear_group_bit(bitop, fb->group, flowbit_state);
else
{
- for (i = 0; i < num_ids; i++)
- bitop->clear(ids[i]);
+ for ( auto id : fb->ids )
+ bitop->clear(id);
}
result = 1;
break;
case FLOWBITS_RESET:
- if (!group)
+ if ( fb->group.empty() )
bitop->reset();
else
- clear_group_bit(bitop, group, flowbit_state);
+ clear_group_bit(bitop, fb->group, flowbit_state);
+
result = 1;
break;
case FLOWBITS_ISSET:
-
- if (is_set_flowbits(bitop,(uint8_t)eval, ids, num_ids, group, flowbit_state))
- {
+ if ( is_set_flowbits(bitop, fb, flowbit_state) )
result = 1;
- }
else
- {
return IpsOption::FAILED_BIT;
- }
-
break;
case FLOWBITS_ISNOTSET:
- if (!is_set_flowbits(bitop, (uint8_t)eval, ids, num_ids, group, flowbit_state))
- {
+ if ( !is_set_flowbits(bitop, fb, flowbit_state) )
result = 1;
- }
else
- {
return IpsOption::FAILED_BIT;
- }
break;
case FLOWBITS_TOGGLE:
- if (group)
- toggle_group_bit(bitop, group, flowbit_state);
- else
+ if ( !fb->group.empty() )
+ toggle_group_bit(bitop, fb->group, flowbit_state);
+
+ else for ( auto id : fb->ids )
{
- for (i = 0; i < num_ids; i++)
- {
- if (bitop->is_set(ids[i]))
- {
- bitop->clear(ids[i]);
- }
- else
- {
- bitop->set(ids[i]);
- }
- }
+ if (bitop->is_set(id))
+ bitop->clear(id);
+ else
+ bitop->set(id);
}
result = 1;
return IpsOption::NO_ALERT;
default:
- /*
- ** Always return failure here.
- */
return IpsOption::NO_MATCH;
}
- /*
- ** Now return what we found
- */
if (result == 1)
- {
return IpsOption::MATCH;
- }
return IpsOption::NO_MATCH;
}
void flowbits_ginit(SnortConfig* sc)
{
sc->flowbit_state = new FlowBitState;
- sc->flowbit_state->flowbits_hash = new GHash(10000, 0, 0, FlowItemFree);
+ sc->flowbit_state->flowbits_hash = new GHash(10000, 0, 0, free_item);
// this is used during parse time and runtime so do NOT
// enable splay mode (which is NOT useful here anyway)
- sc->flowbit_state->flowbits_grp_hash = new GHash(10000, 0, 0, FlowBitsGrpFree);
+ sc->flowbit_state->flowbits_grp_hash = new GHash(10000, 0, 0, free_group);
sc->flowbit_state->flowbits_bit_queue = sfqueue_new();
}
// parsing methods
//-------------------------------------------------------------------------
-static bool validateName(char* name)
+static bool validate_name(const char* name)
{
- unsigned i;
-
- if (!name)
- return false;
+ assert(name);
- for (i=0; i<strlen(name); i++)
+ for ( unsigned i=0; i<strlen(name); i++ )
{
- if (!isalnum(name[i])&&(nullptr == strchr(ALLOWED_SPECIAL_CHARS,name[i])))
+ if (!isalnum(name[i]) and (nullptr == strchr(ALLOWED_SPECIAL_CHARS,name[i])))
return false;
}
return true;
}
-static FLOWBITS_OBJECT* getFlowBitItem(char* flowbitName, FLOWBITS_OP* flowbits,
- FlowBitState* flowbit_state)
+static FLOWBITS_OBJECT* get_item(
+ const char* bit, FLOWBITS_OP* flowbits, FlowBitState* flowbit_state)
{
- FLOWBITS_OBJECT* flowbits_item;
-
- if (!validateName(flowbitName))
+ if ( !validate_name(bit) )
{
ParseAbort("%s: name is limited to any alphanumeric string including %s",
s_name, ALLOWED_SPECIAL_CHARS);
}
- flowbits_item = (FLOWBITS_OBJECT*)flowbit_state->flowbits_hash->find(flowbitName);
+ FLOWBITS_OBJECT* flowbits_item = (FLOWBITS_OBJECT*)flowbit_state->flowbits_hash->find(bit);
- if (flowbits_item == nullptr)
+ if ( !flowbits_item )
{
- flowbits_item = (FLOWBITS_OBJECT*)snort_calloc(sizeof(FLOWBITS_OBJECT));
+ flowbits_item = new FLOWBITS_OBJECT;
if (sfqueue_count(flowbit_state->flowbits_bit_queue) > 0)
{
}
}
- int hstatus = flowbit_state->flowbits_hash->insert(flowbitName, flowbits_item);
+ int hstatus = flowbit_state->flowbits_hash->insert(bit, flowbits_item);
+
if (hstatus != HASH_OK)
- ParseError("Could not add flowbits key (%s) to hash.",flowbitName);
+ ParseError("Could not add flowbits key (%s) to hash.", bit);
}
flowbits_item->toggle = flowbit_state->flowbits_toggle;
flowbits_item->types |= flowbits->type;
return flowbits_item;
}
-static void processFlowbits(
- char* flowbits_names, FLOWBITS_OP* flowbits, FlowBitState* flowbit_state)
+static void parse_flowbits(
+ const char* flowbits_names, FLOWBITS_OP* flowbits, FlowBitState* flowbit_state)
{
- char** toks;
- int num_toks;
- int i;
- char* flowbits_name;
-
FLOWBITS_OBJECT* flowbits_item;
- if (!flowbits_names || ((*flowbits_names) == 0))
- {
+ if ( !flowbits_names or ((*flowbits_names) == 0) )
return;
- }
- flowbits_name = snort_strdup(flowbits_names);
-
- if (nullptr != strchr(flowbits_name, '|'))
+ if ( strchr(flowbits_names, '|') )
{
- if (nullptr != strchr(flowbits_name, '&'))
+ if ( strchr(flowbits_names, '&') )
{
ParseError("%s: tag id opcode '|' and '&' are used together.", s_name);
return;
}
- toks = mSplit(flowbits_name, "|", 0, &num_toks, 0);
- flowbits->ids = (uint16_t*)snort_calloc(num_toks, sizeof(*(flowbits->ids)));
- flowbits->num_ids = num_toks;
- for (i = 0; i < num_toks; i++)
+ std::string bits = flowbits_names;
+ std::replace(bits.begin(), bits.end(), '|', ' ');
+ std::stringstream ss(bits);
+ std::string tok;
+
+ while ( ss >> tok )
{
- flowbits_item = getFlowBitItem(toks[i], flowbits, flowbit_state);
- flowbits->ids[i] = flowbits_item->id;
+ flowbits_item = get_item(tok.c_str(), flowbits, flowbit_state);
+ flowbits->ids.push_back(flowbits_item->id);
}
flowbits->eval = FLOWBITS_OR;
- mSplitFree(&toks, num_toks);
}
- else if (nullptr != strchr(flowbits_name, '&'))
+ else if ( strchr(flowbits_names, '&') )
{
- toks = mSplit(flowbits_name, "&", 0, &num_toks, 0);
- flowbits->ids = (uint16_t*)snort_calloc(num_toks, sizeof(*(flowbits->ids)));
- flowbits->num_ids = num_toks;
- for (i = 0; i < num_toks; i++)
+ std::string bits = flowbits_names;
+ std::replace(bits.begin(), bits.end(), '&', ' ');
+ std::stringstream ss(bits);
+ std::string tok;
+
+ while ( ss >> tok )
{
- flowbits_item = getFlowBitItem(toks[i], flowbits, flowbit_state);
- flowbits->ids[i] = flowbits_item->id;
+ flowbits_item = get_item(tok.c_str(), flowbits, flowbit_state);
+ flowbits->ids.push_back(flowbits_item->id);
}
flowbits->eval = FLOWBITS_AND;
- mSplitFree(&toks, num_toks);
}
- else if (!strcasecmp(flowbits_name,"all"))
+ else if ( !strcasecmp(flowbits_names, "all") )
{
flowbits->eval = FLOWBITS_ALL;
}
- else if (!strcasecmp(flowbits_name,"any"))
+ else if ( !strcasecmp(flowbits_names, "any") )
{
flowbits->eval = FLOWBITS_ANY;
}
else
{
- flowbits_item = getFlowBitItem(flowbits_name, flowbits, flowbit_state);
- flowbits->ids = (uint16_t*)snort_calloc(sizeof(*(flowbits->ids)));
- flowbits->num_ids = 1;
- flowbits->ids[0] = flowbits_item->id;
+ flowbits_item = get_item(flowbits_names, flowbits, flowbit_state);
+ flowbits->ids.push_back(flowbits_item->id);
}
-
- snort_free(flowbits_name);
}
static void validateFlowbitsSyntax(FLOWBITS_OP* flowbits)
switch (flowbits->type)
{
case FLOWBITS_SET:
- if ((flowbits->eval == FLOWBITS_AND) && (flowbits->ids))
+ if ( (flowbits->eval == FLOWBITS_AND) and !flowbits->ids.empty() )
break;
ParseError("%s: operation set uses syntax: flowbits:set,bit[&bit],[group].", s_name);
return;
case FLOWBITS_SETX:
- if ((flowbits->eval == FLOWBITS_AND)&&(flowbits->group) && (flowbits->ids) )
+ if ( (flowbits->eval == FLOWBITS_AND) and !flowbits->group.empty() and
+ !flowbits->ids.empty() )
break;
ParseError("%s: operation setx uses syntax: flowbits:setx,bit[&bit],group.", s_name);
return;
case FLOWBITS_UNSET:
- if (((flowbits->eval == FLOWBITS_AND) && (!flowbits->group) && (flowbits->ids))
- ||((flowbits->eval == FLOWBITS_ALL) && (flowbits->group)))
+ if (((flowbits->eval == FLOWBITS_AND) and flowbits->group.empty() and !flowbits->ids.empty())
+ or ((flowbits->eval == FLOWBITS_ALL) and !flowbits->group.empty()))
break;
ParseError("%s: operation unset uses syntax: flowbits:unset,bit[&bit] OR"
return;
case FLOWBITS_TOGGLE:
- if (((flowbits->eval == FLOWBITS_AND) && (!flowbits->group) &&(flowbits->ids))
- ||((flowbits->eval == FLOWBITS_ALL) && (flowbits->group)))
+ if (((flowbits->eval == FLOWBITS_AND) and flowbits->group.empty() and !flowbits->ids.empty())
+ or ((flowbits->eval == FLOWBITS_ALL) and !flowbits->group.empty()))
break;
ParseError("%s: operation toggle uses syntax: flowbits:toggle,bit[&bit] OR"
return;
case FLOWBITS_ISSET:
- if ((((flowbits->eval == FLOWBITS_AND) || (flowbits->eval == FLOWBITS_OR)) &&
- (!flowbits->group) && flowbits->ids)
- ||((((flowbits->eval == FLOWBITS_ANY))||(flowbits->eval == FLOWBITS_ALL)) &&
- (flowbits->group)))
+ if ((((flowbits->eval == FLOWBITS_AND) or (flowbits->eval == FLOWBITS_OR)) and
+ flowbits->group.empty() and !flowbits->ids.empty())
+ or (((flowbits->eval == FLOWBITS_ANY) or (flowbits->eval == FLOWBITS_ALL)) and
+ !flowbits->group.empty()))
break;
ParseError("%s: operation isset uses syntax: flowbits:isset,bit[&bit] OR "
return;
case FLOWBITS_ISNOTSET:
- if ((((flowbits->eval == FLOWBITS_AND) || (flowbits->eval == FLOWBITS_OR)) &&
- (!flowbits->group) && flowbits->ids)
- ||((((flowbits->eval == FLOWBITS_ANY))||(flowbits->eval == FLOWBITS_ALL)) &&
- (flowbits->group)))
+ if ((((flowbits->eval == FLOWBITS_AND) or (flowbits->eval == FLOWBITS_OR)) and
+ flowbits->group.empty() and !flowbits->ids.empty())
+ or ((((flowbits->eval == FLOWBITS_ANY)) or (flowbits->eval == FLOWBITS_ALL)) and
+ !flowbits->group.empty()))
break;
ParseError("%s: operation isnotset uses syntax: flowbits:isnotset,bit[&bit] OR "
return;
case FLOWBITS_RESET:
- if (flowbits->ids == nullptr)
+ if ( flowbits->ids.empty() )
break;
+
ParseError(
"%s: operation unset uses syntax: flowbits:reset OR flowbits:reset, group.", s_name);
return;
case FLOWBITS_NOALERT:
- if ((flowbits->ids == nullptr) && (flowbits->group == nullptr))
+ if ( flowbits->ids.empty() and flowbits->group.empty() )
break;
+
ParseError("%s: operation noalert uses syntax: flowbits:noalert.", s_name);
return;
}
}
-static FLOWBITS_GRP* getFlowBitGroup(char* groupName, FlowBitState* flowbit_state)
+static FLOWBITS_GRP* get_group(const char* group, FlowBitState* flowbit_state)
{
- FLOWBITS_GRP* flowbits_grp = nullptr;
-
- if (!groupName)
- return nullptr;
-
- if (!validateName(groupName))
+ if (!validate_name(group))
{
ParseAbort(
"%s: flowbits group name is limited to any alphanumeric string including %s",
s_name, ALLOWED_SPECIAL_CHARS);
}
- flowbits_grp = (FLOWBITS_GRP*)flowbit_state->flowbits_grp_hash->find(groupName);
+ FLOWBITS_GRP* flowbits_grp = (FLOWBITS_GRP*)flowbit_state->flowbits_grp_hash->find(group);
if ( !flowbits_grp )
{
// new group defined, add (bitop set later once we know size)
- flowbits_grp = (FLOWBITS_GRP*)snort_calloc(sizeof(*flowbits_grp));
- int hstatus = flowbit_state->flowbits_grp_hash->insert(groupName, flowbits_grp);
- if (hstatus != HASH_OK)
- ParseAbort("Could not add flowbits group (%s) to hash.\n",groupName);
-
+ flowbits_grp = new FLOWBITS_GRP;
+ flowbit_state->flowbits_grp_hash->insert(group, flowbits_grp);
flowbit_state->flowbits_grp_count++;
flowbits_grp->group_id = flowbit_state->flowbits_grp_count;
- flowbits_grp->name = snort_strdup(groupName);
+ flowbits_grp->name = group;
}
return flowbits_grp;
}
-static void processFlowBitsWithGroup(char* flowbitsName, char* groupName, FLOWBITS_OP* flowbits,
- FlowBitState* flowbit_state)
+static void parse_flowbits_with_group(
+ const char* bits, const char* group, FLOWBITS_OP* flowbits, FlowBitState* flowbit_state)
{
- processFlowbits(flowbitsName, flowbits, flowbit_state);
- if (groupName && !(flowbits->group))
+ parse_flowbits(bits, flowbits, flowbit_state);
+
+ if ( group and flowbits->group.empty() )
{
- flowbits->group = snort_strdup(groupName);
- FLOWBITS_GRP* flowbits_grp = getFlowBitGroup(groupName, flowbit_state);
+ flowbits->group = group;
+ FLOWBITS_GRP* flowbits_grp = get_group(group, flowbit_state);
flowbits->group_id = flowbits_grp->group_id;
}
validateFlowbitsSyntax(flowbits);
- if ( flowbits->group )
+ if ( !flowbits->group.empty() )
flowbit_state->op_list.push_front(flowbits);
}
-static FLOWBITS_OP* flowbits_parse(const char* data, SnortConfig* sc)
+static FLOWBITS_OP* flowbits_parse(
+ std::string& op, std::string& bits, std::string& group, SnortConfig* sc)
{
- char** toks;
- int num_toks;
- char* typeName = nullptr;
- char* groupName = nullptr;
- char* flowbitsName = nullptr;
- FLOWBITS_GRP* flowbits_grp;
-
- FLOWBITS_OP* flowbits = new FLOWBITS_OP;
-
- toks = mSplit(data, ",", 0, &num_toks, 0);
-
- if (num_toks < 1)
- {
- ParseAbort("%s: must specify operation.", s_name);
- }
- else if (num_toks > 3)
- {
- ParseAbort("%s: too many arguments.", s_name);
- }
-
FlowBitState* flowbit_state = sc->flowbit_state;
assert(flowbit_state != nullptr);
- typeName = toks[0];
+ FLOWBITS_OP* flowbits = new FLOWBITS_OP;
+ flowbits->name = op;
- if (!strcasecmp("set",typeName))
- {
+ if ( op == "set" )
flowbits->type = FLOWBITS_SET;
- }
- else if (!strcasecmp("setx",typeName))
- {
+
+ else if ( op == "setx" )
flowbits->type = FLOWBITS_SETX;
- }
- else if (!strcasecmp("unset",typeName))
- {
+
+ else if ( op == "unset" )
flowbits->type = FLOWBITS_UNSET;
- }
- else if (!strcasecmp("toggle",typeName))
- {
+
+ else if ( op == "toggle" )
flowbits->type = FLOWBITS_TOGGLE;
- }
- else if (!strcasecmp("isset",typeName))
- {
+
+ else if ( op == "isset" )
flowbits->type = FLOWBITS_ISSET;
- }
- else if (!strcasecmp("isnotset",typeName))
- {
+
+ else if ( op == "isnotset" )
flowbits->type = FLOWBITS_ISNOTSET;
- }
- else if (!strcasecmp("noalert", typeName))
+
+ else if ( op == "noalert" )
{
- if (num_toks > 1)
+ if ( !bits.empty() )
{
- ParseAbort("%s: do not specify a tag id for the keyword 'noalert'.", s_name);
+ ParseError("%s: invalid configuration.", s_name);
+ delete flowbits;
+ return nullptr;
}
flowbits->type = FLOWBITS_NOALERT;
- flowbits->ids = nullptr;
- flowbits->num_ids = 0;
- flowbits->name = snort_strdup(typeName);
-
- mSplitFree(&toks, num_toks);
return flowbits;
}
- else if (!strcasecmp("reset",typeName))
+ else if ( op == "reset" )
{
- if (num_toks > 2)
+ if ( !group.empty() )
{
- ParseAbort("%s: too many arguments for the keyword 'reset'.", s_name);
+ ParseError("%s: invalid configuration.", s_name);
+ delete flowbits;
+ return nullptr;
}
-
- if (num_toks == 2)
+ if ( !bits.empty() )
{
- /*Save the group name*/
- groupName = snort_strdup(toks[1]);
- flowbits_grp = getFlowBitGroup(groupName, flowbit_state);
- flowbits->group = groupName;
+ group = bits;
+ FLOWBITS_GRP* flowbits_grp = get_group(group.c_str(), flowbit_state);
+ flowbits->group = group;
flowbits->group_id = flowbits_grp->group_id;
}
flowbits->type = FLOWBITS_RESET;
- flowbits->ids = nullptr;
- flowbits->num_ids = 0;
- flowbits->name = snort_strdup(typeName);
- mSplitFree(&toks, num_toks);
return flowbits;
}
else
{
- ParseAbort("%s: invalid token %s.", s_name, typeName);
- }
-
- flowbits->name = snort_strdup(typeName);
- /*
- ** Let's parse the flowbits name
- */
- if ( num_toks < 2 )
- {
- ParseAbort("flowbit: flowbits tag id must be provided.");
- }
-
- flowbitsName = toks[1];
-
- if (num_toks == 3)
- {
- groupName = toks[2];
+ ParseError("%s: invalid configuration.", s_name);
+ delete flowbits;
+ return nullptr;
}
- processFlowBitsWithGroup(flowbitsName, groupName, flowbits, flowbit_state);
- mSplitFree(&toks, num_toks);
+ parse_flowbits_with_group(bits.c_str(), group.c_str(), flowbits, flowbit_state);
return flowbits;
}
{
const FLOWBITS_OP* fbop = flowbit_state->op_list.front();
FLOWBITS_GRP* fbg =
- (FLOWBITS_GRP*)flowbit_state->flowbits_grp_hash->find(fbop->group);
+ (FLOWBITS_GRP*)flowbit_state->flowbits_grp_hash->find(fbop->group.c_str());
assert(fbg);
- for ( int i = 0; i < fbop->num_ids; ++i )
+ for ( unsigned i = 0; i < fbop->ids.size(); ++i )
update_group(fbg, fbop->ids[i]);
flowbit_state->op_list.pop_front();
}
}
-static void FlowBitsVerify(FlowBitState* flowbit_state)
+static void flowbits_verify(FlowBitState* flowbit_state)
{
GHashNode* n;
unsigned num_flowbits = 0;
continue;
}
- if ((fb->set > 0) && (fb->isset == 0))
+ if ((fb->set > 0) and (fb->isset == 0))
{
ParseWarning(WARN_FLOWBITS, "%s key '%s' is set but not checked.",
s_name, (const char*)n->key);
unchecked++;
}
- else if ((fb->isset > 0) && (fb->set == 0))
+ else if ((fb->isset > 0) and (fb->set == 0))
{
ParseWarning(WARN_FLOWBITS, "%s key '%s' is checked but not ever set.",
s_name, (const char*)n->key);
unset++;
}
- else if ((fb->set == 0) && (fb->isset == 0))
+ else if ((fb->set == 0) and (fb->isset == 0))
{
continue; /* don't count this bit as used */
}
LogCount("not set", unset);
}
-static void FlowItemFree(void* d)
+static void free_item(void* d)
{
FLOWBITS_OBJECT* data = (FLOWBITS_OBJECT*)d;
- snort_free(data);
+ delete data;
}
-static void FlowBitsGrpFree(void* d)
+static void free_group(void* d)
{
FLOWBITS_GRP* data = (FLOWBITS_GRP*)d;
+
if (data->GrpBitOp)
delete data->GrpBitOp;
- if (data->name)
- snort_free(data->name);
- snort_free(data);
+
+ delete data;
}
//-------------------------------------------------------------------------
static const Parameter s_params[] =
{
- { "~command", Parameter::PT_STRING, nullptr, nullptr,
+ { "~op", Parameter::PT_STRING, nullptr, nullptr,
"set|reset|isset|etc." }, // FIXIT-L replace this legacy flowbits parsing with PT_SELECT
- { "~arg1", Parameter::PT_STRING, nullptr, nullptr,
+ { "~bits", Parameter::PT_STRING, nullptr, nullptr,
"bits or group" },
- { "~arg2", Parameter::PT_STRING, nullptr, nullptr,
+ { "~group", Parameter::PT_STRING, nullptr, nullptr,
"group if arg1 is bits" },
{ nullptr, Parameter::PT_MAX, nullptr, nullptr, nullptr }
FLOWBITS_OP* get_data();
public:
- string args;
+ std::string op;
+ std::string bits;
+ std::string group;
FLOWBITS_OP* fbop = nullptr;
};
bool FlowbitsModule::begin(const char*, int, SnortConfig*)
{
- args.clear();
+ op.clear();
+ bits.clear();
+ group.clear();
return true;
}
bool FlowbitsModule::set(const char*, Value& v, SnortConfig*)
{
- if ( v.is("~command") )
- args = v.get_string();
+ if ( v.is("~op") )
+ op = v.get_string();
+
+ else if ( v.is("~bits") )
+ bits = v.get_string();
+
+ else if ( v.is("~group") )
+ group = v.get_string();
- else if ( v.is("~arg1") || v.is("~arg2") )
- {
- args += ", ";
- args += v.get_string();
- }
else
return false;
bool FlowbitsModule::end(const char*, int, SnortConfig* sc)
{
- fbop = flowbits_parse(args.c_str(), sc);
- return true;
+ if ( op.empty() )
+ return false;
+
+ fbop = flowbits_parse(op, bits, group, sc);
+ return fbop != nullptr;
}
FLOWBITS_OP* FlowbitsModule::get_data()
{
FlowBitState* flowbit_state = sc->flowbit_state;
init_groups(flowbit_state);
- FlowBitsVerify(flowbit_state);
+ flowbits_verify(flowbit_state);
}
#if 0
if (flowbits->group)
{
- if (group_name && strcmp(group_name, flowbits->group))
+ if (group_name and strcmp(group_name, flowbits->group))
snort_free(group_name);
((FLOWBITS_OP*)idx_dup)->group = snort_strdup(flowbits->group);
}
#include "framework/module.h"
#include "hash/hash_key_operations.h"
#include "log/messages.h"
-#include "parser/mstring.h"
#include "profiler/profiler.h"
#include "utils/snort_bounds.h"
static void isdataat_parse(const char* data, IsDataAtData* idx)
{
- char** toks;
- int num_toks;
- char* endp;
- char* offset;
-
- toks = mSplit(data, ",", 3, &num_toks, 0);
- offset = toks[0];
+ const char* offset = data;
if (*offset == '!')
{
/* set how many bytes to process from the packet */
if (isdigit(offset[0]) || offset[0] == '-')
{
+ char* endp;
+
idx->offset_var = IPS_OPTIONS_NO_VAR;
idx->offset = strtol(offset, &endp, 10);
if (offset == endp)
{
- ParseError("unable to parse as byte value %s", toks[0]);
+ ParseError("unable to parse as byte value %s", data);
return;
}
return;
}
}
-
- mSplitFree(&toks,num_toks);
}
//-------------------------------------------------------------------------
static IpsOption* msg_ctor(Module* p, OptTreeNode* otn)
{
MsgModule* m = (MsgModule*)p;
- otn->sigInfo.message = snort_strdup(m->msg.c_str());
+ otn->sigInfo.message = m->msg;
return nullptr;
}
static const Parameter s_params[] =
{
- { "~scheme", Parameter::PT_STRING, nullptr, nullptr,
- "reference scheme" },
-
- { "~id", Parameter::PT_STRING, nullptr, nullptr,
- "reference id" },
+ { "~ref", Parameter::PT_STRING, nullptr, nullptr,
+ "reference: <scheme>,<id>" },
{ nullptr, Parameter::PT_MAX, nullptr, nullptr, nullptr }
};
bool ReferenceModule::set(const char*, Value& v, SnortConfig*)
{
- if ( v.is("~scheme") )
- scheme = v.get_string();
+ if ( !v.is("~ref") )
+ return false;
- else if ( v.is("~id") )
- id = v.get_string();
+ const char* ref = v.get_string();
+ const char* sep = strchr(ref, ',');
- else
+ if ( !sep or !strlen(sep + 1) )
return false;
+ scheme.assign(ref, sep - ref);
+ id = sep + 1;
+
return true;
}
static IpsOption* reference_ctor(Module* p, OptTreeNode* otn)
{
ReferenceModule* m = (ReferenceModule*)p;
- AddReference(m->snort_config, &otn->sigInfo.refs, m->scheme.c_str(), m->id.c_str());
+ add_reference(m->snort_config, otn, m->scheme, m->id);
return nullptr;
}
*/
void LogPriorityData(TextLog* log, const Event& e)
{
- if ((e.sig_info->class_type != nullptr)
- && (e.sig_info->class_type->name != nullptr))
- {
- TextLog_Print(log, "[Classification: %s] ", e.sig_info->class_type->name);
- }
+ if ( e.sig_info->class_type and !e.sig_info->class_type->text.empty() )
+ TextLog_Print(log, "[Classification: %s] ", e.sig_info->class_type->text.c_str());
TextLog_Print(log, "[Priority: %d] ", e.sig_info->priority);
}
* reference stuff cloned from signature.c
*--------------------------------------------------------------------
*/
-static void LogReference(TextLog* log, ReferenceNode* refNode)
-{
- if (refNode)
- {
- if (refNode->system)
- {
- if (refNode->system->url)
- TextLog_Print(log, "[Xref => %s%s]", refNode->system->url,
- refNode->id);
- else
- TextLog_Print(log, "[Xref => %s %s]", refNode->system->name,
- refNode->id);
- }
- else
- {
- TextLog_Print(log, "[Xref => %s]", refNode->id);
- }
- }
-}
-/*
- * prints out cross reference data associated with an alert
- */
void LogXrefs(TextLog* log, const Event& e)
{
- ReferenceNode* refNode = e.sig_info->refs;
-
- while ( refNode )
+ for ( const auto ref : e.sig_info->refs )
{
- LogReference(log, refNode);
- refNode = refNode->next;
+ if ( !ref->system )
+ TextLog_Print(log, "[Xref => %s]", ref->id.c_str());
+
+ else if ( !ref->system->url.empty() )
+ TextLog_Print(log, "[Xref => %s%s]", ref->system->url.c_str(), ref->id.c_str());
+
+ else
+ TextLog_Print(log, "[Xref => %s %s]", ref->system->name.c_str(), ref->id.c_str());
}
}
static void ff_class(const Args& a)
{
const char* cls = "none";
- if ( a.event.sig_info->class_type and a.event.sig_info->class_type->name )
- cls = a.event.sig_info->class_type->name;
+ if ( a.event.sig_info->class_type and !a.event.sig_info->class_type->text.empty() )
+ cls = a.event.sig_info->class_type->text.c_str();
TextLog_Puts(csv_log, cls);
}
{
const char* cls = "none";
- if ( a.event.sig_info->class_type and a.event.sig_info->class_type->name )
- cls = a.event.sig_info->class_type->name;
+ if ( a.event.sig_info->class_type and !a.event.sig_info->class_type->text.empty() )
+ cls = a.event.sig_info->class_type->text.c_str();
print_label(a, "class");
TextLog_Quote(json_log, cls);
lua_event.event_id = event->event_id;
lua_event.event_ref = event->event_reference;
- if ( event->sig_info->message )
- lua_event.msg = event->sig_info->message;
+ if ( !event->sig_info->message.empty() )
+ lua_event.msg = event->sig_info->message.c_str();
else
lua_event.msg = "";
- lua_event.svc = event->sig_info->num_services ? event->sig_info->services[1].service : "n/a";
-
return &lua_event;
}
else
SnortSnprintfAppend(event_string, sizeof(event_string), "ALERT ");
- if ((event.sig_info->class_type != nullptr)
- && (event.sig_info->class_type->name != nullptr))
+ if ( event.sig_info->class_type and !event.sig_info->class_type->text.empty() )
{
SnortSnprintfAppend(event_string, sizeof(event_string),
- "[Classification: %s] ", event.sig_info->class_type->name);
+ "[Classification: %s] ", event.sig_info->class_type->text.c_str());
}
if (event.sig_info->priority != 0)
#include <thread>
#include "control/idle_processing.h"
+#include "detection/signature.h"
#include "framework/module.h"
#include "helpers/process.h"
#include "helpers/ring.h"
FatalError("see prior %u warnings\n", warnings);
}
+ if ( SnortConfig::dump_msg_map() )
+ {
+ dump_msg_map(SnortConfig::get_conf());
+ return false;
+ }
+
if ( just_validate() )
{
LogMessage("\nSnort successfully validated the configuration (with %u warnings).\n",
enum HelpType
{
HT_BUF, HT_CFG, HT_CMD, HT_DBR, HT_DDR,
- HT_DMM, HT_GID, HT_HMO, HT_HPL, HT_DFL,
+ HT_GID, HT_HMO, HT_HPL, HT_DFL,
HT_IPS, HT_LST, HT_MOD, HT_PEG, HT_PLG
};
case HT_DFL:
ModuleManager::dump_defaults(val);
break;
- case HT_DMM:
- ModuleManager::dump_msg_map(val);
- break;
case HT_GID:
ModuleManager::show_gids(val);
break;
show_help(sc, val, HT_DDR);
}
-[[noreturn]] void dump_msg_map(SnortConfig* sc, const char* val)
-{
- show_help(sc, val, HT_DMM);
-}
-
[[noreturn]] void dump_rule_hex(SnortConfig*, const char* val)
{
SoManager::rule_to_hex(val);
[[noreturn]] void dump_builtin_rules(snort::SnortConfig* sc, const char*);
[[noreturn]] void dump_defaults(snort::SnortConfig* sc, const char*);
[[noreturn]] void dump_dynamic_rules(snort::SnortConfig* sc, const char*);
-[[noreturn]] void dump_msg_map(snort::SnortConfig* sc, const char*);
[[noreturn]] void dump_rule_hex(snort::SnortConfig* sc, const char*);
[[noreturn]] void dump_rule_text(snort::SnortConfig* sc, const char*);
[[noreturn]] void dump_version(snort::SnortConfig* sc);
bool ClassificationsModule::end(const char*, int idx, SnortConfig* sc)
{
if ( idx )
- AddClassification(sc, name.c_str(), text.c_str(), priority);
+ add_classification(sc, name.c_str(), text.c_str(), priority);
return true;
}
bool ReferencesModule::end(const char*, int idx, SnortConfig* sc)
{
if ( idx )
- ReferenceSystemAdd(sc, name.c_str(), url.c_str());
+ reference_system_add(sc, name, url.c_str());
return true;
}
// private implementation
//-------------------------------------------------------------------------
-static void FreeClassifications(ClassType* head)
-{
- while ( head )
- {
- ClassType* tmp = head;
- head = head->next;
-
- if ( tmp->name )
- snort_free(tmp->name);
-
- if ( tmp->type )
- snort_free(tmp->type);
-
- snort_free(tmp);
- }
-}
-
-static void FreeReferences(ReferenceSystemNode* head)
-{
- while ( head )
- {
- ReferenceSystemNode* tmp = head;
- head = head->next;
-
- if ( tmp->name )
- snort_free(tmp->name);
-
- if ( tmp->url )
- snort_free(tmp->url);
-
- snort_free(tmp);
- }
-}
-
static PolicyMode init_policy_mode(PolicyMode mode)
{
switch ( mode )
return;
}
- FreeClassifications(classifications);
- FreeReferences(references);
+ for ( auto ct : classifications )
+ delete ct.second;
+
+ for ( auto rs : references )
+ delete rs.second;
for ( auto* s : scratchers )
s->cleanup(this);
#include <sys/types.h>
#include <list>
+#include <unordered_map>
#include <vector>
#include "events/event_queue.h"
{
RUN_FLAG__READ = 0x00000001,
RUN_FLAG__DAEMON = 0x00000002,
- // unused = 0x00000004,
+ RUN_FLAG__DUMP_MSG_MAP = 0x00000004,
// unused = 0x00000008,
RUN_FLAG__INLINE = 0x00000010,
struct Plugins;
struct PORT_RULE_MAP;
struct RateFilterConfig;
-struct ReferenceSystemNode;
+struct ReferenceSystem;
struct RuleListNode;
struct RulePortTables;
struct SFDAQConfig;
int thiszone = 0;
+ std::unordered_map<std::string, ClassType*> classifications;
+ std::unordered_map<std::string, ReferenceSystem*> references;
+
RuleStateMap* rule_states = nullptr;
- ClassType* classifications = nullptr;
- ReferenceSystemNode* references = nullptr;
GHash* otn_map = nullptr;
ProtocolReference* proto_ref = nullptr;
{ return get_conf()->address_anomaly_check_enabled; }
// mode related
+ static bool dump_msg_map()
+ { return get_conf()->run_flags & RUN_FLAG__DUMP_MSG_MAP; }
+
static bool test_mode()
{ return get_conf()->run_flags & RUN_FLAG__TEST; }
"enable Inline-Test Mode Operation" },
{ "--gen-msg-map", Parameter::PT_IMPLIED, nullptr, nullptr,
- "dump builtin rules in gen-msg.map format for use by other tools" },
+ "dump configured rules in gen-msg.map format for use by other tools" },
{ "--help", Parameter::PT_IMPLIED, nullptr, nullptr,
"list command line options" },
sc->run_flags |= RUN_FLAG__INLINE_TEST;
else if ( v.is("--gen-msg-map") )
- dump_msg_map(sc, v.get_string());
-
+ {
+ sc->run_flags |= (RUN_FLAG__DUMP_MSG_MAP | RUN_FLAG__TEST);
+ sc->output_flags |= OUTPUT_FLAG__ALERT_REFS;
+ sc->set_quiet(true);
+ }
else if ( v.is("--help") )
help_basic(sc, v.get_string());
cout << "no match" << endl;
}
-void ModuleManager::dump_msg_map(const char* pfx)
-{
- std::vector<RulePtr> rule_set = get_rules(pfx);
-
- for ( auto rp : rule_set )
- {
- cout << rp.mod->get_gid() << " || ";
- cout << rp.rule->sid << " || ";
- cout << rp.mod->get_name() << ": ";
- cout << rp.rule->msg << endl;
- }
- if ( !rule_set.size() )
- cout << "no match" << endl;
-}
-
static void show_pegs(const char* = nullptr, bool exact = false);
static void show_rules(const char* = nullptr, bool exact = false);
- static void dump_msg_map(const char* = nullptr);
static void dump_rules(const char* = nullptr);
static void dump_defaults(const char* = nullptr);
#define SFDAQ_CONFIG_H
#include <string>
-#include <unordered_map>
#include <vector>
using DaqVar = std::pair<std::string, std::string>;
cmd_line.h
config_file.cc
config_file.h
- mstring.cc
- mstring.h
vars.cc
vars.h
)
#include "config_file.h"
#include <cstring>
+#include <sstream>
+#include <string>
#include "detection/detect.h"
#include "detection/detection_engine.h"
#include "main/analyzer.h"
#include "main/policy.h"
-#include "mstring.h"
-
-#define CHECKSUM_MODE_OPT__ALL "all"
-#define CHECKSUM_MODE_OPT__NONE "none"
-#define CHECKSUM_MODE_OPT__IP "ip"
-#define CHECKSUM_MODE_OPT__NO_IP "noip"
-#define CHECKSUM_MODE_OPT__TCP "tcp"
-#define CHECKSUM_MODE_OPT__NO_TCP "notcp"
-#define CHECKSUM_MODE_OPT__UDP "udp"
-#define CHECKSUM_MODE_OPT__NO_UDP "noudp"
-#define CHECKSUM_MODE_OPT__ICMP "icmp"
-#define CHECKSUM_MODE_OPT__NO_ICMP "noicmp"
-
using namespace snort;
static std::string lua_conf;
static int GetChecksumFlags(const char* args)
{
- char** toks;
- int num_toks;
- int i;
int negative_flags = 0;
int positive_flags = 0;
int got_positive_flag = 0;
if (args == nullptr)
return CHECKSUM_FLAG__ALL;
- toks = mSplit(args, " \t", 10, &num_toks, 0);
- for (i = 0; i < num_toks; i++)
+ std::stringstream ss(args);
+ std::string tok;
+
+ while ( ss >> tok )
{
- if (strcasecmp(toks[i], CHECKSUM_MODE_OPT__ALL) == 0)
+ if ( tok == "all" )
{
positive_flags = CHECKSUM_FLAG__ALL;
negative_flags = 0;
got_positive_flag = 1;
}
- else if (strcasecmp(toks[i], CHECKSUM_MODE_OPT__NONE) == 0)
+ else if ( tok == "none" )
{
positive_flags = 0;
negative_flags = CHECKSUM_FLAG__ALL;
got_negative_flag = 1;
}
- else if (strcasecmp(toks[i], CHECKSUM_MODE_OPT__IP) == 0)
+ else if ( tok == "ip" )
{
positive_flags |= CHECKSUM_FLAG__IP;
negative_flags &= ~CHECKSUM_FLAG__IP;
got_positive_flag = 1;
}
- else if (strcasecmp(toks[i], CHECKSUM_MODE_OPT__NO_IP) == 0)
+ else if ( tok == "noip" )
{
positive_flags &= ~CHECKSUM_FLAG__IP;
negative_flags |= CHECKSUM_FLAG__IP;
got_negative_flag = 1;
}
- else if (strcasecmp(toks[i], CHECKSUM_MODE_OPT__TCP) == 0)
+ else if ( tok == "tcp" )
{
positive_flags |= CHECKSUM_FLAG__TCP;
negative_flags &= ~CHECKSUM_FLAG__TCP;
got_positive_flag = 1;
}
- else if (strcasecmp(toks[i], CHECKSUM_MODE_OPT__NO_TCP) == 0)
+ else if ( tok == "notcp" )
{
positive_flags &= ~CHECKSUM_FLAG__TCP;
negative_flags |= CHECKSUM_FLAG__TCP;
got_negative_flag = 1;
}
- else if (strcasecmp(toks[i], CHECKSUM_MODE_OPT__UDP) == 0)
+ else if ( tok == "udp" )
{
positive_flags |= CHECKSUM_FLAG__UDP;
negative_flags &= ~CHECKSUM_FLAG__UDP;
got_positive_flag = 1;
}
- else if (strcasecmp(toks[i], CHECKSUM_MODE_OPT__NO_UDP) == 0)
+ else if ( tok == "noudp" )
{
positive_flags &= ~CHECKSUM_FLAG__UDP;
negative_flags |= CHECKSUM_FLAG__UDP;
got_negative_flag = 1;
}
- else if (strcasecmp(toks[i], CHECKSUM_MODE_OPT__ICMP) == 0)
+ else if ( tok == "icmp" )
{
positive_flags |= CHECKSUM_FLAG__ICMP;
negative_flags &= ~CHECKSUM_FLAG__ICMP;
got_positive_flag = 1;
}
- else if (strcasecmp(toks[i], CHECKSUM_MODE_OPT__NO_ICMP) == 0)
+ else if ( tok == "noicmp" )
{
positive_flags &= ~CHECKSUM_FLAG__ICMP;
negative_flags |= CHECKSUM_FLAG__ICMP;
}
else
{
- ParseError("unknown command line checksum option: %s.", toks[i]);
+ ParseError("unknown command line checksum option: %s.", tok.c_str());
return ret_flags;
}
}
ret_flags = negative_flags;
}
- mSplitFree(&toks, num_toks);
return ret_flags;
}
+++ /dev/null
-//--------------------------------------------------------------------------
-// Copyright (C) 2014-2020 Cisco and/or its affiliates. All rights reserved.
-// Copyright (C) 2002-2013 Sourcefire, Inc.
-// Copyright (C) 1998-2002 Martin Roesch <roesch@sourcefire.com>
-//
-// This program is free software; you can redistribute it and/or modify it
-// under the terms of the GNU General Public License Version 2 as published
-// by the Free Software Foundation. You may not use, modify or distribute
-// this program under any other version of the GNU General Public License.
-//
-// 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.,
-// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-//--------------------------------------------------------------------------
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "mstring.h"
-
-#include <cassert>
-
-#include "utils/util.h"
-
-namespace snort
-{
-static char* mSplitAddTok(const char*, const int, const char*, const char);
-
-/****************************************************************
- *
- * Function: mSplit()
- *
- * Purpose: Splits a string into tokens non-destructively.
- *
- * Parameters:
- * char *
- * The string to be split
- * char *
- * A string of token separators
- * int
- * The maximum number of tokens to be returned. A value
- * of 0 means to get them all.
- * int *
- * Place to store the number of tokens returned
- * char
- * The "escape metacharacter", treat the character after
- * this character as a literal and "escape" a separator.
- *
- * Note if max_toks is reached, the last tok in the returned
- * token array will possibly have separator characters in it.
- *
- * Returns:
- * 2D char array with one token per "row" of the returned
- * array.
- *
- ****************************************************************/
-// FIXIT-L eliminate mSplit(); create iterator service if needed
-char** mSplit(const char* str, const char* sep_chars, const int max_toks,
- int* num_toks, const char meta_char)
-{
- size_t cur_tok = 0; /* current token index into array of strings */
- size_t tok_start; /* index to start of token */
- size_t i, j;
- int escaped = 0;
- /* It's rare we'll need more than this even if max_toks is set really
- * high. Store toks here until finished, then allocate. If more than
- * this is necessary, then allocate max toks */
- char* toks_buf[TOKS_BUF_SIZE];
- size_t toks_buf_size = TOKS_BUF_SIZE;
- int toks_buf_size_increment = 10;
- char** toks_alloc = nullptr; /* Used if the static buf isn't enough */
- char** toks = toks_buf; /* Pointer to one of the two above */
- char** retstr;
- const char* whitespace = " \t";
-
- assert(num_toks);
- assert(str);
-
- *num_toks = 0;
- size_t str_length = strlen(str);
-
- if (str_length == 0)
- return nullptr;
-
- if (sep_chars == nullptr)
- sep_chars = whitespace;
-
- size_t sep_length = strlen(sep_chars);
-
- /* Meta char cannot also be a separator char */
- for (i = 0; i < sep_length; i++)
- {
- if (sep_chars[i] == meta_char)
- return nullptr;
- }
-
- /* Move past initial separator characters and whitespace */
- for (i = 0; i < str_length; i++)
- {
- if (isspace((int)str[i]))
- continue;
-
- for (j = 0; j < sep_length; j++)
- {
- if (str[i] == sep_chars[j])
- break;
- }
-
- /* Not a separator character or whitespace */
- if (j == sep_length)
- break;
- }
-
- if (i == str_length)
- {
- /* Nothing but separator characters or whitespace in string */
- return nullptr;
- }
-
- /* User only wanted one tok so return the rest of the string in
- * one tok */
- if ((cur_tok + 1) == (size_t)max_toks)
- {
- retstr = (char**)snort_calloc(sizeof(char*));
- retstr[cur_tok] = snort_strndup(&str[i], str_length - i);
- *num_toks = cur_tok + 1;
- return retstr;
- }
-
- /* Mark the beginning of the next tok */
- tok_start = i;
- for (; i < str_length; i++)
- {
- if (!escaped)
- {
- /* Got an escape character. Don't include it now, but
- * must be a character after it. */
- if (str[i] == meta_char)
- {
- escaped = 1;
- continue;
- }
-
- /* See if the current character is a separator */
- for (j = 0; j < sep_length; j++)
- {
- if (str[i] == sep_chars[j])
- break;
- }
-
- /* It's a normal character */
- if (j == sep_length)
- continue;
-
- /* Current character matched a separator character. Trim off
- * whitespace previous to the separator. If we get here, there
- * is at least one savable character */
- for (j = i; j > tok_start; j--)
- {
- if (!isspace((int)str[j - 1]))
- break;
- }
-
- /* Allocate a buffer. The length will not have included the
- * meta char of escaped separators */
- toks[cur_tok] = mSplitAddTok(&str[tok_start], j - tok_start, sep_chars, meta_char);
-
- /* Increment current token index */
- cur_tok++;
-
- /* Move past any more separator characters or whitespace */
- for (; i < str_length; i++)
- {
- if (isspace((int)str[i]))
- continue;
-
- for (j = 0; j < sep_length; j++)
- {
- if (str[i] == sep_chars[j])
- break;
- }
-
- /* Not a separator character or whitespace */
- if (j == sep_length)
- break;
- }
-
- /* Nothing but separator characters or whitespace left in the string */
- if (i == str_length)
- {
- *num_toks = cur_tok;
-
- if (toks != toks_alloc)
- {
- retstr = (char**)snort_calloc(cur_tok, sizeof(char*));
- memcpy(retstr, toks, (sizeof(char*) * cur_tok));
- }
- else
- {
- retstr = toks;
- }
-
- return retstr;
- }
-
- /* Reached the size of our current string buffer and need to
- * allocate something bigger. Only get here once if max toks
- * set to something other than 0 because we'll just allocate
- * max toks in that case. */
- if (cur_tok == toks_buf_size)
- {
- char** tmp;
-
- if (toks_alloc != nullptr)
- tmp = toks_alloc;
- else
- tmp = toks_buf;
-
- if (max_toks != 0)
- toks_buf_size = max_toks;
- else
- toks_buf_size = cur_tok + toks_buf_size_increment;
-
- toks_alloc = (char**)snort_calloc(toks_buf_size, sizeof(char*));
- memcpy(toks_alloc, tmp, (sizeof(char*) * cur_tok));
- toks = toks_alloc;
-
- if (tmp != toks_buf)
- snort_free(tmp);
- }
-
- if ((max_toks != 0) && ((cur_tok + 1) == (size_t)max_toks))
- {
- /* Return rest of string as last tok */
- *num_toks = cur_tok + 1;
-
- /* Already got a ret string */
- if (toks != toks_alloc)
- {
- retstr = (char**)snort_calloc(cur_tok + 1, sizeof(char*));
- memcpy(retstr, toks, (sizeof(char*) * (cur_tok + 1)));
- }
- else
- {
- retstr = toks;
- }
-
- /* Trim whitespace at end of last tok */
- for (j = str_length; j > tok_start; j--)
- {
- if (!isspace((int)str[j - 1]))
- break;
- }
-
- retstr[cur_tok] = snort_strndup(&str[i], j - i);
- return retstr;
- }
-
- tok_start = i;
- }
- else
- {
- /* This character is escaped with the meta char */
- escaped = 0;
- }
- }
-
- /* Last character was an escape character */
- if (escaped)
- {
- for (i = 0; i < cur_tok; i++)
- snort_free(toks[i]);
-
- if (toks == toks_alloc)
- snort_free(toks_alloc);
-
- return nullptr;
- }
-
- /* Trim whitespace at end of last tok */
- for (j = i; j > tok_start; j--)
- {
- if (!isspace((int)str[j - 1]))
- break;
- }
-
- /* Last character was not a separator character so we've got
- * one more tok. Unescape escaped separator characters */
- if (toks != toks_alloc)
- {
- retstr = (char**)snort_calloc(cur_tok + 1, sizeof(char*));
- memcpy(retstr, toks, (sizeof(char*) * (cur_tok + 1)));
- }
- else
- {
- retstr = toks;
- }
-
- retstr[cur_tok] = mSplitAddTok(&str[tok_start], j - tok_start, sep_chars, meta_char);
-
- /* Just add one to cur_tok index instead of incrementing
- * since we're done */
- *num_toks = cur_tok + 1;
- return retstr;
-}
-
-static char* mSplitAddTok(
- const char* str, const int len, const char* sep_chars, const char meta_char)
-{
- size_t i, j, k;
- char* tok;
- int tok_len = 0;
- int got_meta = 0;
- size_t sep_length = strlen(sep_chars);
-
- /* Get the length of the returned tok
- * Could have a maximum token length and use a fixed sized array and
- * fill it in as we go but don't want to put on that constraint */
- for (i = 0; (int)i < len; i++)
- {
- if (!got_meta)
- {
- if (str[i] == meta_char)
- {
- got_meta = 1;
- continue;
- }
- }
- else
- {
- /* See if the current character is a separator */
- for (j = 0; j < sep_length; j++)
- {
- if (str[i] == sep_chars[j])
- break;
- }
-
- /* It's a non-separator character, so include
- * the meta character in the return tok */
- if (j == sep_length)
- tok_len++;
-
- got_meta = 0;
- }
-
- tok_len++;
- }
-
- /* Allocate it and fill it in */
- tok = (char*)snort_calloc(tok_len + 1);
-
- for (i = 0, k = 0; (int)i < len; i++)
- {
- if (!got_meta)
- {
- if (str[i] == meta_char)
- {
- got_meta = 1;
- continue;
- }
- }
- else
- {
- /* See if the current character is a separator */
- for (j = 0; j < sep_length; j++)
- {
- if (str[i] == sep_chars[j])
- break;
- }
-
- /* It's a non-separator character, so include
- * the meta character in the return tok */
- if (j == sep_length)
- tok[k++] = meta_char;
-
- got_meta = 0;
- }
-
- tok[k++] = str[i];
- }
-
- return tok;
-}
-
-/****************************************************************
- *
- * Free the buffer allocated by mSplit().
- *
- * char** toks = NULL;
- * int num_toks = 0;
- * toks = (str, " ", 2, &num_toks, 0);
- * mSplitFree(&toks, num_toks);
- *
- * At this point, toks is again NULL.
- *
- ****************************************************************/
-void mSplitFree(char*** pbuf, int num_toks)
-{
- int i;
- char** buf; /* array of string pointers */
-
- if ( pbuf==nullptr || *pbuf==nullptr )
- {
- return;
- }
-
- buf = *pbuf;
-
- for ( i=0; i<num_toks; i++ )
- {
- if ( buf[i] != nullptr )
- {
- snort_free(buf[i]);
- buf[i] = nullptr;
- }
- }
-
- snort_free(buf);
- *pbuf = nullptr;
-}
-} // namespace snort
+++ /dev/null
-//--------------------------------------------------------------------------
-// Copyright (C) 2014-2020 Cisco and/or its affiliates. All rights reserved.
-// Copyright (C) 2002-2013 Sourcefire, Inc.
-// Copyright (C) 1998-2002 Martin Roesch <roesch@sourcefire.com>
-//
-// This program is free software; you can redistribute it and/or modify it
-// under the terms of the GNU General Public License Version 2 as published
-// by the Free Software Foundation. You may not use, modify or distribute
-// this program under any other version of the GNU General Public License.
-//
-// 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.,
-// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-//--------------------------------------------------------------------------
-
-#ifndef MSTRING_H
-#define MSTRING_H
-
-// Provide a variety of string functions not included in libc.
-// Deprecated - Do not use this in new code.
-
-#include "main/snort_types.h"
-
-#define TOKS_BUF_SIZE 100
-
-namespace snort
-{
-SO_PUBLIC char** mSplit(const char*, const char*, const int, int*, const char);
-SO_PUBLIC void mSplitFree(char*** toks, int numtoks);
-}
-#endif
-
void add_service_to_otn(SnortConfig* sc, OptTreeNode* otn, const char* svc_name)
{
- if ( !strcmp(svc_name, "file") and !otn->sigInfo.num_services )
+ if ( !strcmp(svc_name, "file") and otn->sigInfo.services.empty() )
{
// well-known services supporting file_data
// applies to both alert file and service:file rules
if ( !strcmp(svc_name, "http") )
add_service_to_otn(sc, otn, "http2");
- if (otn->sigInfo.num_services >= sc->max_metadata_services)
- {
- ParseError("too many service's specified for rule, can't add %s", svc_name);
- return;
- }
SnortProtocolId svc_id = sc->proto_ref->add(svc_name);
- for ( unsigned i = 0; i < otn->sigInfo.num_services; ++i )
- if ( otn->sigInfo.services[i].snort_protocol_id == svc_id )
+ for ( const auto& si : otn->sigInfo.services )
+ if ( si.snort_protocol_id == svc_id )
return; // already added
- if ( !otn->sigInfo.services )
- otn->sigInfo.services =
- (SignatureServiceInfo*)snort_calloc(sc->max_metadata_services, sizeof(SignatureServiceInfo));
-
- int idx = otn->sigInfo.num_services++;
-
- otn->sigInfo.services[idx].service = snort_strdup(svc_name);
- otn->sigInfo.services[idx].snort_protocol_id = svc_id;
+ SignatureServiceInfo si(svc_name, svc_id);
+ otn->sigInfo.services.emplace_back(si);
}
// only keep drop rules ...
// the alert case is tested for separately with SnortConfig::treat_drop_as_alert().
static inline int ScKeepDropRules()
{
- return ( SnortConfig::inline_mode() || SnortConfig::adaptor_inline_mode() || SnortConfig::treat_drop_as_ignore() );
+ return ( SnortConfig::inline_mode() or SnortConfig::adaptor_inline_mode() or
+ SnortConfig::treat_drop_as_ignore() );
}
static inline int ScLoadAsDropRules()
static int detect_rule_count = 0;
static int builtin_rule_count = 0;
static int so_rule_count = 0;
-static int head_count = 0; /* number of header blocks (chain heads?) */
-static int otn_count = 0; /* number of chains */
+static int head_count = 0; // rule headers
+static int otn_count = 0; // rule bodies
+static int dup_count = 0; // rule bodies
static int rule_proto = 0;
static rule_count_t tcpCnt;
return rtn;
}
-// Conditionally removes duplicate SID/GIDs. Keeps duplicate with
+// Conditionally removes duplicate OTN. Keeps duplicate with
// higher revision. If revision is the same, keeps newest rule.
static int mergeDuplicateOtn(
SnortConfig* sc, OptTreeNode* otn_cur,
if ( otn_new->sigInfo.rev < otn_cur->sigInfo.rev )
{
- // current OTN is newer version. Keep current and discard the new one.
- // OTN is for new policy group, salvage RTN
- deleteRtnFromOtn(otn_new, sc);
-
+ // keep orig, free new
ParseWarning(WARN_RULES, "%u:%u duplicates previous rule. Using revision %u.",
otn_cur->sigInfo.gid, otn_cur->sigInfo.sid, otn_cur->sigInfo.rev);
+ // OTN is for new policy group, salvage RTN
+ deleteRtnFromOtn(otn_new, sc);
+
// Now free the OTN itself -- this function is also used
// by the hash-table calls out of OtnRemove, so it cannot
// be modified to delete data for rule options
- OtnFree(otn_new);
+ delete otn_new;
// Add rtn to current otn for the first rule instance in a policy,
// otherwise ignore it
return true;
}
-
- // delete current rule instance and keep the new one
+ // keep new, free orig
+ ParseWarning(WARN_RULES, "%u:%u duplicates previous rule. Using revision %u.",
+ otn_new->sigInfo.gid, otn_new->sigInfo.sid, otn_new->sigInfo.rev);
for ( unsigned i = 0; i < otn_cur->proto_node_num; ++i )
{
RuleTreeNode* rtnTmp2 = deleteRtnFromOtn(otn_cur, i, sc, (rtn_cur != rtn_new));
if ( rtnTmp2 and (i != get_ips_policy()->policy_id) )
- {
addRtnToOtn(sc, otn_new, rtnTmp2, i);
- }
}
if (rtn_cur)
- {
- if (SnortConfig::conf_error_out())
- {
- ParseError("%u:%u:%u duplicates previous rule.",
- otn_new->sigInfo.gid, otn_new->sigInfo.sid, otn_new->sigInfo.rev);
- return true;
- }
- else
- {
- ParseWarning(WARN_RULES, "%u:%u duplicates previous rule. Using revision %u.",
- otn_new->sigInfo.gid, otn_new->sigInfo.sid, otn_new->sigInfo.rev);
- }
DestroyRuleTreeNode(rtn_cur);
- }
- OtnRemove(sc->otn_map, otn_cur);
+ OtnRemove(sc->otn_map, otn_cur);
return false;
}
so_rule_count = 0;
head_count = 0;
otn_count = 0;
+ dup_count = 0;
rule_proto = 0;
memset(&ipCnt, 0, sizeof(ipCnt));
void parse_rule_print()
{
- if ( !rule_count )
+ if ( !rule_count and !skip_count )
return;
LogLabel("rule counts");
LogCount("total rules loaded", rule_count);
LogCount("total rules not loaded", skip_count);
+ LogCount("duplicate rules", dup_count);
LogCount("text rules", detect_rule_count);
LogCount("builtin rules", builtin_rule_count);
LogCount("so rules", so_rule_count);
if ( !stub )
otn->sigInfo.gid = GID_DEFAULT;
- otn->chain_node_number = otn_count;
otn->snort_protocol_id = rtn.snort_protocol_id;
if ( SnortConfig::get_default_rule_state() )
if ( rtn.dip )
sfvar_free(rtn.dip);
- OtnFree(otn);
+ delete otn;
}
static bool is_builtin(uint32_t gid)
entered = true;
parse_rules_string(sc, rule);
}
- OtnFree(otn);
+ delete otn;
return;
}
if ( !sc->metadata_filter.empty() and !otn->metadata_matched() )
{
- OtnFree(otn);
+ delete otn;
FreeRuleTreeNode(&rtn);
ClearIpsOptionsVars();
skip_count++;
if ( otn_dup )
{
+ dup_count++;
otn->ruleIndex = otn_dup->ruleIndex;
if ( mergeDuplicateOtn(sc, otn_dup, otn, new_rtn) )
return;
}
}
- otn_count++;
- rule_count++;
+ else
+ {
+ otn_count++;
+ rule_count++;
+ }
if ( otn->soid )
{
otn->sigInfo.builtin = false;
- so_rule_count++;
+ if ( !otn_dup )
+ so_rule_count++;
}
else if ( is_builtin(otn->sigInfo.gid) )
{
otn->sigInfo.gid, otn->sigInfo.sid);
otn->sigInfo.builtin = true;
- builtin_rule_count++;
+ if ( !otn_dup )
+ builtin_rule_count++;
}
else
{
otn->sigInfo.gid, otn->sigInfo.sid);
otn->sigInfo.builtin = false;
- detect_rule_count++;
+ if ( !otn_dup )
+ detect_rule_count++;
}
if ( !otn_dup )
otn->ruleIndex = parser_get_rule_index(otn->sigInfo.gid, otn->sigInfo.sid);
- if ( !otn->sigInfo.message )
- otn->sigInfo.message = snort_strdup("\"no msg in rule\""); // yes, stored as "msg"
+ if ( otn->sigInfo.message.empty() )
+ otn->sigInfo.message = "\"no msg in rule\"";
OptFpList* fpl = AddOptFuncToList(OptListEnd, otn);
fpl->type = RULE_OPTION_TYPE_LEAF_NODE;
static const State fsm[] =
{
- { -1, 0, TT_NONE, FSM_ERR, nullptr, "" },
- { 0, 15, TT_LITERAL, FSM_KEY, "include", "" },
- { 0, 1, TT_LITERAL, FSM_ACT, nullptr, "(" },
- { 1, 8, TT_PUNCT, FSM_STB, "(", "(:,;)" },
- { 1, 2, TT_LITERAL, FSM_PRO, nullptr, "(" },
- { 2, 8, TT_PUNCT, FSM_HDR, "(", "(:,;)" },
- { 2, 3, TT_LIST, FSM_SIP, nullptr, "" },
- { 2, 3, TT_LITERAL, FSM_SIP, nullptr, "" },
- { 3, 5, TT_LITERAL, FSM_SPX, "->", nullptr },
- { 3, 5, TT_LITERAL, FSM_SPX, "<>", nullptr },
- { 3, 4, TT_LIST, FSM_SP, nullptr, nullptr },
- { 3, 4, TT_LITERAL, FSM_SP, nullptr, nullptr },
- { 4, 5, TT_LITERAL, FSM_DIR, nullptr, nullptr },
- { 5, 6, TT_LIST, FSM_DIP, nullptr, "(" },
- { 5, 6, TT_LITERAL, FSM_DIP, nullptr, "(" },
- { 6, 8, TT_PUNCT, FSM_DPX, "(", "(:,;)" },
- { 6, 7, TT_LIST, FSM_DP, nullptr, "(:,;)" },
- { 6, 7, TT_LITERAL, FSM_DP, nullptr, "(:,;)" },
- { 7, 8, TT_PUNCT, FSM_SOB, "(", nullptr },
- { 8, 0, TT_PUNCT, FSM_EOB, ")", nullptr },
- { 8, 13, TT_LITERAL, FSM_KEY, "metadata", nullptr },
- { 8, 16, TT_LITERAL, FSM_KEY, "reference",":;" },
- { 8, 9, TT_LITERAL, FSM_KEY, nullptr, nullptr },
- { 9, 8, TT_PUNCT, FSM_END, ";", nullptr },
- { 9, 10, TT_PUNCT, FSM_NOP, ":", nullptr },
- // we can't allow this because the syntax is squiffy
- // would prefer to require a ; after the last option
- // (and delete all the other cases like this too)
- //{ 9, 0, TT_PUNCT, FSM_EOB, ")", "" },
+ { -1, 0, TT_NONE, FSM_ERR, nullptr, "" },
+ { 0, 15, TT_LITERAL, FSM_KEY, "include", "" },
+ { 0, 1, TT_LITERAL, FSM_ACT, nullptr, "(" },
+ { 1, 8, TT_PUNCT, FSM_STB, "(", "(:,;)" },
+ { 1, 2, TT_LITERAL, FSM_PRO, nullptr, "(" },
+ { 2, 8, TT_PUNCT, FSM_HDR, "(", "(:,;)" },
+ { 2, 3, TT_LIST, FSM_SIP, nullptr, "" },
+ { 2, 3, TT_LITERAL, FSM_SIP, nullptr, "" },
+ { 3, 5, TT_LITERAL, FSM_SPX, "->", nullptr },
+ { 3, 5, TT_LITERAL, FSM_SPX, "<>", nullptr },
+ { 3, 4, TT_LIST, FSM_SP, nullptr, nullptr },
+ { 3, 4, TT_LITERAL, FSM_SP, nullptr, nullptr },
+ { 4, 5, TT_LITERAL, FSM_DIR, nullptr, nullptr },
+ { 5, 6, TT_LIST, FSM_DIP, nullptr, "(" },
+ { 5, 6, TT_LITERAL, FSM_DIP, nullptr, "(" },
+ { 6, 8, TT_PUNCT, FSM_DPX, "(", "(:,;)" },
+ { 6, 7, TT_LIST, FSM_DP, nullptr, "(:,;)" },
+ { 6, 7, TT_LITERAL, FSM_DP, nullptr, "(:,;)" },
+ { 7, 8, TT_PUNCT, FSM_SOB, "(", nullptr },
+ { 8, 0, TT_PUNCT, FSM_EOB, ")", nullptr },
+ { 8, 13, TT_LITERAL, FSM_KEY, "metadata", nullptr },
+ { 8, 16, TT_LITERAL, FSM_KEY, "reference",":;" },
+ { 8, 9, TT_LITERAL, FSM_KEY, nullptr, nullptr },
+ { 9, 8, TT_PUNCT, FSM_END, ";", nullptr },
+ { 9, 10, TT_PUNCT, FSM_NOP, ":", nullptr },
+ // we can't allow this because the syntax is squiffy
+ // would prefer to require a ; after the last option
+ // (and delete all the other cases like this too)
+ // { 9, 0, TT_PUNCT, FSM_EOB, ")", "" },
{ 10, 12, TT_STRING, FSM_OPT, nullptr, nullptr },
{ 10, 11, TT_LITERAL, FSM_OPT, nullptr, nullptr },
{ 11, 12, TT_STRING, FSM_VAL, nullptr, nullptr },
{ 11, 12, TT_LITERAL, FSM_VAL, nullptr, nullptr },
{ 11, 8, TT_PUNCT, FSM_END, ";", nullptr },
- { 11, 0, TT_PUNCT, FSM_EOB, ")", "" },
+ { 11, 0, TT_PUNCT, FSM_EOB, ")", "" },
{ 11, 10, TT_PUNCT, FSM_SET, ",", nullptr },
{ 12, 8, TT_PUNCT, FSM_END, ";", nullptr },
- { 12, 0, TT_PUNCT, FSM_EOB, ")", "" },
+ { 12, 0, TT_PUNCT, FSM_EOB, ")", "" },
{ 12, 10, TT_PUNCT, FSM_SET, ",", nullptr },
{ 13, 14, TT_PUNCT, FSM_NOP, ":", nullptr },
{ 14, 8, TT_PUNCT, FSM_END, ";", "(:,;)" },
{ 14, 14, TT_NONE, FSM_SET, ",", nullptr },
{ 14, 14, TT_NONE, FSM_ADD, nullptr, nullptr },
{ 15, 0, TT_LITERAL, FSM_INC, nullptr, nullptr },
- { 16, 14, TT_PUNCT, FSM_NOP, ":", ";" },
+ { 16, 14, TT_PUNCT, FSM_NOP, ":", ";" },
};
static const State* get_state(int num, TokenType type, const string& tok)
#include <cassert>
#include <iostream>
+#include <sstream>
+#include <string>
#include "detection/fp_config.h"
#include "detection/rules.h"
#include "utils/util_cstring.h"
#include "config_file.h"
-#include "mstring.h"
#include "parse_conf.h"
#include "parse_rule.h"
#include "parse_stream.h"
if ( !*order )
order = "pass drop alert log"; // FIXIT-H apply builtin module defaults
- int num_toks;
- char** toks = mSplit(order, " \t", 0, &num_toks, 0);
+ std::stringstream ss(order);
+ std::string tok;
- for ( int i = 0; i < num_toks; i++ )
+ while ( ss >> tok )
{
RuleListNode* prev = nullptr;
RuleListNode* node = sc->rule_lists;
while (node != nullptr)
{
- if (strcmp(toks[i], node->name) == 0)
+ if ( tok == node->name )
{
if (prev == nullptr)
sc->rule_lists = node->next;
// ignore rule types that aren't in use
}
- mSplitFree(&toks, num_toks);
-
/* anything left in the rule lists needs to be moved to the ordered lists */
while (sc->rule_lists != nullptr)
{
si_table.set_field("class_id", si->class_id);
si_table.set_field("priority", si->priority);
si_table.set_field("builtin", si->builtin);
- si_table.set_field("num_services", si->num_services);
Lua::Table(L, 2).set_field_from_stack("sig_info", si_table.index);
}
si_table.get_field("class_id", si->class_id);
si_table.get_field("priority", si->priority);
si_table.get_field("builtin", si->builtin);
- si_table.get_field("num_services", si->num_services);
}
set_fields(L, 2, self);
class AssistantGadgetEvent : public snort::DataEvent
{
public:
- AssistantGadgetEvent(snort::Packet* packet, const char* _service)
- : p(packet), service(_service)
+ AssistantGadgetEvent(snort::Packet* packet, const char* _service) :
+ p(packet), service(_service)
{ }
snort::Packet* get_packet() override
{
public:
BackOrifice() = default;
-
+
void eval(Packet*) override;
};
{
public:
Http2DataCutter(Http2FlowData* flow_data, uint32_t len, HttpCommon::SourceId
- src_id, bool is_padded);
+ src_id, bool is_padded);
snort::StreamSplitter::Status scan(const uint8_t* data, uint32_t length,
- uint32_t* flush_offset);
+ uint32_t* flush_offset);
const snort::StreamBuffer reassemble(unsigned total, unsigned offset, const uint8_t* data,
unsigned len);
{
public:
~Http2DataFrame() override {}
- void clear() override;
+ void clear() override;
uint32_t get_xtradata_mask() override { return xtradata_mask; }
bool is_detection_required() const override { return detection_required; }
-
+
friend Http2Frame* Http2Frame::new_frame(const uint8_t*, const int32_t, const uint8_t*,
const int32_t, Http2FlowData*, HttpCommon::SourceId);
//--------------------------------------------------------------------------
// http2_dummy_packet.h author Katura Harvey <katharve@cisco.com>
-/*
+/*
* The purpose of this Packet subclass is to enable H2I to take direction from http_inspect on
* whether or not to send a frame to detection. When http_inspect is processing normal HTTP/1.1
* traffic it is dealing with a real packet that has a context, the field on which disable_all()
return new Http2SettingsFrame(header, header_len, data, data_len, session_data,
source_id);
case FT_DATA:
- return new Http2DataFrame(header, header_len, data, data_len, session_data, source_id);
+ return new Http2DataFrame(header, header_len, data, data_len, session_data, source_id);
default:
return new Http2Frame(header, header_len, data, data_len, session_data, source_id);
}
{
public:
~Http2HeadersFrame() override;
- void clear() override;
+ void clear() override;
const Field& get_buf(unsigned id) override;
uint32_t get_xtradata_mask() override { return xtradata_mask; }
{ assert(hi_flow_data == nullptr); hi_flow_data = flow_data; }
HttpMsgSection* get_hi_msg_section() const { return hi_msg_section; }
void set_hi_msg_section(HttpMsgSection* section) { hi_msg_section = section; }
- uint32_t get_xtradata_mask() { return (current_frame != nullptr) ?
+ uint32_t get_xtradata_mask() { return (current_frame != nullptr) ?
current_frame->get_xtradata_mask() : 0; }
Http2Frame *get_current_frame() { return current_frame; }
- Http2DataCutter* get_data_cutter(HttpCommon::SourceId source_id, uint32_t len=0, bool is_padded=false);
- void set_data_cutter(Http2DataCutter* cutter, HttpCommon::SourceId source_id) { data_cutter[source_id] = cutter; }
- bool get_abort_data_processing(HttpCommon::SourceId source_id) const { return abort_data_processing[source_id]; }
- void set_abort_data_processing(HttpCommon::SourceId source_id) { abort_data_processing[source_id] = true; }
-
+
+ Http2DataCutter* get_data_cutter(
+ HttpCommon::SourceId source_id, uint32_t len=0, bool is_padded=false);
+
+ void set_data_cutter(Http2DataCutter* cutter, HttpCommon::SourceId source_id)
+ { data_cutter[source_id] = cutter; }
+
+ bool get_abort_data_processing(HttpCommon::SourceId source_id) const
+ { return abort_data_processing[source_id]; }
+
+ void set_abort_data_processing(HttpCommon::SourceId source_id)
+ { abort_data_processing[source_id] = true; }
+
#ifdef REG_TEST
void print_frame(FILE* output);
#endif
pkt->flow->set_flow_data(session_data = new Http2FlowData(pkt->flow));
Http2Module::increment_peg_counts(PEG_FLOW);
}
-
+
#ifdef REG_TEST
uint32_t dummy_flush_offset;
// General mechanism to abort using scan
if (session_data->frame_type[source_id] == FT__ABORT)
return HttpStreamSplitter::status_value(StreamSplitter::ABORT, true);
-
+
const StreamSplitter::Status ret_val =
implement_scan(session_data, data, length, flush_offset, source_id);
else
{
uint32_t data_offset = 0;
-
+
if (offset == 0)
{
// This is the first reassemble() for this frame and we need to allocate some buffers
HttpEnums::SectionType get_type_expected(HttpCommon::SourceId source_id)
{ return type_expected[source_id]; }
-
+
private:
bool for_http2 = false;
return;
case URI_AUTHORITY:
{
- if ((host.length() > 0) &&
- UriNormalizer::need_norm(host, false, uri_param, infractions, events))
+ if ((host.length() > 0) &&
+ UriNormalizer::need_norm(host, false, uri_param, infractions, events))
{
const int total_length = uri.length();
// This URI is OK, normalization not required
path_norm.set(path);
query_norm.set(query);
-
+
const int path_len = (path.length() > 0) ? path.length() : 0;
// query_len = length of query + 1 (? char)
const int query_len = (query.length() >= 0) ? query.length() + 1 : 0;
uint8_t *buf = new uint8_t[host.length()];
*infractions += INF_URI_NEED_NORM_HOST;
-
- UriNormalizer::normalize(host, host_norm, false, buf, uri_param,
+
+ UriNormalizer::normalize(host, host_norm, false, buf, uri_param,
infractions, events, true);
}
else
if (fragment_norm.length() != STAT_NOT_COMPUTE)
return fragment_norm;
- if ((fragment.length() > 0) and
+ if ((fragment.length() > 0) and
UriNormalizer::need_norm(fragment, false, uri_param, infractions, events))
{
uint8_t *buf = new uint8_t[fragment.length()];
client.init_flush_policy();
server.init_flush_policy();
+
+ set_no_ack(config->no_ack);
}
splitter_init = true;
}
// FIXIT-H need to do something here to handle check for need to swap trackers??
if ( !config )
- {
config = get_tcp_cfg(flow->ssn_server);
- set_no_ack(config->no_ack);
- }
if( !tcp_init )
set_os_policy();
flow->set_ttl(tsd.get_pkt(), true);
}
+void TcpStreamSession::set_no_ack(bool b)
+{
+ if (
+ server.get_flush_policy() == STREAM_FLPOLICY_ON_DATA and
+ client.get_flush_policy() == STREAM_FLPOLICY_ON_DATA )
+ {
+ no_ack = b;
+ }
+}
+
uint8_t TcpStreamSession::get_reassembly_direction()
{
uint8_t dir = SSN_DIR_NONE;
//-------------------------------------------------------------------------
// tcp module stuff
//-------------------------------------------------------------------------
+
void TcpStreamSession::print()
{
char buf[64];
server.print();
}
-
void SetPacketHeaderFoo(const snort::Packet* p);
void GetPacketHeaderFoo(DAQ_PktHdr_t* pkth, uint32_t dir);
void SwapPacketHeaderFoo();
- void set_no_ack(bool b) { no_ack = b; }
+ void set_no_ack(bool);
bool no_ack_mode_enabled() { return no_ack; }
virtual void update_perf_base_state(char) { }
#include "stats.h"
+#include <cassert>
+
#include "detection/detection_engine.h"
#include "file_api/file_stats.h"
#include "filters/sfthreshold.h"
LogMessage("%25.25s: %lu.%06lu\n", "seconds",
(unsigned long)difftime.tv_sec, (unsigned long)difftime.tv_usec);
- uint64_t num_pkts = (uint64_t)ModuleManager::get_module("daq")->get_global_count("received");
+ Module* daq = ModuleManager::get_module("daq");
+ assert(daq);
+
+ uint64_t num_pkts = (uint64_t)daq->get_global_count("analyzed");
+ uint64_t num_byts = (uint64_t)daq->get_global_count("rx_bytes");
- LogMessage("%25.25s: " STDu64 "\n", "packets", num_pkts);
+ if ( uint64_t pps = (num_pkts / total_secs) )
+ LogMessage("%25.25s: " STDu64 "\n", "pkts/sec", pps);
- uint64_t pps = (num_pkts / total_secs);
- LogMessage("%25.25s: " STDu64 "\n", "pkts/sec", pps);
+ if ( uint64_t mbps = 8 * num_byts / total_secs / 1024 / 1024 )
+ LogMessage("%25.25s: " STDu64 "\n", "Mbits/sec", mbps);
}
//-------------------------------------------------------------------------