return d;
}
-static DeStateStoreFlowRules *DeStateStoreFlowRulesAlloc(void)
-{
- DeStateStoreFlowRules *d = SCMalloc(sizeof(DeStateStoreFlowRules));
- if (unlikely(d == NULL))
- return NULL;
- memset(d, 0, sizeof(DeStateStoreFlowRules));
-
- return d;
-}
static int DeStateSearchState(DetectEngineState *state, uint8_t direction, SigIntId num)
{
return;
}
-static void DeStateFlowRuleAppend(DetectEngineStateFlow *state, const Signature *s,
- const SigMatchData *smd, uint32_t inspect_flags,
- uint8_t direction)
-{
- int jump = 0;
- int i = 0;
- DetectEngineStateDirectionFlow *dir_state = &state->dir_state[direction & STREAM_TOSERVER ? 0 : 1];
- DeStateStoreFlowRules *store = dir_state->head;
-
- if (store == NULL) {
- store = DeStateStoreFlowRulesAlloc();
- if (store != NULL) {
- dir_state->head = store;
- dir_state->tail = store;
- }
- } else {
- jump = dir_state->cnt / DE_STATE_CHUNK_SIZE;
- for (i = 0; i < jump; i++) {
- store = store->next;
- }
- if (store == NULL) {
- store = DeStateStoreFlowRulesAlloc();
- if (store != NULL) {
- dir_state->tail->next = store;
- dir_state->tail = store;
- }
- }
- }
-
- if (store == NULL)
- return;
-
- SigIntId idx = dir_state->cnt++ % DE_STATE_CHUNK_SIZE;
- store->store[idx].sid = s->num;
- store->store[idx].flags = inspect_flags;
- store->store[idx].nm = smd;
-
- return;
-}
-
static void DeStateStoreStateVersion(Flow *f,
const uint8_t alversion, uint8_t direction)
{
return d;
}
-DetectEngineStateFlow *DetectEngineStateFlowAlloc(void)
-{
- DetectEngineStateFlow *d = SCMalloc(sizeof(DetectEngineStateFlow));
- if (unlikely(d == NULL))
- return NULL;
- memset(d, 0, sizeof(DetectEngineStateFlow));
-
- return d;
-}
-
void DetectEngineStateFree(DetectEngineState *state)
{
DeStateStore *store;
return;
}
-void DetectEngineStateFlowFree(DetectEngineStateFlow *state)
-{
- DeStateStoreFlowRules *store;
- DeStateStoreFlowRules *store_next;
- int i = 0;
-
- for (i = 0; i < 2; i++) {
- store = state->dir_state[i].head;
- while (store != NULL) {
- store_next = store->next;
- SCFree(store);
- store = store_next;
- }
- }
- SCFree(state);
-
- return;
-}
-
static int HasStoredSigs(Flow *f, uint8_t flags)
{
- if (f->de_state != NULL && f->de_state->dir_state[flags & STREAM_TOSERVER ? 0 : 1].cnt != 0) {
- SCLogDebug("global sigs present");
- return 1;
- }
-
if (AppLayerParserProtocolSupportsTxs(f->proto, f->alproto)) {
AppProto alproto = f->alproto;
void *alstate = FlowGetAppState(f);
*
* \retval 0 no inspectable state
* \retval 1 inspectable state
- * \retval 2 inspectable state, but no update
*/
int DeStateFlowHasInspectableState(Flow *f, AppProto alproto,
const uint8_t alversion, uint8_t flags)
{
int r = 0;
- if (!(flags & STREAM_EOF) && f->de_state &&
- f->detect_alversion[flags & STREAM_TOSERVER ? 0 : 1] == alversion) {
- SCLogDebug("unchanged state");
- r = 2;
- } else if (HasStoredSigs(f, flags)) {
+ if (HasStoredSigs(f, flags)) {
r = 1;
} else {
r = 0;
return r;
}
-static int StoreState(DetectEngineThreadCtx *det_ctx,
- Flow *f, const uint8_t flags, const uint8_t alversion,
- const Signature *s, const SigMatchData *smd,
- const uint32_t inspect_flags,
- const uint16_t file_no_match)
+static int StoreState(Flow *f, const uint8_t flags, const uint8_t alversion)
{
- if (f->de_state == NULL) {
- f->de_state = DetectEngineStateFlowAlloc();
- if (f->de_state == NULL) {
- return 0;
- }
- }
-
- DeStateFlowRuleAppend(f->de_state, s, smd, inspect_flags, flags);
DeStateStoreStateVersion(f, alversion, flags);
return 1;
}
}
}
- StoreState(det_ctx, f, flags, alversion,
- s, smd, inspect_flags, file_no_match);
+ StoreState(f, flags, alversion);
}
end:
det_ctx->tx_id = 0;
return 1;
}
-/** \internal
- * \brief Continue Detection for a single "flow" rule (AMATCH)
- */
-static int DoInspectFlowRule(ThreadVars *tv,
- DetectEngineCtx *de_ctx, DetectEngineThreadCtx *det_ctx,
- DeStateStoreFlowRule *item, const uint8_t dir_state_flags,
- Packet *p, Flow *f, AppProto alproto, uint8_t flags)
-{
- /* flag rules that are either full inspected or unable to match
- * in the de_state_sig_array so that prefilter filters them out */
- if (item->flags & (DE_STATE_FLAG_FULL_INSPECT|DE_STATE_FLAG_SIG_CANT_MATCH)) {
- det_ctx->de_state_sig_array[item->sid] = DE_STATE_MATCH_NO_NEW_STATE;
- return 0;
- }
-
- uint8_t alert = 0;
- uint32_t inspect_flags = item->flags;
- int total_matches = 0;
- int full_match = 0;
- const SigMatchData *smd = NULL;
- const Signature *s = de_ctx->sig_array[item->sid];
-
- RULE_PROFILING_START(p);
-
- /* DCERPC matches */
- if (s->sm_arrays[DETECT_SM_LIST_DMATCH] != NULL &&
- (alproto == ALPROTO_DCERPC || alproto == ALPROTO_SMB ||
- alproto == ALPROTO_SMB2) &&
- !(item->flags & DE_STATE_FLAG_DCE_PAYLOAD_INSPECT))
- {
- void *alstate = FlowGetAppState(f);
- if (alstate != NULL) {
- KEYWORD_PROFILING_SET_LIST(det_ctx, DETECT_SM_LIST_DMATCH);
- if (DetectEngineInspectDcePayload(de_ctx, det_ctx, s, f,
- flags, alstate) == 1)
- {
- total_matches++;
- inspect_flags |= DE_STATE_FLAG_DCE_PAYLOAD_INSPECT;
- }
- }
- }
- /* update full_match with DMATCH result */
- if (s->sm_arrays[DETECT_SM_LIST_DMATCH] != NULL) {
- full_match = ((inspect_flags & DE_STATE_FLAG_DCE_PAYLOAD_INSPECT) != 0);
- }
-
- /* check the results */
- if (total_matches > 0 && (full_match || (inspect_flags & DE_STATE_FLAG_SIG_CANT_MATCH)))
- {
- if (full_match)
- alert = 1;
- inspect_flags |= DE_STATE_FLAG_FULL_INSPECT;
- }
- /* prevent the rule loop from reinspecting this rule */
- det_ctx->de_state_sig_array[item->sid] = DE_STATE_MATCH_NO_NEW_STATE;
- RULE_PROFILING_END(det_ctx, s, (alert == 1), p);
-
- /* store the progress in the state */
- item->flags |= inspect_flags;
- item->nm = smd;
-
- if (alert) {
- SigMatchSignaturesRunPostMatch(tv, de_ctx, det_ctx, p, s);
-
- if (!(s->flags & SIG_FLAG_NOALERT)) {
- PacketAlertAppend(det_ctx, s, p, 0,
- PACKET_ALERT_FLAG_STATE_MATCH);
- } else {
- DetectSignatureApplyActions(p, s);
- }
- }
-
- DetectFlowvarProcessList(det_ctx, f);
- return 1;
-}
-
void DeStateDetectContinueDetection(ThreadVars *tv, DetectEngineCtx *de_ctx,
DetectEngineThreadCtx *det_ctx,
Packet *p, Flow *f, uint8_t flags,
}
}
- /* continue on flow based state rules (AMATCH) */
- if (f->de_state != NULL) {
- DetectEngineStateDirectionFlow *dir_state = &f->de_state->dir_state[direction];
- DeStateStoreFlowRules *store = dir_state->head;
- /* Loop through stored 'items' (stateful rules) and inspect them */
- for (; store != NULL; store = store->next) {
- for (store_cnt = 0;
- store_cnt < DE_STATE_CHUNK_SIZE && state_cnt < dir_state->cnt;
- store_cnt++, state_cnt++)
- {
- DeStateStoreFlowRule *rule = &store->store[store_cnt];
-
- int r = DoInspectFlowRule(tv, de_ctx, det_ctx,
- rule, dir_state->flags,
- p, f, alproto, flags);
- if (r < 0) {
- goto end;
- }
- }
- }
- DeStateStoreStateVersion(f, alversion, flags);
- }
-
end:
det_ctx->tx_id = 0;
det_ctx->tx_id_set = 0;
return;
}
-void DetectEngineStateReset(DetectEngineStateFlow *state, uint8_t direction)
-{
- if (state != NULL) {
- if (direction & STREAM_TOSERVER) {
- state->dir_state[0].cnt = 0;
- state->dir_state[0].flags = 0;
- }
- if (direction & STREAM_TOCLIENT) {
- state->dir_state[1].cnt = 0;
- state->dir_state[1].flags = 0;
- }
- }
-
- return;
-}
-
/** \brief Reset de state for active tx'
* To be used on detect engine reload.
* \param f write LOCKED flow
* \author Anoop Saldanha <anoopsaldanha@gmail.com>
*/
-/* On DeState and locking.
- *
- * The DeState is part of a flow, but it can't be protected by the flow lock.
- * Reason is we need to lock the DeState data for an entire detection run,
- * as we're looping through on "continued" detection and rely on only a single
- * detection instance setting it up on first run. We can't keep the entire flow
- * locked during detection for performance reasons, it would slow us down too
- * much.
- *
- * So a new lock was introduced. The only part of the process where we need
- * the flow lock is obviously when we're getting/setting the de_state ptr from
- * to the flow.
- */
#ifndef __DETECT_ENGINE_STATE_H__
#define __DETECT_ENGINE_STATE_H__
#define DE_STATE_MATCH_HAS_NEW_STATE 0x00
#define DE_STATE_MATCH_NO_NEW_STATE 0x80
-/* TX BASED (inspect engines) */
-
typedef struct DeStateStoreItem_ {
uint32_t flags;
SigIntId sid;
DetectEngineStateDirection dir_state[2];
} DetectEngineState;
-/* FLOW BASED (AMATCH) */
-
-typedef struct DeStateStoreFlowRule_ {
- const SigMatchData *nm;
- uint32_t flags;
- SigIntId sid;
-} DeStateStoreFlowRule;
-
-typedef struct DeStateStoreFlowRules_ {
- DeStateStoreFlowRule store[DE_STATE_CHUNK_SIZE];
- struct DeStateStoreFlowRules_ *next;
-} DeStateStoreFlowRules;
-
-typedef struct DetectEngineStateDirectionFlow_ {
- DeStateStoreFlowRules *head;
- DeStateStoreFlowRules *tail;
- SigIntId cnt;
- uint8_t flags;
-} DetectEngineStateDirectionFlow;
-
-typedef struct DetectEngineStateFlow_ {
- DetectEngineStateDirectionFlow dir_state[2];
-} DetectEngineStateFlow;
-
/**
* \brief Alloc a DetectEngineState object.
*
* \param state DetectEngineState instance to free.
*/
void DetectEngineStateFree(DetectEngineState *state);
-void DetectEngineStateFlowFree(DetectEngineStateFlow *state);
/**
* \brief Check if a flow already contains(newly updated as well) de state.
*/
void DeStateUpdateInspectTransactionId(Flow *f, const uint8_t flags);
-/**
- * \brief Reset a DetectEngineState state.
- *
- * \param state Pointer to the state(LOCKED).
- * \param direction Direction flags - STREAM_TOSERVER or STREAM_TOCLIENT.
- */
-void DetectEngineStateReset(DetectEngineStateFlow *state, uint8_t direction);
-
void DetectEngineStateResetTxs(Flow *f);
void DeStateRegisterTests(void);
goto end;
}
- DetectEngineStateReset(f.de_state, STREAM_TOSERVER | STREAM_TOCLIENT);
-
FLOWLOCK_WRLOCK(&f);
r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
STREAM_TOSERVER, http_buf2, http_buf2_len);
goto end;
}
- DetectEngineStateReset(f.de_state, STREAM_TOSERVER | STREAM_TOCLIENT);
-
FLOWLOCK_WRLOCK(&f);
r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
STREAM_TOSERVER, http_buf2, http_buf2_len);
goto end;
}
- DetectEngineStateReset(f.de_state, STREAM_TOSERVER | STREAM_TOCLIENT);
-
FLOWLOCK_WRLOCK(&f);
r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
STREAM_TOSERVER, http_buf2, http_buf2_len);
goto end;
}
- DetectEngineStateReset(f.de_state, STREAM_TOSERVER | STREAM_TOCLIENT);
-
FLOWLOCK_WRLOCK(&f);
r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
STREAM_TOSERVER, http_buf2, http_buf2_len);
goto end;
}
- DetectEngineStateReset(f.de_state, STREAM_TOSERVER | STREAM_TOCLIENT);
-
FLOWLOCK_WRLOCK(&f);
r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
STREAM_TOSERVER, http_buf2, http_buf2_len);
goto end;
}
- DetectEngineStateReset(f.de_state, STREAM_TOSERVER | STREAM_TOCLIENT);
-
FLOWLOCK_WRLOCK(&f);
r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
STREAM_TOSERVER, http_buf2, http_buf2_len);
goto end;
}
- DetectEngineStateReset(f.de_state, STREAM_TOSERVER | STREAM_TOCLIENT);
-
FLOWLOCK_WRLOCK(&f);
r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
STREAM_TOSERVER, http_buf2, http_buf2_len);
goto end;
}
- DetectEngineStateReset(f.de_state, STREAM_TOSERVER | STREAM_TOCLIENT);
-
FLOWLOCK_WRLOCK(&f);
r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
STREAM_TOSERVER, http_buf2, http_buf2_len);
goto end;
}
- DetectEngineStateReset(f.de_state, STREAM_TOSERVER | STREAM_TOCLIENT);
-
FLOWLOCK_WRLOCK(&f);
r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
STREAM_TOSERVER, http_buf2, http_buf2_len);
goto end;
}
- DetectEngineStateReset(f.de_state, STREAM_TOSERVER | STREAM_TOCLIENT);
-
FLOWLOCK_WRLOCK(&f);
r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
STREAM_TOSERVER, http_buf2, http_buf2_len);
goto end;
}
- DetectEngineStateReset(f.de_state, STREAM_TOSERVER | STREAM_TOCLIENT);
-
FLOWLOCK_WRLOCK(&f);
r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
STREAM_TOSERVER, http_buf2, http_buf2_len);
goto end;
}
- DetectEngineStateReset(f.de_state, STREAM_TOSERVER | STREAM_TOCLIENT);
-
FLOWLOCK_WRLOCK(&f);
r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
STREAM_TOSERVER, http_buf2, http_buf2_len);
goto end;
}
- DetectEngineStateReset(f.de_state, STREAM_TOSERVER | STREAM_TOCLIENT);
-
FLOWLOCK_WRLOCK(&f);
r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
STREAM_TOSERVER, http_buf2, http_buf2_len);
goto end;
}
- DetectEngineStateReset(f.de_state, STREAM_TOSERVER | STREAM_TOCLIENT);
-
FLOWLOCK_WRLOCK(&f);
r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
STREAM_TOSERVER, http_buf2, http_buf2_len);
goto end;
}
- DetectEngineStateReset(f.de_state, STREAM_TOSERVER | STREAM_TOCLIENT);
-
FLOWLOCK_WRLOCK(&f);
r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
STREAM_TOSERVER, http_buf2, http_buf2_len);
}
p->alerts.cnt = 0;
- DetectEngineStateReset(f.de_state, STREAM_TOSERVER | STREAM_TOCLIENT);
p->payload = http_buf2;
p->payload_len = http_buf2_len;
GenericVarFree(pflow->flowvar);
pflow->flowvar = NULL;
- DetectEngineStateReset(pflow->de_state,
- (STREAM_TOSERVER|STREAM_TOCLIENT));
DetectEngineStateResetTxs(pflow);
}
/* initialize to 0(DE_STATE_MATCH_HAS_NEW_STATE) */
DeStateDetectContinueDetection(th_v, de_ctx, det_ctx, p, pflow,
flow_flags, alproto, alversion);
- } else if (has_inspectable_state == 2) {
- /* no inspectable state, so pretend we don't have a state at all */
- has_state = 0;
}
}
PACKET_PROFILING_DETECT_END(p, PROF_DETECT_STATEFUL);
(f)->detect_alversion[1] = 0; \
(f)->alparser = NULL; \
(f)->alstate = NULL; \
- (f)->de_state = NULL; \
(f)->sgh_toserver = NULL; \
(f)->sgh_toclient = NULL; \
(f)->flowvar = NULL; \
(f)->thread_id = 0; \
(f)->detect_alversion[0] = 0; \
(f)->detect_alversion[1] = 0; \
- if ((f)->de_state != NULL) { \
- DetectEngineStateReset((f)->de_state, (STREAM_TOSERVER | STREAM_TOCLIENT)); \
- } \
(f)->sgh_toserver = NULL; \
(f)->sgh_toclient = NULL; \
GenericVarFree((f)->flowvar); \
SC_ATOMIC_DESTROY((f)->use_cnt); \
\
FLOWLOCK_DESTROY((f)); \
- if ((f)->de_state != NULL) { \
- DetectEngineStateFlowFree((f)->de_state); \
- } \
GenericVarFree((f)->flowvar); \
} while(0)
/** detection engine ctx id used to inspect this flow. Set at initial
* inspection. If it doesn't match the currently in use de_ctx, the
- * de_state and stored sgh ptrs are reset. */
+ * stored sgh ptrs are reset. */
uint32_t de_ctx_id;
/** Thread ID for the stream/detect portion of this flow */
AppLayerParserState *alparser; /**< parser internal state */
void *alstate; /**< application layer state */
- /** detection engine state */
- struct DetectEngineStateFlow_ *de_state;
-
/** toclient sgh for this flow. Only use when FLOW_SGH_TOCLIENT flow flag
* has been set. */
const struct SigGroupHead_ *sgh_toclient;