]> git.ipfire.org Git - thirdparty/suricata.git/commitdiff
detect: start of pkt hooks
authorVictor Julien <vjulien@oisf.net>
Thu, 23 Jan 2025 15:11:30 +0000 (16:11 +0100)
committerVictor Julien <victor@inliniac.net>
Mon, 7 Apr 2025 20:04:13 +0000 (22:04 +0200)
New facility to allow a user to specify where to hook a rule
into the engine. This patch adds this for packets, adding two
hooks:

- `all`: to let a rule be evaluated by all rules
- `flow_start`: to have a rule be evaluated only for the first
  packet in both directions

Implemented by adding a hook flags field in the packet.

src/decode.h
src/detect-engine-build.c
src/detect-engine-prefilter-common.c
src/detect-engine-prefilter.c
src/detect-engine-prefilter.h
src/detect-flowbits.c
src/detect-parse.c
src/detect.h
src/flow.c
src/packet.c

index ed4882314bda95a7fdb0ea2f27a8b079f3561d6e..4753497298c38dea349308e0cc91d9e7bad6795b 100644 (file)
@@ -512,8 +512,13 @@ typedef struct Packet_
     /* coccinelle: Packet:flowflags:FLOW_PKT_ */
 
     uint8_t app_update_direction; // enum StreamUpdateDir
+
+    /** sig mask flags this packet has, used in signature matching */
     SignatureMask sig_mask;
 
+    /** bit flags of SignatureHookPkt values this packet should trigger */
+    uint16_t pkt_hooks;
+
     /* Pkt Flags */
     uint32_t flags;
 
index c36e54db1a66bbc6fd2ed55402e0044eab630fa6..7c7429fdb459a1833b4b6587045fec99ae2556a2 100644 (file)
@@ -208,6 +208,10 @@ static bool SignatureInspectsBuffers(const Signature *s)
  */
 int SignatureIsIPOnly(DetectEngineCtx *de_ctx, const Signature *s)
 {
+    /* explicit hook means no IP-only */
+    if (s->init_data->hook.type != SIGNATURE_HOOK_TYPE_NOT_SET)
+        return 0;
+
     if (s->alproto != ALPROTO_UNKNOWN)
         return 0;
 
@@ -276,6 +280,10 @@ int SignatureIsIPOnly(DetectEngineCtx *de_ctx, const Signature *s)
  */
 static int SignatureIsPDOnly(const DetectEngineCtx *de_ctx, const Signature *s)
 {
+    /* explicit hook means no PD-only */
+    if (s->init_data->hook.type != SIGNATURE_HOOK_TYPE_NOT_SET)
+        return 0;
+
     if (s->alproto != ALPROTO_UNKNOWN)
         return 0;
 
@@ -354,6 +362,10 @@ static int SignatureIsInspectingPayload(DetectEngineCtx *de_ctx, const Signature
  */
 static int SignatureIsDEOnly(DetectEngineCtx *de_ctx, const Signature *s)
 {
+    /* explicit hook means no DE-only */
+    if (s->init_data->hook.type != SIGNATURE_HOOK_TYPE_NOT_SET)
+        SCReturnInt(0);
+
     if (s->alproto != ALPROTO_UNKNOWN) {
         SCReturnInt(0);
     }
index 3c3321b8f58fabf30e8f775c39555a09d36c57a2..6c5ff625489574380dfbc2ab0caee0a6591e9021 100644 (file)
@@ -142,8 +142,9 @@ static int SetupEngineForPacketHeader(DetectEngineCtx *de_ctx, SigGroupHead *sgh
     SCLogDebug("%s: ctx %p extra type %u extra value %u, sig cnt %u",
             sigmatch_table[sm_type].name, ctx, ctx->type, ctx->value,
             ctx->sigs_cnt);
-    PrefilterAppendEngine(
-            de_ctx, sgh, Match, mask, ctx, PrefilterPacketHeaderFree, sigmatch_table[sm_type].name);
+    enum SignatureHookPkt hook = SIGNATURE_HOOK_PKT_NOT_SET; // TODO review
+    PrefilterAppendEngine(de_ctx, sgh, Match, mask, hook, ctx, PrefilterPacketHeaderFree,
+            sigmatch_table[sm_type].name);
     return 0;
 }
 
@@ -245,7 +246,8 @@ static int SetupEngineForPacketHeaderPrefilterPacketU8HashCtx(DetectEngineCtx *d
     }
 
     if (cnt) {
-        PrefilterAppendEngine(de_ctx, sgh, Match, mask, ctx, PrefilterPacketU8HashCtxFree,
+        enum SignatureHookPkt hook = SIGNATURE_HOOK_PKT_NOT_SET; // TODO review
+        PrefilterAppendEngine(de_ctx, sgh, Match, mask, hook, ctx, PrefilterPacketU8HashCtxFree,
                 sigmatch_table[sm_type].name);
     } else {
         PrefilterPacketU8HashCtxFree(ctx);
index 55f6c7416305fd02fa077beea74fed2ca6452cbf..ea000cc04ddb5fef015595d4e7b4009f0ef6d64d 100644 (file)
@@ -205,7 +205,12 @@ void Prefilter(DetectEngineThreadCtx *det_ctx, const SigGroupHead *sgh, Packet *
         /* run packet engines */
         PrefilterEngine *engine = sgh->pkt_engines;
         do {
-            if ((engine->ctx.pkt_mask & mask) == engine->ctx.pkt_mask) {
+            /* run engine if:
+             * mask matches
+             * no hook is used OR hook matches
+             */
+            if (((engine->ctx.pkt.mask & mask) == engine->ctx.pkt.mask) &&
+                    (engine->ctx.pkt.hook == 0 || (p->pkt_hooks & BIT_U16(engine->ctx.pkt.hook)))) {
                 PREFILTER_PROFILING_START(det_ctx);
                 engine->cb.Prefilter(det_ctx, p, engine->pectx);
                 PREFILTER_PROFILING_END(det_ctx, engine->gid);
@@ -248,7 +253,8 @@ void Prefilter(DetectEngineThreadCtx *det_ctx, const SigGroupHead *sgh, Packet *
 }
 
 int PrefilterAppendEngine(DetectEngineCtx *de_ctx, SigGroupHead *sgh, PrefilterPktFn PrefilterFunc,
-        SignatureMask mask, void *pectx, void (*FreeFunc)(void *pectx), const char *name)
+        SignatureMask mask, enum SignatureHookPkt hook, void *pectx, void (*FreeFunc)(void *pectx),
+        const char *name)
 {
     if (sgh == NULL || PrefilterFunc == NULL || pectx == NULL)
         return -1;
@@ -258,10 +264,14 @@ int PrefilterAppendEngine(DetectEngineCtx *de_ctx, SigGroupHead *sgh, PrefilterP
         return -1;
     memset(e, 0x00, sizeof(*e));
 
+    // TODO right now we represent the hook in a u8 in the prefilter engine for space reasons.
+    BUG_ON(hook >= 8);
+
     e->Prefilter = PrefilterFunc;
     e->pectx = pectx;
     e->Free = FreeFunc;
     e->pkt_mask = mask;
+    e->pkt_hook = hook;
 
     if (sgh->init->pkt_engines == NULL) {
         sgh->init->pkt_engines = e;
@@ -609,6 +619,14 @@ static void PrefilterPktNonPF(DetectEngineThreadCtx *det_ctx, Packet *p, const v
     }
 }
 
+static void PrefilterPktNonPFHookFlowStart(
+        DetectEngineThreadCtx *det_ctx, Packet *p, const void *pectx)
+{
+    if (p->flowflags & (FLOW_PKT_TOSERVER_FIRST | FLOW_PKT_TOCLIENT_FIRST)) {
+        PrefilterPktNonPF(det_ctx, p, pectx);
+    }
+}
+
 /** \internal
  *  \brief engine to select the non-prefilter rules for frames
  *  Checks the alproto and type as well.
@@ -785,10 +803,22 @@ static int SetupNonPrefilter(DetectEngineCtx *de_ctx, SigGroupHead *sgh)
     }
     uint32_t frame_non_pf_array_size = 0;
 
+    struct PrefilterNonPFDataSig *pkt_hook_flow_start_non_pf_array =
+            SCCalloc(max_sids, sizeof(*pkt_hook_flow_start_non_pf_array));
+    if (pkt_hook_flow_start_non_pf_array == NULL) {
+        SCFree(pkt_non_pf_array);
+        SCFree(frame_non_pf_array);
+        return -1;
+    }
+    uint32_t pkt_hook_flow_start_non_pf_array_size = 0;
+    SignatureMask pkt_hook_flow_start_mask = 0;
+    bool pkt_hook_flow_start_mask_init = false;
+
     HashListTable *tx_engines_hash =
             HashListTableInit(256, TxNonPFHash, TxNonPFCompare, TxNonPFFree);
     if (tx_engines_hash == NULL) {
         SCFree(pkt_non_pf_array);
+        SCFree(pkt_hook_flow_start_non_pf_array);
         SCFree(frame_non_pf_array);
         return -1;
     }
@@ -798,6 +828,7 @@ static int SetupNonPrefilter(DetectEngineCtx *de_ctx, SigGroupHead *sgh)
                 HashTableInit(512, NonPFNamesHash, NonPFNamesCompare, NonPFNamesFree);
         if (de_ctx->non_pf_engine_names == NULL) {
             SCFree(pkt_non_pf_array);
+            SCFree(pkt_hook_flow_start_non_pf_array);
             SCFree(frame_non_pf_array);
             HashListTableFree(tx_engines_hash);
             return -1;
@@ -830,6 +861,44 @@ static int SetupNonPrefilter(DetectEngineCtx *de_ctx, SigGroupHead *sgh)
         bool tx_non_pf = false;
         bool frame_non_pf = false;
         bool pkt_non_pf = false;
+
+        if (s->init_data->hook.type == SIGNATURE_HOOK_TYPE_PKT &&
+                s->init_data->hook.t.pkt.ph == SIGNATURE_HOOK_PKT_FLOW_START) {
+            // TODO code duplication with regular pkt case below
+
+            /* for pkt non prefilter, we have some space in the structure,
+             * so we can squeeze another filter */
+            uint8_t type;
+            uint16_t value;
+            if ((s->flags & SIG_FLAG_DSIZE) && s->dsize_mode == DETECT_UINT_EQ) {
+                SCLogDebug("dsize extra match");
+                type = 2;
+                value = s->dsize_low;
+            } else if (s->dp != NULL && s->dp->next == NULL && s->dp->port == s->dp->port2) {
+                type = 1;
+                value = s->dp->port;
+            } else {
+                type = 0;
+                value = s->alproto;
+            }
+            pkt_hook_flow_start_non_pf_array[pkt_hook_flow_start_non_pf_array_size].sid = s->num;
+            pkt_hook_flow_start_non_pf_array[pkt_hook_flow_start_non_pf_array_size].value = value;
+            pkt_hook_flow_start_non_pf_array[pkt_hook_flow_start_non_pf_array_size].type = type;
+            pkt_hook_flow_start_non_pf_array[pkt_hook_flow_start_non_pf_array_size].pkt.sig_mask =
+                    s->mask;
+            pkt_hook_flow_start_non_pf_array_size++;
+
+            if (pkt_hook_flow_start_mask_init) {
+                pkt_hook_flow_start_mask &= s->mask;
+            } else {
+                pkt_hook_flow_start_mask = s->mask;
+                pkt_hook_flow_start_mask_init = true;
+            }
+
+            SCLogDebug("flow_start hook");
+            continue; // done for this sig
+        }
+
         for (uint32_t x = 0; x < s->init_data->buffer_index; x++) {
             const int list_id = s->init_data->buffers[x].id;
             const DetectBufferType *buf = DetectEngineBufferTypeGetById(de_ctx, list_id);
@@ -984,12 +1053,32 @@ static int SetupNonPrefilter(DetectEngineCtx *de_ctx, SigGroupHead *sgh)
         data->size = pkt_non_pf_array_size;
         memcpy((uint8_t *)&data->array, pkt_non_pf_array,
                 pkt_non_pf_array_size * sizeof(data->array[0]));
-        if (PrefilterAppendEngine(de_ctx, sgh, PrefilterPktNonPF, pkt_mask, (void *)data,
+        enum SignatureHookPkt hook = SIGNATURE_HOOK_PKT_NOT_SET; // TODO review
+        if (PrefilterAppendEngine(de_ctx, sgh, PrefilterPktNonPF, pkt_mask, hook, (void *)data,
                     PrefilterNonPFDataFree, "packet:non_pf") < 0) {
             SCFree(data);
             goto error;
         }
     }
+    if (pkt_hook_flow_start_non_pf_array_size) {
+        struct PrefilterNonPFData *data = SCCalloc(
+                1, sizeof(*data) + pkt_hook_flow_start_non_pf_array_size * sizeof(data->array[0]));
+        if (data == NULL)
+            goto error;
+        data->size = pkt_hook_flow_start_non_pf_array_size;
+        memcpy((uint8_t *)&data->array, pkt_hook_flow_start_non_pf_array,
+                pkt_hook_flow_start_non_pf_array_size * sizeof(data->array[0]));
+        SCLogDebug("packet:flow_start:non_pf added with %u rules", data->size);
+        enum SignatureHookPkt hook = SIGNATURE_HOOK_PKT_FLOW_START;
+        if (PrefilterAppendEngine(de_ctx, sgh,
+                    PrefilterPktNonPFHookFlowStart, // TODO no longer needed to have a dedicated
+                                                    // callback
+                    pkt_hook_flow_start_mask, hook, (void *)data, PrefilterNonPFDataFree,
+                    "packet:flow_start:non_pf") < 0) {
+            SCFree(data);
+            goto error;
+        }
+    }
     if (frame_non_pf_array_size) {
         SCLogDebug("%u frame non-pf sigs", frame_non_pf_array_size);
         struct PrefilterNonPFData *data =
@@ -1006,6 +1095,8 @@ static int SetupNonPrefilter(DetectEngineCtx *de_ctx, SigGroupHead *sgh)
         }
     }
 
+    SCFree(pkt_hook_flow_start_non_pf_array);
+    pkt_hook_flow_start_non_pf_array = NULL;
     SCFree(pkt_non_pf_array);
     pkt_non_pf_array = NULL;
     SCFree(frame_non_pf_array);
@@ -1016,6 +1107,7 @@ error:
     if (tx_engines_hash) {
         HashListTableFree(tx_engines_hash);
     }
+    SCFree(pkt_hook_flow_start_non_pf_array);
     SCFree(pkt_non_pf_array);
     SCFree(frame_non_pf_array);
     return -1;
@@ -1061,7 +1153,11 @@ int PrefilterSetupRuleGroup(DetectEngineCtx *de_ctx, SigGroupHead *sgh)
         for (el = sgh->init->pkt_engines ; el != NULL; el = el->next) {
             e->local_id = el->id;
             e->cb.Prefilter = el->Prefilter;
-            e->ctx.pkt_mask = el->pkt_mask;
+            e->ctx.pkt.mask = el->pkt_mask;
+            // TODO right now we represent the hook in a u8 in the prefilter engine for space
+            // reasons.
+            BUG_ON(el->pkt_hook >= 8);
+            e->ctx.pkt.hook = (uint8_t)el->pkt_hook;
             e->pectx = el->pectx;
             el->pectx = NULL; // e now owns the ctx
             e->gid = el->gid;
@@ -1086,7 +1182,11 @@ int PrefilterSetupRuleGroup(DetectEngineCtx *de_ctx, SigGroupHead *sgh)
         for (el = sgh->init->payload_engines ; el != NULL; el = el->next) {
             e->local_id = el->id;
             e->cb.Prefilter = el->Prefilter;
-            e->ctx.pkt_mask = el->pkt_mask;
+            e->ctx.pkt.mask = el->pkt_mask;
+            // TODO right now we represent the hook in a u8 in the prefilter engine for space
+            // reasons.
+            BUG_ON(el->pkt_hook >= 8);
+            e->ctx.pkt.hook = (uint8_t)el->pkt_hook;
             e->pectx = el->pectx;
             el->pectx = NULL; // e now owns the ctx
             e->gid = el->gid;
@@ -1518,8 +1618,9 @@ int PrefilterGenericMpmPktRegister(DetectEngineCtx *de_ctx, SigGroupHead *sgh, M
     pectx->mpm_ctx = mpm_ctx;
     pectx->transforms = &mpm_reg->transforms;
 
+    enum SignatureHookPkt hook = SIGNATURE_HOOK_PKT_NOT_SET; // TODO review
     int r = PrefilterAppendEngine(
-            de_ctx, sgh, PrefilterMpmPkt, 0, pectx, PrefilterMpmPktFree, mpm_reg->pname);
+            de_ctx, sgh, PrefilterMpmPkt, 0, hook, pectx, PrefilterMpmPktFree, mpm_reg->pname);
     if (r != 0) {
         SCFree(pectx);
     }
index 222f5a1528677f8e1a1413bd005b0b971f401432..3dbd2a45e4425b84369d0b73a6ce9a2f72b8a5ef 100644 (file)
@@ -54,7 +54,8 @@ void Prefilter(DetectEngineThreadCtx *, const SigGroupHead *, Packet *p, const u
         const SignatureMask mask);
 
 int PrefilterAppendEngine(DetectEngineCtx *de_ctx, SigGroupHead *sgh, PrefilterPktFn PrefilterFunc,
-        SignatureMask mask, void *pectx, void (*FreeFunc)(void *pectx), const char *name);
+        SignatureMask mask, enum SignatureHookPkt hook, void *pectx, void (*FreeFunc)(void *pectx),
+        const char *name);
 
 void PrefilterPostRuleMatch(
         DetectEngineThreadCtx *det_ctx, const SigGroupHead *sgh, Packet *p, Flow *f);
index face78c902945c0c3b8cea3a985c57c2d70debbd..79f3bb88065b89e8eac6fdfaf6e744c7c255fd70 100644 (file)
@@ -1332,8 +1332,9 @@ static int PrefilterSetupFlowbits(DetectEngineCtx *de_ctx, SigGroupHead *sgh)
     /* finally, register the states with their engines */
     static const char *g_prefilter_flowbits_isset = "flowbits:isset";
     if (isset_ctx != NULL) {
-        PrefilterAppendEngine(de_ctx, sgh, PrefilterFlowbitMatch, SIG_MASK_REQUIRE_FLOW, isset_ctx,
-                PrefilterFlowbitFree, g_prefilter_flowbits_isset);
+        enum SignatureHookPkt hook = SIGNATURE_HOOK_PKT_NOT_SET; // TODO review
+        PrefilterAppendEngine(de_ctx, sgh, PrefilterFlowbitMatch, SIG_MASK_REQUIRE_FLOW, hook,
+                isset_ctx, PrefilterFlowbitFree, g_prefilter_flowbits_isset);
         SCLogDebug("isset: added prefilter engine");
 
         if (set_ctx != NULL && !RB_EMPTY(&set_ctx->fb_tree)) {
index 15b2cc3677d1043bbd7d1117173e98ac1d0e8197..4647aa4f68bff253d683439ddaeb4b38ca59a84c 100644 (file)
@@ -1198,6 +1198,7 @@ void DetectRegisterAppLayerHookLists(void)
     }
 }
 
+#ifdef DEBUG
 static const char *SignatureHookTypeToString(enum SignatureHookType t)
 {
     switch (t) {
@@ -1205,11 +1206,68 @@ static const char *SignatureHookTypeToString(enum SignatureHookType t)
             return "not_set";
         case SIGNATURE_HOOK_TYPE_APP:
             return "app";
-            // case SIGNATURE_HOOK_TYPE_PKT:
-            //     return "pkt";
+        case SIGNATURE_HOOK_TYPE_PKT:
+            return "pkt";
     }
     return "unknown";
 }
+#endif
+
+static enum SignatureHookPkt HookPktFromString(const char *str)
+{
+    if (strcmp(str, "flow_start") == 0) {
+        return SIGNATURE_HOOK_PKT_FLOW_START;
+    } else if (strcmp(str, "all") == 0) {
+        return SIGNATURE_HOOK_PKT_ALL;
+    }
+    return SIGNATURE_HOOK_PKT_NOT_SET;
+}
+
+#ifdef DEBUG
+static const char *HookPktToString(const enum SignatureHookPkt ph)
+{
+    switch (ph) {
+        case SIGNATURE_HOOK_PKT_NOT_SET:
+            return "not set";
+        case SIGNATURE_HOOK_PKT_FLOW_START:
+            return "flow_start";
+        case SIGNATURE_HOOK_PKT_ALL:
+            return "all";
+    }
+    return "error";
+}
+#endif
+
+static SignatureHook SetPktHook(const char *hook_str)
+{
+    SignatureHook h = {
+        .type = SIGNATURE_HOOK_TYPE_PKT,
+        .t.pkt.ph = HookPktFromString(hook_str),
+    };
+    return h;
+}
+
+/**
+ * \param proto_hook string of protocol and hook, e.g. dns:request_complete
+ */
+static int SigParseProtoHookPkt(Signature *s, const char *proto_hook, const char *p, const char *h)
+{
+    enum SignatureHookPkt hook = HookPktFromString(h);
+    if (hook != SIGNATURE_HOOK_PKT_NOT_SET) {
+        s->init_data->hook = SetPktHook(h);
+        if (s->init_data->hook.t.pkt.ph == SIGNATURE_HOOK_PKT_NOT_SET) {
+            return -1; // TODO unreachable?
+        }
+    } else {
+        SCLogError("unknown pkt hook %s", h);
+        return -1;
+    }
+
+    SCLogDebug("protocol:%s hook:%s: type:%s parsed hook:%s", p, h,
+            SignatureHookTypeToString(s->init_data->hook.type),
+            HookPktToString(s->init_data->hook.t.pkt.ph));
+    return 0;
+}
 
 static SignatureHook SetAppHook(const AppProto alproto, int progress)
 {
@@ -1334,6 +1392,13 @@ static int SigParseProto(Signature *s, const char *protostr)
                     p, p);
             SCReturnInt(-1);
         }
+    } else if (h != NULL) {
+        SCLogDebug("non-app-layer rule with %s:%s", p, h);
+
+        if (SigParseProtoHookPkt(s, protostr, p, h) < 0) {
+            SCLogError("protocol \"%s\" does not support hook \"%s\"", p, h);
+            SCReturnInt(-1);
+        }
     }
 
     /* if any of these flags are set they are set in a mutually exclusive
@@ -2702,6 +2767,14 @@ static Signature *SigInitHelper(DetectEngineCtx *de_ctx, const char *sigstr,
         }
     }
 
+    if (sig->init_data->hook.type == SIGNATURE_HOOK_TYPE_PKT) {
+        if (sig->init_data->hook.t.pkt.ph == SIGNATURE_HOOK_PKT_FLOW_START) {
+            if ((sig->flags & SIG_FLAG_TOSERVER) != 0) {
+                sig->init_data->init_flags |= SIG_FLAG_INIT_FLOW;
+            }
+        }
+    }
+
     if (!(sig->init_data->init_flags & SIG_FLAG_INIT_FLOW)) {
         if ((sig->flags & (SIG_FLAG_TOSERVER|SIG_FLAG_TOCLIENT)) == 0) {
             sig->flags |= SIG_FLAG_TOSERVER;
index 8eb1d94af6c4965e92b7e42f7053658d5a394654..4c353c1a6d12746954a74ee36968881f76116399 100644 (file)
@@ -547,9 +547,15 @@ typedef struct SignatureInitDataBuffer_ {
     SigMatch *tail;
 } SignatureInitDataBuffer;
 
+enum SignatureHookPkt {
+    SIGNATURE_HOOK_PKT_NOT_SET,
+    SIGNATURE_HOOK_PKT_FLOW_START,
+    SIGNATURE_HOOK_PKT_ALL, /**< match each packet */
+};
+
 enum SignatureHookType {
     SIGNATURE_HOOK_TYPE_NOT_SET,
-    // SIGNATURE_HOOK_TYPE_PKT,
+    SIGNATURE_HOOK_TYPE_PKT,
     SIGNATURE_HOOK_TYPE_APP,
 };
 
@@ -565,6 +571,9 @@ typedef struct SignatureHook_ {
              *  specific progress value. */
             int app_progress;
         } app;
+        struct {
+            enum SignatureHookPkt ph;
+        } pkt;
     } t;
 } SignatureHook;
 
@@ -1452,6 +1461,8 @@ typedef struct PrefilterEngineList_ {
 
     SignatureMask pkt_mask; /**< mask for pkt engines */
 
+    enum SignatureHookPkt pkt_hook;
+
     /** Context for matching. Might be MpmCtx for MPM engines, other ctx'
      *  for other engines. */
     void *pectx;
@@ -1479,13 +1490,19 @@ typedef struct PrefilterEngine_ {
     AppProto alproto;
 
     union {
-        SignatureMask pkt_mask; /**< mask for pkt engines */
+        struct {
+            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 */
         uint8_t tx_min_progress;
         uint8_t frame_type;
     } ctx;
 
+    bool is_last;
+    bool is_last_for_progress;
+
     /** Context for matching. Might be MpmCtx for MPM engines, other ctx'
      *  for other engines. */
     void *pectx;
@@ -1500,8 +1517,6 @@ typedef struct PrefilterEngine_ {
 
     /* global id for this prefilter */
     uint32_t gid;
-    bool is_last;
-    bool is_last_for_progress;
 } PrefilterEngine;
 
 typedef struct SigGroupHeadInitData_ {
index a07ea762a1bb2732e7bf51f03fbe2152574866cb..04a8ff5f9309034f79bb6326ebbcc7cfbf918047 100644 (file)
@@ -438,6 +438,7 @@ void FlowHandlePacketUpdate(Flow *f, Packet *p, ThreadVars *tv, DecodeThreadVars
             if (FlowUpdateSeenFlag(p)) {
                 f->flags |= FLOW_TO_DST_SEEN;
                 p->flowflags |= FLOW_PKT_TOSERVER_FIRST;
+                p->pkt_hooks |= BIT_U16(SIGNATURE_HOOK_PKT_FLOW_START);
             }
         }
         /* xfer proto detect ts flag to first packet in ts dir */
@@ -463,6 +464,7 @@ void FlowHandlePacketUpdate(Flow *f, Packet *p, ThreadVars *tv, DecodeThreadVars
             if (FlowUpdateSeenFlag(p)) {
                 f->flags |= FLOW_TO_SRC_SEEN;
                 p->flowflags |= FLOW_PKT_TOCLIENT_FIRST;
+                p->pkt_hooks |= BIT_U16(SIGNATURE_HOOK_PKT_FLOW_START);
             }
         }
         /* xfer proto detect tc flag to first packet in tc dir */
index 558d366e6e864e388e7480c1159f0390c6c78d7f..5254c8cde90059a107bdd75b94db8e902265061b 100644 (file)
@@ -98,6 +98,7 @@ void PacketReinit(Packet *p)
     PACKET_FREE_EXTDATA(p);
     p->app_update_direction = 0;
     p->sig_mask = 0;
+    p->pkt_hooks = 0;
     p->flags = 0;
     p->flowflags = 0;
     p->pkt_src = 0;