#define SSNFLAG_ABORT_CLIENT 0x10000000
#define SSNFLAG_ABORT_SERVER 0x20000000
+#define SSNFLAG_HARD_EXPIRATION 0x40000000
+
#define SSNFLAG_NONE 0x00000000 /* nothing, an MT bag of chips */
#define SSNFLAG_SEEN_BOTH (SSNFLAG_SEEN_SERVER | SSNFLAG_SEEN_CLIENT)
bool is_suspended() const
{ return context_chain.front(); }
+ void set_default_session_timeout(uint32_t dst, bool force)
+ {
+ if (force || (default_session_timeout == 0))
+ default_session_timeout = dst;
+ }
+
+ void set_hard_expiration()
+ { ssn_state.session_flags |= SSNFLAG_HARD_EXPIRATION; }
+
+ bool is_hard_expiration()
+ { return (ssn_state.session_flags & SSNFLAG_HARD_EXPIRATION) != 0; }
+
public: // FIXIT-M privatize if possible
// fields are organized by initialization and size to minimize
// void space and allow for memset of tail end of struct
unsigned network_policy_id;
unsigned reputation_id;
+ uint32_t default_session_timeout;
+
uint16_t client_port;
uint16_t server_port;
while ( flow and (retired < num_flows) )
{
- if ( flow->last_data_seen + config.proto[to_utype(flow->key->pkt_type)].nominal_timeout > thetime )
+ if ( flow->is_hard_expiration() )
+ {
+ if ( flow->expire_time > (uint64_t) thetime )
+ break;
+ }
+ else if ( flow->last_data_seen + config.proto[to_utype(flow->key->pkt_type)].nominal_timeout > thetime )
break;
if ( HighAvailabilityManager::in_standby(flow) or
)
add_cpputest( session_test )
+
+add_cpputest( flow_test
+ SOURCES ../flow.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_test.cc author Prajwal Srinivas <psreenat@cisco.com>
+// unit test main
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "protocols/ip.h"
+#include "protocols/layer.h"
+#include "protocols/packet.h"
+#include "flow/flow.h"
+#include "flow/flow_stash.h"
+#include "flow/ha.h"
+#include "main/snort_debug.h"
+#include "framework/inspector.h"
+#include "framework/data_bus.h"
+#include "memory/memory_cap.h"
+#include "detection/detection_engine.h"
+
+#include <CppUTest/CommandLineTestRunner.h>
+#include <CppUTest/TestHarness.h>
+
+using namespace snort;
+
+Packet::Packet(bool) { }
+Packet::~Packet() { }
+
+void Inspector::rem_ref() {}
+
+void Inspector::add_ref() {}
+
+void memory::MemoryCap::update_allocations(size_t n) {}
+
+void memory::MemoryCap::update_deallocations(size_t n) {}
+
+bool memory::MemoryCap::free_space(size_t n) { return false; }
+
+bool HighAvailabilityManager::active() { return false; }
+
+FlowHAState::FlowHAState() = default;
+
+void FlowHAState::reset() {}
+
+snort::FlowStash::~FlowStash() {}
+
+void FlowStash::reset() {}
+
+void DetectionEngine::onload(Flow* flow) {}
+
+Packet* DetectionEngine::set_next_packet(Packet* parent) { return nullptr; }
+
+IpsContext* DetectionEngine::get_context() { return nullptr; }
+
+DetectionEngine::DetectionEngine() = default;
+
+DetectionEngine::~DetectionEngine() {}
+
+bool snort::layer::set_outer_ip_api(const Packet* const p,
+ ip::IpApi& api,
+ int8_t& curr_layer)
+{ return false; }
+
+uint8_t ip::IpApi::ttl() const { return 0; }
+
+const Layer* snort::layer::get_mpls_layer(const Packet* const p) { return nullptr; }
+
+void snort::DataBus::publish(const char* key, Packet* p, Flow* f) {}
+
+TEST_GROUP(nondefault_timeout)
+{
+ void setup() override
+ {
+ }
+
+ void teardown() override
+ {
+ }
+};
+
+TEST(nondefault_timeout, hard_expiration)
+{
+ uint64_t validate = 100;
+ Packet pkt(false);
+ Flow *flow = new Flow();
+ DAQ_PktHdr_t pkthdr;
+
+ pkt.pkth = &pkthdr;
+ pkthdr.ts.tv_sec = 0;
+
+ flow->set_default_session_timeout(validate, true);
+ flow->set_hard_expiration();
+ flow->set_expire(&pkt, validate);
+
+ CHECK( flow->is_hard_expiration() == true);
+ CHECK( flow->expire_time == validate );
+
+ delete flow;
+}
+
+int main(int argc, char** argv)
+{
+ int return_value = CommandLineTestRunner::RunAllTests(argc, argv);
+ return return_value;
+}
+
+
ssn_time.tv_usec = 0;
flow->ssn_state.session_flags |= SSNFLAG_SEEN_SENDER;
SESSION_STATS_ADD(icmpStats);
+
+ StreamIcmpConfig* pc = get_icmp_cfg(flow->ssn_server);
+ flow->set_default_session_timeout(pc->session_timeout, false);
+
return true;
}
int IcmpSession::process(Packet* p)
{
int status;
+
+ flow->set_expire(p, flow->default_session_timeout);
switch (p->ptrs.icmph->type)
{
void show(SnortConfig*) override;
NORETURN_ASSERT void eval(Packet*) override;
-private:
+public:
StreamIcmpConfig* config;
};
assert(false);
}
+StreamIcmpConfig* get_icmp_cfg(Inspector* ins)
+{
+ assert(ins);
+ return ((StreamIcmp*)ins)->config;
+}
+
//-------------------------------------------------------------------------
// api stuff
//-------------------------------------------------------------------------
#include <cstdint>
+namespace snort
+{
+class Inspector;
+}
+
struct StreamIcmpConfig
{
uint32_t session_timeout;
StreamIcmpConfig();
};
+StreamIcmpConfig* get_icmp_cfg(snort::Inspector*);
+
#endif
// Reset the session timeout.
if ( lws->ssn_server )
{
- StreamIpConfig* pc = get_ip_cfg(lws->ssn_server);
- lws->set_expire(p, pc->session_timeout);
+ lws->set_expire(p, lws->default_session_timeout);
}
}
SESSION_STATS_ADD(ip_stats);
memset(&tracker, 0, sizeof(tracker));
+ StreamIpConfig* pc = get_ip_cfg(flow->ssn_server);
+ flow->set_default_session_timeout(pc->session_timeout, false);
+
if ( p->ptrs.decode_flags & DECODE_FRAG )
{
ip_stats.trackers_created++;
{
StreamIpConfig* sic = new StreamIpConfig;
sic->session_timeout = 360;
+ lws.set_default_session_timeout(sic->session_timeout, true);
StreamIp si(sic);
lws.ssn_server = &si;
/* New session, previous was marked as reset. Clear the reset flag. */
flow->clear_session_flags(SSNFLAG_RESET);
- flow->set_expire(tsd.get_pkt(), config->session_timeout);
+
+ flow->set_expire(tsd.get_pkt(), flow->default_session_timeout);
update_perf_base_state(TcpStreamTracker::TCP_SYN_SENT);
TcpStreamSession::setup(p);
splitter_init = false;
+ TcpStreamConfig* pc = get_tcp_cfg(flow->ssn_server);
+ flow->set_default_session_timeout(pc->session_timeout, false);
+
SESSION_STATS_ADD(tcpStats);
tcpStats.setups++;
return true;
if (!(pkt_action_mask & ACTION_LWSSN_CLOSED))
{
flow->markup_packet_flags(p);
- flow->set_expire(p, config->session_timeout);
+
+ flow->set_expire(p, flow->default_session_timeout);
}
else
TcpHAManager::process_deletion(*p->flow);
flow->ssn_state.direction = FROM_CLIENT;
StreamUdpConfig* pc = get_udp_cfg(flow->ssn_server);
- flow->set_expire(p, pc->session_timeout);
+ flow->set_default_session_timeout(pc->session_timeout, false);
SESSION_STATS_ADD(udpStats);
ProcessUdp(flow, p, pc, nullptr);
flow->markup_packet_flags(p);
- flow->set_expire(p, pc->session_timeout);
+
+ flow->set_expire(p, flow->default_session_timeout);
return 0;
}
}
}
- StreamUserConfig* pc = get_user_cfg(flow->ssn_server);
- flow->set_expire(p, pc->session_timeout);
+ flow->set_expire(p, flow->default_session_timeout);
}
void UserSession::restart(Packet* p)
client.init();
server.init();
+ StreamUserConfig* pc = get_user_cfg(flow->ssn_server);
+ flow->set_default_session_timeout(pc->session_timeout, false);
+
#ifdef ENABLE_EXPECTED_USER
if ( Stream::expected_flow(flow, p) )
return false;