From: Russ Combs (rucombs) Date: Mon, 9 Mar 2020 23:59:23 +0000 (+0000) Subject: Merge pull request #2050 in SNORT/snort3 from ~RUCOMBS/snort3:long_road to master X-Git-Tag: 3.0.0-269~6 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=19edc10e8f113247f6105ad7cba3d55c6bfa4988;p=thirdparty%2Fsnort3.git Merge pull request #2050 in SNORT/snort3 from ~RUCOMBS/snort3:long_road to master Squashed commit of the following: commit 7fac732d47e375c11ccaaa09c460ce097698c052 Author: russ Date: Sat Mar 7 16:55:46 2020 -0500 build: use const and auto references where possible commit ab2497818f6dbcfb448deee8b29ba60ba69dcda6 Author: russ Date: Fri Mar 6 17:56:59 2020 -0500 style: remove tabs and too long lines commit ef713d0a2672db3c3e99fec22085a871c9554493 Author: russ Date: Sun Mar 1 23:56:53 2020 -0500 parser: remove legacy parsing code commit 8cb33a613e08adc45eacc3ec7ec1f0fef4e6aba6 Author: russ Date: Sun Mar 1 13:09:13 2020 -0500 service: update implementation to vector commit f1abe6fd867f95825860489b075f77c392fa2efc Author: russ Date: Sun Mar 1 12:37:42 2020 -0500 rules: add constructors for references and classifications commit a8bd8c55d6a1f639a5107a86d34d1126d1759cf4 Author: russ Date: Sun Mar 1 11:21:10 2020 -0500 classifications: use consistent variable names commit b7c8f3bcc6ea05b65c607cb3955860c4cc4539dd Author: russ Date: Sun Mar 1 11:01:39 2020 -0500 reference: update implementation to vector commit 7d0e021b805a82aeabe2af0fa09259d5afc3a2e7 Author: russ Date: Sun Mar 1 10:23:08 2020 -0500 references: update implementation with unordered map commit f85ef33a59b2bc3d6a81fbcc0ed97ac433fd8f4d Author: russ Date: Sun Mar 1 09:38:47 2020 -0500 classifications: update implementation with unordered map commit 7046a630d3e94901b0c0bb0c61404666ba547e8d Author: russ Date: Sun Mar 1 08:45:28 2020 -0500 build: tweak includes commit 43db2d95c454236cf638c280736fa6ac506e9eaa Author: russ Date: Sat Feb 29 17:12:58 2020 -0500 stats: update shutdown timing stats Fix pkts/sec to use analyzed packet count. Also remove packets which is already provided under daq stats. Add Mbits/sec. commit 3a331613022272a845ca4e3ee30e2e6d486abe1f Author: russ Date: Thu Feb 27 09:32:55 2020 -0500 # This is a combination of 2 commits. # This is the 1st commit message: rules: simplify implementation of services, classifications, and references by using std::string # The commit message #2 will be skipped: # fixup std::string commit ee176681f558429e98e1a2dcca9bc318b2051f56 Author: russ Date: Wed Feb 26 23:16:21 2020 -0500 rules: update --gen-msg-map to include all configured rules with references commit 431dddb0a50b2dd1766cc12f8d5454d43367aaa1 Author: russ Date: Sun Feb 23 08:15:54 2020 -0500 rules: remove cruft commit 51816c1d9776221651bc639bd9870df4d6285212 Author: russ Date: Sun Feb 23 08:15:07 2020 -0500 rules: fix warnings and startup counts for duplicates commit 1c9f4b1ca655c9e8ed3bab2814caaa21616891b5 Author: russ Date: Sun Feb 23 08:12:19 2020 -0500 stream_tcp: no_ack applies only to ips mode --- diff --git a/src/codecs/link/test/cisco_meta_data_test.cc b/src/codecs/link/test/cisco_meta_data_test.cc index d66b38fa1..740b09187 100644 --- a/src/codecs/link/test/cisco_meta_data_test.cc +++ b/src/codecs/link/test/cisco_meta_data_test.cc @@ -16,7 +16,7 @@ // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. //-------------------------------------------------------------------------- -// cisco_meta_data_test.cc author Sunirmal Mukherjee +// cisco_meta_data_test.cc author Sunirmal Mukherjee // unit test main #ifdef HAVE_CONFIG_H @@ -74,7 +74,7 @@ static inline void push_layer(Packet* p, lyr.start = hdr_start; lyr.length = (uint16_t)len; } - + TEST_GROUP(cisco_meta_data_test) { }; @@ -86,14 +86,17 @@ TEST(cisco_meta_data_test, cisco_meta_data_class_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(cmd_data + sizeof(cisco_meta_data::CiscoMetaDataHdr)); + reinterpret_cast(cmd_data + + sizeof(cisco_meta_data::CiscoMetaDataHdr)); + cmd_options->sgt = 512; len = (sizeof(cisco_meta_data::CiscoMetaDataHdr) + sizeof(cisco_meta_data::CiscoMetaDataOpt)); diff --git a/src/detection/detect.cc b/src/detection/detect.cc index dd1add31a..ddaa9c4ad 100644 --- a/src/detection/detect.cc +++ b/src/detection/detect.cc @@ -88,7 +88,7 @@ void CallLogFuncs(Packet* p, const OptTreeNode* otn, ListHead* head) 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) @@ -113,7 +113,7 @@ 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); } /* diff --git a/src/detection/detection_options.cc b/src/detection/detection_options.cc index 884ebe2ab..f3b2cb631 100644 --- a/src/detection/detection_options.cc +++ b/src/detection/detection_options.cc @@ -422,23 +422,22 @@ int detection_option_node_evaluate( 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 } } diff --git a/src/detection/fp_utils.cc b/src/detection/fp_utils.cc index 1738780d2..a2b57e070 100644 --- a/src/detection/fp_utils.cc +++ b/src/detection/fp_utils.cc @@ -356,7 +356,7 @@ PatternMatchVector get_fp_content( } } - 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; diff --git a/src/detection/service_map.cc b/src/detection/service_map.cc index 65eedc998..4e7dee794 100644 --- a/src/detection/service_map.cc +++ b/src/detection/service_map.cc @@ -212,10 +212,10 @@ void fpCreateServiceMaps(SnortConfig* sc) 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); } } } diff --git a/src/detection/signature.cc b/src/detection/signature.cc index 5d6f8fb4a..f8d5ef51a 100644 --- a/src/detection/signature.cc +++ b/src/detection/signature.cc @@ -23,6 +23,7 @@ #endif #include +#include #include "signature.h" @@ -38,122 +39,86 @@ 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) { @@ -166,56 +131,38 @@ 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; } @@ -276,3 +223,25 @@ void OtnLookupFree(GHash* otn_map) 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(); + } +} + diff --git a/src/detection/signature.h b/src/detection/signature.h index d27f93ad4..e2bc047c9 100644 --- a/src/detection/signature.h +++ b/src/detection/signature.h @@ -26,6 +26,7 @@ #include #include +#include #include "target_based/snort_protocols.h" @@ -37,44 +38,44 @@ struct SnortConfig; 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; }; @@ -89,10 +90,11 @@ enum Target struct SigInfo { - char* message = nullptr; - ClassType* class_type = nullptr; - ReferenceNode* refs = nullptr; - SignatureServiceInfo* services = nullptr; + std::string message; + std::vector refs; + std::vector services; + + const ClassType* class_type = nullptr; uint32_t gid = 0; uint32_t sid = 0; @@ -100,7 +102,6 @@ struct SigInfo uint32_t class_id = 0; uint32_t priority = 0; - uint32_t num_services = 0; bool builtin = false; Target target = TARGET_NONE; @@ -112,10 +113,9 @@ OptTreeNode* OtnLookup(snort::GHash*, uint32_t gid, uint32_t sid); 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 diff --git a/src/detection/treenodes.h b/src/detection/treenodes.h index 73d86697d..7449124f9 100644 --- a/src/detection/treenodes.h +++ b/src/detection/treenodes.h @@ -148,6 +148,8 @@ struct RuleTreeNode // represents body part of rule struct OptTreeNode { + ~OptTreeNode(); + using Flag = uint8_t; static constexpr Flag WARNED_FP = 0x01; static constexpr Flag STATELESS = 0x02; @@ -169,7 +171,7 @@ struct OptTreeNode // 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; diff --git a/src/framework/mpse.h b/src/framework/mpse.h index d15f61f8a..9784168cb 100644 --- a/src/framework/mpse.h +++ b/src/framework/mpse.h @@ -27,8 +27,6 @@ #include #include -#include -#include #include "framework/base_api.h" #include "main/snort_types.h" diff --git a/src/framework/mpse_batch.h b/src/framework/mpse_batch.h index ebbb6d618..f6d7c6ce0 100644 --- a/src/framework/mpse_batch.h +++ b/src/framework/mpse_batch.h @@ -20,6 +20,9 @@ #ifndef MPSE_BATCH_H #define MPSE_BATCH_H +#include +#include + #include "framework/mpse.h" #include "main/snort_types.h" diff --git a/src/hash/test/ghash_test.cc b/src/hash/test/ghash_test.cc index fba122d44..f0543f88c 100644 --- a/src/hash/test/ghash_test.cc +++ b/src/hash/test/ghash_test.cc @@ -191,7 +191,7 @@ TEST(ghash, userfree_test) // 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); diff --git a/src/ips_options/ips_classtype.cc b/src/ips_options/ips_classtype.cc index 298718f6f..4c03736d9 100644 --- a/src/ips_options/ips_classtype.cc +++ b/src/ips_options/ips_classtype.cc @@ -55,7 +55,7 @@ public: { return DETECT; } public: - ClassType* type; + const ClassType* type; }; bool ClassTypeModule::set(const char*, Value& v, SnortConfig* sc) @@ -63,7 +63,7 @@ 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; } diff --git a/src/ips_options/ips_flowbits.cc b/src/ips_options/ips_flowbits.cc index 5b6336faf..7078efd78 100644 --- a/src/ips_options/ips_flowbits.cc +++ b/src/ips_options/ips_flowbits.cc @@ -17,23 +17,7 @@ // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. //-------------------------------------------------------------------------- -/* - ** Major rewrite: Hui Cao - ** - ** 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 #ifdef HAVE_CONFIG_H #include "config.h" @@ -42,6 +26,8 @@ #include "ips_flowbits.h" #include +#include +#include #include "framework/ips_option.h" #include "framework/module.h" @@ -49,7 +35,6 @@ #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" @@ -57,18 +42,13 @@ #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 @@ -90,11 +70,11 @@ static THREAD_LOCAL ProfileStats flowBitsPerfStats; */ 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 @@ -114,33 +94,25 @@ 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 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 @@ -155,11 +127,10 @@ 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 { @@ -195,8 +166,8 @@ uint32_t FlowBitsOption::hash() const { 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; @@ -205,7 +176,7 @@ uint32_t FlowBitsOption::hash() const 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) { @@ -218,13 +189,13 @@ uint32_t FlowBitsOption::hash() const } 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; @@ -241,13 +212,13 @@ bool FlowBitsOption::operator==(const IpsOption& ips) const 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; @@ -259,14 +230,7 @@ bool FlowBitsOption::operator==(const IpsOption& ips) const 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); } //------------------------------------------------------------------------- @@ -286,20 +250,21 @@ static inline BitOp* get_flow_bitop(const Packet* p, FlowBitState* flowbit_state 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; @@ -307,23 +272,25 @@ static inline int clear_group_bit(BitOp* bitop, char* group, FlowBitState* flowb /* 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; @@ -338,47 +305,47 @@ static inline int toggle_group_bit(BitOp* bitop, char* group, FlowBitState* flow } 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); @@ -388,10 +355,12 @@ static inline int is_set_flowbits( 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 ) @@ -404,12 +373,9 @@ static inline int is_set_flowbits( } } -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); @@ -418,77 +384,62 @@ static IpsOption::EvalStatus check_flowbits( 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; @@ -503,19 +454,11 @@ static IpsOption::EvalStatus check_flowbits( 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; } @@ -526,11 +469,11 @@ static IpsOption::EvalStatus check_flowbits( 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(); } @@ -569,37 +512,32 @@ int FlowBits_SetOperation(void* option_data) // 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; iflowbits_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) { @@ -618,9 +556,10 @@ static FLOWBITS_OBJECT* getFlowBitItem(char* flowbitName, FLOWBITS_OP* flowbits, } } - 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; @@ -645,71 +584,60 @@ static FLOWBITS_OBJECT* getFlowBitItem(char* flowbitName, FLOWBITS_OP* flowbits, 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) @@ -717,22 +645,23 @@ 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" @@ -740,8 +669,8 @@ static void validateFlowbitsSyntax(FLOWBITS_OP* flowbits) 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" @@ -749,10 +678,10 @@ static void validateFlowbitsSyntax(FLOWBITS_OP* flowbits) 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 " @@ -761,10 +690,10 @@ static void validateFlowbitsSyntax(FLOWBITS_OP* flowbits) 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 " @@ -773,15 +702,17 @@ static void validateFlowbitsSyntax(FLOWBITS_OP* flowbits) 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; @@ -791,165 +722,112 @@ static void validateFlowbitsSyntax(FLOWBITS_OP* flowbits) } } -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; } @@ -981,17 +859,17 @@ static void init_groups(FlowBitState* flowbit_state) { 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; @@ -1013,19 +891,19 @@ static void FlowBitsVerify(FlowBitState* flowbit_state) 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 */ } @@ -1045,20 +923,20 @@ static void FlowBitsVerify(FlowBitState* flowbit_state) 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; } //------------------------------------------------------------------------- @@ -1067,13 +945,13 @@ static void FlowBitsGrpFree(void* d) 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 } @@ -1100,26 +978,31 @@ public: 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; @@ -1128,8 +1011,11 @@ bool FlowbitsModule::set(const char*, Value& v, SnortConfig*) 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() @@ -1173,7 +1059,7 @@ static void flowbits_verify(SnortConfig* sc) { FlowBitState* flowbit_state = sc->flowbit_state; init_groups(flowbit_state); - FlowBitsVerify(flowbit_state); + flowbits_verify(flowbit_state); } #if 0 @@ -1184,7 +1070,7 @@ char* group_name = ((FLOWBITS_OP*)idx_dup)->group; 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); } diff --git a/src/ips_options/ips_isdataat.cc b/src/ips_options/ips_isdataat.cc index f39124891..37df2ddac 100644 --- a/src/ips_options/ips_isdataat.cc +++ b/src/ips_options/ips_isdataat.cc @@ -44,7 +44,6 @@ #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" @@ -171,13 +170,7 @@ IpsOption::EvalStatus IsDataAtOption::eval(Cursor& c, Packet*) 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 == '!') { @@ -192,12 +185,14 @@ static void isdataat_parse(const char* data, IsDataAtData* idx) /* 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; } @@ -216,8 +211,6 @@ static void isdataat_parse(const char* data, IsDataAtData* idx) return; } } - - mSplitFree(&toks,num_toks); } //------------------------------------------------------------------------- diff --git a/src/ips_options/ips_msg.cc b/src/ips_options/ips_msg.cc index 0946d98ba..9133c137e 100644 --- a/src/ips_options/ips_msg.cc +++ b/src/ips_options/ips_msg.cc @@ -85,7 +85,7 @@ static void mod_dtor(Module* m) 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; } diff --git a/src/ips_options/ips_reference.cc b/src/ips_options/ips_reference.cc index 947b53909..78f5cf9ba 100644 --- a/src/ips_options/ips_reference.cc +++ b/src/ips_options/ips_reference.cc @@ -37,11 +37,8 @@ using namespace snort; 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: ," }, { nullptr, Parameter::PT_MAX, nullptr, nullptr, nullptr } }; @@ -75,15 +72,18 @@ bool ReferenceModule::begin(const char*, int, SnortConfig* sc) 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; } @@ -104,7 +104,7 @@ static void mod_dtor(Module* m) 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; } diff --git a/src/log/log_text.cc b/src/log/log_text.cc index 17cb4a968..0c72dbc44 100644 --- a/src/log/log_text.cc +++ b/src/log/log_text.cc @@ -72,11 +72,8 @@ void LogTimeStamp(TextLog* log, Packet* p) */ 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); } @@ -1034,37 +1031,19 @@ void LogICMPHeader(TextLog* log, Packet* p) * 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()); } } diff --git a/src/loggers/alert_csv.cc b/src/loggers/alert_csv.cc index 51c25ff90..91d44be93 100644 --- a/src/loggers/alert_csv.cc +++ b/src/loggers/alert_csv.cc @@ -77,8 +77,8 @@ static void ff_action(const Args& a) 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); } diff --git a/src/loggers/alert_json.cc b/src/loggers/alert_json.cc index 812e17b1a..8f7d1cac6 100644 --- a/src/loggers/alert_json.cc +++ b/src/loggers/alert_json.cc @@ -90,8 +90,8 @@ static bool 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(); print_label(a, "class"); TextLog_Quote(json_log, cls); diff --git a/src/loggers/alert_luajit.cc b/src/loggers/alert_luajit.cc index 2c54b6e02..17620bced 100644 --- a/src/loggers/alert_luajit.cc +++ b/src/loggers/alert_luajit.cc @@ -57,13 +57,11 @@ SO_PUBLIC const SnortEvent* get_event() 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; } diff --git a/src/loggers/alert_syslog.cc b/src/loggers/alert_syslog.cc index 620605f17..eb7b40d37 100644 --- a/src/loggers/alert_syslog.cc +++ b/src/loggers/alert_syslog.cc @@ -210,11 +210,10 @@ static void AlertSyslog( 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) diff --git a/src/main.cc b/src/main.cc index f95e191b5..8d5afaa53 100644 --- a/src/main.cc +++ b/src/main.cc @@ -26,6 +26,7 @@ #include #include "control/idle_processing.h" +#include "detection/signature.h" #include "framework/module.h" #include "helpers/process.h" #include "helpers/ring.h" @@ -789,6 +790,12 @@ static bool set_mode() 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", diff --git a/src/main/help.cc b/src/main/help.cc index fa9e689a4..0743f76b9 100644 --- a/src/main/help.cc +++ b/src/main/help.cc @@ -146,7 +146,7 @@ void help_args(const char* pfx) 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 }; @@ -178,9 +178,6 @@ enum HelpType 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; @@ -312,11 +309,6 @@ void config_markup(SnortConfig*, const char*) 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); diff --git a/src/main/help.h b/src/main/help.h index c0c5b34ef..c51cfa20d 100644 --- a/src/main/help.h +++ b/src/main/help.h @@ -55,7 +55,6 @@ void help_args(const char* pfx); [[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); diff --git a/src/main/modules.cc b/src/main/modules.cc index cbb683d84..08a511d56 100644 --- a/src/main/modules.cc +++ b/src/main/modules.cc @@ -520,7 +520,7 @@ bool ClassificationsModule::begin(const char*, int, SnortConfig*) 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; } @@ -587,7 +587,7 @@ bool ReferencesModule::begin(const char*, int, SnortConfig*) 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; } diff --git a/src/main/snort_config.cc b/src/main/snort_config.cc index 3fb2de0cf..7576067d0 100644 --- a/src/main/snort_config.cc +++ b/src/main/snort_config.cc @@ -94,40 +94,6 @@ static std::vector scratch_handlers; // 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 ) @@ -252,8 +218,11 @@ SnortConfig::~SnortConfig() 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); diff --git a/src/main/snort_config.h b/src/main/snort_config.h index ce428f451..204140c91 100644 --- a/src/main/snort_config.h +++ b/src/main/snort_config.h @@ -26,6 +26,7 @@ #include #include +#include #include #include "events/event_queue.h" @@ -41,7 +42,7 @@ enum RunFlag { RUN_FLAG__READ = 0x00000001, RUN_FLAG__DAEMON = 0x00000002, - // unused = 0x00000004, + RUN_FLAG__DUMP_MSG_MAP = 0x00000004, // unused = 0x00000008, RUN_FLAG__INLINE = 0x00000010, @@ -139,7 +140,7 @@ struct MemoryConfig; struct Plugins; struct PORT_RULE_MAP; struct RateFilterConfig; -struct ReferenceSystemNode; +struct ReferenceSystem; struct RuleListNode; struct RulePortTables; struct SFDAQConfig; @@ -343,9 +344,10 @@ public: int thiszone = 0; + std::unordered_map classifications; + std::unordered_map references; + RuleStateMap* rule_states = nullptr; - ClassType* classifications = nullptr; - ReferenceSystemNode* references = nullptr; GHash* otn_map = nullptr; ProtocolReference* proto_ref = nullptr; @@ -501,6 +503,9 @@ public: { 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; } diff --git a/src/main/snort_module.cc b/src/main/snort_module.cc index 17cd9c3c0..94cdde1af 100644 --- a/src/main/snort_module.cc +++ b/src/main/snort_module.cc @@ -352,7 +352,7 @@ static const Parameter s_params[] = "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" }, @@ -847,8 +847,11 @@ bool SnortModule::set(const char*, Value& v, SnortConfig* sc) 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()); diff --git a/src/managers/module_manager.cc b/src/managers/module_manager.cc index 25a43605a..08b21f7da 100644 --- a/src/managers/module_manager.cc +++ b/src/managers/module_manager.cc @@ -1578,18 +1578,3 @@ void ModuleManager::show_rules(const char* pfx, bool exact) cout << "no match" << endl; } -void ModuleManager::dump_msg_map(const char* pfx) -{ - std::vector 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; -} - diff --git a/src/managers/module_manager.h b/src/managers/module_manager.h index eef450c2d..c522d92c4 100644 --- a/src/managers/module_manager.h +++ b/src/managers/module_manager.h @@ -69,7 +69,6 @@ public: 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); diff --git a/src/packet_io/sfdaq_config.h b/src/packet_io/sfdaq_config.h index 9e2f30779..1bd4d4173 100644 --- a/src/packet_io/sfdaq_config.h +++ b/src/packet_io/sfdaq_config.h @@ -22,7 +22,6 @@ #define SFDAQ_CONFIG_H #include -#include #include using DaqVar = std::pair; diff --git a/src/parser/CMakeLists.txt b/src/parser/CMakeLists.txt index 479045e91..c3658eaa6 100644 --- a/src/parser/CMakeLists.txt +++ b/src/parser/CMakeLists.txt @@ -22,8 +22,6 @@ add_library (parser OBJECT cmd_line.h config_file.cc config_file.h - mstring.cc - mstring.h vars.cc vars.h ) diff --git a/src/parser/config_file.cc b/src/parser/config_file.cc index 1de73bbfe..bca951db8 100644 --- a/src/parser/config_file.cc +++ b/src/parser/config_file.cc @@ -24,6 +24,8 @@ #include "config_file.h" #include +#include +#include #include "detection/detect.h" #include "detection/detection_engine.h" @@ -31,19 +33,6 @@ #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; @@ -57,9 +46,6 @@ const char* get_snort_conf_dir() 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; @@ -69,64 +55,66 @@ static int GetChecksumFlags(const char* args) 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; @@ -134,7 +122,7 @@ static int GetChecksumFlags(const char* args) } else { - ParseError("unknown command line checksum option: %s.", toks[i]); + ParseError("unknown command line checksum option: %s.", tok.c_str()); return ret_flags; } } @@ -162,7 +150,6 @@ static int GetChecksumFlags(const char* args) ret_flags = negative_flags; } - mSplitFree(&toks, num_toks); return ret_flags; } diff --git a/src/parser/mstring.cc b/src/parser/mstring.cc deleted file mode 100644 index 2aef7a691..000000000 --- a/src/parser/mstring.cc +++ /dev/null @@ -1,427 +0,0 @@ -//-------------------------------------------------------------------------- -// Copyright (C) 2014-2020 Cisco and/or its affiliates. All rights reserved. -// Copyright (C) 2002-2013 Sourcefire, Inc. -// Copyright (C) 1998-2002 Martin Roesch -// -// 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 - -#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 -// -// 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 - diff --git a/src/parser/parse_conf.cc b/src/parser/parse_conf.cc index d7f7fc173..6bcc38d17 100644 --- a/src/parser/parse_conf.cc +++ b/src/parser/parse_conf.cc @@ -238,7 +238,7 @@ void ParseIpVar(SnortConfig* sc, const char* var, const char* val) 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 @@ -255,25 +255,14 @@ void add_service_to_otn(SnortConfig* sc, OptTreeNode* otn, const char* svc_name) 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 ... @@ -283,7 +272,8 @@ void add_service_to_otn(SnortConfig* sc, OptTreeNode* otn, const char* svc_name) // 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() diff --git a/src/parser/parse_rule.cc b/src/parser/parse_rule.cc index daadfdf1b..46de30591 100644 --- a/src/parser/parse_rule.cc +++ b/src/parser/parse_rule.cc @@ -72,8 +72,9 @@ static int skip_count = 0; 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; @@ -777,7 +778,7 @@ static RuleTreeNode* ProcessHeadNode( 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, @@ -801,17 +802,17 @@ static int mergeDuplicateOtn( 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 @@ -822,36 +823,22 @@ static int mergeDuplicateOtn( 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; } @@ -870,6 +857,7 @@ void parse_rule_init() so_rule_count = 0; head_count = 0; otn_count = 0; + dup_count = 0; rule_proto = 0; memset(&ipCnt, 0, sizeof(ipCnt)); @@ -884,12 +872,13 @@ void parse_rule_term() 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); @@ -1067,7 +1056,6 @@ OptTreeNode* parse_rule_open(SnortConfig* sc, RuleTreeNode& rtn, bool stub) 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() ) @@ -1102,7 +1090,7 @@ static void parse_rule_state(SnortConfig* sc, const RuleTreeNode& rtn, OptTreeNo if ( rtn.dip ) sfvar_free(rtn.dip); - OtnFree(otn); + delete otn; } static bool is_builtin(uint32_t gid) @@ -1160,13 +1148,13 @@ void parse_rule_close(SnortConfig* sc, RuleTreeNode& rtn, OptTreeNode* otn) 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++; @@ -1184,6 +1172,7 @@ void parse_rule_close(SnortConfig* sc, RuleTreeNode& rtn, OptTreeNode* otn) if ( otn_dup ) { + dup_count++; otn->ruleIndex = otn_dup->ruleIndex; if ( mergeDuplicateOtn(sc, otn_dup, otn, new_rtn) ) @@ -1193,13 +1182,17 @@ void parse_rule_close(SnortConfig* sc, RuleTreeNode& rtn, OptTreeNode* otn) 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) ) { @@ -1208,7 +1201,8 @@ void parse_rule_close(SnortConfig* sc, RuleTreeNode& rtn, OptTreeNode* otn) otn->sigInfo.gid, otn->sigInfo.sid); otn->sigInfo.builtin = true; - builtin_rule_count++; + if ( !otn_dup ) + builtin_rule_count++; } else { @@ -1217,14 +1211,15 @@ void parse_rule_close(SnortConfig* sc, RuleTreeNode& rtn, OptTreeNode* otn) 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; diff --git a/src/parser/parse_stream.cc b/src/parser/parse_stream.cc index 8f6259b57..61c86348c 100644 --- a/src/parser/parse_stream.cc +++ b/src/parser/parse_stream.cc @@ -403,51 +403,51 @@ struct State 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) diff --git a/src/parser/parser.cc b/src/parser/parser.cc index 05a7b299c..964d3bb17 100644 --- a/src/parser/parser.cc +++ b/src/parser/parser.cc @@ -27,6 +27,8 @@ #include #include +#include +#include #include "detection/fp_config.h" #include "detection/rules.h" @@ -53,7 +55,6 @@ #include "utils/util_cstring.h" #include "config_file.h" -#include "mstring.h" #include "parse_conf.h" #include "parse_rule.h" #include "parse_stream.h" @@ -550,17 +551,17 @@ void OrderRuleLists(SnortConfig* sc) 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; @@ -580,8 +581,6 @@ void OrderRuleLists(SnortConfig* sc) // 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) { diff --git a/src/piglet_plugins/pp_event_iface.cc b/src/piglet_plugins/pp_event_iface.cc index 873ffbb49..04501d75a 100644 --- a/src/piglet_plugins/pp_event_iface.cc +++ b/src/piglet_plugins/pp_event_iface.cc @@ -106,7 +106,6 @@ static const luaL_Reg methods[] = 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); } @@ -138,7 +137,6 @@ static const luaL_Reg methods[] = 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); diff --git a/src/pub_sub/assistant_gadget_event.h b/src/pub_sub/assistant_gadget_event.h index 6980558a5..bbea51bc4 100644 --- a/src/pub_sub/assistant_gadget_event.h +++ b/src/pub_sub/assistant_gadget_event.h @@ -37,8 +37,8 @@ struct Packet; 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 diff --git a/src/service_inspectors/back_orifice/back_orifice.cc b/src/service_inspectors/back_orifice/back_orifice.cc index 19c180bc3..3e5b07fcb 100644 --- a/src/service_inspectors/back_orifice/back_orifice.cc +++ b/src/service_inspectors/back_orifice/back_orifice.cc @@ -429,7 +429,7 @@ class BackOrifice : public Inspector { public: BackOrifice() = default; - + void eval(Packet*) override; }; diff --git a/src/service_inspectors/http2_inspect/http2_data_cutter.h b/src/service_inspectors/http2_inspect/http2_data_cutter.h index 8755a1993..9e010603e 100644 --- a/src/service_inspectors/http2_inspect/http2_data_cutter.h +++ b/src/service_inspectors/http2_inspect/http2_data_cutter.h @@ -30,9 +30,9 @@ class Http2DataCutter { 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); diff --git a/src/service_inspectors/http2_inspect/http2_data_frame.h b/src/service_inspectors/http2_inspect/http2_data_frame.h index 904f5aafa..08ff4cc4a 100644 --- a/src/service_inspectors/http2_inspect/http2_data_frame.h +++ b/src/service_inspectors/http2_inspect/http2_data_frame.h @@ -28,11 +28,11 @@ class Http2DataFrame : public Http2Frame { 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); diff --git a/src/service_inspectors/http2_inspect/http2_dummy_packet.h b/src/service_inspectors/http2_inspect/http2_dummy_packet.h index 043ff0eaa..9e3ca2a86 100644 --- a/src/service_inspectors/http2_inspect/http2_dummy_packet.h +++ b/src/service_inspectors/http2_inspect/http2_dummy_packet.h @@ -17,7 +17,7 @@ //-------------------------------------------------------------------------- // http2_dummy_packet.h author Katura Harvey -/* +/* * 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() diff --git a/src/service_inspectors/http2_inspect/http2_frame.cc b/src/service_inspectors/http2_inspect/http2_frame.cc index 1b34537d3..a36ac5d08 100644 --- a/src/service_inspectors/http2_inspect/http2_frame.cc +++ b/src/service_inspectors/http2_inspect/http2_frame.cc @@ -59,7 +59,7 @@ Http2Frame* Http2Frame::new_frame(const uint8_t* header, const int32_t header_le 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); } diff --git a/src/service_inspectors/http2_inspect/http2_headers_frame.h b/src/service_inspectors/http2_inspect/http2_headers_frame.h index 27722facc..43fce110a 100644 --- a/src/service_inspectors/http2_inspect/http2_headers_frame.h +++ b/src/service_inspectors/http2_inspect/http2_headers_frame.h @@ -31,7 +31,7 @@ class Http2HeadersFrame : public Http2Frame { 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; } diff --git a/src/service_inspectors/http2_inspect/http2_stream.h b/src/service_inspectors/http2_inspect/http2_stream.h index 408d6c2f9..4476c1055 100644 --- a/src/service_inspectors/http2_inspect/http2_stream.h +++ b/src/service_inspectors/http2_inspect/http2_stream.h @@ -45,14 +45,22 @@ public: { 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 diff --git a/src/service_inspectors/http2_inspect/http2_stream_splitter.cc b/src/service_inspectors/http2_inspect/http2_stream_splitter.cc index 0d9c71afe..8d60e1b87 100644 --- a/src/service_inspectors/http2_inspect/http2_stream_splitter.cc +++ b/src/service_inspectors/http2_inspect/http2_stream_splitter.cc @@ -58,7 +58,7 @@ StreamSplitter::Status Http2StreamSplitter::scan(Packet* pkt, const uint8_t* dat 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; @@ -91,7 +91,7 @@ StreamSplitter::Status Http2StreamSplitter::scan(Packet* pkt, const uint8_t* dat // 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); diff --git a/src/service_inspectors/http2_inspect/http2_stream_splitter_impl.cc b/src/service_inspectors/http2_inspect/http2_stream_splitter_impl.cc index 100d779dd..b7cb538f3 100644 --- a/src/service_inspectors/http2_inspect/http2_stream_splitter_impl.cc +++ b/src/service_inspectors/http2_inspect/http2_stream_splitter_impl.cc @@ -317,7 +317,7 @@ const StreamBuffer implement_reassemble(Http2FlowData* session_data, unsigned to else { uint32_t data_offset = 0; - + if (offset == 0) { // This is the first reassemble() for this frame and we need to allocate some buffers diff --git a/src/service_inspectors/http_inspect/http_flow_data.h b/src/service_inspectors/http_inspect/http_flow_data.h index 13eb602c0..249bb9343 100644 --- a/src/service_inspectors/http_inspect/http_flow_data.h +++ b/src/service_inspectors/http_inspect/http_flow_data.h @@ -69,7 +69,7 @@ public: HttpEnums::SectionType get_type_expected(HttpCommon::SourceId source_id) { return type_expected[source_id]; } - + private: bool for_http2 = false; diff --git a/src/service_inspectors/http_inspect/http_uri.cc b/src/service_inspectors/http_inspect/http_uri.cc index c72480de3..ad7207154 100644 --- a/src/service_inspectors/http_inspect/http_uri.cc +++ b/src/service_inspectors/http_inspect/http_uri.cc @@ -199,8 +199,8 @@ void HttpUri::normalize() 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(); @@ -248,7 +248,7 @@ void HttpUri::normalize() // 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; @@ -342,8 +342,8 @@ const Field& HttpUri::get_norm_host() 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 @@ -357,7 +357,7 @@ const Field& HttpUri::get_norm_fragment() 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()]; diff --git a/src/stream/tcp/tcp_session.cc b/src/stream/tcp/tcp_session.cc index d5e472522..e6d1a9d68 100644 --- a/src/stream/tcp/tcp_session.cc +++ b/src/stream/tcp/tcp_session.cc @@ -985,6 +985,8 @@ bool TcpSession::do_packet_analysis_pre_checks(Packet* p, TcpSegmentDescriptor& client.init_flush_policy(); server.init_flush_policy(); + + set_no_ack(config->no_ack); } splitter_init = true; } @@ -1040,10 +1042,7 @@ int TcpSession::process(Packet* p) // 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(); diff --git a/src/stream/tcp/tcp_stream_session.cc b/src/stream/tcp/tcp_stream_session.cc index 89454849f..c0a0f6675 100644 --- a/src/stream/tcp/tcp_stream_session.cc +++ b/src/stream/tcp/tcp_stream_session.cc @@ -138,6 +138,16 @@ void TcpStreamSession::update_session_on_client_packet(TcpSegmentDescriptor& tsd 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; @@ -412,6 +422,7 @@ void TcpStreamSession::start_proxy() //------------------------------------------------------------------------- // tcp module stuff //------------------------------------------------------------------------- + void TcpStreamSession::print() { char buf[64]; @@ -430,4 +441,3 @@ void TcpStreamSession::print() server.print(); } - diff --git a/src/stream/tcp/tcp_stream_session.h b/src/stream/tcp/tcp_stream_session.h index 948e3cd95..c86300523 100644 --- a/src/stream/tcp/tcp_stream_session.h +++ b/src/stream/tcp/tcp_stream_session.h @@ -66,7 +66,7 @@ public: 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) { } diff --git a/src/utils/stats.cc b/src/utils/stats.cc index 751c8cab7..c39c90e67 100644 --- a/src/utils/stats.cc +++ b/src/utils/stats.cc @@ -23,6 +23,8 @@ #include "stats.h" +#include + #include "detection/detection_engine.h" #include "file_api/file_stats.h" #include "filters/sfthreshold.h" @@ -153,12 +155,17 @@ static void timing_stats() 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); } //-------------------------------------------------------------------------