detect: support per tx sub states

Support for per transaction sub states: different state machines per
transaction type.

Skip engines not belonging to our substate.

Store tx_type in DetectTransaction.

Each protocol supporting sub states will register states from 1 and up.

To support:

Ticket: #8386.
This commit is contained in:
Victor Julien
2026-07-09 17:19:29 +00:00
parent b6bc025789
commit 95365ce05b
12 changed files with 325 additions and 95 deletions
+13
View File
@@ -894,6 +894,12 @@ extern "C" {
alproto: AppProto, direction: u8, GetData: InspectionSingleBufferGetDataPtr,
) -> ::std::os::raw::c_int;
}
extern "C" {
pub fn SCDetectHelperBufferProgressRegisterSubState(
name: *const ::std::os::raw::c_char, alproto: AppProto, direction: u8, sub_state: u8,
progress: u8,
) -> ::std::os::raw::c_int;
}
extern "C" {
pub fn SCDetectRegisterMpmGeneric(
name: *const ::std::os::raw::c_char, desc: *const ::std::os::raw::c_char,
@@ -918,6 +924,13 @@ extern "C" {
alproto: AppProto, direction: u8, GetData: InspectionMultiBufferGetDataPtr, progress: u8,
) -> ::std::os::raw::c_int;
}
extern "C" {
pub fn SCDetectHelperMultiBufferProgressMpmRegisterSubState(
name: *const ::std::os::raw::c_char, desc: *const ::std::os::raw::c_char,
alproto: AppProto, direction: u8, GetData: InspectionMultiBufferGetDataPtr, sub_state: u8,
progress: u8,
) -> ::std::os::raw::c_int;
}
extern "C" {
pub fn SCDetectHelperTransformRegister(
kw: *const SCTransformTableElmt,
+4
View File
@@ -58,6 +58,7 @@
#include "detect-icmp-id.h"
#include "detect-tcp-window.h"
#include "detect-app-layer-protocol.h"
#include "app-layer-parser.h"
static int rule_warnings_only = 0;
@@ -1460,6 +1461,9 @@ void EngineAnalysisRules2(const DetectEngineCtx *de_ctx, const Signature *s)
SCJbSetBool(ctx.js, "is_mpm", app->mpm);
SCJbSetString(ctx.js, "app_proto", AppProtoToString(app->alproto));
SCJbSetUint(ctx.js, "progress", app->progress);
if (app->sub_state)
SCJbSetString(ctx.js, "sub_state",
AppLayerParserGetSubStateName(app->alproto, app->sub_state));
if (app->v2.transforms != NULL) {
SCJbOpenArray(ctx.js, "transforms");
+31
View File
@@ -45,6 +45,20 @@ int SCDetectHelperBufferProgressRegister(
return DetectBufferTypeRegister(name);
}
int SCDetectHelperBufferProgressRegisterSubState(
const char *name, AppProto alproto, uint8_t direction, uint8_t sub_state, uint8_t progress)
{
if (direction & STREAM_TOSERVER) {
DetectAppLayerInspectEngineRegisterSubState(name, alproto, SIG_FLAG_TOSERVER, sub_state,
(uint8_t)progress, DetectEngineInspectGenericList, NULL);
}
if (direction & STREAM_TOCLIENT) {
DetectAppLayerInspectEngineRegisterSubState(name, alproto, SIG_FLAG_TOCLIENT, sub_state,
(uint8_t)progress, DetectEngineInspectGenericList, NULL);
}
return DetectBufferTypeRegister(name);
}
int SCDetectHelperBufferMpmRegister(const char *name, const char *desc, AppProto alproto,
uint8_t direction, InspectionSingleBufferGetDataPtr GetData)
{
@@ -117,6 +131,23 @@ int SCDetectHelperMultiBufferProgressMpmRegister(const char *name, const char *d
return DetectBufferTypeGetByName(name);
}
int SCDetectHelperMultiBufferProgressMpmRegisterSubState(const char *name, const char *desc,
AppProto alproto, uint8_t direction, InspectionMultiBufferGetDataPtr GetData,
uint8_t sub_state, uint8_t progress)
{
if (direction & STREAM_TOSERVER) {
DetectAppLayerMultiRegisterSubState(
name, alproto, SIG_FLAG_TOSERVER, sub_state, progress, GetData, 2);
}
if (direction & STREAM_TOCLIENT) {
DetectAppLayerMultiRegisterSubState(
name, alproto, SIG_FLAG_TOCLIENT, sub_state, progress, GetData, 2);
}
DetectBufferTypeSupportsMultiInstance(name);
DetectBufferTypeSetDescriptionByName(name, desc);
return DetectBufferTypeGetByName(name);
}
int SCDetectHelperMultiBufferMpmRegister(const char *name, const char *desc, AppProto alproto,
uint8_t direction, InspectionMultiBufferGetDataPtr GetData)
{
+5
View File
@@ -85,6 +85,8 @@ int SCDetectHelperBufferProgressRegister(
int SCDetectHelperBufferMpmRegister(const char *name, const char *desc, AppProto alproto,
uint8_t direction, InspectionSingleBufferGetDataPtr GetData);
int SCDetectHelperBufferProgressRegisterSubState(
const char *name, AppProto alproto, uint8_t direction, uint8_t sub_state, uint8_t progress);
int SCDetectRegisterMpmGeneric(const char *name, const char *desc, AppProto alproto,
uint8_t direction, InspectionBufferGetDataPtr GetData, uint8_t progress);
int SCDetectHelperBufferProgressMpmRegister(const char *name, const char *desc, AppProto alproto,
@@ -94,6 +96,9 @@ int SCDetectHelperMultiBufferMpmRegister(const char *name, const char *desc, App
int SCDetectHelperMultiBufferProgressMpmRegister(const char *name, const char *desc,
AppProto alproto, uint8_t direction, InspectionMultiBufferGetDataPtr GetData,
uint8_t progress);
int SCDetectHelperMultiBufferProgressMpmRegisterSubState(const char *name, const char *desc,
AppProto alproto, uint8_t direction, InspectionMultiBufferGetDataPtr GetData,
uint8_t sub_state, uint8_t progress);
int SCDetectHelperTransformRegister(const SCTransformTableElmt *kw);
+26 -5
View File
@@ -89,7 +89,8 @@ static int g_mpm_list_cnt[DETECT_BUFFER_MPM_TYPE_SIZE] = { 0, 0, 0 };
static void RegisterInternal(const char *name, int direction, int priority,
PrefilterRegisterFunc PrefilterRegister, InspectionBufferGetDataPtr GetData,
InspectionSingleBufferGetDataPtr GetDataSingle,
InspectionMultiBufferGetDataPtr GetMultiData, AppProto alproto, uint8_t tx_min_progress)
InspectionMultiBufferGetDataPtr GetMultiData, AppProto alproto, uint8_t sub_state,
uint8_t tx_min_progress)
{
SCLogDebug("registering %s/%d/%d/%p/%p/%u/%d", name, direction, priority,
PrefilterRegister, GetData, alproto, tx_min_progress);
@@ -109,7 +110,7 @@ static void RegisterInternal(const char *name, int direction, int priority,
// every HTTP2 can be accessed from DOH2
if (alproto == ALPROTO_HTTP2 || alproto == ALPROTO_DNS) {
RegisterInternal(name, direction, priority, PrefilterRegister, GetData, GetDataSingle,
GetMultiData, ALPROTO_DOH2, tx_min_progress);
GetMultiData, ALPROTO_DOH2, sub_state, tx_min_progress);
}
DetectBufferMpmRegistry *am = SCCalloc(1, sizeof(*am));
BUG_ON(am == NULL);
@@ -132,6 +133,7 @@ static void RegisterInternal(const char *name, int direction, int priority,
}
am->app_v2.alproto = alproto;
am->app_v2.tx_min_progress = tx_min_progress;
am->app_v2.sub_state = sub_state;
if (g_mpm_list[DETECT_BUFFER_MPM_TYPE_APP] == NULL) {
g_mpm_list[DETECT_BUFFER_MPM_TYPE_APP] = am;
@@ -147,21 +149,31 @@ static void RegisterInternal(const char *name, int direction, int priority,
g_mpm_list_cnt[DETECT_BUFFER_MPM_TYPE_APP]++;
SupportFastPatternForSigMatchList(sm_list, priority);
SCLogDebug("%s: sub_state %u", name, am->app_v2.sub_state);
}
void DetectAppLayerMpmRegister(const char *name, int direction, int priority,
PrefilterRegisterFunc PrefilterRegister, InspectionBufferGetDataPtr GetData,
AppProto alproto, uint8_t tx_min_progress)
{
RegisterInternal(name, direction, priority, PrefilterRegister, GetData, NULL, NULL, alproto,
RegisterInternal(name, direction, priority, PrefilterRegister, GetData, NULL, NULL, alproto, 0,
tx_min_progress);
}
void DetectAppLayerMpmRegisterSubState(const char *name, int direction, int priority,
PrefilterRegisterFunc PrefilterRegister, InspectionBufferGetDataPtr GetData,
AppProto alproto, uint8_t sub_state, uint8_t tx_min_progress)
{
SCLogDebug("%s: sub_state %u", name, sub_state);
RegisterInternal(name, direction, priority, PrefilterRegister, GetData, NULL, NULL, alproto,
sub_state, tx_min_progress);
}
void DetectAppLayerMpmRegisterSingle(const char *name, int direction, int priority,
PrefilterRegisterFunc PrefilterRegister, InspectionSingleBufferGetDataPtr GetData,
AppProto alproto, uint8_t tx_min_progress)
{
RegisterInternal(name, direction, priority, PrefilterRegister, NULL, GetData, NULL, alproto,
RegisterInternal(name, direction, priority, PrefilterRegister, NULL, GetData, NULL, alproto, 0,
tx_min_progress);
}
@@ -169,10 +181,18 @@ void DetectAppLayerMpmMultiRegister(const char *name, int direction, int priorit
PrefilterRegisterFunc PrefilterRegister, InspectionMultiBufferGetDataPtr GetData,
AppProto alproto, uint8_t tx_min_progress)
{
RegisterInternal(name, direction, priority, PrefilterRegister, NULL, NULL, GetData, alproto,
RegisterInternal(name, direction, priority, PrefilterRegister, NULL, NULL, GetData, alproto, 0,
tx_min_progress);
}
void DetectAppLayerMpmMultiRegisterSubState(const char *name, int direction, int priority,
PrefilterRegisterFunc PrefilterRegister, InspectionMultiBufferGetDataPtr GetData,
AppProto alproto, uint8_t sub_state, uint8_t tx_min_progress)
{
RegisterInternal(name, direction, priority, PrefilterRegister, NULL, NULL, GetData, alproto,
sub_state, tx_min_progress);
}
/** \internal
* \brief build basic profiling name (pname) making sure the id is always fully printed
*/
@@ -263,6 +283,7 @@ void DetectAppLayerMpmRegisterByParentId(DetectEngineCtx *de_ctx,
am->app_v2.GetData = t->app_v2.GetData;
am->app_v2.alproto = t->app_v2.alproto;
am->app_v2.tx_min_progress = t->app_v2.tx_min_progress;
am->app_v2.sub_state = t->app_v2.sub_state;
am->priority = t->priority;
am->sgh_mpm_context = t->sgh_mpm_context;
am->sgh_mpm_context = MpmFactoryRegisterMpmCtxProfile(
+7
View File
@@ -87,12 +87,19 @@ typedef int (*PrefilterRegisterFunc)(DetectEngineCtx *de_ctx, SigGroupHead *sgh,
void DetectAppLayerMpmRegister(const char *name, int direction, int priority,
PrefilterRegisterFunc PrefilterRegister, InspectionBufferGetDataPtr GetData,
AppProto alproto, uint8_t tx_min_progress);
void DetectAppLayerMpmRegisterSubState(const char *name, int direction, int priority,
PrefilterRegisterFunc PrefilterRegister, InspectionBufferGetDataPtr GetData,
AppProto alproto, uint8_t sub_state, uint8_t tx_min_progress);
void DetectAppLayerMpmRegisterSingle(const char *name, int direction, int priority,
PrefilterRegisterFunc PrefilterRegister, InspectionSingleBufferGetDataPtr GetData,
AppProto alproto, uint8_t tx_min_progress);
void DetectAppLayerMpmMultiRegister(const char *name, int direction, int priority,
PrefilterRegisterFunc PrefilterRegister, InspectionMultiBufferGetDataPtr GetData,
AppProto alproto, uint8_t tx_min_progress);
/** As DetectAppLayerMpmMultiRegister, but with a sub state argument */
void DetectAppLayerMpmMultiRegisterSubState(const char *name, int direction, int priority,
PrefilterRegisterFunc PrefilterRegister, InspectionMultiBufferGetDataPtr GetData,
AppProto alproto, uint8_t sub_state, uint8_t tx_min_progress);
void DetectAppLayerMpmRegisterByParentId(
DetectEngineCtx *de_ctx,
const int id, const int parent_id,
+123 -74
View File
@@ -104,11 +104,20 @@ void DetectRunPrefilterTx(DetectEngineThreadCtx *det_ctx,
/* reset rule store */
det_ctx->pmq.rule_id_array_cnt = 0;
SCLogDebug("packet %" PRIu64 " tx %p progress %d tx->detect_progress %02x", PcapPacketCntGet(p),
tx->tx_ptr, tx->tx_progress, tx->detect_progress);
SCLogDebug("packet %" PRIu64 " tx %p id %" PRIu64 " progress %d tx->detect_progress %02x",
PcapPacketCntGet(p), tx->tx_ptr, tx->tx_id, tx->tx_progress, tx->detect_progress);
PrefilterEngine *engine = sgh->tx_engines;
do {
SCLogDebug("%" PRIu64 ": engine %p for %s progress %u sub_state %u tx %u",
PcapPacketCntGet(p), engine, AppProtoToString(engine->alproto),
engine->ctx.app.tx_min_progress, engine->ctx.app.sub_state, tx->tx_type);
if (engine->alproto != ALPROTO_UNKNOWN && engine->ctx.app.sub_state != tx->tx_type) {
SCLogDebug("%" PRIu64 ": engine %p sub_state %u mismatch with tx %u",
PcapPacketCntGet(p), engine, engine->ctx.app.sub_state, tx->tx_type);
// not for the tx sub state
goto next;
}
// based on flow alproto, and engine, we get right tx_ptr
void *tx_ptr = DetectGetInnerTx(tx->tx_ptr, alproto, engine->alproto, flow_flags);
if (tx_ptr == NULL) {
@@ -116,30 +125,31 @@ void DetectRunPrefilterTx(DetectEngineThreadCtx *det_ctx,
goto next;
}
if (engine->ctx.tx_min_progress != -1) {
if (engine->ctx.app.tx_min_progress != -1) {
#ifdef DEBUG
const char *pname = AppLayerParserGetStateNameById(ipproto, engine->alproto,
engine->ctx.tx_min_progress, flow_flags & (STREAM_TOSERVER | STREAM_TOCLIENT));
SCLogDebug("engine %p min_progress %d %s:%s", engine, engine->ctx.tx_min_progress,
engine->ctx.app.tx_min_progress,
flow_flags & (STREAM_TOSERVER | STREAM_TOCLIENT));
SCLogDebug("engine %p min_progress %d %s:%s", engine, engine->ctx.app.tx_min_progress,
AppProtoToString(engine->alproto), pname);
#endif
/* if engine needs tx state to be higher, break out. */
if (engine->ctx.tx_min_progress > tx->tx_progress)
if (engine->ctx.app.tx_min_progress > tx->tx_progress)
break;
if (tx->tx_progress > engine->ctx.tx_min_progress) {
SCLogDebug("tx->tx_progress %u > engine->ctx.tx_min_progress %d", tx->tx_progress,
engine->ctx.tx_min_progress);
if (tx->tx_progress > engine->ctx.app.tx_min_progress) {
SCLogDebug("tx->tx_progress %u > engine->ctx.app.tx_min_progress %d",
tx->tx_progress, engine->ctx.app.tx_min_progress);
/* if state value is at or beyond engine state, we can skip it. It means we ran at
* least once already. */
if (tx->detect_progress > engine->ctx.tx_min_progress) {
if (tx->detect_progress > engine->ctx.app.tx_min_progress) {
SCLogDebug("tx already marked progress as beyond engine: %u > %u",
tx->detect_progress, engine->ctx.tx_min_progress);
tx->detect_progress, engine->ctx.app.tx_min_progress);
goto next;
} else {
SCLogDebug("tx->tx_progress %u > engine->ctx.tx_min_progress %d: "
SCLogDebug("tx->tx_progress %u > engine->ctx.app.tx_min_progress %d: "
"tx->detect_progress %u",
tx->tx_progress, engine->ctx.tx_min_progress, tx->detect_progress);
tx->tx_progress, engine->ctx.app.tx_min_progress, tx->detect_progress);
}
}
#ifdef DEBUG
@@ -150,21 +160,21 @@ void DetectRunPrefilterTx(DetectEngineThreadCtx *det_ctx,
tx->tx_data_ptr, flow_flags);
PREFILTER_PROFILING_END(det_ctx, engine->gid);
SCLogDebug("engine %p min_progress %d %s:%s: results %u", engine,
engine->ctx.tx_min_progress, AppProtoToString(engine->alproto), pname,
engine->ctx.app.tx_min_progress, AppProtoToString(engine->alproto), pname,
det_ctx->pmq.rule_id_array_cnt - old);
if (tx->tx_progress > engine->ctx.tx_min_progress && engine->is_last_for_progress &&
if (tx->tx_progress > engine->ctx.app.tx_min_progress && engine->is_last_for_progress &&
tx->tx_ptr == tx_ptr) {
/* track with an offset of one, so that tx->progress 0 complete is tracked
* as 1, progress 1 as 2, etc. This is to allow 0 to mean: nothing tracked, even
* though a parser may use 0 as a valid value. */
// tx->tx_ptr == tx_ptr ensures we do not use a dns engine progress
// to update a HTTP2 tx detect_progress in case of DOH2
tx->detect_progress = engine->ctx.tx_min_progress + 1;
SCLogDebug("tx->tx_progress %d engine->ctx.tx_min_progress %d "
tx->detect_progress = engine->ctx.app.tx_min_progress + 1;
SCLogDebug("tx->tx_progress %d engine->ctx.app.tx_min_progress %d "
"engine->is_last_for_progress %d => tx->detect_progress updated to %02x",
tx->tx_progress, engine->ctx.tx_min_progress, engine->is_last_for_progress,
tx->detect_progress);
tx->tx_progress, engine->ctx.app.tx_min_progress,
engine->is_last_for_progress, tx->detect_progress);
}
} else {
PREFILTER_PROFILING_START(det_ctx);
@@ -353,9 +363,9 @@ int PrefilterAppendPayloadEngine(DetectEngineCtx *de_ctx, SigGroupHead *sgh,
return 0;
}
int PrefilterAppendTxEngine(DetectEngineCtx *de_ctx, SigGroupHead *sgh,
PrefilterTxFn PrefilterTxFunc, AppProto alproto, int8_t tx_min_progress, void *pectx,
void (*FreeFunc)(void *pectx), const char *name)
int PrefilterAppendTxEngineSubState(DetectEngineCtx *de_ctx, SigGroupHead *sgh,
PrefilterTxFn PrefilterTxFunc, AppProto alproto, uint8_t sub_state,
const int8_t tx_min_progress, void *pectx, void (*FreeFunc)(void *pectx), const char *name)
{
if (sgh == NULL || PrefilterTxFunc == NULL || pectx == NULL)
return -1;
@@ -369,6 +379,7 @@ int PrefilterAppendTxEngine(DetectEngineCtx *de_ctx, SigGroupHead *sgh,
e->pectx = pectx;
e->alproto = alproto;
e->tx_min_progress = tx_min_progress;
e->sub_state = sub_state;
e->Free = FreeFunc;
if (sgh->init->tx_engines == NULL) {
@@ -385,9 +396,18 @@ int PrefilterAppendTxEngine(DetectEngineCtx *de_ctx, SigGroupHead *sgh,
e->name = name;
e->gid = PrefilterStoreGetId(de_ctx, e->name, e->Free);
SCLogDebug("%s: sub_state %u", name, e->sub_state);
return 0;
}
int PrefilterAppendTxEngine(DetectEngineCtx *de_ctx, SigGroupHead *sgh,
PrefilterTxFn PrefilterTxFunc, AppProto alproto, const int8_t tx_min_progress, void *pectx,
void (*FreeFunc)(void *pectx), const char *name)
{
return PrefilterAppendTxEngineSubState(
de_ctx, sgh, PrefilterTxFunc, alproto, 0, tx_min_progress, pectx, FreeFunc, name);
}
int PrefilterAppendFrameEngine(DetectEngineCtx *de_ctx, SigGroupHead *sgh,
PrefilterFrameFn PrefilterFrameFunc, AppProto alproto, uint8_t frame_type, void *pectx,
void (*FreeFunc)(void *pectx), const char *name)
@@ -520,14 +540,18 @@ static int PrefilterSetupRuleGroupSortHelper(const void *a, const void *b)
{
const PrefilterEngine *s0 = a;
const PrefilterEngine *s1 = b;
if (s1->ctx.tx_min_progress == s0->ctx.tx_min_progress) {
if (s1->alproto == s0->alproto) {
return s0->local_id > s1->local_id ? 1 : -1;
if (s1->ctx.app.sub_state == s0->ctx.app.sub_state) {
if (s1->ctx.app.tx_min_progress == s0->ctx.app.tx_min_progress) {
if (s1->alproto == s0->alproto) {
return s0->local_id > s1->local_id ? 1 : -1;
} else {
return s0->alproto > s1->alproto ? 1 : -1;
}
} else {
return s0->alproto > s1->alproto ? 1 : -1;
return s0->ctx.app.tx_min_progress > s1->ctx.app.tx_min_progress ? 1 : -1;
}
} else {
return s0->ctx.tx_min_progress > s1->ctx.tx_min_progress ? 1 : -1;
return s0->ctx.app.sub_state > s1->ctx.app.sub_state ? 1 : -1;
}
}
@@ -701,6 +725,7 @@ static void NonPFNamesFree(void *data)
struct TxNonPFData {
AppProto alproto;
uint8_t sub_state;
int dir; /**< 0: toserver, 1: toclient */
uint8_t progress; /**< progress state value to register at */
int sig_list; /**< special handling: normally 0, but for special cases (app-layer-state,
@@ -713,15 +738,15 @@ struct TxNonPFData {
static uint32_t TxNonPFHash(HashListTable *h, void *data, uint16_t _len)
{
struct TxNonPFData *d = data;
return (d->alproto + d->progress + d->dir + d->sig_list) % h->array_size;
return (d->alproto + d->sub_state + d->progress + d->dir + d->sig_list) % h->array_size;
}
static char TxNonPFCompare(void *data1, uint16_t _len1, void *data2, uint16_t len2)
{
struct TxNonPFData *d1 = data1;
struct TxNonPFData *d2 = data2;
return d1->alproto == d2->alproto && d1->progress == d2->progress && d1->dir == d2->dir &&
d1->sig_list == d2->sig_list;
return d1->alproto == d2->alproto && d1->sub_state == d2->sub_state &&
d1->progress == d2->progress && d1->dir == d2->dir && d1->sig_list == d2->sig_list;
}
static void TxNonPFFree(void *data)
@@ -732,13 +757,14 @@ static void TxNonPFFree(void *data)
}
static int TxNonPFAddSig(DetectEngineCtx *de_ctx, HashListTable *tx_engines_hash,
const AppProto alproto, const int dir, const uint8_t progress, const int sig_list,
const char *name, const Signature *s)
const AppProto alproto, const uint8_t sub_state, const int dir, const uint8_t progress,
const int sig_list, const char *name, const Signature *s)
{
const uint32_t max_sids = DetectEngineGetMaxSigId(de_ctx);
struct TxNonPFData lookup = {
.alproto = alproto,
.sub_state = sub_state,
.dir = dir,
.progress = progress,
.sig_list = sig_list,
@@ -770,6 +796,7 @@ static int TxNonPFAddSig(DetectEngineCtx *de_ctx, HashListTable *tx_engines_hash
return -1;
}
add->dir = dir;
add->sub_state = sub_state;
add->alproto = alproto;
add->progress = progress;
add->sig_list = sig_list;
@@ -950,8 +977,9 @@ static int SetupNonPrefilter(DetectEngineCtx *de_ctx, SigGroupHead *sgh)
}
const int sm_list = DetectEngineAppHookToSmlist(
s->alproto, state, dir == 0 ? STREAM_TOSERVER : STREAM_TOCLIENT);
if (TxNonPFAddSig(de_ctx, tx_engines_hash, s->alproto, dir, state, sm_list, pname,
s) != 0) {
uint8_t sub_state = s->init_data->hook.t.app.sub_state;
if (TxNonPFAddSig(de_ctx, tx_engines_hash, s->alproto, sub_state, dir, state,
sm_list, pname, s) != 0) {
goto error;
}
tx_non_pf = true;
@@ -1014,7 +1042,8 @@ static int SetupNonPrefilter(DetectEngineCtx *de_ctx, SigGroupHead *sgh)
int sig_list = 0;
if (list_id == app_state_list_id)
sig_list = app_state_list_id;
if (TxNonPFAddSig(de_ctx, tx_engines_hash, app->alproto, app->dir,
const uint8_t sub_state = app->sub_state;
if (TxNonPFAddSig(de_ctx, tx_engines_hash, app->alproto, sub_state, app->dir,
app->progress, sig_list, buf->name, s) != 0) {
goto error;
}
@@ -1035,7 +1064,8 @@ static int SetupNonPrefilter(DetectEngineCtx *de_ctx, SigGroupHead *sgh)
s->alproto, s->init_data->hook.t.app.app_progress,
dir == 0 ? STREAM_TOSERVER : STREAM_TOCLIENT);
if (TxNonPFAddSig(de_ctx, tx_engines_hash, s->alproto, dir,
uint8_t sub_state = s->init_data->hook.t.app.sub_state;
if (TxNonPFAddSig(de_ctx, tx_engines_hash, s->alproto, sub_state, dir,
s->init_data->hook.t.app.app_progress, s->init_data->hook.sm_list, pname,
s) != 0) {
goto error;
@@ -1129,8 +1159,8 @@ static int SetupNonPrefilter(DetectEngineCtx *de_ctx, SigGroupHead *sgh)
for (uint32_t i = 0; i < t->sigs_cnt; i++) {
data->array[i] = t->sigs[i].sid;
}
if (PrefilterAppendTxEngine(de_ctx, sgh, PrefilterTxNonPF, t->alproto, engine_progress,
(void *)data, PrefilterNonPFDataFree, t->engine_name) < 0) {
if (PrefilterAppendTxEngineSubState(de_ctx, sgh, PrefilterTxNonPF, t->alproto, t->sub_state,
engine_progress, (void *)data, PrefilterNonPFDataFree, t->engine_name) < 0) {
SCFree(data);
goto error;
}
@@ -1308,7 +1338,8 @@ int PrefilterSetupRuleGroup(DetectEngineCtx *de_ctx, SigGroupHead *sgh)
for (el = sgh->init->tx_engines ; el != NULL; el = el->next) {
e->local_id = local_id++;
e->alproto = el->alproto;
e->ctx.tx_min_progress = el->tx_min_progress;
e->ctx.app.tx_min_progress = el->tx_min_progress;
e->ctx.app.sub_state = el->sub_state;
e->cb.PrefilterTx = el->PrefilterTx;
e->pectx = el->pectx;
el->pectx = NULL; // e now owns the ctx
@@ -1323,45 +1354,58 @@ int PrefilterSetupRuleGroup(DetectEngineCtx *de_ctx, SigGroupHead *sgh)
sgh->tx_engines[local_id - 1].is_last_for_progress = true;
PrefilterEngine *engine;
/* per alproto to set is_last_for_progress per alproto because the inspect
* loop skips over engines that are not the correct alproto */
for (AppProto a = ALPROTO_FAILED + 1; a < g_alproto_max; a++) {
int last_tx_progress = 0;
bool last_tx_progress_set = false;
PrefilterEngine *prev_engine = NULL;
engine = sgh->tx_engines;
do {
if (engine->ctx.tx_min_progress != -1)
BUG_ON(engine->ctx.tx_min_progress < last_tx_progress);
if (engine->alproto == a) {
if (last_tx_progress_set && engine->ctx.tx_min_progress > last_tx_progress) {
if (prev_engine) {
prev_engine->is_last_for_progress = true;
}
}
/* loop over sub-states. Protocols not supporting sub-states
* will just use 0. */
const uint8_t max_sub_state = AppLayerParserGetMaxSubState(a);
for (uint8_t sub = 0; sub <= max_sub_state; sub++) {
int last_tx_progress = 0;
bool last_tx_progress_set = false;
PrefilterEngine *prev_engine = NULL;
engine = sgh->tx_engines;
do {
if (engine->ctx.app.sub_state == sub) {
if (engine->ctx.app.tx_min_progress != -1)
BUG_ON(engine->ctx.app.tx_min_progress < last_tx_progress);
if (engine->alproto == a) {
if (last_tx_progress_set &&
engine->ctx.app.tx_min_progress > last_tx_progress) {
if (prev_engine) {
prev_engine->is_last_for_progress = true;
}
}
last_tx_progress_set = true;
prev_engine = engine;
} else {
if (prev_engine) {
prev_engine->is_last_for_progress = true;
last_tx_progress_set = true;
prev_engine = engine;
if (!engine->is_last) {
PrefilterEngine *next_engine = engine + 1;
engine->is_last_for_progress =
(next_engine->ctx.app.sub_state != sub);
}
} else {
if (prev_engine) {
prev_engine->is_last_for_progress = true;
}
}
last_tx_progress = engine->ctx.app.tx_min_progress;
}
}
last_tx_progress = engine->ctx.tx_min_progress;
if (engine->is_last)
break;
engine++;
} while (1);
if (engine->is_last)
break;
engine++;
} while (1);
}
}
#ifdef DEBUG
SCLogDebug("sgh %p", sgh);
engine = sgh->tx_engines;
do {
SCLogDebug("engine: gid %u alproto %s tx_min_progress %d is_last %s "
SCLogDebug("engine: gid %u alproto %s sub_state %u tx_min_progress %d is_last %s "
"is_last_for_progress %s",
engine->gid, AppProtoToString(engine->alproto), engine->ctx.tx_min_progress,
engine->is_last ? "true" : "false",
engine->gid, AppProtoToString(engine->alproto), engine->ctx.app.sub_state,
engine->ctx.app.tx_min_progress, engine->is_last ? "true" : "false",
engine->is_last_for_progress ? "true" : "false");
if (engine->is_last)
break;
@@ -1622,9 +1666,10 @@ int PrefilterGenericMpmRegister(DetectEngineCtx *de_ctx, SigGroupHead *sgh, MpmC
pectx->mpm_ctx = mpm_ctx;
pectx->transforms = &mpm_reg->transforms;
int r = PrefilterAppendTxEngine(de_ctx, sgh, PrefilterMpm,
mpm_reg->app_v2.alproto, mpm_reg->app_v2.tx_min_progress,
pectx, PrefilterGenericMpmFree, mpm_reg->pname);
SCLogDebug("mpm_reg %s sub_state %u", mpm_reg->name, mpm_reg->app_v2.sub_state);
int r = PrefilterAppendTxEngineSubState(de_ctx, sgh, PrefilterMpm, mpm_reg->app_v2.alproto,
mpm_reg->app_v2.sub_state, mpm_reg->app_v2.tx_min_progress, pectx,
PrefilterGenericMpmFree, mpm_reg->pname);
if (r != 0) {
SCFree(pectx);
}
@@ -1643,8 +1688,10 @@ int PrefilterSingleMpmRegister(DetectEngineCtx *de_ctx, SigGroupHead *sgh, MpmCt
pectx->mpm_ctx = mpm_ctx;
pectx->transforms = &mpm_reg->transforms;
int r = PrefilterAppendTxEngine(de_ctx, sgh, PrefilterMpmTxSingle, mpm_reg->app_v2.alproto,
mpm_reg->app_v2.tx_min_progress, pectx, PrefilterGenericMpmFree, mpm_reg->pname);
SCLogDebug("mpm_reg %s sub_state %u", mpm_reg->name, mpm_reg->app_v2.sub_state);
int r = PrefilterAppendTxEngineSubState(de_ctx, sgh, PrefilterMpmTxSingle,
mpm_reg->app_v2.alproto, mpm_reg->app_v2.sub_state, mpm_reg->app_v2.tx_min_progress,
pectx, PrefilterGenericMpmFree, mpm_reg->pname);
if (r != 0) {
SCFree(pectx);
}
@@ -1696,8 +1743,10 @@ int PrefilterMultiGenericMpmRegister(DetectEngineCtx *de_ctx, SigGroupHead *sgh,
pectx->mpm_ctx = mpm_ctx;
pectx->transforms = &mpm_reg->transforms;
int r = PrefilterAppendTxEngine(de_ctx, sgh, PrefilterMultiMpm, mpm_reg->app_v2.alproto,
mpm_reg->app_v2.tx_min_progress, pectx, PrefilterMultiGenericMpmFree, mpm_reg->pname);
SCLogDebug("mpm_reg %s sub_state %u", mpm_reg->name, mpm_reg->app_v2.sub_state);
int r = PrefilterAppendTxEngineSubState(de_ctx, sgh, PrefilterMultiMpm, mpm_reg->app_v2.alproto,
mpm_reg->app_v2.sub_state, mpm_reg->app_v2.tx_min_progress, pectx,
PrefilterMultiGenericMpmFree, mpm_reg->pname);
if (r != 0) {
SCFree(pectx);
}
+6
View File
@@ -43,6 +43,9 @@ typedef struct DetectTransaction_ {
const uint8_t tx_progress;
const uint8_t tx_end_state;
bool is_last; /* is this the last tx? */
/** app-layer specific transaction type (for sub-state support). 0 if not used. */
const uint8_t tx_type;
} DetectTransaction;
typedef struct PrefilterStore_ {
@@ -63,6 +66,9 @@ void PrefilterPostRuleMatch(
int PrefilterAppendPayloadEngine(DetectEngineCtx *de_ctx, SigGroupHead *sgh,
PrefilterPktFn PrefilterFunc, void *pectx, void (*FreeFunc)(void *pectx), const char *name);
int PrefilterAppendTxEngineSubState(DetectEngineCtx *de_ctx, SigGroupHead *sgh,
PrefilterTxFn PrefilterTxFunc, AppProto alproto, uint8_t sub_state,
const int8_t tx_min_progress, void *pectx, void (*FreeFunc)(void *pectx), const char *name);
int PrefilterAppendTxEngine(DetectEngineCtx *de_ctx, SigGroupHead *sgh,
PrefilterTxFn PrefilterTxFunc, const AppProto alproto, const int8_t tx_min_progress,
void *pectx, void (*FreeFunc)(void *pectx), const char *name);
+51 -9
View File
@@ -198,8 +198,8 @@ void DetectPktInspectEngineRegister(const char *name,
*
* \note errors are fatal */
static void AppLayerInspectEngineRegisterInternal(const char *name, AppProto alproto, uint32_t dir,
uint8_t progress, InspectEngineFuncPtr Callback, InspectionBufferGetDataPtr GetData,
InspectionSingleBufferGetDataPtr GetDataSingle,
uint8_t sub_state, uint8_t progress, InspectEngineFuncPtr Callback,
InspectionBufferGetDataPtr GetData, InspectionSingleBufferGetDataPtr GetDataSingle,
InspectionMultiBufferGetDataPtr GetMultiData)
{
BUG_ON(progress >= 48);
@@ -212,7 +212,8 @@ static void AppLayerInspectEngineRegisterInternal(const char *name, AppProto alp
SCLogDebug("name %s id %d", name, sm_list);
if ((alproto == ALPROTO_FAILED) || (!(dir == SIG_FLAG_TOSERVER || dir == SIG_FLAG_TOCLIENT)) ||
(sm_list < DETECT_SM_LIST_MATCH) || (sm_list >= SHRT_MAX) || (Callback == NULL)) {
(sm_list < DETECT_SM_LIST_MATCH) || (sm_list >= SHRT_MAX) || (progress >= 48) ||
(Callback == NULL)) {
SCLogError("Invalid arguments");
BUG_ON(1);
} else if (Callback == DetectEngineInspectBufferGeneric && GetData == NULL) {
@@ -237,8 +238,8 @@ static void AppLayerInspectEngineRegisterInternal(const char *name, AppProto alp
}
// every DNS or HTTP2 can be accessed from DOH2
if (alproto == ALPROTO_HTTP2 || alproto == ALPROTO_DNS) {
AppLayerInspectEngineRegisterInternal(
name, ALPROTO_DOH2, dir, progress, Callback, GetData, GetDataSingle, GetMultiData);
AppLayerInspectEngineRegisterInternal(name, ALPROTO_DOH2, dir, sub_state, progress,
Callback, GetData, GetDataSingle, GetMultiData);
}
DetectEngineAppInspectionEngine *new_engine =
@@ -251,6 +252,7 @@ static void AppLayerInspectEngineRegisterInternal(const char *name, AppProto alp
new_engine->sm_list = (uint16_t)sm_list;
new_engine->sm_list_base = (uint16_t)sm_list;
new_engine->progress = progress;
new_engine->sub_state = sub_state;
new_engine->v2.Callback = Callback;
if (Callback == DetectEngineInspectBufferGeneric) {
new_engine->v2.GetData = GetData;
@@ -283,7 +285,8 @@ void DetectAppLayerInspectEngineRegister(const char *name, AppProto alproto, uin
const int sm_list = DetectBufferTypeGetByName(name);
if (t->sm_list == sm_list && t->alproto == alproto && t_direction == dir &&
t->progress == progress && t->v2.Callback == Callback && t->v2.GetData == GetData) {
t->sub_state == 0 && t->progress == progress && t->v2.Callback == Callback &&
t->v2.GetData == GetData) {
DEBUG_VALIDATE_BUG_ON(1);
return;
}
@@ -291,9 +294,32 @@ void DetectAppLayerInspectEngineRegister(const char *name, AppProto alproto, uin
}
AppLayerInspectEngineRegisterInternal(
name, alproto, dir, progress, Callback, GetData, NULL, NULL);
name, alproto, dir, 0, (uint8_t)progress, Callback, GetData, NULL, NULL);
}
void DetectAppLayerInspectEngineRegisterSubState(const char *name, AppProto alproto, uint32_t dir,
uint8_t sub_state, uint8_t progress, InspectEngineFuncPtr Callback,
InspectionBufferGetDataPtr GetData)
{
/* before adding, check that we don't add a duplicate entry, which will
* propagate all the way into the packet runtime if allowed. */
DetectEngineAppInspectionEngine *t = g_app_inspect_engines;
while (t != NULL) {
const uint32_t t_direction = t->dir == 0 ? SIG_FLAG_TOSERVER : SIG_FLAG_TOCLIENT;
const int sm_list = DetectBufferTypeGetByName(name);
if (t->sm_list == sm_list && t->alproto == alproto && t_direction == dir &&
t->sub_state == sub_state && t->progress == progress &&
t->v2.Callback == Callback && t->v2.GetData == GetData) {
DEBUG_VALIDATE_BUG_ON(1);
return;
}
t = t->next;
}
AppLayerInspectEngineRegisterInternal(
name, alproto, dir, sub_state, progress, Callback, GetData, NULL, NULL);
}
void DetectAppLayerInspectEngineRegisterSingle(const char *name, AppProto alproto, uint32_t dir,
uint8_t progress, InspectEngineFuncPtr Callback, InspectionSingleBufferGetDataPtr GetData)
{
@@ -314,7 +340,7 @@ void DetectAppLayerInspectEngineRegisterSingle(const char *name, AppProto alprot
}
AppLayerInspectEngineRegisterInternal(
name, alproto, dir, progress, Callback, NULL, GetData, NULL);
name, alproto, dir, 0, (uint8_t)progress, Callback, NULL, GetData, NULL);
}
/* copy an inspect engine with transforms to a new list id. */
@@ -337,6 +363,7 @@ static void DetectAppLayerInspectEngineCopy(
DEBUG_VALIDATE_BUG_ON(sm_list < 0 || sm_list > UINT16_MAX);
new_engine->sm_list_base = (uint16_t)sm_list;
new_engine->progress = t->progress;
new_engine->sub_state = t->sub_state;
new_engine->v2 = t->v2;
new_engine->v2.transforms = transforms; /* assign transforms */
@@ -370,6 +397,7 @@ static void DetectAppLayerInspectEngineCopyListToDetectCtx(DetectEngineCtx *de_c
new_engine->sm_list = t->sm_list;
new_engine->sm_list_base = t->sm_list;
new_engine->progress = t->progress;
new_engine->sub_state = t->sub_state;
new_engine->v2 = t->v2;
if (list == NULL) {
@@ -753,6 +781,7 @@ static void AppendAppInspectEngine(DetectEngineCtx *de_ctx,
new_engine->smd = smd;
new_engine->match_on_null = smd ? DetectContentInspectionMatchOnAbsentBuffer(smd) : false;
new_engine->progress = t->progress;
new_engine->sub_state = t->sub_state;
new_engine->v2 = t->v2;
SCLogDebug("sm_list %d new_engine->v2 %p/%p/%p", new_engine->sm_list, new_engine->v2.Callback,
new_engine->v2.GetData, new_engine->v2.transforms);
@@ -903,6 +932,7 @@ int DetectEngineAppInspectionEngine2Signature(DetectEngineCtx *de_ctx, Signature
DetectEngineAppInspectionEngine t = {
.alproto = s->init_data->hook.t.app.alproto,
.progress = state,
.sub_state = s->init_data->hook.t.app.sub_state,
.sm_list = (uint16_t)sm_list,
.sm_list_base = (uint16_t)sm_list,
.dir = dir,
@@ -985,6 +1015,7 @@ int DetectEngineAppInspectionEngine2Signature(DetectEngineCtx *de_ctx, Signature
DetectEngineAppInspectionEngine t = {
.alproto = s->init_data->hook.t.app.alproto,
.progress = s->init_data->hook.t.app.app_progress,
.sub_state = s->init_data->hook.t.app.sub_state,
.sm_list = (uint16_t)s->init_data->hook.sm_list,
.sm_list_base = (uint16_t)s->init_data->hook.sm_list,
.dir = dir,
@@ -2202,12 +2233,23 @@ uint8_t DetectEngineInspectBufferGeneric(DetectEngineCtx *de_ctx, DetectEngineTh
}
}
// wrapper for both DetectAppLayerInspectEngineRegister and DetectAppLayerMpmRegister
// with cast of callback function
void DetectAppLayerMultiRegisterSubState(const char *name, AppProto alproto, uint32_t dir,
uint8_t sub_state, uint8_t progress, InspectionMultiBufferGetDataPtr GetData, int priority)
{
AppLayerInspectEngineRegisterInternal(name, alproto, dir, sub_state, progress,
DetectEngineInspectMultiBufferGeneric, NULL, NULL, GetData);
DetectAppLayerMpmMultiRegisterSubState(name, dir, priority, PrefilterMultiGenericMpmRegister,
GetData, alproto, sub_state, progress);
}
// wrapper for both DetectAppLayerInspectEngineRegister and DetectAppLayerMpmRegister
// with cast of callback function
void DetectAppLayerMultiRegister(const char *name, AppProto alproto, uint32_t dir, uint8_t progress,
InspectionMultiBufferGetDataPtr GetData, int priority)
{
AppLayerInspectEngineRegisterInternal(name, alproto, dir, progress,
AppLayerInspectEngineRegisterInternal(name, alproto, dir, 0, (uint8_t)progress,
DetectEngineInspectMultiBufferGeneric, NULL, NULL, GetData);
DetectAppLayerMpmMultiRegister(
name, dir, priority, PrefilterMultiGenericMpmRegister, GetData, alproto, progress);
+11
View File
@@ -162,9 +162,20 @@ int DetectEngineInspectPktBufferGeneric(
void DetectAppLayerInspectEngineRegister(const char *name, AppProto alproto, uint32_t dir,
uint8_t progress, InspectEngineFuncPtr Callback2, InspectionBufferGetDataPtr GetData);
/**
* \brief register an app inspection engine for a tx type
* \param type the tx type
*/
void DetectAppLayerInspectEngineRegisterSubState(const char *name, AppProto alproto, uint32_t dir,
uint8_t type, uint8_t progress, InspectEngineFuncPtr Callback2,
InspectionBufferGetDataPtr GetData);
void DetectAppLayerInspectEngineRegisterSingle(const char *name, AppProto alproto, uint32_t dir,
uint8_t progress, InspectEngineFuncPtr Callback2, InspectionSingleBufferGetDataPtr GetData);
void DetectAppLayerMultiRegisterSubState(const char *name, AppProto alproto, uint32_t dir,
uint8_t sub_state, uint8_t progress, InspectionMultiBufferGetDataPtr GetData, int priority);
void DetectAppLayerMultiRegister(const char *name, AppProto alproto, uint32_t dir, uint8_t progress,
InspectionMultiBufferGetDataPtr GetData, int priority);
+36 -4
View File
@@ -1328,14 +1328,33 @@ static int DetectRunTxInspectRule(ThreadVars *tv, DetectEngineCtx *de_ctx,
const DetectEngineAppInspectionEngine *engine = s->app_inspect;
do {
TRACE_SID_TXS(s->id, tx, "engine %p inspect_flags %x", engine, inspect_flags);
// also if it is not the same direction, but
// this is a transactional signature, and we are toclient
if (!(inspect_flags & BIT_U32(engine->id)) &&
(direction == engine->dir || ((s->flags & SIG_FLAG_TXBOTHDIR) && direction == 1))) {
if (engine->alproto != ALPROTO_UNKNOWN && // app-layer-events is registered for each
// proto this way
tx->tx_type != engine->sub_state) {
TRACE_SID_TXS(s->id, tx,
"skip because engine alproto %s sub_state %u != tx_type %u (engine "
"progress %u)",
AppProtoToString(engine->alproto), engine->sub_state, tx->tx_type,
engine->progress);
engine = engine->next;
continue;
}
TRACE_SID_TXS(s->id, tx,
"inspecting engine alproto %s sub_state %u == tx_type %u (engine progress %u)",
AppProtoToString(engine->alproto), engine->sub_state, tx->tx_type,
engine->progress);
void *tx_ptr = DetectGetInnerTx(tx->tx_ptr, f->alproto, engine->alproto, flow_flags);
if (tx_ptr == NULL) {
TRACE_SID_TXS(s->id, tx, "no tx_ptr after DetectGetInnerTx");
if (engine->alproto != ALPROTO_UNKNOWN) {
TRACE_SID_TXS(s->id, tx, "no tx_ptr skip engine");
/* special case: file_data on 'alert tcp' will have engines
* in the list that are not for us. */
engine = engine->next;
@@ -1344,6 +1363,7 @@ static int DetectRunTxInspectRule(ThreadVars *tv, DetectEngineCtx *de_ctx,
tx_ptr = tx->tx_ptr;
}
}
TRACE_SID_TXS(s->id, tx, "tx_ptr %p", tx_ptr);
/* engines are sorted per progress, except that the one with
* mpm/prefilter enabled is first */
@@ -1434,6 +1454,8 @@ static int DetectRunTxInspectRule(ThreadVars *tv, DetectEngineCtx *de_ctx,
break;
} else if (!(inspect_flags & BIT_U32(engine->id)) && s->flags & SIG_FLAG_TXBOTHDIR &&
direction != engine->dir) {
TRACE_SID_TXS(s->id, tx, "handle bidir engine");
// for transactional rules, the engines on the opposite direction
// are ordered by progress on the different side
// so we have a two mixed-up lists, and we skip the elements
@@ -1517,7 +1539,7 @@ static int DetectRunTxInspectRule(ThreadVars *tv, DetectEngineCtx *de_ctx,
#define NO_TX \
{ \
NULL, 0, NULL, NULL, 0, 0, 0, 0, false, \
NULL, 0, NULL, NULL, 0, 0, 0, 0, false, 0, \
}
/** \internal
@@ -1530,11 +1552,16 @@ static DetectTransaction GetDetectTx(const uint8_t ipproto, const AppProto alpro
DEBUG_VALIDATE_BUG_ON(tx_end_state >= 48);
AppLayerTxData *txd = AppLayerParserGetTxData(ipproto, alproto, tx_ptr);
const int tx_progress = AppLayerParserGetStateProgress(ipproto, alproto, tx_ptr, flow_flags);
const uint8_t tx_progress =
(uint8_t)AppLayerParserGetStateProgress(ipproto, alproto, tx_ptr, flow_flags);
DEBUG_VALIDATE_BUG_ON(tx_progress >= 48);
const uint8_t e_tx_end_state = txd->tx_type == 0 ? (uint8_t)tx_end_state
: (flow_flags & STREAM_TOSERVER) ? txd->tx_type_eop_ts
: txd->tx_type_eop_tc;
bool updated = (flow_flags & STREAM_TOSERVER) ? txd->updated_ts : txd->updated_tc;
if (!updated && tx_progress < tx_end_state && ((flow_flags & STREAM_EOF) == 0)) {
if (!updated && tx_progress < e_tx_end_state && ((flow_flags & STREAM_EOF) == 0)) {
DetectTransaction no_tx = NO_TX;
return no_tx;
}
@@ -1555,6 +1582,10 @@ static DetectTransaction GetDetectTx(const uint8_t ipproto, const AppProto alpro
return no_tx;
}
if (txd->tx_type != 0) {
SCLogDebug("using tx_type %u", txd->tx_type);
}
const uint8_t detect_progress =
(flow_flags & STREAM_TOSERVER) ? txd->detect_progress_ts : txd->detect_progress_tc;
@@ -1570,8 +1601,9 @@ static DetectTransaction GetDetectTx(const uint8_t ipproto, const AppProto alpro
.detect_progress = detect_progress,
.detect_progress_orig = detect_progress,
.tx_progress = (uint8_t)tx_progress,
.tx_end_state = (uint8_t)tx_end_state,
.tx_end_state = e_tx_end_state,
.is_last = false,
.tx_type = txd->tx_type,
};
return tx;
}
+12 -3
View File
@@ -424,6 +424,7 @@ typedef struct DetectEngineAppInspectionEngine_ {
uint16_t sm_list;
uint16_t sm_list_base; /**< base buffer being transformed */
uint8_t progress;
uint8_t sub_state; /**< matches tx type */
struct {
union {
@@ -578,6 +579,8 @@ typedef struct SignatureHook_ {
union {
struct {
AppProto alproto;
/** sub state for a specific transaction type or 0 if not used */
uint8_t sub_state;
/** progress value of the app-layer hook specified in the rule. Sets the app_proto
* specific progress value. */
uint8_t app_progress;
@@ -796,6 +799,7 @@ typedef struct DetectBufferMpmRegistry_ {
};
AppProto alproto;
uint8_t tx_min_progress;
uint8_t sub_state;
} app_v2;
/* pkt matching: use if type == DETECT_BUFFER_MPM_TYPE_PKT */
@@ -1594,6 +1598,8 @@ typedef struct PrefilterEngineList_ {
SignatureMask pkt_mask; /**< mask for pkt engines */
uint8_t sub_state;
enum SignatureHookPkt pkt_hook;
/** Context for matching. Might be MpmCtx for MPM engines, other ctx'
@@ -1627,9 +1633,12 @@ typedef struct PrefilterEngine_ {
SignatureMask mask; /**< mask for pkt engines */
uint8_t hook; /**< enum SignatureHookPkt */
} pkt;
/** Minimal Tx progress we need before running the engine. Only used
* with Tx Engine. Set to -1 for all states. */
int8_t tx_min_progress;
struct {
/** Minimal Tx progress we need before running the engine. Only used
* with Tx Engine. Set to -1 for all states. */
int8_t tx_min_progress;
uint8_t sub_state;
} app;
uint8_t frame_type;
} ctx;