return;
}
+/** \internal
+ * \brief sort helper for sorting alerts by priority
+ *
+ * Sorting is done first based on num and then using tx_id, if nums are equal.
+ * The Signature::num field is set based on internal priority. Higher priority
+ * rules have lower nums.
+ */
+static int AlertQueueSortHelper(const void *a, const void *b)
+{
+ const PacketAlert *pa0 = a;
+ const PacketAlert *pa1 = b;
+ if (pa1->num == pa0->num)
+ return pa0->tx_id < pa1->tx_id ? 1 : -1;
+ else
+ return pa0->num > pa1->num ? 1 : -1;
+}
+
/**
* \brief Check the threshold of the sigs that match, set actions, break on pass action
* This function iterate the packet alerts array, removing those that didn't match
void PacketAlertFinalize(DetectEngineCtx *de_ctx, DetectEngineThreadCtx *det_ctx, Packet *p)
{
SCEnter();
+
+ /* sort the alert queue before thresholding and appending to Packet */
+ qsort(det_ctx->alert_queue, det_ctx->alert_queue_size, sizeof(PacketAlert),
+ AlertQueueSortHelper);
+
int i = 0;
+ uint16_t max_pos = det_ctx->alert_queue_size;
- while (i < p->alerts.cnt) {
- const Signature *s = de_ctx->sig_array[p->alerts.alerts[i].num];
- SCLogDebug("Sig->num: %" PRIu32 " SID %u", p->alerts.alerts[i].num, s->id);
+ while (i < max_pos) {
+ const Signature *s = de_ctx->sig_array[det_ctx->alert_queue[i].num];
+ uint8_t res = PacketAlertHandle(de_ctx, det_ctx, s, p, &det_ctx->alert_queue[i]);
- int res = PacketAlertHandle(de_ctx, det_ctx, s, p, &p->alerts.alerts[i]);
if (res > 0) {
/* Now, if we have an alert, we have to check if we want
* to tag this session or src/dst host */
* - match is in applayer
* - match is in stream */
if (s->action & (ACTION_DROP | ACTION_PASS)) {
- if ((p->alerts.alerts[i].flags &
+ if ((det_ctx->alert_queue[i].flags &
(PACKET_ALERT_FLAG_STATE_MATCH | PACKET_ALERT_FLAG_STREAM_MATCH)) ||
(s->flags & (SIG_FLAG_IPONLY | SIG_FLAG_PDONLY | SIG_FLAG_APPLAYER))) {
- p->alerts.alerts[i].flags |= PACKET_ALERT_FLAG_APPLY_ACTION_TO_FLOW;
+ det_ctx->alert_queue[i].flags |= PACKET_ALERT_FLAG_APPLY_ACTION_TO_FLOW;
SCLogDebug("packet %" PRIu64 " sid %u action %02x alert_flags %02x (set "
"PACKET_ALERT_FLAG_APPLY_ACTION_TO_FLOW)",
- p->pcap_cnt, s->id, s->action, p->alerts.alerts[i].flags);
+ p->pcap_cnt, s->id, s->action, det_ctx->alert_queue[i].flags);
}
}
/* set actions on packet */
- PacketApplySignatureActions(p, p->alerts.alerts[i].s, p->alerts.alerts[i].flags);
-
- if (PACKET_TEST_ACTION(p, ACTION_PASS)) {
- /* Ok, reset the alert cnt to end in the previous of pass
- * so we ignore the rest with less prio */
- p->alerts.cnt = i;
- break;
- }
+ PacketApplySignatureActions(p, s, det_ctx->alert_queue[i].flags);
}
/* Thresholding removes this alert */
if (res == 0 || res == 2 || (s->flags & SIG_FLAG_NOALERT)) {
- PacketAlertRemove(p, i);
+ /* we will not copy this to the AlertQueue */
+ } else if (p->alerts.cnt < packet_alert_max) {
+ p->alerts.alerts[p->alerts.cnt] = det_ctx->alert_queue[i];
+ SCLogDebug("Appending sid %" PRIu32 " alert to Packet::alerts at pos %u", s->id, i);
- if (p->alerts.cnt == 0)
+ if (PACKET_TEST_ACTION(p, ACTION_PASS)) {
+ /* Ok, reset the alert cnt to end in the previous of pass
+ * so we ignore the rest with less prio */
break;
- } else {
- i++;
+ }
+ p->alerts.cnt++;
}
+ i++;
}
/* At this point, we should have all the new alerts. Now check the tag