/** * \brief Handle a packet and check if needs a threshold logic * * \param de_ctx Detection Context * \param sig Signature pointer * \param p Packet structure * * \retval 1 alert is not suppressed * \retval 0 alert is suppressed */ static int PacketAlertHandle(DetectEngineCtx *de_ctx, DetectEngineThreadCtx *det_ctx, Signature *s, Packet *p, uint16_t pos) { SCEnter(); int ret = 1; DetectThresholdData *td = NULL; SigMatch *sm = NULL; if (!(PKT_IS_IPV4(p) || PKT_IS_IPV6(p))) { SCReturnInt(1); } do { td = SigGetThresholdTypeIter(s, p, &sm); if (td != NULL) { SCLogDebug("td %p", td); ret = PacketAlertThreshold(de_ctx, det_ctx, td, p, s); if (ret == 0) { /* It doesn't match threshold, remove it */ PacketAlertRemove(p, pos); break; } } } while (sm != NULL); SCReturnInt(ret); }
/** * \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 * the threshold, and those that match after a signature with the action "pass". * The array is sorted by action priority/order * \param de_ctx detection engine context * \param det_ctx detection engine thread context * \param p pointer to the packet */ void PacketAlertFinalize(DetectEngineCtx *de_ctx, DetectEngineThreadCtx *det_ctx, Packet *p) { SCEnter(); int i = 0; Signature *s = NULL; SigMatch *sm = NULL; while (i < p->alerts.cnt) { SCLogDebug("Sig->num: %"PRIu16, p->alerts.alerts[i].num); s = de_ctx->sig_array[p->alerts.alerts[i].num]; int res = PacketAlertHandle(de_ctx, det_ctx, s, p, 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 */ sm = s->sm_lists[DETECT_SM_LIST_TMATCH]; while (sm) { /* tags are set only for alerts */ sigmatch_table[sm->type].Match(NULL, det_ctx, p, s, sm); sm = sm->next; } if (s->flags & SIG_FLAG_IPONLY) { if (((p->flowflags & FLOW_PKT_TOSERVER) && !(p->flowflags & FLOW_PKT_TOSERVER_IPONLY_SET)) || ((p->flowflags & FLOW_PKT_TOCLIENT) && !(p->flowflags & FLOW_PKT_TOCLIENT_IPONLY_SET))) { SCLogDebug("testing against \"ip-only\" signatures"); if (p->flow != NULL) { /* Update flow flags for iponly */ FLOWLOCK_WRLOCK(p->flow); FlowSetIPOnlyFlagNoLock(p->flow, p->flowflags & FLOW_PKT_TOSERVER ? 1 : 0); if (s->action & ACTION_DROP) p->flow->flags |= FLOW_ACTION_DROP; if (s->action & ACTION_REJECT) p->flow->flags |= FLOW_ACTION_DROP; if (s->action & ACTION_REJECT_DST) p->flow->flags |= FLOW_ACTION_DROP; if (s->action & ACTION_REJECT_BOTH) p->flow->flags |= FLOW_ACTION_DROP; if (s->action & ACTION_PASS) { FlowSetNoPacketInspectionFlag(p->flow); } FLOWLOCK_UNLOCK(p->flow); } } } /* set verdict on packet */ p->action |= p->alerts.alerts[i].action; if (p->action & 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; /* if the signature wants to drop, check if the * PACKET_ALERT_FLAG_DROP_FLOW flag is set. */ } else if ((p->action & ACTION_DROP) && ((p->alerts.alerts[i].flags & PACKET_ALERT_FLAG_DROP_FLOW) || (s->flags & SIG_FLAG_APPLAYER)) && p->flow != NULL) { FLOWLOCK_WRLOCK(p->flow); /* This will apply only on IPS mode (check StreamTcpPacket) */ p->flow->flags |= FLOW_ACTION_DROP; FLOWLOCK_UNLOCK(p->flow); } } /* Thresholding removes this alert */ if (res == 0 || res == 2) { PacketAlertRemove(p, i); if (p->alerts.cnt == 0) break; } else { i++; } } /* At this point, we should have all the new alerts. Now check the tag * keyword context for sessions and hosts */ TagHandlePacket(de_ctx, det_ctx, p); }