#include "stream/stream_splitter.h"
#include "pp_flow_iface.h"
+#include "pp_packet_iface.h"
#include "pp_raw_buffer_iface.h"
using namespace snort;
Lua::Args args(L);
auto& self = StreamSplitterIface.get(L, 1);
- auto& flow = FlowIface.get(L, 2);
+ auto& pkt = PacketIface.get(L, 2);
auto& rb = RawBufferIface.get(L, 3);
uint32_t len = args[4].opt_size(rb.size(), rb.size());
uint32_t flags = args[5].opt_size();
uint32_t fp = 0;
- auto status = self.scan(&flow, get_data(rb), len, flags, &fp);
+ auto status = self.scan(&pkt, get_data(rb), len, flags, &fp);
stack_push<StreamSplitter::Status, unsigned>(L, status);
Lua::Stack<uint32_t>::push(L, fp);
}
StreamSplitter::Status DceHttpProxySplitter::scan(
- Flow*, const uint8_t* data, uint32_t len,
+ Packet*, const uint8_t* data, uint32_t len,
uint32_t flags, uint32_t* fp)
{
StreamSplitter::Status status;
TEST_CASE("DceHttpProxySplitter-scan - first_proxy_request", "[http_proxy_splitter]")
{
DceHttpProxySplitter* splitter = new DceHttpProxySplitter(true);
- Flow* flow = new Flow();
uint32_t fp;
REQUIRE(splitter->cutover_inspector() == false);
- REQUIRE(splitter->scan(flow, (const uint8_t*)"RPC", 3, PKT_FROM_CLIENT, &fp) ==
+ REQUIRE(splitter->scan(nullptr, (const uint8_t*)"RPC", 3, PKT_FROM_CLIENT, &fp) ==
StreamSplitter::SEARCH);
REQUIRE(splitter->cutover_inspector() == false);
- delete flow;
delete splitter;
}
TEST_CASE("DceHttpProxySplitter-scan - first_proxy_request_no_direction", "[http_proxy_splitter]")
{
DceHttpProxySplitter* splitter = new DceHttpProxySplitter(true);
- Flow* flow = new Flow();
uint32_t fp;
REQUIRE(splitter->cutover_inspector() == false);
- REQUIRE(splitter->scan(flow, (const uint8_t*)"RPC", 3, 0, &fp) == StreamSplitter::ABORT);
+ REQUIRE(splitter->scan(nullptr, (const uint8_t*)"RPC", 3, 0, &fp) == StreamSplitter::ABORT);
REQUIRE(splitter->cutover_inspector() == false);
- delete flow;
delete splitter;
}
TEST_CASE("DceHttpProxySplitter-scan - bad_first_proxy_request", "[http_proxy_splitter]")
{
DceHttpProxySplitter* splitter = new DceHttpProxySplitter(true);
- Flow* flow = new Flow();
uint32_t fp;
- REQUIRE(splitter->scan(flow, (const uint8_t*)"xxx", 1, PKT_FROM_CLIENT, &fp) ==
+ REQUIRE(splitter->scan(nullptr, (const uint8_t*)"xxx", 1, PKT_FROM_CLIENT, &fp) ==
StreamSplitter::ABORT);
REQUIRE(splitter->cutover_inspector() == false);
- delete flow;
delete splitter;
}
TEST_CASE("DceHttpProxySplitter-scan - first_bad_second_proxy_request", "[http_proxy_splitter]")
{
DceHttpProxySplitter* splitter = new DceHttpProxySplitter(true);
- Flow* flow = new Flow();
uint32_t fp;
- REQUIRE(splitter->scan(flow, (const uint8_t*)"RPC", 3, PKT_FROM_CLIENT, &fp) ==
+ REQUIRE(splitter->scan(nullptr, (const uint8_t*)"RPC", 3, PKT_FROM_CLIENT, &fp) ==
StreamSplitter::SEARCH);
REQUIRE(splitter->cutover_inspector() == false);
- REQUIRE(splitter->scan(flow, (const uint8_t*)"R", 1, PKT_FROM_CLIENT, &fp) ==
+ REQUIRE(splitter->scan(nullptr, (const uint8_t*)"R", 1, PKT_FROM_CLIENT, &fp) ==
StreamSplitter::ABORT);
REQUIRE(splitter->cutover_inspector() == false);
- delete flow;
delete splitter;
}
TEST_CASE("DceHttpProxySplitter-scan - first_good_second_proxy_request", "[http_proxy_splitter]")
{
DceHttpProxySplitter* splitter = new DceHttpProxySplitter(true);
- Flow* flow = new Flow();
uint32_t fp;
- REQUIRE(splitter->scan(flow, (const uint8_t*)"RPC", 3, PKT_FROM_CLIENT, &fp) ==
+ REQUIRE(splitter->scan(nullptr, (const uint8_t*)"RPC", 3, PKT_FROM_CLIENT, &fp) ==
StreamSplitter::SEARCH);
- REQUIRE(splitter->scan(flow, (const uint8_t*)"_CON", 4, PKT_FROM_CLIENT, &fp) ==
+ REQUIRE(splitter->scan(nullptr, (const uint8_t*)"_CON", 4, PKT_FROM_CLIENT, &fp) ==
StreamSplitter::SEARCH);
REQUIRE(splitter->cutover_inspector() == false);
- delete flow;
delete splitter;
}
TEST_CASE("DceHttpProxySplitter-scan - full_proxy_request", "[http_proxy_splitter]")
{
DceHttpProxySplitter* splitter = new DceHttpProxySplitter(true);
- Flow* flow = new Flow();
uint32_t fp = 0;
- REQUIRE(splitter->scan(flow, (const uint8_t*)HTTP_PROXY_REQUEST,
+ REQUIRE(splitter->scan(nullptr, (const uint8_t*)HTTP_PROXY_REQUEST,
strlen(HTTP_PROXY_REQUEST), PKT_FROM_CLIENT, &fp) == StreamSplitter::FLUSH);
REQUIRE(fp == strlen(HTTP_PROXY_REQUEST));
- REQUIRE(splitter->scan(flow, (const uint8_t*)"0", 1, PKT_FROM_CLIENT, &fp) ==
+ REQUIRE(splitter->scan(nullptr, (const uint8_t*)"0", 1, PKT_FROM_CLIENT, &fp) ==
StreamSplitter::FLUSH);
REQUIRE(splitter->cutover_inspector() == true);
- delete flow;
delete splitter;
}
DceHttpProxySplitter* splitter = new DceHttpProxySplitter(true);
const char* extra = "ignore";
char* string = new char[strlen(HTTP_PROXY_REQUEST)+strlen(extra)+1];
- Flow* flow = new Flow();
uint32_t fp = 0;
strncpy(string,(const char*)HTTP_PROXY_REQUEST,strlen(HTTP_PROXY_REQUEST)+1);
strncpy(string+strlen(HTTP_PROXY_REQUEST),extra,strlen(extra)+1);
- REQUIRE(splitter->scan(flow, (const uint8_t*)string,
+ REQUIRE(splitter->scan(nullptr, (const uint8_t*)string,
(strlen(HTTP_PROXY_REQUEST)+strlen(extra)), PKT_FROM_CLIENT, &fp) ==
StreamSplitter::FLUSH);
REQUIRE(fp == strlen(HTTP_PROXY_REQUEST));
- REQUIRE(splitter->scan(flow, (const uint8_t*)"0", 1, PKT_FROM_CLIENT, &fp) ==
+ REQUIRE(splitter->scan(nullptr, (const uint8_t*)"0", 1, PKT_FROM_CLIENT, &fp) ==
StreamSplitter::FLUSH);
REQUIRE(splitter->cutover_inspector() == true);
- delete flow;
delete splitter;
delete[] string;
}
TEST_CASE("DceHttpProxySplitter-scan - first_proxy_response", "[http_proxy_splitter]")
{
DceHttpProxySplitter* splitter = new DceHttpProxySplitter(false);
- Flow* flow = new Flow();
uint32_t fp;
REQUIRE(splitter->cutover_inspector() == false);
- REQUIRE(splitter->scan(flow, (const uint8_t*)"xxx", 3, PKT_FROM_SERVER, &fp) ==
+ REQUIRE(splitter->scan(nullptr, (const uint8_t*)"xxx", 3, PKT_FROM_SERVER, &fp) ==
StreamSplitter::ABORT);
REQUIRE(splitter->cutover_inspector() == false);
- delete flow;
delete splitter;
}
TEST_CASE("DceHttpProxySplitter-scan - good_1_proxy_response", "[http_proxy_splitter]")
{
DceHttpProxySplitter* splitter = new DceHttpProxySplitter(false);
- Flow* flow = new Flow();
uint32_t fp = 0;
REQUIRE(splitter->cutover_inspector() == false);
- REQUIRE(splitter->scan(flow, (const uint8_t*)"HTTP/1.xxx\n\n", 12,
+ REQUIRE(splitter->scan(nullptr, (const uint8_t*)"HTTP/1.xxx\n\n", 12,
PKT_FROM_SERVER, &fp) == StreamSplitter::FLUSH);
REQUIRE((fp == 12));
REQUIRE(splitter->cutover_inspector() == true);
- delete flow;
delete splitter;
}
TEST_CASE("DceHttpProxySplitter-scan - good_2_proxy_response", "[http_proxy_splitter]")
{
DceHttpProxySplitter* splitter = new DceHttpProxySplitter(false);
- Flow* flow = new Flow();
uint32_t fp = 0;
REQUIRE(splitter->cutover_inspector() == false);
- REQUIRE(splitter->scan(flow, (const uint8_t*)"HTTP/1.xxx\nxx\n\n", 15,
+ REQUIRE(splitter->scan(nullptr, (const uint8_t*)"HTTP/1.xxx\nxx\n\n", 15,
PKT_FROM_SERVER, &fp) == StreamSplitter::FLUSH);
REQUIRE((fp == 15));
REQUIRE(splitter->cutover_inspector() == true);
- delete flow;
delete splitter;
}
TEST_CASE("DceHttpProxySplitter-scan - good_3_proxy_response", "[http_proxy_splitter]")
{
DceHttpProxySplitter* splitter = new DceHttpProxySplitter(false);
- Flow* flow = new Flow();
uint32_t fp = 0;
REQUIRE(splitter->cutover_inspector() == false);
- REQUIRE(splitter->scan(flow, (const uint8_t*)"HTTP/1.xxx\nxx\n\nyyy", 18,
+ REQUIRE(splitter->scan(nullptr, (const uint8_t*)"HTTP/1.xxx\nxx\n\nyyy", 18,
PKT_FROM_SERVER, &fp) == StreamSplitter::FLUSH);
REQUIRE((fp == 18));
REQUIRE(splitter->cutover_inspector() == true);
- delete flow;
delete splitter;
}
TEST_CASE("DceHttpProxySplitter-scan - bad_1_proxy_response", "[http_proxy_splitter]")
{
DceHttpProxySplitter* splitter = new DceHttpProxySplitter(false);
- Flow* flow = new Flow();
uint32_t fp;
REQUIRE(splitter->cutover_inspector() == false);
- REQUIRE(splitter->scan(flow, (const uint8_t*)"HTTP/1.xxx\nx\n", 13, PKT_FROM_SERVER, &fp) ==
+ REQUIRE(splitter->scan(nullptr, (const uint8_t*)"HTTP/1.xxx\nx\n", 13, PKT_FROM_SERVER, &fp) ==
StreamSplitter::SEARCH);
REQUIRE(splitter->cutover_inspector() == false);
- delete flow;
delete splitter;
}
TEST_CASE("DceHttpProxySplitter-scan - bad_2_proxy_response", "[http_proxy_splitter]")
{
DceHttpProxySplitter* splitter = new DceHttpProxySplitter(false);
- Flow* flow = new Flow();
uint32_t fp;
REQUIRE(splitter->cutover_inspector() == false);
- REQUIRE(splitter->scan(flow, (const uint8_t*)"HTTP/1.xxx\nx", 12, PKT_FROM_SERVER, &fp) ==
+ REQUIRE(splitter->scan(nullptr, (const uint8_t*)"HTTP/1.xxx\nx", 12, PKT_FROM_SERVER, &fp) ==
StreamSplitter::SEARCH);
REQUIRE(splitter->cutover_inspector() == false);
- delete flow;
delete splitter;
}
TEST_CASE("DceHttpProxySplitter-scan - bad_3_proxy_response", "[http_proxy_splitter]")
{
DceHttpProxySplitter* splitter = new DceHttpProxySplitter(false);
- Flow* flow = new Flow();
uint32_t fp;
REQUIRE(splitter->cutover_inspector() == false);
- REQUIRE(splitter->scan(flow, (const uint8_t*)"HTTP/1.", 7, PKT_FROM_SERVER, &fp) ==
+ REQUIRE(splitter->scan(nullptr, (const uint8_t*)"HTTP/1.", 7, PKT_FROM_SERVER, &fp) ==
StreamSplitter::SEARCH);
REQUIRE(splitter->cutover_inspector() == false);
- delete flow;
delete splitter;
}
public:
DceHttpProxySplitter(bool c2s);
- Status scan(snort::Flow*, const uint8_t* data, uint32_t len,
+ Status scan(snort::Packet*, const uint8_t* data, uint32_t len,
uint32_t flags, uint32_t* fp) override;
const snort::StreamBuffer reassemble(snort::Flow*, unsigned, unsigned,
#define HTTP_SERVER_MARKER "ncacn_http/1.0"
StreamSplitter::Status DceHttpServerSplitter::scan(
- Flow*, const uint8_t* data, uint32_t len, uint32_t flags, uint32_t* fp)
+ Packet*, const uint8_t* data, uint32_t len, uint32_t flags, uint32_t* fp)
{
if ( (flags & PKT_FROM_CLIENT) != 0 )
return StreamSplitter::ABORT;
TEST_CASE("DceHttpServerSplitter-scan - first_server", "[http_server_splitter]")
{
DceHttpServerSplitter* splitter = new DceHttpServerSplitter(false);
- Flow* flow = new Flow();
uint32_t fp;
REQUIRE(splitter->cutover_inspector() == false);
- REQUIRE(splitter->scan(flow, (const uint8_t*)"n", 1, PKT_FROM_SERVER, &fp) ==
+ REQUIRE(splitter->scan(nullptr, (const uint8_t*)"n", 1, PKT_FROM_SERVER, &fp) ==
StreamSplitter::SEARCH);
REQUIRE(splitter->cutover_inspector() == false);
- delete flow;
delete splitter;
}
TEST_CASE("DceHttpServerSplitter-scan - first_server_wrong_direction", "[http_server_splitter]")
{
DceHttpServerSplitter* splitter = new DceHttpServerSplitter(false);
- Flow* flow = new Flow();
uint32_t fp;
REQUIRE(splitter->cutover_inspector() == false);
- REQUIRE(splitter->scan(flow, (const uint8_t*)"n", 1, PKT_FROM_CLIENT, &fp) ==
+ REQUIRE(splitter->scan(nullptr, (const uint8_t*)"n", 1, PKT_FROM_CLIENT, &fp) ==
StreamSplitter::ABORT);
REQUIRE(splitter->cutover_inspector() == false);
- delete flow;
delete splitter;
}
TEST_CASE("DceHttpServerSplitter-scan - bad_first_server", "[http_server_splitter]")
{
DceHttpServerSplitter* splitter = new DceHttpServerSplitter(false);
- Flow* flow = new Flow();
uint32_t fp;
- REQUIRE(splitter->scan(flow, (const uint8_t*)"x", 1, PKT_FROM_SERVER, &fp) ==
+ REQUIRE(splitter->scan(nullptr, (const uint8_t*)"x", 1, PKT_FROM_SERVER, &fp) ==
StreamSplitter::ABORT);
REQUIRE(splitter->cutover_inspector() == false);
- delete flow;
delete splitter;
}
TEST_CASE("DceHttpServerSplitter-scan - first_bad_second_server", "[http_server_splitter]")
{
DceHttpServerSplitter* splitter = new DceHttpServerSplitter(false);
- Flow* flow = new Flow();
uint32_t fp;
- REQUIRE(splitter->scan(flow, (const uint8_t*)"n", 1, PKT_FROM_SERVER, &fp) ==
+ REQUIRE(splitter->scan(nullptr, (const uint8_t*)"n", 1, PKT_FROM_SERVER, &fp) ==
StreamSplitter::SEARCH);
REQUIRE(splitter->cutover_inspector() == false);
- REQUIRE(splitter->scan(flow, (const uint8_t*)"n", 1, PKT_FROM_SERVER, &fp) ==
+ REQUIRE(splitter->scan(nullptr, (const uint8_t*)"n", 1, PKT_FROM_SERVER, &fp) ==
StreamSplitter::ABORT);
REQUIRE(splitter->cutover_inspector() == false);
- delete flow;
delete splitter;
}
TEST_CASE("DceHttpServerSplitter-scan - first_good_second_server", "[http_server_splitter]")
{
DceHttpServerSplitter* splitter = new DceHttpServerSplitter(false);
- Flow* flow = new Flow();
uint32_t fp;
- REQUIRE(splitter->scan(flow, (const uint8_t*)"n", 1, PKT_FROM_SERVER, &fp) ==
+ REQUIRE(splitter->scan(nullptr, (const uint8_t*)"n", 1, PKT_FROM_SERVER, &fp) ==
StreamSplitter::SEARCH);
- REQUIRE(splitter->scan(flow, (const uint8_t*)"c", 1, PKT_FROM_SERVER, &fp) ==
+ REQUIRE(splitter->scan(nullptr, (const uint8_t*)"c", 1, PKT_FROM_SERVER, &fp) ==
StreamSplitter::SEARCH);
REQUIRE(splitter->cutover_inspector() == false);
- delete flow;
delete splitter;
}
TEST_CASE("DceHttpServerSplitter-scan - full_server", "[http_server_splitter]")
{
DceHttpServerSplitter* splitter = new DceHttpServerSplitter(false);
- Flow* flow = new Flow();
uint32_t fp;
- REQUIRE(splitter->scan(flow, (const uint8_t*)HTTP_SERVER_MARKER,
+ REQUIRE(splitter->scan(nullptr, (const uint8_t*)HTTP_SERVER_MARKER,
strlen(HTTP_SERVER_MARKER), PKT_FROM_SERVER, &fp) == StreamSplitter::FLUSH);
REQUIRE(fp == strlen(HTTP_SERVER_MARKER));
REQUIRE(splitter->cutover_inspector() == true);
- delete flow;
delete splitter;
}
DceHttpServerSplitter* splitter = new DceHttpServerSplitter(false);
const char* extra = "ignore";
char* string = new char[strlen(HTTP_SERVER_MARKER)+strlen(extra)+1];
- Flow* flow = new Flow();
uint32_t fp;
strncpy(string,(const char*)HTTP_SERVER_MARKER,strlen(HTTP_SERVER_MARKER)+1);
strncpy(string+strlen(HTTP_SERVER_MARKER),extra,strlen(extra)+1);
- REQUIRE(splitter->scan(flow, (const uint8_t*)string,
+ REQUIRE(splitter->scan(nullptr, (const uint8_t*)string,
(strlen(HTTP_SERVER_MARKER)+strlen(extra)), PKT_FROM_SERVER, &fp) ==
StreamSplitter::FLUSH);
REQUIRE(fp == strlen(HTTP_SERVER_MARKER));
REQUIRE(splitter->cutover_inspector() == true);
- delete flow;
delete splitter;
delete[] string;
}
public:
DceHttpServerSplitter(bool c2s);
- Status scan(snort::Flow*, const uint8_t* data, uint32_t len,
+ Status scan(snort::Packet*, const uint8_t* data, uint32_t len,
uint32_t flags, uint32_t* fp) override;
// FIXIT-M - Should be able to implement but framework does not permit
/* const StreamBuffer* reassemble(Flow*, unsigned, unsigned,
}
StreamSplitter::Status Dce2SmbSplitter::scan(
- Flow* flow, const uint8_t* data, uint32_t len,
+ Packet* pkt, const uint8_t* data, uint32_t len,
uint32_t flags, uint32_t* fp)
{
DCE2_PafSmbData* pfdata = &state;
- return dce2_smb_paf(pfdata, flow, data, len, flags, fp);
+ return dce2_smb_paf(pfdata, pkt->flow, data, len, flags, fp);
}
public:
Dce2SmbSplitter(bool c2s);
- Status scan(snort::Flow*, const uint8_t* data, uint32_t len,
+ Status scan(snort::Packet*, const uint8_t* data, uint32_t len,
uint32_t flags, uint32_t* fp) override;
bool is_paf() override
}
StreamSplitter::Status Dce2TcpSplitter::scan(
- Flow* flow, const uint8_t* data, uint32_t len,
+ Packet* pkt, const uint8_t* data, uint32_t len,
uint32_t flags, uint32_t* fp)
{
DCE2_PafTcpData* pfdata = &state;
- return dce2_tcp_paf(pfdata, flow, data, len, flags, fp);
+ return dce2_tcp_paf(pfdata, pkt->flow, data, len, flags, fp);
}
public:
Dce2TcpSplitter(bool c2s);
- Status scan(snort::Flow*, const uint8_t* data, uint32_t len,
+ Status scan(snort::Packet*, const uint8_t* data, uint32_t len,
uint32_t flags, uint32_t* fp) override;
bool is_paf() override
}
StreamSplitter::Status Dnp3Splitter::scan(
- Flow*, const uint8_t* data, uint32_t len,
+ Packet*, const uint8_t* data, uint32_t len,
uint32_t, uint32_t* fp)
{
dnp3_paf_data* pfdata = &state;
public:
Dnp3Splitter(bool c2s);
- Status scan(snort::Flow*, const uint8_t* data, uint32_t len,
+ Status scan(snort::Packet*, const uint8_t* data, uint32_t len,
uint32_t flags, uint32_t* fp) override;
bool is_paf() override
// flush at last line feed in data
// preproc will deal with any pipelined commands
StreamSplitter::Status FtpSplitter::scan(
- Flow*, const uint8_t* data, uint32_t len,
+ Packet*, const uint8_t* data, uint32_t len,
uint32_t, uint32_t* fp)
{
#ifdef HAVE_MEMRCHR
public:
FtpSplitter(bool c2s);
- Status scan(snort::Flow*, const uint8_t* data, uint32_t len,
+ Status scan(snort::Packet*, const uint8_t* data, uint32_t len,
uint32_t flags, uint32_t* fp) override;
bool is_paf() override { return true; }
fdfd->session.packet_flags |= FTPDATA_FLG_FLUSH;
}
-StreamSplitter::Status FtpDataSplitter::scan(Flow* flow, const uint8_t*, uint32_t len,
+StreamSplitter::Status FtpDataSplitter::scan(Packet* pkt, const uint8_t*, uint32_t len,
uint32_t, uint32_t* fp)
{
+ Flow* flow = pkt->flow;
+ assert(flow);
+
if ( len )
{
if(expected_seg_size == 0)
#include "stream/flush_bucket.h"
#include "stream/stream_splitter.h"
-namespace snort
-{
-class Flow;
-}
-
//---------------------------------------------------------------------------------
// FtpDataSplitter - flush when current seg size is different from previous segment
//---------------------------------------------------------------------------------
}
- Status scan(snort::Flow*, const uint8_t*, uint32_t len, uint32_t flags, uint32_t* fp ) override;
+ Status scan(snort::Packet*, const uint8_t*, uint32_t len, uint32_t flags, uint32_t* fp ) override;
bool finish(snort::Flow*) override;
private:
#include <cassert>
+#include "protocols/packet.h"
+
#include "http2_stream_splitter.h"
#include "http2_module.h"
using namespace Http2Enums;
// Mindless scan() that just flushes whatever it is given
-StreamSplitter::Status Http2StreamSplitter::scan(Flow* flow, const uint8_t* data, uint32_t length,
+StreamSplitter::Status Http2StreamSplitter::scan(Packet* pkt, const uint8_t* data, uint32_t length,
uint32_t, uint32_t* flush_offset)
{
// This is the session state information we share with Http2Inspect and store with stream. A
// session is defined by a TCP connection. Since scan() is the first to see a new TCP
// connection the new flow data object is created here.
- Http2FlowData* session_data = (Http2FlowData*)flow->get_flow_data(Http2FlowData::inspector_id);
+ Http2FlowData* session_data = (Http2FlowData*)pkt->flow->get_flow_data(Http2FlowData::inspector_id);
if (session_data == nullptr)
{
- flow->set_flow_data(session_data = new Http2FlowData);
+ pkt->flow->set_flow_data(session_data = new Http2FlowData);
Http2Module::increment_peg_counts(PEG_FLOW);
}
public:
Http2StreamSplitter(bool is_client_to_server) : snort::StreamSplitter(is_client_to_server),
source_id(is_client_to_server ? Http2Enums::SRC_CLIENT : Http2Enums::SRC_SERVER) { }
- Status scan(snort::Flow* flow, const uint8_t* data, uint32_t length, uint32_t not_used,
+ Status scan(snort::Packet* pkt, const uint8_t* data, uint32_t length, uint32_t not_used,
uint32_t* flush_offset) override;
const snort::StreamBuffer reassemble(snort::Flow* flow, unsigned total, unsigned offset, const
uint8_t* data, unsigned len, uint32_t flags, unsigned& copied) override;
snort::StreamSplitter(is_client_to_server),
my_inspector(my_inspector_),
source_id(is_client_to_server ? HttpEnums::SRC_CLIENT : HttpEnums::SRC_SERVER) {}
- Status scan(snort::Flow* flow, const uint8_t* data, uint32_t length, uint32_t not_used,
+ Status scan(snort::Packet* pkt, const uint8_t* data, uint32_t length, uint32_t not_used,
uint32_t* flush_offset) override;
const snort::StreamBuffer reassemble(snort::Flow* flow, unsigned total, unsigned, const
uint8_t* data, unsigned len, uint32_t flags, unsigned& copied) override;
}
}
-StreamSplitter::Status HttpStreamSplitter::scan(Flow* flow, const uint8_t* data, uint32_t length,
+StreamSplitter::Status HttpStreamSplitter::scan(Packet* pkt, const uint8_t* data, uint32_t length,
uint32_t, uint32_t* flush_offset)
{
snort::Profile profile(HttpModule::get_profile_stats());
assert(length <= MAX_OCTETS);
+ Flow* flow = pkt->flow;
+
// This is the session state information we share with HttpInspect and store with stream. A
// session is defined by a TCP connection. Since scan() is the first to see a new TCP
// connection the new flow data object is created here.
*/
StreamSplitter::Status ImapSplitter::scan(
- Flow* , const uint8_t* data, uint32_t len,
+ Packet*, const uint8_t* data, uint32_t len,
uint32_t flags, uint32_t* fp)
{
ImapPafData* pfdata = &state;
public:
ImapSplitter(bool c2s);
- Status scan(snort::Flow*, const uint8_t* data, uint32_t len,
+ Status scan(snort::Packet*, const uint8_t* data, uint32_t len,
uint32_t flags, uint32_t* fp) override;
bool is_paf() override { return true; }
// Reads up until the length octet is found, then sets a flush point.
StreamSplitter::Status ModbusSplitter::scan(
- Flow*, const uint8_t* data, uint32_t len, uint32_t /*flags*/, uint32_t* fp)
+ Packet*, const uint8_t* data, uint32_t len, uint32_t /*flags*/, uint32_t* fp)
{
uint32_t bytes_processed = 0;
public:
ModbusSplitter(bool);
- Status scan(snort::Flow*, const uint8_t* data, uint32_t len, uint32_t flags,
+ Status scan(snort::Packet*, const uint8_t* data, uint32_t len, uint32_t flags,
uint32_t* fp) override;
bool is_paf() override { return true; }
*/
StreamSplitter::Status PopSplitter::scan(
- Flow* ssn, const uint8_t* data, uint32_t len,
+ Packet* pkt, const uint8_t* data, uint32_t len,
uint32_t flags, uint32_t* fp)
{
PopPafData* pfdata = &state;
if (flags & PKT_FROM_SERVER)
return pop_paf_server(pfdata, data, len, fp);
else
- return pop_paf_client(ssn, pfdata, data, len, fp);
+ return pop_paf_client(pkt->flow, pfdata, data, len, fp);
}
bool pop_is_data_end(Flow* ssn)
public:
PopSplitter(bool c2s);
- Status scan(snort::Flow*, const uint8_t* data, uint32_t len,
+ Status scan(snort::Packet*, const uint8_t* data, uint32_t len,
uint32_t flags, uint32_t* fp) override;
bool is_paf() override { return true; }
public:
RpcSplitter(bool c2s) : StreamSplitter(c2s) { }
- Status scan(Flow*, const uint8_t*, uint32_t,
+ Status scan(Packet*, const uint8_t*, uint32_t,
uint32_t, uint32_t*) override
{ return SEARCH; }
}
StreamSplitter::Status SipSplitter::scan(
- Flow *, const uint8_t* data, uint32_t len,
+ Packet*, const uint8_t* data, uint32_t len,
uint32_t, uint32_t* fp)
{
for (uint32_t i = 0; i < len; i++)
public:
SipSplitter(bool c2s);
- Status scan(snort::Flow*, const uint8_t* data, uint32_t len,
+ Status scan(snort::Packet*, const uint8_t* data, uint32_t len,
uint32_t flags, uint32_t* fp) override;
bool is_paf() override
ss.process_command(ch);
}
- snort::StreamSplitter::Status splitter_scan(snort::Flow *flow, const uint8_t* data,
+ snort::StreamSplitter::Status splitter_scan(snort::Packet* pkt, const uint8_t* data,
uint32_t len, uint32_t flags, uint32_t* fp)
{
- return ss.scan(flow, data, len, flags, fp);
+ return ss.scan(pkt, data, len, flags, fp);
}
bool is_init()
*/
StreamSplitter::Status SmtpSplitter::scan(
- Flow* , const uint8_t* data, uint32_t len,
+ Packet*, const uint8_t* data, uint32_t len,
uint32_t flags, uint32_t* fp)
{
SmtpPafData* pfdata = &state;
public:
SmtpSplitter(bool c2s, int max_auth_cmd_line_len);
- Status scan(snort::Flow*, const uint8_t* data, uint32_t len,
+ Status scan(snort::Packet*, const uint8_t* data, uint32_t len,
uint32_t flags, uint32_t* fp) override;
bool is_paf() override { return true; }
}
StreamSplitter::Status SslSplitter::scan(
- Flow*, const uint8_t* data, uint32_t len,
+ Packet*, const uint8_t* data, uint32_t len,
uint32_t, uint32_t* fp)
{
uint32_t n = 0;
public:
SslSplitter(bool c2s);
- Status scan(snort::Flow*, const uint8_t* data, uint32_t len,
+ Status scan(snort::Packet*, const uint8_t* data, uint32_t len,
uint32_t flags, uint32_t* fp) override;
bool is_paf() override
MagicSplitter(bool, class Wizard*);
~MagicSplitter() override;
- Status scan(Flow*, const uint8_t* data, uint32_t len,
+ Status scan(Packet*, const uint8_t* data, uint32_t len,
uint32_t flags, uint32_t* fp) override;
bool is_paf() override { return true; }
// FIXIT-M stop search on hit and failure (no possible match)
StreamSplitter::Status MagicSplitter::scan(
- Flow* f, const uint8_t* data, uint32_t len,
+ Packet* pkt, const uint8_t* data, uint32_t len,
uint32_t, uint32_t*)
{
Profile profile(wizPerfStats);
- count_scan(f);
+ count_scan(pkt->flow);
- if ( wizard->cast_spell(wand, f, data, len) )
- count_hit(f);
+ if ( wizard->cast_spell(wand, pkt->flow, data, len) )
+ count_hit(pkt->flow);
else if ( wizard->finished(wand) )
return ABORT;
#include "paf.h"
+#include "detection/detection_engine.h"
#include "protocols/packet.h"
using namespace snort;
//--------------------------------------------------------------------
static bool paf_callback (
- StreamSplitter* ss, PAF_State* ps, PafAux& px, Flow* ssn,
+ StreamSplitter* ss, PAF_State* ps, PafAux& px, Packet* pkt,
const uint8_t* data, uint32_t len, uint32_t flags)
{
ps->fpt = 0;
- ps->paf = ss->scan(ssn, data, len, flags, &ps->fpt);
+
+ ps->paf = ss->scan(pkt, data, len, flags, &ps->fpt);
if ( ps->paf == StreamSplitter::ABORT )
return false;
//--------------------------------------------------------------------
static inline bool paf_eval (
- StreamSplitter* ss, PAF_State* ps, PafAux& px, Flow* ssn,
+ StreamSplitter* ss, PAF_State* ps, PafAux& px, Packet* pkt,
uint32_t flags, const uint8_t* data, uint32_t len)
{
uint16_t fuzz = 0; // FIXIT-L PAF add a little zippedy-do-dah
case StreamSplitter::SEARCH:
if ( px.len > px.idx )
{
- return paf_callback(ss, ps, px, ssn, data, len, flags);
+ return paf_callback(ss, ps, px, pkt, data, len, flags);
}
return false;
ps->paf = StreamSplitter::SEARCH;
return true;
}
- if ( px.len >= ss->max(ssn) + fuzz )
+ if ( px.len >= ss->max(pkt->flow) + fuzz )
{
px.ft = FT_MAX;
return false;
case StreamSplitter::LIMIT:
// if we are within PAF_LIMIT_FUZZ character of paf_max ...
- if ( px.len + PAF_LIMIT_FUZZ >= ss->max(ssn) + fuzz)
+ if ( px.len + PAF_LIMIT_FUZZ >= ss->max(pkt->flow) + fuzz)
{
px.ft = FT_LIMIT;
ps->paf = StreamSplitter::LIMITED;
len -= delta;
}
px.idx = ps->fpt;
- return paf_callback(ss, ps, px, ssn, data, len, flags);
+ return paf_callback(ss, ps, px, pkt, data, len, flags);
}
return false;
//--------------------------------------------------------------------
int32_t paf_check (
- StreamSplitter* ss, PAF_State* ps, Flow* ssn,
+ StreamSplitter* ss, PAF_State* ps, Packet* pkt,
const uint8_t* data, uint32_t len, uint32_t total,
uint32_t seq, uint32_t* flags)
{
// unflushed data.
uint16_t fuzz = 0; // FIXIT-L PAF add a little zippedy-do-dah
- if ( total >= MAX_PAF_MAX && total > ss->max(ssn) + fuzz )
+ if ( total >= MAX_PAF_MAX && total > ss->max(pkt->flow) + fuzz )
{
px.len = MAX_PAF_MAX + fuzz;
len = len + px.len - total;
px.ft = FT_NOP;
uint32_t idx = px.idx;
- bool cont = paf_eval(ss, ps, px, ssn, *flags, data, len);
+ bool cont = paf_eval(ss, ps, px, pkt, *flags, data, len);
if ( px.ft != FT_NOP )
{
if ( ps->paf == StreamSplitter::ABORT )
*flags = 0;
- else if ( (ps->paf != StreamSplitter::FLUSH) && (px.len > ss->max(ssn)+fuzz) )
+ else if ( (ps->paf != StreamSplitter::FLUSH) && (px.len > ss->max(pkt->flow)+fuzz) )
{
px.ft = FT_MAX;
uint32_t fp = paf_flush(ps, px, flags);
namespace snort
{
-class Flow;
+struct Packet;
}
void* paf_new(unsigned max); // create new paf config (per policy)
}
// called on each in order segment
-int32_t paf_check(snort::StreamSplitter* paf_config, PAF_State*, snort::Flow* ssn,
+int32_t paf_check(snort::StreamSplitter* paf_config, PAF_State*, snort::Packet* p,
const uint8_t* data, uint32_t len, uint32_t total, uint32_t seq, uint32_t* flags);
#endif
}
StreamSplitter::Status AtomSplitter::scan(
- Flow*, const uint8_t*, uint32_t len, uint32_t, uint32_t* fp)
+ Packet*, const uint8_t*, uint32_t len, uint32_t, uint32_t* fp)
{
bytes += len;
segs++;
LogSplitter::LogSplitter(bool b) : StreamSplitter(b) { }
-StreamSplitter::Status LogSplitter::scan(Flow*, const uint8_t*, uint32_t len, uint32_t,
+StreamSplitter::Status LogSplitter::scan(Packet*, const uint8_t*, uint32_t len, uint32_t,
uint32_t* fp)
{
*fp = len;
// stop-and-wait splitter
//--------------------------------------------------------------------------
-StreamSplitter::Status StopAndWaitSplitter::scan(Flow* flow, const uint8_t*, uint32_t len,
+StreamSplitter::Status StopAndWaitSplitter::scan(Packet* pkt, const uint8_t*, uint32_t len,
uint32_t, uint32_t*)
{
- StopAndWaitSplitter* peer = (StopAndWaitSplitter*)Stream::get_splitter(flow, !to_server());
+ assert(pkt);
+ StopAndWaitSplitter* peer = (StopAndWaitSplitter*)Stream::get_splitter(pkt->flow, !to_server());
if ( peer and peer->saw_data() )
{
namespace snort
{
class Flow;
+struct Packet;
struct StreamBuffer
{
// (scan (reassemble)*)* finish (reassemble)*
virtual Status scan(
- Flow*,
+ Packet*,
const uint8_t* data, // in order segment data as it arrives
uint32_t len, // length of data
uint32_t flags, // packet flags indicating direction of data
public:
AtomSplitter(bool, uint16_t size = 0);
- Status scan(Flow*, const uint8_t*, uint32_t, uint32_t, uint32_t*) override;
+ Status scan(Packet*, const uint8_t*, uint32_t, uint32_t, uint32_t*) override;
void update() override;
private:
public:
LogSplitter(bool);
- Status scan(Flow*, const uint8_t*, uint32_t, uint32_t, uint32_t*) override;
+ Status scan(Packet*, const uint8_t*, uint32_t, uint32_t, uint32_t*) override;
};
//-------------------------------------------------------------------------
public:
StopAndWaitSplitter(bool b) : StreamSplitter(b) { }
- Status scan(Flow*, const uint8_t*, uint32_t, uint32_t, uint32_t*) override;
+ Status scan(Packet*, const uint8_t*, uint32_t, uint32_t, uint32_t*) override;
private:
bool saw_data()
// see flush_pdu_ackd() for details
// the key difference is that we operate on forward moving data
// because we don't wait until it is acknowledged
-int32_t TcpReassembler::flush_pdu_ips(TcpReassemblerState& trs, uint32_t* flags)
+int32_t TcpReassembler::flush_pdu_ips(TcpReassemblerState& trs, uint32_t* flags, Packet* p)
{
DeepProfile profile(s5TcpPAFPerfStats);
continue;
}
+ assert(trs.sos.session->flow == p->flow);
+
flush_pt = paf_check(
- trs.tracker->splitter, &trs.tracker->paf_state, trs.sos.session->flow,
- tsn->payload(), size, total, tsn->c_seq, flags);
+ trs.tracker->splitter, &trs.tracker->paf_state, p, tsn->payload(),
+ size, total, tsn->c_seq, flags);
if (flush_pt >= 0)
{
// - if we partially scan a segment we must save state so we
// know where we left off and can resume scanning the remainder
-int32_t TcpReassembler::flush_pdu_ackd(TcpReassemblerState& trs, uint32_t* flags)
+int32_t TcpReassembler::flush_pdu_ackd(TcpReassemblerState& trs, uint32_t* flags, Packet* p)
{
DeepProfile profile(s5TcpPAFPerfStats);
if ( SEQ_GT(end, trs.tracker->r_win_base))
size = trs.tracker->r_win_base - tsn->c_seq;
+ assert(trs.sos.session->flow == p->flow);
+
total += size;
flush_pt = paf_check(
- trs.tracker->splitter, &trs.tracker->paf_state, trs.sos.session->flow,
- tsn->payload(), size, total, tsn->c_seq, flags);
+ trs.tracker->splitter, &trs.tracker->paf_state, p, tsn->payload(),
+ size, total, tsn->c_seq, flags);
if ( flush_pt >= 0 )
{
case STREAM_FLPOLICY_ON_DATA:
{
uint32_t flags = get_forward_packet_dir(trs, p);
- int32_t flush_amt = flush_pdu_ips(trs, &flags);
+ int32_t flush_amt = flush_pdu_ips(trs, &flags, p);
while ( flush_amt >= 0 )
{
flushed += this_flush;
flags = get_forward_packet_dir(trs, p);
- flush_amt = flush_pdu_ips(trs, &flags);
+ flush_amt = flush_pdu_ips(trs, &flags, p);
}
if ( !flags && trs.tracker->splitter->is_paf() )
case STREAM_FLPOLICY_ON_ACK:
{
uint32_t flags = get_reverse_packet_dir(trs, p);
- int32_t flush_amt = flush_pdu_ackd(trs, &flags);
+ int32_t flush_amt = flush_pdu_ackd(trs, &flags, p);
while (flush_amt >= 0)
{
{
purge_to_seq(trs, trs.sos.seglist_base_seq);
flags = get_reverse_packet_dir(trs, p);
- flush_amt = flush_pdu_ackd(trs, &flags);
+ flush_amt = flush_pdu_ackd(trs, &flags, p);
}
else
break; // bail if nothing flushed
void final_flush(TcpReassemblerState&, snort::Packet*, uint32_t dir);
uint32_t get_reverse_packet_dir(TcpReassemblerState&, const snort::Packet*);
uint32_t get_forward_packet_dir(TcpReassemblerState&, const snort::Packet*);
- int32_t flush_pdu_ips(TcpReassemblerState&, uint32_t*);
+ int32_t flush_pdu_ips(TcpReassemblerState&, uint32_t*, snort::Packet*);
void fallback(TcpReassemblerState&);
- int32_t flush_pdu_ackd(TcpReassemblerState&, uint32_t* flags);
+ int32_t flush_pdu_ackd(TcpReassemblerState&, uint32_t* flags, snort::Packet*);
int purge_to_seq(TcpReassemblerState&, uint32_t flush_seq);
bool next_no_gap(TcpSegmentNode&);
static StreamSplitter* next_splitter = nullptr;
Flow::Flow() = default;
+Packet::Packet(bool) { }
+Packet::~Packet() { }
struct Packet* DetectionEngine::get_current_packet()
{ return nullptr; }
TEST(other_splitter, stop_and_wait)
{
- Flow flow;
+ Packet pkt(false);
StopAndWaitSplitter cs(false);
StopAndWaitSplitter ss(true);
uint32_t fp = 0;
next_splitter = &ss;
- CHECK(cs.scan(nullptr, nullptr, 123, 0, &fp) == StreamSplitter::SEARCH);
+ CHECK(cs.scan(&pkt, nullptr, 123, 0, &fp) == StreamSplitter::SEARCH);
CHECK(fp == 0);
CHECK(flushed == 0);
next_splitter = &cs;
- CHECK(ss.scan(nullptr, nullptr, 456, 0, &fp) == StreamSplitter::SEARCH);
+ CHECK(ss.scan(&pkt, nullptr, 456, 0, &fp) == StreamSplitter::SEARCH);
CHECK(fp == 0);
CHECK(flushed == 1);
next_splitter = &ss;
- CHECK(cs.scan(nullptr, nullptr, 123, 0, &fp) == StreamSplitter::SEARCH);
+ CHECK(cs.scan(&pkt, nullptr, 123, 0, &fp) == StreamSplitter::SEARCH);
CHECK(fp == 0);
CHECK(flushed == 2);
}
trace_logf(stream_user, "scan[%d]\n", len);
int32_t flush_amt = paf_check(
- splitter, &paf_state, p->flow, us->get_unused_data(), len,
+ splitter, &paf_state, p, us->get_unused_data(), len,
total, paf_state.seq, &flags);
if ( flush_amt >= 0 )