expect_cache.h
flow.h
flow_key.h
+ flow_stash.h
+ stash_item.h
)
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}
}
mpls_client.length = 0;
mpls_server.length = 0;
+
+ stash = new FlowStash;
}
void Flow::term()
if ( ha_state )
delete ha_state;
+
+ if (stash)
+ delete stash;
}
inline void Flow::clean()
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);
#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
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; }
Session* session;
BitOp* bitop;
FlowHAState* ha_state;
+ FlowStash* stash;
uint8_t ip_proto;
PktType pkt_type; // ^^
--- /dev/null
+//--------------------------------------------------------------------------
+// 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;
+ }
+}
--- /dev/null
+//--------------------------------------------------------------------------
+// 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
--- /dev/null
+//--------------------------------------------------------------------------
+// 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
../../sfip/sf_ip.cc
$<TARGET_OBJECTS:catch_tests>
)
+
+add_cpputest( flow_stash_test
+ SOURCES ../flow_stash.cc
+)
--- /dev/null
+//--------------------------------------------------------------------------
+// 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);
+}
Flow::Flow() { ha_state = new FlowHAState; key = new FlowKey; }
+FlowStash::~FlowStash() { }
+
SideChannel* SideChannelManager::get_side_channel(SCPort)
{ return &s_side_channel; }
return 0;
}
+FlowStash::~FlowStash() { }
+
#endif