]> git.ipfire.org Git - thirdparty/snort3.git/commitdiff
Merge pull request #2050 in SNORT/snort3 from ~RUCOMBS/snort3:long_road to master
authorRuss Combs (rucombs) <rucombs@cisco.com>
Mon, 9 Mar 2020 23:59:23 +0000 (23:59 +0000)
committerRuss Combs (rucombs) <rucombs@cisco.com>
Mon, 9 Mar 2020 23:59:23 +0000 (23:59 +0000)
Squashed commit of the following:

commit 7fac732d47e375c11ccaaa09c460ce097698c052
Author: russ <rucombs@cisco.com>
Date:   Sat Mar 7 16:55:46 2020 -0500

    build: use const and auto references where possible

commit ab2497818f6dbcfb448deee8b29ba60ba69dcda6
Author: russ <rucombs@cisco.com>
Date:   Fri Mar 6 17:56:59 2020 -0500

    style: remove tabs and too long lines

commit ef713d0a2672db3c3e99fec22085a871c9554493
Author: russ <rucombs@cisco.com>
Date:   Sun Mar 1 23:56:53 2020 -0500

    parser: remove legacy parsing code

commit 8cb33a613e08adc45eacc3ec7ec1f0fef4e6aba6
Author: russ <rucombs@cisco.com>
Date:   Sun Mar 1 13:09:13 2020 -0500

    service: update implementation to vector

commit f1abe6fd867f95825860489b075f77c392fa2efc
Author: russ <rucombs@cisco.com>
Date:   Sun Mar 1 12:37:42 2020 -0500

    rules: add constructors for references and classifications

commit a8bd8c55d6a1f639a5107a86d34d1126d1759cf4
Author: russ <rucombs@cisco.com>
Date:   Sun Mar 1 11:21:10 2020 -0500

    classifications: use consistent variable names

commit b7c8f3bcc6ea05b65c607cb3955860c4cc4539dd
Author: russ <rucombs@cisco.com>
Date:   Sun Mar 1 11:01:39 2020 -0500

    reference: update implementation to vector

commit 7d0e021b805a82aeabe2af0fa09259d5afc3a2e7
Author: russ <rucombs@cisco.com>
Date:   Sun Mar 1 10:23:08 2020 -0500

    references: update implementation with unordered map

commit f85ef33a59b2bc3d6a81fbcc0ed97ac433fd8f4d
Author: russ <rucombs@cisco.com>
Date:   Sun Mar 1 09:38:47 2020 -0500

    classifications: update implementation with unordered map

commit 7046a630d3e94901b0c0bb0c61404666ba547e8d
Author: russ <rucombs@cisco.com>
Date:   Sun Mar 1 08:45:28 2020 -0500

    build: tweak includes

commit 43db2d95c454236cf638c280736fa6ac506e9eaa
Author: russ <rucombs@cisco.com>
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 <rucombs@cisco.com>
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 <rucombs@cisco.com>
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 <rucombs@cisco.com>
Date:   Sun Feb 23 08:15:54 2020 -0500

    rules: remove cruft

commit 51816c1d9776221651bc639bd9870df4d6285212
Author: russ <rucombs@cisco.com>
Date:   Sun Feb 23 08:15:07 2020 -0500

    rules: fix warnings and startup counts for duplicates

commit 1c9f4b1ca655c9e8ed3bab2814caaa21616891b5
Author: russ <rucombs@cisco.com>
Date:   Sun Feb 23 08:12:19 2020 -0500

    stream_tcp: no_ack applies only to ips mode

56 files changed:
src/codecs/link/test/cisco_meta_data_test.cc
src/detection/detect.cc
src/detection/detection_options.cc
src/detection/fp_utils.cc
src/detection/service_map.cc
src/detection/signature.cc
src/detection/signature.h
src/detection/treenodes.h
src/framework/mpse.h
src/framework/mpse_batch.h
src/hash/test/ghash_test.cc
src/ips_options/ips_classtype.cc
src/ips_options/ips_flowbits.cc
src/ips_options/ips_isdataat.cc
src/ips_options/ips_msg.cc
src/ips_options/ips_reference.cc
src/log/log_text.cc
src/loggers/alert_csv.cc
src/loggers/alert_json.cc
src/loggers/alert_luajit.cc
src/loggers/alert_syslog.cc
src/main.cc
src/main/help.cc
src/main/help.h
src/main/modules.cc
src/main/snort_config.cc
src/main/snort_config.h
src/main/snort_module.cc
src/managers/module_manager.cc
src/managers/module_manager.h
src/packet_io/sfdaq_config.h
src/parser/CMakeLists.txt
src/parser/config_file.cc
src/parser/mstring.cc [deleted file]
src/parser/mstring.h [deleted file]
src/parser/parse_conf.cc
src/parser/parse_rule.cc
src/parser/parse_stream.cc
src/parser/parser.cc
src/piglet_plugins/pp_event_iface.cc
src/pub_sub/assistant_gadget_event.h
src/service_inspectors/back_orifice/back_orifice.cc
src/service_inspectors/http2_inspect/http2_data_cutter.h
src/service_inspectors/http2_inspect/http2_data_frame.h
src/service_inspectors/http2_inspect/http2_dummy_packet.h
src/service_inspectors/http2_inspect/http2_frame.cc
src/service_inspectors/http2_inspect/http2_headers_frame.h
src/service_inspectors/http2_inspect/http2_stream.h
src/service_inspectors/http2_inspect/http2_stream_splitter.cc
src/service_inspectors/http2_inspect/http2_stream_splitter_impl.cc
src/service_inspectors/http_inspect/http_flow_data.h
src/service_inspectors/http_inspect/http_uri.cc
src/stream/tcp/tcp_session.cc
src/stream/tcp/tcp_stream_session.cc
src/stream/tcp/tcp_stream_session.h
src/utils/stats.cc

index d66b38fa1e84ea18b418ad343a3c319b59e795f3..740b0918796a177bd42abb65af57c669f066e496 100644 (file)
@@ -16,7 +16,7 @@
 // 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 //--------------------------------------------------------------------------
 
-// cisco_meta_data_test.cc author Sunirmal Mukherjee <sunimukh@cisco.com> 
+// cisco_meta_data_test.cc author Sunirmal Mukherjee <sunimukh@cisco.com>
 // unit test main
 
 #ifdef HAVE_CONFIG_H
@@ -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<cisco_meta_data::CiscoMetaDataOpt*>(cmd_data + sizeof(cisco_meta_data::CiscoMetaDataHdr)); 
+        reinterpret_cast<cisco_meta_data::CiscoMetaDataOpt*>(cmd_data +
+            sizeof(cisco_meta_data::CiscoMetaDataHdr));
+
     cmd_options->sgt = 512;
 
     len = (sizeof(cisco_meta_data::CiscoMetaDataHdr) + sizeof(cisco_meta_data::CiscoMetaDataOpt));
index dd1add31af52b457412f912fa80aca5b8c4ad14d..ddaa9c4ad587f5b7acf04b2a03bdbd52ffdef5b1 100644 (file)
@@ -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);
 }
 
 /*
index 884ebe2ab3a58b0fb116f6c6b6bded2b86aa1f65..f3b2cb6316e234fdf9a44775f16b5d2569486805 100644 (file)
@@ -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
                 }
             }
index 1738780d2f4da91680f480731763c15b8cf0f62e..a2b57e0707607ab6b106f74103e7b0c73dee12df 100644 (file)
@@ -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;
index 65eedc998aa3f5c5e49aae3b123676835b9c8c05..4e7dee794a8ec1b1e13795e66864a703b4e45d01 100644 (file)
@@ -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);
                 }
             }
         }
index 5d6f8fb4a3bd82837eed37884d465f7805087118..f8d5ef51addb8796112a6b3e459e65d664ff3982 100644 (file)
@@ -23,6 +23,7 @@
 #endif
 
 #include <cassert>
+#include <iostream>
 
 #include "signature.h"
 
 
 using namespace snort;
 
-/********************** Reference System Implementation ***********************/
+//--------------------------------------------------------------------------
+// reference systems
+//--------------------------------------------------------------------------
 
-ReferenceSystemNode* ReferenceSystemAdd(
-    SnortConfig* sc, const char* name, const char* url)
+const ReferenceSystem* reference_system_add(
+    SnortConfig* sc, const std::string& name, const char* url)
 {
     if ( !sc->alert_refs() )
         return nullptr;
 
-    assert(name);
-
-    ReferenceSystemNode* node = (ReferenceSystemNode*)snort_calloc(sizeof(*node));
-    node->name = snort_strdup(name);
+    assert(!name.empty());
 
-    if ( url )
-        node->url = snort_strdup(url);
+    ReferenceSystem* sys = new ReferenceSystem(name, url);
+    sc->references[sys->name] = sys;
 
-    ReferenceSystemNode** head = &sc->references;
-    node->next = *head;
-    *head = node;
-
-    return node;
+    return sys;
 }
 
-static ReferenceSystemNode* ReferenceSystemLookup(
-    ReferenceSystemNode* head, const char* name)
+static const ReferenceSystem* reference_system_lookup(SnortConfig* sc, const std::string& key)
 {
-    assert(name);
+    const auto it = sc->references.find(key);
 
-    while ( head )
-    {
-        if ( !strcasecmp(name, head->name) )
-            break;
+    if ( it != sc->references.end() )
+        return it->second;
 
-        head = head->next;
-    }
-    return head;
+    return nullptr;
 }
 
-/********************* Reference Implementation *******************************/
+//--------------------------------------------------------------------------
+// references
+//--------------------------------------------------------------------------
 
-void AddReference(
-    SnortConfig* sc, ReferenceNode** head, const char* system, const char* id)
+void add_reference(
+    SnortConfig* sc, OptTreeNode* otn, const std::string& system, const std::string& id)
 {
     if ( !sc->alert_refs() )
         return;
 
-    assert(sc and head and system and id);
-
-    /* create the new node */
-    ReferenceNode* node = (ReferenceNode*)snort_calloc(sizeof(ReferenceNode));
+    assert(sc and otn and !system.empty() and !id.empty());
 
-    node->system = ReferenceSystemLookup(sc->references, system);
+    const ReferenceSystem* sys = reference_system_lookup(sc, system);
 
-    if ( !node->system )
-        node->system = ReferenceSystemAdd(sc, system);
+    if ( !sys )
+        sys = reference_system_add(sc, system);
 
-    node->id = snort_strdup(id);
-
-    node->next = *head;
-    *head = node;
+    ReferenceNode* node = new ReferenceNode(sys, id);
+    otn->sigInfo.refs.push_back(node);
 }
 
-/************************ Class/Priority Implementation ***********************/
+//--------------------------------------------------------------------------
+// classifications
+//--------------------------------------------------------------------------
 
-void AddClassification(
-    SnortConfig* sc, const char* type, const char* name, unsigned priority)
+void add_classification(
+    SnortConfig* sc, const char* name, const char* text, unsigned priority)
 {
-    int max_id = 0;
-    ClassType* current = sc->classifications;
-
-    while (current != nullptr)
+    if ( get_classification(sc, name) )
     {
-        /* dup check */
-        if (strcasecmp(current->type, type) == 0)
-        {
-            ParseWarning(WARN_CONF,
-                "Duplicate classification \"%s\""
-                "found, ignoring this line", type);
-            return;
-        }
-
-        if (current->id > max_id)
-            max_id = current->id;
-
-        current = current->next;
+        ParseWarning(WARN_CONF, "Duplicate classification '%s' found, ignoring this line", name);
+        return;
     }
 
-    ClassType* new_node = (ClassType*)snort_calloc(sizeof(ClassType));
-
-    new_node->type = snort_strdup(type);
-    new_node->name = snort_strdup(name);
-    new_node->priority = priority;
-    new_node->id = max_id + 1;
-
-    /* insert node */
-    new_node->next = sc->classifications;
-    sc->classifications = new_node;
+    ClassType* ct = new ClassType(name, text, priority, sc->classifications.size() + 1);
+    sc->classifications[ct->name] = ct;
 }
 
-/* NOTE:  This lookup can only be done during parse time */
-ClassType* ClassTypeLookupByType(SnortConfig* sc, const char* type)
+const ClassType* get_classification(SnortConfig* sc, const char* type)
 {
-    assert(sc and type);
-    ClassType* node = sc->classifications;
+    std::string key = type;
+    const auto it = sc->classifications.find(key);
 
-    while ( node )
-    {
-        if ( !strcasecmp(type, node->type) )
-            break;
+    if ( it != sc->classifications.end() )
+        return it->second;
 
-        node = node->next;
-    }
-    return node;
+    return nullptr;
 }
 
-/***************** Otn Utilities ***********************/
+//--------------------------------------------------------------------------
+// otn utilities
+//--------------------------------------------------------------------------
 
 void OtnRemove(GHash* otn_map, OptTreeNode* otn)
 {
@@ -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();
+    }
+}
+
index d27f93ad43d9d9a4d846bff59fa12641224374ed..e2bc047c90e77d7000d6ffd02e86faa48b3de0b1 100644 (file)
@@ -26,6 +26,7 @@
 
 #include <cstdint>
 #include <cstdio>
+#include <string>
 
 #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<const ReferenceNode*> refs;
+    std::vector<SignatureServiceInfo> 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
 
index 73d86697d68b3978e0c49b8cd1dfad6c73ca732b..7449124f9124761bb16b02b4aa716e9a55d4629d 100644 (file)
@@ -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;
index d15f61f8a5afc3199054ee6ae17f95c45acca0d6..9784168cb5c3d63c760f2bfa42eca315dc89aeed 100644 (file)
@@ -27,8 +27,6 @@
 
 #include <cassert>
 #include <string>
-#include <unordered_map>
-#include <vector>
 
 #include "framework/base_api.h"
 #include "main/snort_types.h"
index ebbb6d6189d3e0665178d7c1c844e5668b35d886..f6d7c6ce065f45c9fa2e3594e19f61bc783fbddb 100644 (file)
@@ -20,6 +20,9 @@
 #ifndef MPSE_BATCH_H
 #define MPSE_BATCH_H
 
+#include <unordered_map>
+#include <vector>
+
 #include "framework/mpse.h"
 #include "main/snort_types.h"
 
index fba122d4468ced1df3f1445d2bc582d4baa5b11b..f0543f88c96f01a1292cd39794963d31b25b3b54 100644 (file)
@@ -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);
 
index 298718f6f94a06d851f698225b6e716a4f2bdc39..4c03736d95979a232a4c932e9feeebf231e0d69f 100644 (file)
@@ -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;
 }
index 5b6336fafab443a5bb185daf87c882ded8bdfd35..7078efd78581541e918b6f16cdb20b95eabf4db0 100644 (file)
 // 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 //--------------------------------------------------------------------------
 
-/*
- ** Major rewrite: Hui Cao <hcao@sourcefire.com>
- **
- ** Add flowbits OR support
- **
- ** sp_flowbits
- **
- ** Purpose:
- **
- ** Wouldn't it be nice if we could do some simple state tracking
- ** across multiple packets?  Well, this allows you to do just that.
- **
- ** Effect:
- **
- ** - [Un]set a bitmask stored with the session
- ** - Check the value of the bitmask
- */
+// Major rewrite: Hui Cao <hcao@sourcefire.com>
 
 #ifdef HAVE_CONFIG_H
 #include "config.h"
@@ -42,6 +26,8 @@
 #include "ips_flowbits.h"
 
 #include <forward_list>
+#include <sstream>
+#include <string>
 
 #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"
 #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<uint16_t> ids;
+    Flowbits_eval eval = FLOWBITS_AND;
+
     uint32_t group_id = 0;
-    ~FLOWBITS_OP();
+    uint8_t type = 0;         /* Set, Unset, Invert, IsSet, IsNotSet, Reset  */
 };
 
-FLOWBITS_OP::~FLOWBITS_OP()
-{
-    if (ids != nullptr)
-        snort_free(ids);
-    if (name != nullptr)
-        snort_free(name);
-    if (group != nullptr)
-        snort_free(group);
-}
-
 struct FLOWBITS_GRP
 {
-    uint16_t count;
-    uint16_t max_id;
-    char* name;
-    uint32_t group_id;
-    BitOp* GrpBitOp;
+    std::string name;
+    BitOp* GrpBitOp = nullptr;
+
+    uint32_t group_id = 0;
+
+    uint16_t count = 0;
+    uint16_t max_id = 0;
 };
 
 struct FlowBitState
@@ -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; i<strlen(name); i++)
+    for ( unsigned i=0; i<strlen(name); i++ )
     {
-        if (!isalnum(name[i])&&(nullptr == strchr(ALLOWED_SPECIAL_CHARS,name[i])))
+        if (!isalnum(name[i]) and (nullptr == strchr(ALLOWED_SPECIAL_CHARS,name[i])))
             return false;
     }
     return true;
 }
 
-static FLOWBITS_OBJECT* getFlowBitItem(char* flowbitName, FLOWBITS_OP* flowbits,
-    FlowBitState* flowbit_state)
+static FLOWBITS_OBJECT* get_item(
+    const char* bit, FLOWBITS_OP* flowbits, FlowBitState* flowbit_state)
 {
-    FLOWBITS_OBJECT* flowbits_item;
-
-    if (!validateName(flowbitName))
+    if ( !validate_name(bit) )
     {
         ParseAbort("%s: name is limited to any alphanumeric string including %s",
             s_name, ALLOWED_SPECIAL_CHARS);
     }
 
-    flowbits_item = (FLOWBITS_OBJECT*)flowbit_state->flowbits_hash->find(flowbitName);
+    FLOWBITS_OBJECT* flowbits_item = (FLOWBITS_OBJECT*)flowbit_state->flowbits_hash->find(bit);
 
-    if (flowbits_item == nullptr)
+    if ( !flowbits_item )
     {
-        flowbits_item = (FLOWBITS_OBJECT*)snort_calloc(sizeof(FLOWBITS_OBJECT));
+        flowbits_item = new FLOWBITS_OBJECT;
 
         if (sfqueue_count(flowbit_state->flowbits_bit_queue) > 0)
         {
@@ -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);
 }
index f391248914b82b27a66e486ea3e4eff92d81b742..37df2ddac3254e377329d66ef917e17d661fea47 100644 (file)
@@ -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);
 }
 
 //-------------------------------------------------------------------------
index 0946d98ba9dfe919b962665842fa932c8ca9766c..9133c137ea604ca282648d9e8c163923b1f44aea 100644 (file)
@@ -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;
 }
 
index 947b53909a63e755c2da7a465626e47ecdd688d3..78f5cf9ba634efc5d51556f1bc6411ebccdb1473 100644 (file)
@@ -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: <scheme>,<id>" },
 
     { 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;
 }
 
index 17cb4a968e72f4d1421b053eb4a278ae659b322c..0c72dbc443496ad3c438fc76888cf45607501235 100644 (file)
@@ -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());
     }
 }
 
index 51c25ff90dec06e5c35d5daddf09b51faddca199..91d44be933d809ba2eb87d6d367b00ec5f2c1f21 100644 (file)
@@ -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);
 }
 
index 812e17b1a8f380a9b4041ee18e8eb272e406546c..8f7d1cac6b26c4c4750ce1dd6f1be0bbe2b4322c 100644 (file)
@@ -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);
index 2c54b6e02c9f7d07e2b03f505c4b8f2b28ab7b91..17620bceda254c1ab7c49398bcb18b185d2aec85 100644 (file)
@@ -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;
 }
 
index 620605f17ef79341511b7abacde3bf2a2cc8b677..eb7b40d37dbfebd68ef7622ee6b9715521bbf98e 100644 (file)
@@ -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)
index f95e191b5c2d226ba3c798b6fe18f0a5f8bd6c1e..8d5afaa53e794ab0569a4f94fc714e9d77adb810 100644 (file)
@@ -26,6 +26,7 @@
 #include <thread>
 
 #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",
index fa9e689a4c341e4bc0e40f5789cf2ef2bcb72a68..0743f76b919b92d7556feddb28363d5a254c691e 100644 (file)
@@ -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);
index c0c5b34ef4db8df1f511d405629ccde59bdd1831..c51cfa20d35ae18598878d9bc416a4d920cca914 100644 (file)
@@ -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);
index cbb683d8426cd3c7d8dbca06c164147c07180f04..08a511d562bf496ffbae2410dc672ac10f13e7be 100644 (file)
@@ -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;
 }
 
index 3fb2de0cf85a4c75c821ad2a24693ff0fd3c7c01..7576067d0b46a4823411ef3b0a9bee9b14b843bf 100644 (file)
@@ -94,40 +94,6 @@ static std::vector<ScratchAllocator*> 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);
index ce428f451554e20dcbc3406e4bab341adc7362a3..204140c918d02739813207e8b796dfa6cd02cc0f 100644 (file)
@@ -26,6 +26,7 @@
 #include <sys/types.h>
 
 #include <list>
+#include <unordered_map>
 #include <vector>
 
 #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<std::string, ClassType*> classifications;
+    std::unordered_map<std::string, ReferenceSystem*> references;
+
     RuleStateMap* rule_states = nullptr;
-    ClassType* classifications = nullptr;
-    ReferenceSystemNode* references = nullptr;
     GHash* otn_map = nullptr;
 
     ProtocolReference* proto_ref = nullptr;
@@ -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; }
 
index 17cd9c3c0c47608487f843954083079d866c923b..94cdde1af826ca67679cf3d901e11e8cdeab92e6 100644 (file)
@@ -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());
 
index 25a43605adc50f929eb4361c8e5b8649d93066ef..08b21f7da032326f36aa1a4984279e6a784f0160 100644 (file)
@@ -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<RulePtr> rule_set = get_rules(pfx);
-
-    for ( auto rp : rule_set )
-    {
-        cout << rp.mod->get_gid() << " || ";
-        cout << rp.rule->sid << " || ";
-        cout << rp.mod->get_name() << ": ";
-        cout << rp.rule->msg << endl;
-    }
-    if ( !rule_set.size() )
-        cout << "no match" << endl;
-}
-
index eef450c2d1d0ccdfa2c891a0da90f338855688fe..c522d92c47fa2ed49db43211a1e8530a2605bd91 100644 (file)
@@ -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);
 
index 9e2f30779aca597c13768aef58c005df2d40e6e1..1bd4d4173dec86532bd477323e770cdb12dad7de 100644 (file)
@@ -22,7 +22,6 @@
 #define SFDAQ_CONFIG_H
 
 #include <string>
-#include <unordered_map>
 #include <vector>
 
 using DaqVar = std::pair<std::string, std::string>;
index 479045e91a5ee8faffa10b4ee5308622b1373119..c3658eaa66fb5e609e7ab122245cc2aa4fda81d2 100644 (file)
@@ -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
 )
index 1de73bbfe49f8091c7a9ec7b32e47e2e6f8de789..bca951db8989f6c3646a2bd7cdea66fc83bd19d2 100644 (file)
@@ -24,6 +24,8 @@
 #include "config_file.h"
 
 #include <cstring>
+#include <sstream>
+#include <string>
 
 #include "detection/detect.h"
 #include "detection/detection_engine.h"
 #include "main/analyzer.h"
 #include "main/policy.h"
 
-#include "mstring.h"
-
-#define CHECKSUM_MODE_OPT__ALL      "all"
-#define CHECKSUM_MODE_OPT__NONE     "none"
-#define CHECKSUM_MODE_OPT__IP       "ip"
-#define CHECKSUM_MODE_OPT__NO_IP    "noip"
-#define CHECKSUM_MODE_OPT__TCP      "tcp"
-#define CHECKSUM_MODE_OPT__NO_TCP   "notcp"
-#define CHECKSUM_MODE_OPT__UDP      "udp"
-#define CHECKSUM_MODE_OPT__NO_UDP   "noudp"
-#define CHECKSUM_MODE_OPT__ICMP     "icmp"
-#define CHECKSUM_MODE_OPT__NO_ICMP  "noicmp"
-
 using namespace snort;
 
 static std::string lua_conf;
@@ -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 (file)
index 2aef7a6..0000000
+++ /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 <roesch@sourcefire.com>
-//
-// This program is free software; you can redistribute it and/or modify it
-// under the terms of the GNU General Public License Version 2 as published
-// by the Free Software Foundation.  You may not use, modify or distribute
-// this program under any other version of the GNU General Public License.
-//
-// This program is distributed in the hope that it will be useful, but
-// WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-// General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License along
-// with this program; if not, write to the Free Software Foundation, Inc.,
-// 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-//--------------------------------------------------------------------------
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "mstring.h"
-
-#include <cassert>
-
-#include "utils/util.h"
-
-namespace snort
-{
-static char* mSplitAddTok(const char*, const int, const char*, const char);
-
-/****************************************************************
- *
- * Function: mSplit()
- *
- * Purpose: Splits a string into tokens non-destructively.
- *
- * Parameters:
- *  char *
- *      The string to be split
- *  char *
- *      A string of token separators
- *  int
- *      The maximum number of tokens to be returned. A value
- *      of 0 means to get them all.
- *  int *
- *      Place to store the number of tokens returned
- *  char
- *      The "escape metacharacter", treat the character after
- *      this character as a literal and "escape" a separator.
- *
- *  Note if max_toks is reached, the last tok in the returned
- *  token array will possibly have separator characters in it.
- *
- *  Returns:
- *      2D char array with one token per "row" of the returned
- *      array.
- *
- ****************************************************************/
-// FIXIT-L eliminate mSplit(); create iterator service if needed
-char** mSplit(const char* str, const char* sep_chars, const int max_toks,
-    int* num_toks, const char meta_char)
-{
-    size_t cur_tok = 0;  /* current token index into array of strings */
-    size_t tok_start;    /* index to start of token */
-    size_t i, j;
-    int escaped = 0;
-    /* It's rare we'll need more than this even if max_toks is set really
-     * high.  Store toks here until finished, then allocate.  If more than
-     * this is necessary, then allocate max toks */
-    char* toks_buf[TOKS_BUF_SIZE];
-    size_t toks_buf_size = TOKS_BUF_SIZE;
-    int toks_buf_size_increment = 10;
-    char** toks_alloc = nullptr;   /* Used if the static buf isn't enough */
-    char** toks = toks_buf;     /* Pointer to one of the two above */
-    char** retstr;
-    const char* whitespace = " \t";
-
-    assert(num_toks);
-    assert(str);
-
-    *num_toks = 0;
-    size_t str_length = strlen(str);
-
-    if (str_length == 0)
-        return nullptr;
-
-    if (sep_chars == nullptr)
-        sep_chars = whitespace;
-
-    size_t sep_length = strlen(sep_chars);
-
-    /* Meta char cannot also be a separator char */
-    for (i = 0; i < sep_length; i++)
-    {
-        if (sep_chars[i] == meta_char)
-            return nullptr;
-    }
-
-    /* Move past initial separator characters and whitespace */
-    for (i = 0; i < str_length; i++)
-    {
-        if (isspace((int)str[i]))
-            continue;
-
-        for (j = 0; j < sep_length; j++)
-        {
-            if (str[i] == sep_chars[j])
-                break;
-        }
-
-        /* Not a separator character or whitespace */
-        if (j == sep_length)
-            break;
-    }
-
-    if (i == str_length)
-    {
-        /* Nothing but separator characters or whitespace in string */
-        return nullptr;
-    }
-
-    /* User only wanted one tok so return the rest of the string in
-     * one tok */
-    if ((cur_tok + 1) == (size_t)max_toks)
-    {
-        retstr = (char**)snort_calloc(sizeof(char*));
-        retstr[cur_tok] = snort_strndup(&str[i], str_length - i);
-        *num_toks = cur_tok + 1;
-        return retstr;
-    }
-
-    /* Mark the beginning of the next tok */
-    tok_start = i;
-    for (; i < str_length; i++)
-    {
-        if (!escaped)
-        {
-            /* Got an escape character.  Don't include it now, but
-             * must be a character after it. */
-            if (str[i] == meta_char)
-            {
-                escaped = 1;
-                continue;
-            }
-
-            /* See if the current character is a separator */
-            for (j = 0; j < sep_length; j++)
-            {
-                if (str[i] == sep_chars[j])
-                    break;
-            }
-
-            /* It's a normal character */
-            if (j == sep_length)
-                continue;
-
-            /* Current character matched a separator character.  Trim off
-             * whitespace previous to the separator.  If we get here, there
-             * is at least one savable character */
-            for (j = i; j > tok_start; j--)
-            {
-                if (!isspace((int)str[j - 1]))
-                    break;
-            }
-
-            /* Allocate a buffer.  The length will not have included the
-             * meta char of escaped separators */
-            toks[cur_tok] = mSplitAddTok(&str[tok_start], j - tok_start, sep_chars, meta_char);
-
-            /* Increment current token index */
-            cur_tok++;
-
-            /* Move past any more separator characters or whitespace */
-            for (; i < str_length; i++)
-            {
-                if (isspace((int)str[i]))
-                    continue;
-
-                for (j = 0; j < sep_length; j++)
-                {
-                    if (str[i] == sep_chars[j])
-                        break;
-                }
-
-                /* Not a separator character or whitespace */
-                if (j == sep_length)
-                    break;
-            }
-
-            /* Nothing but separator characters or whitespace left in the string */
-            if (i == str_length)
-            {
-                *num_toks = cur_tok;
-
-                if (toks != toks_alloc)
-                {
-                    retstr = (char**)snort_calloc(cur_tok, sizeof(char*));
-                    memcpy(retstr, toks, (sizeof(char*) * cur_tok));
-                }
-                else
-                {
-                    retstr = toks;
-                }
-
-                return retstr;
-            }
-
-            /* Reached the size of our current string buffer and need to
-             * allocate something bigger.  Only get here once if max toks
-             * set to something other than 0 because we'll just allocate
-             * max toks in that case. */
-            if (cur_tok == toks_buf_size)
-            {
-                char** tmp;
-
-                if (toks_alloc != nullptr)
-                    tmp = toks_alloc;
-                else
-                    tmp = toks_buf;
-
-                if (max_toks != 0)
-                    toks_buf_size = max_toks;
-                else
-                    toks_buf_size = cur_tok + toks_buf_size_increment;
-
-                toks_alloc = (char**)snort_calloc(toks_buf_size, sizeof(char*));
-                memcpy(toks_alloc, tmp, (sizeof(char*) * cur_tok));
-                toks = toks_alloc;
-
-                if (tmp != toks_buf)
-                    snort_free(tmp);
-            }
-
-            if ((max_toks != 0) && ((cur_tok + 1) == (size_t)max_toks))
-            {
-                /* Return rest of string as last tok */
-                *num_toks = cur_tok + 1;
-
-                /* Already got a ret string */
-                if (toks != toks_alloc)
-                {
-                    retstr = (char**)snort_calloc(cur_tok + 1, sizeof(char*));
-                    memcpy(retstr, toks, (sizeof(char*) * (cur_tok + 1)));
-                }
-                else
-                {
-                    retstr = toks;
-                }
-
-                /* Trim whitespace at end of last tok */
-                for (j = str_length; j > tok_start; j--)
-                {
-                    if (!isspace((int)str[j - 1]))
-                        break;
-                }
-
-                retstr[cur_tok] = snort_strndup(&str[i], j - i);
-                return retstr;
-            }
-
-            tok_start = i;
-        }
-        else
-        {
-            /* This character is escaped with the meta char */
-            escaped = 0;
-        }
-    }
-
-    /* Last character was an escape character */
-    if (escaped)
-    {
-        for (i = 0; i < cur_tok; i++)
-            snort_free(toks[i]);
-
-        if (toks == toks_alloc)
-            snort_free(toks_alloc);
-
-        return nullptr;
-    }
-
-    /* Trim whitespace at end of last tok */
-    for (j = i; j > tok_start; j--)
-    {
-        if (!isspace((int)str[j - 1]))
-            break;
-    }
-
-    /* Last character was not a separator character so we've got
-     * one more tok.  Unescape escaped separator characters */
-    if (toks != toks_alloc)
-    {
-        retstr = (char**)snort_calloc(cur_tok + 1, sizeof(char*));
-        memcpy(retstr, toks, (sizeof(char*) * (cur_tok + 1)));
-    }
-    else
-    {
-        retstr = toks;
-    }
-
-    retstr[cur_tok] = mSplitAddTok(&str[tok_start], j - tok_start, sep_chars, meta_char);
-
-    /* Just add one to cur_tok index instead of incrementing
-     * since we're done */
-    *num_toks = cur_tok + 1;
-    return retstr;
-}
-
-static char* mSplitAddTok(
-    const char* str, const int len, const char* sep_chars, const char meta_char)
-{
-    size_t i, j, k;
-    char* tok;
-    int tok_len = 0;
-    int got_meta = 0;
-    size_t sep_length = strlen(sep_chars);
-
-    /* Get the length of the returned tok
-     * Could have a maximum token length and use a fixed sized array and
-     * fill it in as we go but don't want to put on that constraint */
-    for (i = 0; (int)i < len; i++)
-    {
-        if (!got_meta)
-        {
-            if (str[i] == meta_char)
-            {
-                got_meta = 1;
-                continue;
-            }
-        }
-        else
-        {
-            /* See if the current character is a separator */
-            for (j = 0; j < sep_length; j++)
-            {
-                if (str[i] == sep_chars[j])
-                    break;
-            }
-
-            /* It's a non-separator character, so include
-             * the meta character in the return tok */
-            if (j == sep_length)
-                tok_len++;
-
-            got_meta = 0;
-        }
-
-        tok_len++;
-    }
-
-    /* Allocate it and fill it in */
-    tok = (char*)snort_calloc(tok_len + 1);
-
-    for (i = 0, k = 0; (int)i < len; i++)
-    {
-        if (!got_meta)
-        {
-            if (str[i] == meta_char)
-            {
-                got_meta = 1;
-                continue;
-            }
-        }
-        else
-        {
-            /* See if the current character is a separator */
-            for (j = 0; j < sep_length; j++)
-            {
-                if (str[i] == sep_chars[j])
-                    break;
-            }
-
-            /* It's a non-separator character, so include
-             * the meta character in the return tok */
-            if (j == sep_length)
-                tok[k++] = meta_char;
-
-            got_meta = 0;
-        }
-
-        tok[k++] = str[i];
-    }
-
-    return tok;
-}
-
-/****************************************************************
- *
- * Free the buffer allocated by mSplit().
- *
- * char** toks = NULL;
- * int num_toks = 0;
- * toks = (str, " ", 2, &num_toks, 0);
- * mSplitFree(&toks, num_toks);
- *
- * At this point, toks is again NULL.
- *
- ****************************************************************/
-void mSplitFree(char*** pbuf, int num_toks)
-{
-    int i;
-    char** buf;  /* array of string pointers */
-
-    if ( pbuf==nullptr || *pbuf==nullptr )
-    {
-        return;
-    }
-
-    buf = *pbuf;
-
-    for ( i=0; i<num_toks; i++ )
-    {
-        if ( buf[i] != nullptr )
-        {
-            snort_free(buf[i]);
-            buf[i] = nullptr;
-        }
-    }
-
-    snort_free(buf);
-    *pbuf = nullptr;
-}
-} // namespace snort
diff --git a/src/parser/mstring.h b/src/parser/mstring.h
deleted file mode 100644 (file)
index 575ecab..0000000
+++ /dev/null
@@ -1,37 +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 <roesch@sourcefire.com>
-//
-// This program is free software; you can redistribute it and/or modify it
-// under the terms of the GNU General Public License Version 2 as published
-// by the Free Software Foundation.  You may not use, modify or distribute
-// this program under any other version of the GNU General Public License.
-//
-// This program is distributed in the hope that it will be useful, but
-// WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-// General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License along
-// with this program; if not, write to the Free Software Foundation, Inc.,
-// 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-//--------------------------------------------------------------------------
-
-#ifndef MSTRING_H
-#define MSTRING_H
-
-// Provide a variety of string functions not included in libc.
-// Deprecated - Do not use this in new code.
-
-#include "main/snort_types.h"
-
-#define TOKS_BUF_SIZE   100
-
-namespace snort
-{
-SO_PUBLIC char** mSplit(const char*, const char*, const int, int*, const char);
-SO_PUBLIC void mSplitFree(char*** toks, int numtoks);
-}
-#endif
-
index d7f7fc1738313dbc035b2bab2096309b5a4065a0..6bcc38d176473ad5e2b05d0b9e6f134b50ccf72b 100644 (file)
@@ -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()
index daadfdf1be7f7136dd40b7fa6aab60455beef0f7..46de305919e02eed38c0996057a39f8bc5c1f5cc 100644 (file)
@@ -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;
index 8f6259b576cec9abfd4613e3a7e5ad59660da3b1..61c86348c0bc47af37903d09c8e234ca8e3652bf 100644 (file)
@@ -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)
index 05a7b299cb9f8e93bf497c6c0689d854581a1897..964d3bb1720c43f941ea93c0859a78a17bc279ba 100644 (file)
@@ -27,6 +27,8 @@
 
 #include <cassert>
 #include <iostream>
+#include <sstream>
+#include <string>
 
 #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)
     {
index 873ffbb49db4072b2da5126484c758783e53928f..04501d75ae2afa6bb1c96aaf790d032f39b2831f 100644 (file)
@@ -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);
index 6980558a5629290808112b2aaeb9c6de11c330f1..bbea51bc40984142af1a6726bbca873c512a7877 100644 (file)
@@ -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
index 19c180bc371a3298aca02df6a3a4d74a4eaa3e32..3e5b07fcbb9603e8df44c511bab4c74def3db9d6 100644 (file)
@@ -429,7 +429,7 @@ class BackOrifice : public Inspector
 {
 public:
     BackOrifice() = default;
-    
+
     void eval(Packet*) override;
 };
 
index 8755a19933b07c1a9d3760e8a5016f2b2a430aaf..9e010603e4427725f7db58a36c41e50aae50d7e9 100644 (file)
@@ -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);
 
index 904f5aafa39fc4fcef2816416c231a097b55caaa..08ff4cc4ac195f5b04db5460e5f5d22082446d05 100644 (file)
@@ -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);
 
index 043ff0eaa3a9d1041b52187edefbfdd5de62de42..9e3ca2a866d9ba0db9aea13071788ea1a18f7d19 100644 (file)
@@ -17,7 +17,7 @@
 //--------------------------------------------------------------------------
 // http2_dummy_packet.h author Katura Harvey <katharve@cisco.com>
 
-/* 
+/*
  * The purpose of this Packet subclass is to enable H2I to take direction from http_inspect on
  * whether or not to send a frame to detection. When http_inspect is processing normal HTTP/1.1
  * traffic it is dealing with a real packet that has a context, the field on which disable_all()
index 1b34537d3dc0f2aeb76413e619ce331ffab3b648..a36ac5d0842e9c1b7224d8b97abe0257cd9a74e0 100644 (file)
@@ -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);
     }
index 27722facc261175b4a2bc17f7bacf72e3ea3b5b8..43fce110a0231020f2aaef53ffac27d919c545ca 100644 (file)
@@ -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; }
index 408d6c2f9e81812e7628c8b696a8bbcbb0c401a2..4476c1055375b1e5e59de4b5bf6bb60fe6ee463d 100644 (file)
@@ -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
index 0d9c71afe9a5f1256c7dfb437ef180198e5dd542..8d60e1b870c60bc3099f334afe3a0b5a045bfa1e 100644 (file)
@@ -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);
 
index 100d779dd6933d49a2b0b70bdeaff41796ac5a6a..b7cb538f327934928e40b4b7ca12063414b379ea 100644 (file)
@@ -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
index 13eb602c0b6814ba2ed72369de08ea47811dd24a..249bb9343f264eb00c0d083e0c396d58c181b880 100644 (file)
@@ -69,7 +69,7 @@ public:
 
     HttpEnums::SectionType get_type_expected(HttpCommon::SourceId source_id)
     { return type_expected[source_id]; }
-  
+
 private:
     bool for_http2 = false;
 
index c72480de3417253d44f6b29f83ca7034103be4cc..ad7207154ec2ca5b253b3a49d7dcf3a6c0fb00df 100644 (file)
@@ -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()];
index d5e4725222d4703f13acf1546b5ca347324bae09..e6d1a9d68e87ea5c2c610b52be9380dd459d0d35 100644 (file)
@@ -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();
index 89454849fd0afb3f2b4b9e0239612ca30b5fb001..c0a0f66753dbe6ba8df6740e462775fcbebe15c7 100644 (file)
@@ -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();
 }
 
-
index 948e3cd9565b388e30fe0fb469210dc224c975eb..c863005231bd1d08b0608487dd213238d78fb40c 100644 (file)
@@ -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) { }
index 751c8cab792851dffc1634731eedddc2b2f1211c..c39c90e67fd89615218b3bf9cc3efbf7989e240f 100644 (file)
@@ -23,6 +23,8 @@
 
 #include "stats.h"
 
+#include <cassert>
+
 #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);
 }
 
 //-------------------------------------------------------------------------