]> git.ipfire.org Git - thirdparty/snort3.git/commitdiff
Merge pull request #1541 in SNORT/snort3 from ~SHRARANG/snort3:session_stash to master
authorMike Stepanek (mstepane) <mstepane@cisco.com>
Tue, 12 Mar 2019 16:37:43 +0000 (12:37 -0400)
committerMike Stepanek (mstepane) <mstepane@cisco.com>
Tue, 12 Mar 2019 16:37:43 +0000 (12:37 -0400)
Squashed commit of the following:

commit 2d5082c967e200a4e0199e40813d5a4a1844438a
Author: Shravan Rangaraju <shrarang@cisco.com>
Date:   Mon Mar 11 11:11:21 2019 -0400

    flow: support for flow stash - allows storage of integers and strings

src/flow/CMakeLists.txt
src/flow/flow.cc
src/flow/flow.h
src/flow/flow_stash.cc [new file with mode: 0644]
src/flow/flow_stash.h [new file with mode: 0644]
src/flow/stash_item.h [new file with mode: 0644]
src/flow/test/CMakeLists.txt
src/flow/test/flow_stash_test.cc [new file with mode: 0644]
src/flow/test/ha_test.cc
src/network_inspectors/appid/test/appid_mock_flow.h

index 6397f883d765e64afd8464ace7a604256628b07f..f567ae5800668abde9c16f48b6b38cfe27c2ecb9 100644 (file)
@@ -2,6 +2,8 @@ set (FLOW_INCLUDES
     expect_cache.h
     flow.h
     flow_key.h
+    flow_stash.h
+    stash_item.h
 )
 
 add_library (flow OBJECT
@@ -14,12 +16,15 @@ add_library (flow OBJECT
     flow_control.cc
     flow_control.h
     flow_key.cc
+    flow_stash.h
+    flow_stash.cc
     ha.cc
     ha.h
     ha_module.cc
     ha_module.h
     prune_stats.h
     session.h
+    stash_item.h
 )
 
 install(FILES ${FLOW_INCLUDES}
index 1b28fd04afaea284d4922bed726d511759782577..54854ebd12912b6f6ee9d93fb8fa96f0bc76f847 100644 (file)
@@ -92,6 +92,8 @@ void Flow::init(PktType type)
     }
     mpls_client.length = 0;
     mpls_server.length = 0;
+
+    stash = new FlowStash;
 }
 
 void Flow::term()
@@ -127,6 +129,9 @@ void Flow::term()
 
     if ( ha_state )
         delete ha_state;
+
+    if (stash)
+        delete stash;
 }
 
 inline void Flow::clean()
@@ -189,6 +194,9 @@ void Flow::reset(bool do_cleanup)
     if ( ha_state )
         ha_state->reset();
 
+    if ( stash )
+        stash->reset();
+
     constexpr size_t offset = offsetof(Flow, flow_data);
     // FIXIT-L need a struct to zero here to make future proof
     memset((uint8_t*)this+offset, 0, sizeof(Flow)-offset);
index 5e28e1f3dd6a531e85957b7356b19f04cb930611..9d378bb3822143c012fa317f9d09a1bec8ccb33e 100644 (file)
@@ -34,6 +34,7 @@
 #include "protocols/layer.h"
 #include "sfip/sf_ip.h"
 #include "target_based/snort_protocols.h"
+#include "flow_stash.h"
 
 #define SSNFLAG_SEEN_CLIENT         0x00000001
 #define SSNFLAG_SEEN_SENDER         0x00000001
@@ -188,6 +189,31 @@ public:
     void set_mpls_layer_per_dir(Packet*);
     Layer get_mpls_layer_per_dir(bool);
     void set_service(Packet* pkt, const char* new_service);
+    bool get_attr(const std::string& key, int32_t& val);
+    bool get_attr(const std::string& key, std::string& val);
+    void set_attr(const std::string& key, const int32_t& val);
+    void set_attr(const std::string& key, const std::string& val);
+    // Use this API when the publisher of the attribute allocated memory for it and can give up its
+    // ownership after the call.
+    void set_attr(const std::string& key, std::string* val)
+    {
+        assert(stash);
+        stash->store(key, val);
+    }
+
+    template<typename T>
+    bool get_attr(const std::string& key, T& val)
+    {
+        assert(stash);
+        return stash->get(key, val);
+    }
+
+    template<typename T>
+    void set_attr(const std::string& key, const T& val)
+    {
+        assert(stash);
+        stash->store(key, val);
+    }
 
     uint32_t update_session_flags(uint32_t flags)
     { return ssn_state.session_flags = flags; }
@@ -307,6 +333,7 @@ public:  // FIXIT-M privatize if possible
     Session* session;
     BitOp* bitop;
     FlowHAState* ha_state;
+    FlowStash* stash;
 
     uint8_t ip_proto;
     PktType pkt_type; // ^^
diff --git a/src/flow/flow_stash.cc b/src/flow/flow_stash.cc
new file mode 100644 (file)
index 0000000..59c033e
--- /dev/null
@@ -0,0 +1,107 @@
+//--------------------------------------------------------------------------
+// Copyright (C) 2019-2019 Cisco and/or its affiliates. All rights reserved.
+//
+// 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.
+//--------------------------------------------------------------------------
+
+// flow_stash.cc author Shravan Rangaraju <shrarang@cisco.com>
+
+#include "flow_stash.h"
+
+#include <cassert>
+
+using namespace snort;
+using namespace std;
+
+FlowStash::~FlowStash()
+{
+    reset();
+}
+
+void FlowStash::reset()
+{
+    for(map<string, StashItem*>::iterator it = container.begin(); it != container.end(); ++it)
+    {
+        delete it->second;
+    }
+    container.clear();
+}
+
+bool FlowStash::get(const string& key, int32_t& val)
+{
+    return get(key, val, STASH_ITEM_TYPE_INT32);
+}
+
+bool FlowStash::get(const string& key, string& val)
+{
+    return get(key, val, STASH_ITEM_TYPE_STRING);
+}
+
+void FlowStash::store(const string& key, int32_t val)
+{
+    store(key, val, STASH_ITEM_TYPE_INT32);
+}
+
+void FlowStash::store(const string& key, const string& val)
+{
+    store(key, val, STASH_ITEM_TYPE_STRING);
+}
+
+void FlowStash::store(const std::string& key, std::string* val)
+{
+    auto item = new StashItem(val);
+    auto it_and_status = container.emplace(make_pair(key, item));
+
+    if (!it_and_status.second)
+    {
+        assert(it_and_status.first->second->get_type() == STASH_ITEM_TYPE_STRING);
+        delete it_and_status.first->second;
+        it_and_status.first->second = item;
+    }
+}
+
+template<typename T>
+bool FlowStash::get(const string& key, T& val, StashItemType type)
+{
+#ifdef NDEBUG
+    UNUSED(type);
+#endif
+    auto it = container.find(key);
+
+    if (it != container.end())
+    {
+        assert(it->second->get_type() == type);
+        it->second->get_val(val);
+        return true;
+    }
+    return false;
+}
+
+template<typename T>
+void FlowStash::store(const string& key, T& val, StashItemType type)
+{
+#ifdef NDEBUG
+    UNUSED(type);
+#endif
+    auto item = new StashItem(val);
+    auto it_and_status = container.emplace(make_pair(key, item));
+
+    if (!it_and_status.second)
+    {
+        assert(it_and_status.first->second->get_type() == type);
+        delete it_and_status.first->second;
+        it_and_status.first->second = item;
+    }
+}
diff --git a/src/flow/flow_stash.h b/src/flow/flow_stash.h
new file mode 100644 (file)
index 0000000..2373aa2
--- /dev/null
@@ -0,0 +1,54 @@
+//--------------------------------------------------------------------------
+// Copyright (C) 2019-2019 Cisco and/or its affiliates. All rights reserved.
+//
+// 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.
+//--------------------------------------------------------------------------
+
+// flow_stash.h author Shravan Rangaraju <shrarang@cisco.com>
+
+#ifndef FLOW_STASH_H
+#define FLOW_STASH_H
+
+#include <map>
+#include <string>
+
+#include "main/snort_types.h"
+
+#include "stash_item.h"
+
+namespace snort {
+
+class FlowStash {
+public:
+    ~FlowStash();
+    void reset();
+    bool get(const std::string& key, int32_t& val);
+    bool get(const std::string& key, std::string& val);
+    void store(const std::string& key, int32_t val);
+    void store(const std::string& key, const std::string& val);
+    void store(const std::string& key, std::string* val);
+
+private:
+    std::map<std::string, StashItem*> container;
+
+    template<typename T>
+    bool get(const std::string& key, T& val, StashItemType type);
+    template<typename T>
+    void store(const std::string& key, T& val, StashItemType type);
+};
+
+}
+
+#endif
diff --git a/src/flow/stash_item.h b/src/flow/stash_item.h
new file mode 100644 (file)
index 0000000..a1ec98a
--- /dev/null
@@ -0,0 +1,87 @@
+//--------------------------------------------------------------------------
+// Copyright (C) 2019-2019 Cisco and/or its affiliates. All rights reserved.
+//
+// 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.
+//--------------------------------------------------------------------------
+
+// stash_item.h author Shravan Rangaraju <shrarang@cisco.com>
+
+#ifndef STASH_ITEM_H
+#define STASH_ITEM_H
+
+#include <cstdint>
+#include <string>
+
+namespace snort {
+
+enum StashItemType {
+    STASH_ITEM_TYPE_INT32,
+    STASH_ITEM_TYPE_STRING
+};
+
+union StashItemVal {
+    int32_t int32_val;
+    std::string* str_val;
+};
+
+class StashItem {
+private:
+    StashItemType type;
+    StashItemVal val;
+
+public:
+    StashItem(int32_t int32_val)
+    {
+        type = STASH_ITEM_TYPE_INT32;
+        val.int32_val = int32_val;
+    }
+
+    StashItem(const std::string& str_val)
+    {
+        type = STASH_ITEM_TYPE_STRING;
+        val.str_val = new std::string(str_val);
+    }
+
+    StashItem(std::string* str_val)
+    {
+        type = STASH_ITEM_TYPE_STRING;
+        val.str_val = str_val;
+    }
+
+    ~StashItem()
+    {
+        switch (type)
+        {
+        case STASH_ITEM_TYPE_STRING:
+            delete val.str_val;
+            break;
+        default:
+            break;
+        }
+    }
+
+    StashItemType get_type() const
+    { return type; }
+
+    void get_val(int32_t& int32_val) const
+    { int32_val = val.int32_val; }
+
+    void get_val(std::string& str_val) const
+    { str_val = *(val.str_val); }
+};
+
+}
+
+#endif
index 05bb4b4f25efe5672edc1d657ba70e96c3af2454..a94b730cc4f721d2e11f74bcbfc20418607e4895 100644 (file)
@@ -10,3 +10,7 @@ add_cpputest( ha_module_test
         ../../sfip/sf_ip.cc
         $<TARGET_OBJECTS:catch_tests>
 )
+
+add_cpputest( flow_stash_test
+    SOURCES ../flow_stash.cc
+)
diff --git a/src/flow/test/flow_stash_test.cc b/src/flow/test/flow_stash_test.cc
new file mode 100644 (file)
index 0000000..a9537fb
--- /dev/null
@@ -0,0 +1,137 @@
+//--------------------------------------------------------------------------
+// Copyright (C) 2019-2019 Cisco and/or its affiliates. All rights reserved.
+//
+// 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.
+//--------------------------------------------------------------------------
+
+// flow_stash_test.cc author Shravan Rangaraju <shrarang@cisco.com>
+
+#include <string>
+
+#include "flow/flow_stash.h"
+
+#include <CppUTest/CommandLineTestRunner.h>
+#include <CppUTest/TestHarness.h>
+
+using namespace snort;
+using namespace std;
+
+TEST_GROUP(stash_tests)
+{
+    void setup()
+    {
+    }
+
+    void teardown()
+    {
+    }
+};
+
+TEST(stash_tests, new_int32_item)
+{
+    FlowStash stash;
+
+    stash.store("item_1", 10);
+
+    int32_t val;
+
+    CHECK(stash.get("item_1", val));
+    CHECK_EQUAL(val, 10);
+}
+
+TEST(stash_tests, update_int32_item)
+{
+    FlowStash stash;
+
+    stash.store("item_1", 10);
+    stash.store("item_1", 20);
+
+    int32_t val;
+
+    CHECK(stash.get("item_1", val));
+    CHECK_EQUAL(val, 20);
+}
+
+TEST(stash_tests, new_str_item_ref)
+{
+    FlowStash stash;
+
+    stash.store("item_1", "value_1");
+
+    string val;
+
+    CHECK(stash.get("item_1", val));
+    STRCMP_EQUAL(val.c_str(), "value_1");
+}
+
+TEST(stash_tests, new_str_item_ptr)
+{
+    FlowStash stash;
+
+    stash.store("item_1", new string("value_1"));
+
+    string val;
+
+    CHECK(stash.get("item_1", val));
+    STRCMP_EQUAL(val.c_str(), "value_1");
+}
+
+TEST(stash_tests, update_str_item)
+{
+    FlowStash stash;
+
+    stash.store("item_1", "value_1");
+    stash.store("item_1", new string("value_2"));
+
+    string val;
+
+    CHECK(stash.get("item_1", val));
+    STRCMP_EQUAL(val.c_str(), "value_2");
+}
+
+TEST(stash_tests, non_existent_item)
+{
+    FlowStash stash;
+
+    stash.store("item_1", 10);
+
+    int32_t val;
+
+    CHECK_FALSE(stash.get("item_2", val));
+}
+
+TEST(stash_tests, mixed_items)
+{
+    FlowStash stash;
+
+    stash.store("item_1", 10);
+    stash.store("item_2", "value_2");
+    stash.store("item_3", 30);
+
+    int32_t int32_val;
+    string str_val;
+
+    CHECK(stash.get("item_1", int32_val));
+    CHECK_EQUAL(int32_val, 10);
+    CHECK(stash.get("item_2", str_val));
+    STRCMP_EQUAL(str_val.c_str(), "value_2");
+    CHECK(stash.get("item_3", int32_val));
+    CHECK_EQUAL(int32_val, 30);
+}
+
+int main(int argc, char** argv)
+{
+    return CommandLineTestRunner::RunAllTests(argc, argv);
+}
index dc208edbc28a949aefabc5614d52668b26cebf93..44ea78ab00607848784f7d34967fa9b77dec077a 100644 (file)
@@ -163,6 +163,8 @@ void packet_gettimeofday(struct timeval* tv)
 
 Flow::Flow() { ha_state = new FlowHAState; key = new FlowKey; }
 
+FlowStash::~FlowStash() { }
+
 SideChannel* SideChannelManager::get_side_channel(SCPort)
 { return &s_side_channel; }
 
index 1d0148a066864a8264e77c7d8342ea0af12d1877..6004686f8dd430c3adaf2cc721490d73a7250825 100644 (file)
@@ -50,5 +50,7 @@ int Flow::set_flow_data(FlowData* fd)
     return 0;
 }
 
+FlowStash::~FlowStash() { }
+
 #endif