return 0;
}
-static int ThresholdCheckUpdate(const DetectThresholdData *td, ThresholdEntry *te,
+static int ThresholdCheckUpdate(const DetectEngineCtx *de_ctx, const DetectThresholdData *td,
+ ThresholdEntry *te,
const Packet *p, // ts only? - cache too
const uint32_t sid, const uint32_t gid, const uint32_t rev, PacketAlert *pa)
{
te->current_count = 1;
}
break;
- case TYPE_RATE:
+ case TYPE_RATE: {
SCLogDebug("rate_filter");
+ const uint8_t original_action = pa->action;
ret = 1;
/* Check if we have a timeout enabled, if so,
* we still matching (and enabling the new_action) */
te->current_count = 1;
}
}
+ if (de_ctx->RateFilterCallback && original_action != pa->action) {
+ pa->action = de_ctx->RateFilterCallback(p, sid, gid, rev, original_action,
+ pa->action, de_ctx->rate_filter_callback_arg);
+ if (pa->action == original_action) {
+ /* Reset back to original action, clear modified flag. */
+ pa->flags &= ~PACKET_ALERT_FLAG_RATE_FILTER_MODIFIED;
+ }
+ }
break;
+ }
case TYPE_BACKOFF:
SCLogDebug("backoff");
return ret;
}
-static int ThresholdGetFromHash(struct Thresholds *tctx, const Packet *p, const Signature *s,
- const DetectThresholdData *td, PacketAlert *pa)
+static int ThresholdGetFromHash(const DetectEngineCtx *de_ctx, struct Thresholds *tctx,
+ const Packet *p, const Signature *s, const DetectThresholdData *td, PacketAlert *pa)
{
/* fast track for count 1 threshold */
if (td->count == 1 && td->type == TYPE_THRESHOLD) {
r = ThresholdSetup(td, te, p->ts, s->id, s->gid, s->rev, p->tenant_id);
} else {
// existing, check/update
- r = ThresholdCheckUpdate(td, te, p, s->id, s->gid, s->rev, pa);
+ r = ThresholdCheckUpdate(de_ctx, td, te, p, s->id, s->gid, s->rev, pa);
}
(void)THashDecrUsecnt(res.data);
* \retval 1 normal match
* \retval 0 no match
*/
-static int ThresholdHandlePacketFlow(Flow *f, Packet *p, const DetectThresholdData *td,
- uint32_t sid, uint32_t gid, uint32_t rev, PacketAlert *pa)
+static int ThresholdHandlePacketFlow(const DetectEngineCtx *de_ctx, Flow *f, Packet *p,
+ const DetectThresholdData *td, uint32_t sid, uint32_t gid, uint32_t rev, PacketAlert *pa)
{
int ret = 0;
ThresholdEntry *found = ThresholdFlowLookupEntry(f, sid, gid, rev, p->tenant_id);
}
} else {
// existing, check/update
- ret = ThresholdCheckUpdate(td, found, p, sid, gid, rev, pa);
+ ret = ThresholdCheckUpdate(de_ctx, td, found, p, sid, gid, rev, pa);
}
return ret;
}
}
}
- ret = ThresholdGetFromHash(&ctx, p, s, td, pa);
+ ret = ThresholdGetFromHash(de_ctx, &ctx, p, s, td, pa);
} else if (td->track == TRACK_DST) {
if (PacketIsIPv4(p) && (td->type == TYPE_LIMIT || td->type == TYPE_BOTH)) {
int cache_ret = CheckCache(p, td->track, s->id, s->gid, s->rev);
}
}
- ret = ThresholdGetFromHash(&ctx, p, s, td, pa);
+ ret = ThresholdGetFromHash(de_ctx, &ctx, p, s, td, pa);
} else if (td->track == TRACK_BOTH) {
- ret = ThresholdGetFromHash(&ctx, p, s, td, pa);
+ ret = ThresholdGetFromHash(de_ctx, &ctx, p, s, td, pa);
} else if (td->track == TRACK_RULE) {
- ret = ThresholdGetFromHash(&ctx, p, s, td, pa);
+ ret = ThresholdGetFromHash(de_ctx, &ctx, p, s, td, pa);
} else if (td->track == TRACK_FLOW) {
if (p->flow) {
- ret = ThresholdHandlePacketFlow(p->flow, p, td, s->id, s->gid, s->rev, pa);
+ ret = ThresholdHandlePacketFlow(de_ctx, p->flow, p, td, s->id, s->gid, s->rev, pa);
}
}
uint32_t content_inspect_min_size;
} DetectFileDataCfg;
+/**
+ * \brief Function type for rate filter callback.
+ *
+ * This function should return the new action to be applied. If no change to the
+ * action is to be made, the callback should return the current action provided
+ * in the new_action parameter.
+ */
+typedef uint8_t (*SCDetectRateFilterFunc)(const Packet *p, uint32_t sid, uint32_t gid, uint32_t rev,
+ uint8_t original_action, uint8_t new_action, void *arg);
+
/** \brief main detection engine ctx */
typedef struct DetectEngineCtx_ {
bool failure_fatal;
HashTable *non_pf_engine_names;
const char *firewall_rule_file_exclusive;
+
+ /* user provided rate filter callbacks. */
+ SCDetectRateFilterFunc RateFilterCallback;
+
+ /* use provided data to be passed to rate_filter_callback. */
+ void *rate_filter_callback_arg;
} DetectEngineCtx;
+/**
+ * \brief Register a callback when a rate_filter has been applied to
+ * an alert.
+ *
+ * This callback is added to the current detection engine and will be
+ * copied to all future detection engines over rule reloads.
+ */
+void SCDetectEngineRegisterRateFilterCallback(SCDetectRateFilterFunc cb, void *arg);
+
/* Engine groups profiles (low, medium, high, custom) */
enum {
ENGINE_PROFILE_UNKNOWN,