#include "flow.h"
#include "flow_key.h"
#include "ha_module.h"
+#include "session.h"
using namespace snort;
( pkt_time.tv_usec > next_update.tv_usec ) ) );
}
+void FlowHAState::init_next_update()
+{
+ packet_gettimeofday(&next_update);
+ timeradd(&next_update, &min_session_lifetime, &next_update);
+}
+
void FlowHAState::set_next_update()
{
timeradd(&next_update, &min_sync_interval, &next_update);
{
state = INITIAL_STATE;
pending = NONE_PENDING;
+ init_next_update();
}
FlowHAClient::FlowHAClient(uint8_t length, bool session_client)
if ((i == 0) || full || flow.ha_state->check_pending(1 << (i - 1)))
{
assert(ha->client_map[i]);
- length += (ha->client_map[i]->get_message_size() + sizeof(HAClientHeader));
+ length += (ha->client_map[i]->get_message_size(flow) + sizeof(HAClientHeader));
}
}
Stream::delete_flow(&key);
}
-static Flow* consume_ha_update_message(HAMessage& msg, const FlowKey& key)
+static Flow* consume_ha_update_message(HAMessage& msg, const FlowKey& key, Packet* p)
{
// flow will be nullptr if/when the session does not exist in the caches
+ bool no_flow_found = false;
Flow* flow = Stream::get_flow(&key);
if (!flow)
+ {
+ no_flow_found = true;
ha_stats.update_msgs_recv_no_flow++;
+ }
// pointer to one past the last byte in the message
const uint8_t* content_end = msg.buffer + msg.buffer_length;
if (msg.cursor == content_end)
ha_stats.update_msgs_consumed++;
+ if( p && no_flow_found && flow && flow->session )
+ {
+ flow->session->setup(p);
+ }
+
return flow;
}
-static Flow* consume_ha_message(HAMessage& msg)
+static Flow* consume_ha_message(HAMessage& msg, Packet* p = nullptr)
{
ha_stats.msgs_recv++;
}
case HA_UPDATE_EVENT:
{
- flow = consume_ha_update_message(msg, key);
+ flow = consume_ha_update_message(msg, key, p);
ha_stats.update_msgs_recv++;
break;
}
if (p.daq_instance->ioctl(DIOCTL_GET_FLOW_HA_STATE, &fhs, sizeof(fhs)) == DAQ_SUCCESS)
{
HAMessage ha_msg(fhs.data, fhs.length);
- flow = consume_ha_message(ha_msg);
+ flow = consume_ha_message(ha_msg, &p);
ha_stats.daq_imports++;
// Validate that the imported flow matches up with the given flow key.
if (flow)
bool check_any(uint8_t state);
static void config_timers(struct timeval, struct timeval);
bool sync_interval_elapsed();
+ void init_next_update();
void set_next_update();
void reset();
virtual bool consume(snort::Flow*&, const snort::FlowKey*, snort::HAMessage&, uint8_t size) = 0;
virtual bool produce(snort::Flow&, snort::HAMessage&) = 0;
virtual bool is_update_required(snort::Flow*) { return false; }
- uint8_t get_message_size() { return max_length; }
+ virtual uint8_t get_message_size(Flow&) { return max_length; }
FlowHAClientHandle handle; // Actual handle for the instance
uint8_t index;
HAMessage msg((uint8_t*) &chdr, sizeof(chdr) / 2);
FlowKey key;
- consume_ha_update_message(msg, key);
+ consume_ha_update_message(msg, key, &s_pkt);
CHECK(ha_stats.update_msgs_consumed == 0);
CHECK(ha_stats.truncated_msgs == 1);
}
HAMessage msg((uint8_t*) &chdr, sizeof(chdr));
FlowKey key;
- consume_ha_update_message(msg, key);
+ consume_ha_update_message(msg, key, &s_pkt);
CHECK(ha_stats.update_msgs_consumed == 0);
CHECK(ha_stats.unknown_client_idx == 1);
}
HAMessage msg((uint8_t*) &input, sizeof(input));
FlowKey key;
- consume_ha_update_message(msg, key);
+ consume_ha_update_message(msg, key, &s_pkt);
CHECK(ha_stats.update_msgs_consumed == 0);
CHECK(ha_stats.truncated_msgs == 1);
}
HAMessage msg((uint8_t*) &input, sizeof(input));
FlowKey key;
- consume_ha_update_message(msg, key);
+ consume_ha_update_message(msg, key, &s_pkt);
CHECK(ha_stats.update_msgs_consumed == 0);
CHECK(ha_stats.client_consume_errors == 1);
}
HAMessageHeader hdr = { };
HAMessage msg((uint8_t*) &hdr, sizeof(hdr) / 2);
- CHECK(consume_ha_message(msg) == nullptr);
+ CHECK(consume_ha_message(msg, &s_pkt) == nullptr);
CHECK(ha_stats.truncated_msgs == 1);
}
HAMessageHeader hdr = { 0, HA_MESSAGE_VERSION + 1, 0, 0 };
HAMessage msg((uint8_t*) &hdr, sizeof(hdr));
- CHECK(consume_ha_message(msg) == nullptr);
+ CHECK(consume_ha_message(msg, &s_pkt) == nullptr);
CHECK(ha_stats.msg_version_mismatch == 1);
}
HAMessageHeader hdr = { 0, HA_MESSAGE_VERSION, 0x42, 0 };
HAMessage msg((uint8_t*) &hdr, sizeof(hdr));
- CHECK(consume_ha_message(msg) == nullptr);
+ CHECK(consume_ha_message(msg, &s_pkt) == nullptr);
CHECK(ha_stats.msg_length_mismatch == 1);
}
#include "appid_api.h"
+#include "managers/inspector_manager.h"
#include "utils/util.h"
+#include "appid_module.h"
#include "appid_session.h"
#include "appid_session_api.h"
#include "app_info_table.h"
return sizeof(*appHA);
}
-// FIXIT-H last param AppIdSession ctor is appid inspector, we need that but no good way to get it
-// at the moment...code to allocate session ifdef'ed out until this is resolved...
-uint32_t AppIdApi::consume_ha_state(Flow& flow, const uint8_t* buf, uint8_t, IpProtocol /*proto*/,
- SfIp* /*ip*/, uint16_t /*port*/)
+uint32_t AppIdApi::consume_ha_state(Flow& flow, const uint8_t* buf, uint8_t, IpProtocol proto,
+ SfIp* ip, uint16_t port)
{
const AppIdSessionHA* appHA = (const AppIdSessionHA*)buf;
if (appHA->flags & APPID_HA_FLAGS_APP)
AppIdSession* asd =
(AppIdSession*)(flow.get_flow_data(AppIdSession::inspector_id));
-#ifdef APPID_HA_SUPPORT_ENABLED
if (!asd)
{
- asd = new AppIdSession(proto, ip, port, nullptr);
- flow.set_flow_data(asd);
- asd->service.set_id(appHA->appId[1]);
- if ( asd->service.get_id() == APP_ID_FTP_CONTROL )
+ AppIdInspector* inspector = (AppIdInspector*) InspectorManager::get_inspector(MOD_NAME, true);
+ if(inspector)
{
- asd->set_session_flags(APPID_SESSION_CLIENT_DETECTED |
- APPID_SESSION_NOT_A_SERVICE | APPID_SESSION_SERVICE_DETECTED);
- if ( !ServiceDiscovery::add_ftp_service_state(*asd) )
- asd->set_session_flags(APPID_SESSION_CONTINUE);
- asd->service_disco_state = APPID_DISCO_STATE_STATEFUL;
- }
- else
- asd->service_disco_state = APPID_DISCO_STATE_FINISHED;
-
- asd->client_disco_state = APPID_DISCO_STATE_FINISHED;
+ asd = new AppIdSession(proto, ip, port, *inspector);
+ flow.set_flow_data(asd);
+ asd->service.set_id(appHA->appId[1]);
+ if ( asd->service.get_id() == APP_ID_FTP_CONTROL )
+ {
+ asd->set_session_flags(APPID_SESSION_CLIENT_DETECTED |
+ APPID_SESSION_NOT_A_SERVICE | APPID_SESSION_SERVICE_DETECTED);
+ if ( !ServiceDiscovery::add_ftp_service_state(*asd) )
+ asd->set_session_flags(APPID_SESSION_CONTINUE);
+
+ asd->service_disco_state = APPID_DISCO_STATE_STATEFUL;
+ }
+ else
+ asd->service_disco_state = APPID_DISCO_STATE_FINISHED;
+
+ asd->client_disco_state = APPID_DISCO_STATE_FINISHED;
#ifdef ENABLE_APPID_THIRD_PARTY
- if (asd->tpsession)
- asd->tpsession->set_state(TP_STATE_HA);
+ if (asd->tpsession)
+ asd->tpsession->set_state(TP_STATE_HA);
#endif
+ }
}
-#else
+
if ( !asd )
{
- assert(false);
return sizeof(*appHA);
}
-#endif
if( (appHA->flags & APPID_HA_FLAGS_TP_DONE) && asd->tpsession )
{
using namespace snort;
+namespace snort
+{
+
+class Inspector* InspectorManager::get_inspector(char const*, bool, SnortConfig*)
+{ return nullptr; }
+
+}
+
const char* AppInfoManager::get_app_name(AppId)
{
return test_app_name;
}
// FIXIT - enable this test when consume ha appid api call is fixed
-#ifdef APPID_HA_SUPPORT_ENABLED
TEST(appid_api, produce_ha_state)
{
AppIdSessionHA appHA, cmp_buf;
memset((void*)&cmp_buf, 0, sizeof(cmp_buf));
mock_session->common.flow_type = APPID_FLOW_TYPE_IGNORE;
mock_session->common.flags |= APPID_SESSION_SERVICE_DETECTED | APPID_SESSION_HTTP_SESSION;
- uint32_t val = appid_api.produce_ha_state(flow, (uint8_t*)&appHA);
+ uint32_t val = appid_api.produce_ha_state(*flow, (uint8_t*)&appHA);
CHECK_TRUE(val == sizeof(appHA));
CHECK_TRUE(memcmp(&appHA, &cmp_buf, val) == 0);
mock_session->common.flow_type = APPID_FLOW_TYPE_NORMAL;
- val = appid_api.produce_ha_state(flow, (uint8_t*)&appHA);
+ val = appid_api.produce_ha_state(*flow, (uint8_t*)&appHA);
CHECK_TRUE(val == sizeof(appHA));
CHECK_TRUE(appHA.appId[0] == APPID_UT_ID);
CHECK_TRUE(appHA.appId[1] == APPID_UT_ID + 1);
mock_flow_data= nullptr;
SfIp ip;
ip.pton(AF_INET, "192.168.1.222");
- appid_api.consume_ha_state(flow, (uint8_t*)&appHA, 0, IpProtocol::TCP, &ip, 1066);
+ val = appid_api.consume_ha_state(*flow, (uint8_t*)&appHA, 0, IpProtocol::TCP, &ip, 1066);
+ CHECK_TRUE(val == sizeof(appHA));
+ //FIXIT-H refactor below code to test AppId consume functionality
+ /*
AppIdSession* session = (AppIdSession*)flow->get_flow_data(AppIdSession::inspector_id);
CHECK_TRUE(session);
CHECK_TRUE(session->get_tp_app_id() == appHA.appId[0]);
CHECK_TRUE(session->service_disco_state == APPID_DISCO_STATE_FINISHED);
CHECK_TRUE(session->client_disco_state == APPID_DISCO_STATE_FINISHED);
delete session;
+ */
// test logic when service app is ftp control
appHA.appId[1] = APP_ID_FTP_CONTROL;
mock_flow_data= nullptr;
- appid_api.consume_ha_state(flow, (uint8_t*)&appHA, 0, IpProtocol::TCP, &ip, 1066);
+ val = appid_api.consume_ha_state(*flow, (uint8_t*)&appHA, 0, IpProtocol::TCP, &ip, 1066);
+ CHECK_TRUE(val == sizeof(appHA));
+ //FIXIT-H refactor below code to test AppId consume functionality
+ /*
session = (AppIdSession*)flow->get_flow_data(AppIdSession::inspector_id);
CHECK_TRUE(session);
uint64_t flags = session->get_session_flags(APPID_SESSION_CLIENT_DETECTED |
CHECK_TRUE(session->service_disco_state == APPID_DISCO_STATE_STATEFUL);
CHECK_TRUE(session->client_disco_state == APPID_DISCO_STATE_FINISHED);
delete session;
+ */
}
-#endif
TEST(appid_api, create_appid_session_api)
{
SessionHAContent* hac = (SessionHAContent*) msg.cursor;
hac->ssn_state = flow.ssn_state;
+ hac->ssn_state.session_flags &= ~HA_IGNORED_SESSION_FLAGS;
+
hac->flow_state = flow.flow_state;
hac->flags = 0;
if (!is_client_lower(flow))