SigMatch *sm = s->init_data->smlists[type];
s->sm_arrays[type] = SigMatchList2DataArray(sm);
}
+ /* set up the pkt inspection engines */
+ DetectEnginePktInspectionSetup(s);
+
if (rule_engine_analysis_set) {
#ifdef HAVE_LIBJANSSON
EngineAnalysisRules2(de_ctx, s);
return map->id;
}
+/* returns false if no match, true if match */
+static bool DetectEngineInspectRulePacketMatches(
+ ThreadVars *tv, DetectEngineThreadCtx *det_ctx,
+ const Signature *s, const SigMatchData *sm_data,
+ Flow *f, Packet *p,
+ uint8_t *alert_flags)
+{
+ SCEnter();
+ BUG_ON(sm_data != s->sm_arrays[DETECT_SM_LIST_MATCH]);
+
+ /* run the packet match functions */
+ KEYWORD_PROFILING_SET_LIST(det_ctx, DETECT_SM_LIST_MATCH);
+ const SigMatchData *smd = sm_data;
+
+ SCLogDebug("running match functions, sm %p", smd);
+ while (1) {
+ KEYWORD_PROFILING_START;
+ if (sigmatch_table[smd->type].Match(tv, det_ctx, p, s, smd->ctx) <= 0) {
+ KEYWORD_PROFILING_END(det_ctx, smd->type, 0);
+ SCLogDebug("no match");
+ return false;
+ }
+ KEYWORD_PROFILING_END(det_ctx, smd->type, 1);
+ if (smd->is_last) {
+ SCLogDebug("match and is_last");
+ break;
+ }
+ smd++;
+ }
+ return true;
+}
+
+static bool DetectEngineInspectRulePayloadMatches(
+ ThreadVars *tv, DetectEngineThreadCtx *det_ctx,
+ const Signature *s, const SigMatchData *sm_data,
+ Flow *f, Packet *p,
+ uint8_t *alert_flags)
+{
+ SCEnter();
+
+ BUG_ON(alert_flags == NULL);
+ DetectEngineCtx *de_ctx = det_ctx->de_ctx;
+
+ KEYWORD_PROFILING_SET_LIST(det_ctx, DETECT_SM_LIST_PMATCH);
+ /* if we have stream msgs, inspect against those first,
+ * but not for a "dsize" signature */
+ if (s->flags & SIG_FLAG_REQUIRE_STREAM) {
+ int pmatch = 0;
+ if (p->flags & PKT_DETECT_HAS_STREAMDATA) {
+ pmatch = DetectEngineInspectStreamPayload(de_ctx, det_ctx, s, f, p);
+ if (pmatch) {
+ det_ctx->flags |= DETECT_ENGINE_THREAD_CTX_STREAM_CONTENT_MATCH;
+ /* Tell the engine that this reassembled stream can drop the
+ * rest of the pkts with no further inspection */
+ if (s->action & ACTION_DROP)
+ *alert_flags |= PACKET_ALERT_FLAG_DROP_FLOW;
+
+ *alert_flags |= PACKET_ALERT_FLAG_STREAM_MATCH;
+ }
+ }
+ /* no match? then inspect packet payload */
+ if (pmatch == 0) {
+ SCLogDebug("no match in stream, fall back to packet payload");
+
+ /* skip if we don't have to inspect the packet and segment was
+ * added to stream */
+ if (!(s->flags & SIG_FLAG_REQUIRE_PACKET) && (p->flags & PKT_STREAM_ADD)) {
+ return false;
+ }
+ if (DetectEngineInspectPacketPayload(de_ctx, det_ctx, s, f, p) != 1) {
+ return false;
+ }
+ }
+ } else {
+ if (DetectEngineInspectPacketPayload(de_ctx, det_ctx, s, f, p) != 1) {
+ return false;
+ }
+ }
+ return true;
+}
+
+bool DetectEnginePktInspectionRun(ThreadVars *tv,
+ DetectEngineThreadCtx *det_ctx, const Signature *s,
+ Flow *f, Packet *p,
+ uint8_t *alert_flags)
+{
+ SCEnter();
+ for (DetectEnginePktInspectionEngine *e = s->pkt_inspect; e != NULL; e = e->next) {
+ if (e->Callback(tv, det_ctx, s, e->sm_data, f, p, alert_flags) == false) {
+ SCLogDebug("sid %u: e %p Callback returned false", s->id, e);
+ return false;
+ }
+ SCLogDebug("sid %u: e %p Callback returned true", s->id, e);
+ }
+ SCLogDebug("sid %u: returning true", s->id);
+ return true;
+}
+
+static int DetectEnginePktInspectionAppend(Signature *s,
+ DetectEnginePktInspectionFunc Callback,
+ SigMatchData *data)
+{
+ DetectEnginePktInspectionEngine *e = SCCalloc(1, sizeof(*e));
+ if (e == NULL)
+ return -1;
+
+ e->Callback = Callback;
+ e->sm_data = data;
+
+ if (s->pkt_inspect == NULL) {
+ s->pkt_inspect = e;
+ } else {
+ DetectEnginePktInspectionEngine *a = s->pkt_inspect;
+ while (a->next != NULL) {
+ a = a->next;
+ }
+ a->next = e;
+ }
+
+ return 0;
+}
+
+int DetectEnginePktInspectionSetup(Signature *s)
+{
+ /* only handle PMATCH here if we're not an app inspect rule */
+ if (s->sm_arrays[DETECT_SM_LIST_PMATCH] && (s->init_data->init_flags & SIG_FLAG_INIT_STATE_MATCH) == 0) {
+ if (DetectEnginePktInspectionAppend(s, DetectEngineInspectRulePayloadMatches,
+ s->sm_arrays[DETECT_SM_LIST_PMATCH]) < 0)
+ return -1;
+ SCLogDebug("sid %u: DetectEngineInspectRulePayloadMatches appended", s->id);
+ }
+
+ if (s->sm_arrays[DETECT_SM_LIST_MATCH]) {
+ if (DetectEnginePktInspectionAppend(s, DetectEngineInspectRulePacketMatches,
+ s->sm_arrays[DETECT_SM_LIST_MATCH]) < 0)
+ return -1;
+ SCLogDebug("sid %u: DetectEngineInspectRulePacketMatches appended", s->id);
+ }
+
+ return 0;
+}
+
/* code to control the main thread to do a reload */
enum DetectEngineSyncState {
int DetectEngineAppInspectionEngine2Signature(DetectEngineCtx *de_ctx, Signature *s);
void DetectEngineAppInspectionEngineSignatureFree(Signature *s);
+bool DetectEnginePktInspectionRun(ThreadVars *tv,
+ DetectEngineThreadCtx *det_ctx, const Signature *s,
+ Flow *f, Packet *p,
+ uint8_t *alert_flags);
+int DetectEnginePktInspectionSetup(Signature *s);
+
void DetectEngineSetParseMetadata(void);
void DetectEngineUnsetParseMetadata(void);
int DetectEngineMustParseMetadata(void);
DetectEngineAppInspectionEngineSignatureFree(s);
+ if (s->pkt_inspect) {
+ DetectEnginePktInspectionEngine *e = s->pkt_inspect;
+ while (e) {
+ DetectEnginePktInspectionEngine *next = e->next;
+ SCFree(e);
+ e = next;
+ }
+ }
+
SCFree(s);
}
return 1;
}
-/* returns 0 if no match, 1 if match */
-static inline int DetectRunInspectRulePacketMatches(
- ThreadVars *tv,
- DetectEngineThreadCtx *det_ctx,
- Packet *p,
- const Flow *f,
- const Signature *s)
-{
- /* run the packet match functions */
- if (s->sm_arrays[DETECT_SM_LIST_MATCH] != NULL) {
- KEYWORD_PROFILING_SET_LIST(det_ctx, DETECT_SM_LIST_MATCH);
- SigMatchData *smd = s->sm_arrays[DETECT_SM_LIST_MATCH];
-
- SCLogDebug("running match functions, sm %p", smd);
- while (1) {
- KEYWORD_PROFILING_START;
- if (sigmatch_table[smd->type].Match(tv, det_ctx, p, s, smd->ctx) <= 0) {
- KEYWORD_PROFILING_END(det_ctx, smd->type, 0);
- SCLogDebug("no match");
- return 0;
- }
- KEYWORD_PROFILING_END(det_ctx, smd->type, 1);
- if (smd->is_last) {
- SCLogDebug("match and is_last");
- break;
- }
- smd++;
- }
- }
- return 1;
-}
-
/** \internal
* \brief run packet/stream prefilter engines
*/
goto next;
}
- /* Check the payload keywords. If we are a MPM sig and we've made
- * to here, we've had at least one of the patterns match */
- if (s->sm_arrays[DETECT_SM_LIST_PMATCH] != NULL) {
- KEYWORD_PROFILING_SET_LIST(det_ctx, DETECT_SM_LIST_PMATCH);
- /* if we have stream msgs, inspect against those first,
- * but not for a "dsize" signature */
- if (sflags & SIG_FLAG_REQUIRE_STREAM) {
- int pmatch = 0;
- if (p->flags & PKT_DETECT_HAS_STREAMDATA) {
- pmatch = DetectEngineInspectStreamPayload(de_ctx, det_ctx, s, pflow, p);
- if (pmatch) {
- det_ctx->flags |= DETECT_ENGINE_THREAD_CTX_STREAM_CONTENT_MATCH;
- /* Tell the engine that this reassembled stream can drop the
- * rest of the pkts with no further inspection */
- if (s->action & ACTION_DROP)
- alert_flags |= PACKET_ALERT_FLAG_DROP_FLOW;
-
- alert_flags |= PACKET_ALERT_FLAG_STREAM_MATCH;
- }
- }
- /* no match? then inspect packet payload */
- if (pmatch == 0) {
- SCLogDebug("no match in stream, fall back to packet payload");
-
- /* skip if we don't have to inspect the packet and segment was
- * added to stream */
- if (!(sflags & SIG_FLAG_REQUIRE_PACKET) && (p->flags & PKT_STREAM_ADD)) {
- goto next;
- }
-
- if (DetectEngineInspectPacketPayload(de_ctx, det_ctx, s, pflow, p) != 1) {
- goto next;
- }
- }
- } else {
- if (DetectEngineInspectPacketPayload(de_ctx, det_ctx, s, pflow, p) != 1) {
- goto next;
- }
- }
- }
-
- if (DetectRunInspectRulePacketMatches(tv, det_ctx, p, pflow, s) == 0)
+ if (DetectEnginePktInspectionRun(tv, det_ctx, s, pflow, p, &alert_flags) == false) {
goto next;
+ }
#ifdef PROFILING
smatch = true;
TRACE_SID_TXS(s->id, tx, "DetectRunInspectRuleHeader() no match");
return false;
}
- if (DetectRunInspectRulePacketMatches(tv, det_ctx, p, f, s) == 0) {
- TRACE_SID_TXS(s->id, tx, "DetectRunInspectRulePacketMatches no match");
+ if (DetectEnginePktInspectionRun(tv, det_ctx, s, f, p, NULL) == false) {
+ TRACE_SID_TXS(s->id, tx, "DetectEnginePktInspectionRun no match");
return false;
}
/* stream mpm and negated mpm sigs can end up here with wrong proto */
DetectEngineTransforms transforms;
} DetectBufferType;
+/* Function pointer for the pkt inspect engines. Goal for this
+ * function will be to process the complete list of conditions
+ * passed to it through 'sm_data'. */
+typedef bool (*DetectEnginePktInspectionFunc)(ThreadVars *,
+ struct DetectEngineThreadCtx_ *,
+ const struct Signature_ *s,
+ const struct SigMatchData_ *sm_data,
+ Flow *f,
+ Packet *p,
+ uint8_t *alert_flags);
+
+typedef struct DetectEnginePktInspectionEngine {
+ DetectEnginePktInspectionFunc Callback;
+ SigMatchData *sm_data;
+ struct DetectEnginePktInspectionEngine *next;
+} DetectEnginePktInspectionEngine;
+
#ifdef UNITTESTS
#define sm_lists init_data->smlists
#define sm_lists_tail init_data->smlists_tail
IPOnlyCIDRItem *CidrSrc, *CidrDst;
DetectEngineAppInspectionEngine *app_inspect;
+ DetectEnginePktInspectionEngine *pkt_inspect;
/* Matching structures for the built-ins. The others are in
* their inspect engines. */