120 DetectRunInspectIPOnly(th_v,
de_ctx, det_ctx, pflow, p);
123 DetectRunGetRuleGroup(
de_ctx, p, pflow, &scratch);
126 if (scratch.
sgh == NULL) {
127 SCLogDebug(
"no sgh for this packet, nothing to match against");
132 DetectRunPrefilterPkt(th_v,
de_ctx, det_ctx, p, &scratch);
136 const uint8_t pkt_policy = DetectRulePacketRules(th_v,
de_ctx, det_ctx, p, pflow, &scratch);
152 if (p->
proto == IPPROTO_TCP) {
155 DetectRunAppendDefaultAccept(det_ctx, p);
167 DetectRunFrames(th_v,
de_ctx, det_ctx, p, pflow, &scratch);
175 DetectRunAppendDefaultAccept(det_ctx, p);
178 }
else if (p->
proto == IPPROTO_UDP) {
179 DetectRunFrames(th_v,
de_ctx, det_ctx, p, pflow, &scratch);
183 DetectRunTx(th_v,
de_ctx, det_ctx, p, pflow, &scratch);
192 DetectRunAppendDefaultAccept(det_ctx, p);
196 DetectRunPostRules(th_v,
de_ctx, det_ctx, p, pflow, &scratch);
198 DetectRunCleanup(det_ctx, p, pflow);
211 SCLogDebug(
"running match functions, sm %p", smd);
242 }
else if (p->
proto == 0) {
243 if (!(PacketIsIPv4(p) || PacketIsIPv6(p))) {
252 int proto = PacketGetIPProto(p);
253 if (
proto == IPPROTO_TCP) {
257 const uint16_t port = dir ? p->
dp : p->
sp;
262 SCLogDebug(
"TCP list %p, port %u, direction %s, sghport %p, sgh %p", list, port,
263 dir ?
"toserver" :
"toclient", sghport, sgh);
264 }
else if (
proto == IPPROTO_UDP) {
266 uint16_t port = dir ? p->
dp : p->
sp;
270 SCLogDebug(
"UDP list %p, port %u, direction %s, sghport %p, sgh %p", list, port,
271 dir ?
"toserver" :
"toclient", sghport, sgh);
286 while (final_cnt-- > 0) {
291 if (
likely(
id != previous_id)) {
308 DetectPostInspectFileFlagsUpdate(
Flow *f,
const SigGroupHead *sgh, uint8_t direction)
313 SCLogDebug(
"requesting disabling all file features for flow");
317 SCLogDebug(
"requesting disabling filestore for flow");
321 if (!(sgh->
flags & SIG_GROUP_HEAD_HAVEFILEMAGIC)) {
322 SCLogDebug(
"requesting disabling magic for flow");
327 SCLogDebug(
"requesting disabling md5 for flow");
331 SCLogDebug(
"requesting disabling sha1 for flow");
335 SCLogDebug(
"requesting disabling sha256 for flow");
339 SCLogDebug(
"requesting disabling filesize for flow");
343 if (flow_file_flags != 0) {
359 SCLogDebug(
"STREAMTCP_STREAM_FLAG_DISABLE_RAW ssn.client");
364 DetectPostInspectFileFlagsUpdate(pflow,
374 SCLogDebug(
"STREAMTCP_STREAM_FLAG_DISABLE_RAW ssn.server");
379 DetectPostInspectFileFlagsUpdate(pflow,
384 static inline void DetectRunGetRuleGroup(
392 bool use_flow_sgh =
false;
395 if (PacketGetIPProto(p) == pflow->
proto) {
399 SCLogDebug(
"sgh = pflow->sgh_toserver; => %p", sgh);
403 SCLogDebug(
"sgh = pflow->sgh_toclient; => %p", sgh);
409 if (!(use_flow_sgh)) {
422 DetectRunPostGetFirstRuleGroup(p, pflow, sgh);
442 SCLogDebug(
"testing against \"ip-only\" signatures");
461 static inline bool DetectRunInspectRuleHeader(
const Packet *p,
const Flow *f,
const Signature *s,
462 const uint32_t sflags,
const uint8_t s_proto_flags)
471 const bool fv = f->
flowvar != NULL;
473 SCLogDebug(
"skipping sig as the flow has no flowvars and sig "
474 "has SIG_FLAG_REQUIRE_FLOWVAR flag set.");
514 SCLogDebug(
"port-less protocol and sig needs ports");
520 if (PacketIsIPv4(p)) {
523 }
else if (PacketIsIPv6(p)) {
530 if (PacketIsIPv4(p)) {
533 }
else if (PacketIsIPv6(p)) {
545 static inline void DetectRunPrefilterPkt(
565 DetectPrefilterCopyDeDup(
de_ctx, det_ctx);
580 static bool IsOnlyTxInDirection(
Flow *f, uint64_t txid, uint8_t dir)
583 if (tx_cnt == txid + 1) {
587 if (tx_cnt == txid + 2) {
594 (dir == STREAM_TOCLIENT &&
603 static int SortHelper(
const void *a,
const void *b)
609 return sa->
num > sb->
num ? 1 : -1;
617 bool fw_verdict =
false;
627 (uint64_t)match_cnt);
638 bool skip_fw =
false;
639 uint32_t sflags, next_sflags = 0;
641 next_s = *match_array++;
642 next_sflags = next_s->
flags;
644 while (match_cnt--) {
646 bool break_out_of_packet_filter =
false;
647 uint8_t alert_flags = 0;
652 sflags = next_sflags;
654 next_s = *match_array++;
655 next_sflags = next_s->
flags;
667 }
else if (have_fw_rules) {
674 break_out_of_packet_filter =
true;
697 if (SigDsizePrefilter(p, s, sflags))
708 if (!DetectRunInspectRuleHeader(p, pflow, s, sflags, s_proto_flags)) {
719 DetectRunPostMatch(
tv, det_ctx, p, s);
737 if (pflow->
proto != IPPROTO_UDP) {
740 txd->guessed_applayer_logged++;
757 SCLogDebug(
"sig_array_len %u det_ctx->pmq.rule_id_array_cnt %u",
760 for (uint32_t x = 0; x < match_cnt; x++) {
761 *r++ = match_array[x];
762 SCLogDebug(
"appended %u", match_array[x]->
id);
769 if (
ts->app_inspect == NULL) {
775 qsort(replace, match_cnt,
sizeof(
Signature *), SortHelper);
781 uint32_t skipped = 0;
782 for (uint32_t x = 0; x < match_cnt; x++) {
784 if (last_sig == *
m) {
791 match_cnt -= skipped;
793 next_s = *match_array++;
794 next_sflags = next_s->
flags;
825 break_out_of_packet_filter =
true;
830 break_out_of_packet_filter =
true;
841 break_out_of_packet_filter =
true;
845 DetectVarProcessList(det_ctx, pflow, p);
846 DetectReplaceFree(det_ctx);
850 if (break_out_of_packet_filter)
878 uint8_t flow_flags = 0;
879 bool app_decoder_events =
false;
898 det_ctx->pkt_stream_add_cnt++;
907 flow_flags = STREAM_TOSERVER;
910 flow_flags = STREAM_TOCLIENT;
916 flow_flags |= STREAM_EOF;
947 (p->
proto == IPPROTO_UDP) ||
952 alproto = FlowGetAppProtocol(pflow);
959 SCLogDebug(
"packet doesn't have established flag set (proto %d)", p->
proto);
970 static inline void DetectRunPostRules(
1000 SCLogDebug(
"packet %" PRIu64
": droppit as no ACCEPT set %02x (pkt %s)", p->
pcap_cnt,
1012 if (pflow != NULL) {
1029 FatalError(
"failed to allocate %" PRIu64
" bytes",
1033 SCLogDebug(
"array initialized to %u elements (%"PRIu64
" bytes)",
1045 const uint32_t need)
1056 uint32_t new_size = needed;
1059 FatalError(
"failed to expand to %" PRIu64
" bytes",
1065 SCLogDebug(
"array expanded from %u to %u elements (%"PRIu64
" bytes -> %"PRIu64
" bytes)",
1078 DetectRunTxSortHelper(
const void *a,
const void *b)
1082 if (s1->
id == s0->
id) {
1089 return s0->
id > s1->
id ? 1 : -1;
1093 #define TRACE_SID_TXS(sid,txs,...) \
1095 char _trace_buf[2048]; \
1096 snprintf(_trace_buf, sizeof(_trace_buf), __VA_ARGS__); \
1097 SCLogNotice("%p/%"PRIu64"/%u: %s", txs->tx_ptr, txs->tx_id, sid, _trace_buf); \
1100 #define TRACE_SID_TXS(sid,txs,...)
1109 tx_ptr = SCDoH2GetDnsTx(tx_ptr, flow_flags);
1114 }
else if (engine_alproto != alproto && engine_alproto !=
ALPROTO_UNKNOWN) {
1138 const uint8_t in_flow_flags,
1142 uint32_t *stored_flags,
1146 const uint8_t flow_flags = in_flow_flags;
1147 const int direction = (flow_flags & STREAM_TOSERVER) ? 0 : 1;
1148 uint32_t inspect_flags = stored_flags ? *stored_flags : 0;
1149 int total_matches = 0;
1150 uint16_t file_no_match = 0;
1151 bool retval =
false;
1152 bool mpm_before_progress =
false;
1153 bool mpm_in_progress =
false;
1155 TRACE_SID_TXS(s->
id, tx,
"starting %s", direction ?
"toclient" :
"toserver");
1158 if (
likely(stored_flags == NULL)) {
1177 TRACE_SID_TXS(s->
id, tx,
"engine %p inspect_flags %x", engine, inspect_flags);
1180 if (!(inspect_flags &
BIT_U32(engine->
id)) &&
1184 if (tx_ptr == NULL) {
1188 engine = engine->
next;
1198 SCLogDebug(
"tx progress %d < engine progress %d",
1205 "engine->mpm: t->tx_progress %u > engine->progress %u, so set "
1206 "mpm_before_progress",
1208 mpm_before_progress =
true;
1211 "engine->mpm: t->tx_progress %u == engine->progress %u, so set "
1214 mpm_in_progress =
true;
1218 uint8_t engine_flags = flow_flags;
1219 if (direction != engine->
dir) {
1220 engine_flags = flow_flags ^ (STREAM_TOCLIENT | STREAM_TOSERVER);
1226 TRACE_SID_TXS(s->
id, tx,
"stream skipped, stored result %d used instead", match);
1231 mpm_before_progress =
true;
1245 de_ctx, det_ctx, engine, s, f, engine_flags, alstate, tx_ptr, tx->
tx_id);
1250 TRACE_SID_TXS(s->
id, tx,
"stream ran, store result %d for next tx (if any)", match);
1255 engine = engine->
next;
1262 engine = engine->
next;
1274 if (engine->
mpm && mpm_before_progress) {
1280 direction != engine->
dir) {
1284 if (direction == 0 && engine->
next == NULL) {
1288 engine = engine->
next;
1292 engine = engine->
next;
1293 }
while (engine != NULL);
1294 TRACE_SID_TXS(s->
id, tx,
"inspect_flags %x, total_matches %u, engine %p",
1295 inspect_flags, total_matches, engine);
1297 if (engine == NULL && total_matches) {
1304 *stored_flags = inspect_flags;
1305 TRACE_SID_TXS(s->
id, tx,
"continue inspect flags %08x", inspect_flags);
1312 if (file_no_match) {
1323 inspect_flags, flow_flags, file_no_match);
1327 "mpm won't trigger for it anymore");
1331 "we may have to revisit anyway");
1333 inspect_flags, flow_flags, file_no_match);
1337 "mpm will revisit it");
1338 }
else if (inspect_flags != 0 || file_no_match != 0) {
1341 inspect_flags, flow_flags, file_no_match);
1350 NULL, 0, NULL, NULL, 0, 0, 0, 0, \
1358 const uint64_t tx_id,
void *tx_ptr,
const int tx_end_state,
const uint8_t flow_flags)
1366 bool updated = (flow_flags & STREAM_TOSERVER) ? txd->updated_ts : txd->updated_tc;
1367 if (!updated && tx_progress < tx_end_state && ((flow_flags & STREAM_EOF) == 0)) {
1371 const uint8_t inspected_flag =
1373 if (
unlikely(txd->flags & inspected_flag)) {
1374 SCLogDebug(
"%" PRIu64
" tx already fully inspected for %s. Flags %02x", tx_id,
1375 flow_flags & STREAM_TOSERVER ?
"toserver" :
"toclient", txd->flags);
1381 if (
unlikely(txd->flags & skip_flag)) {
1382 SCLogDebug(
"%" PRIu64
" tx should not be inspected in direction %s. Flags %02x", tx_id,
1383 flow_flags & STREAM_TOSERVER ?
"toserver" :
"toclient", txd->flags);
1388 const uint8_t detect_progress =
1389 (flow_flags & STREAM_TOSERVER) ? txd->detect_progress_ts : txd->detect_progress_tc;
1391 const int dir_int = (flow_flags & STREAM_TOSERVER) ? 0 : 1;
1394 tx_de_state ? &tx_de_state->
dir_state[dir_int] : NULL;
1399 .de_state = tx_dir_state,
1400 .detect_progress = detect_progress,
1401 .detect_progress_orig = detect_progress,
1402 .tx_progress = tx_progress,
1403 .tx_end_state = tx_end_state,
1408 static inline void StoreDetectProgress(
1412 if (
likely(txd != NULL)) {
1413 if (flow_flags & STREAM_TOSERVER) {
1414 txd->detect_progress_ts = progress;
1416 txd->detect_progress_tc = progress;
1423 static inline void RuleMatchCandidateMergeStateRules(
1441 uint32_t j = *array_idx;
1450 uint32_t k = *array_idx;
1472 if (s->
num <= s0->
id) {
1517 bool *skip_fw_hook,
const uint8_t skip_before_progress,
bool *last_for_progress,
1518 bool *fw_next_progress_missing)
1528 if (can_idx + 1 < can_size) {
1534 SCLogDebug(
"peek: next sid progress %u != current progress %u, so current "
1535 "is last for progress",
1537 *last_for_progress =
true;
1540 SCLogDebug(
"peek: missing progress, so we'll drop that unless we get a "
1541 "sweeping accept first");
1542 *fw_next_progress_missing =
true;
1546 SCLogDebug(
"peek: next sid not a fw rule, so current is last for progress");
1547 *last_for_progress =
true;
1550 SCLogDebug(
"peek: no peek beyond last rule");
1552 SCLogDebug(
"peek: there are no rules to allow the state after this rule");
1553 *fw_next_progress_missing =
true;
1557 if ((*skip_fw_hook) ==
true) {
1561 *skip_fw_hook =
false;
1593 static inline bool ApplyAcceptToPacket(
1607 if (total_txs == tx->
tx_id + 1) {
1615 if ((total_txs == tx->
tx_id + 1) &&
1630 const uint8_t flow_flags = scratch->
flow_flags;
1632 void *
const alstate = f->
alstate;
1633 const uint8_t ipproto = f->
proto;
1643 uint32_t fw_verdicted = 0;
1644 uint32_t tx_inspected = 0;
1650 AppLayerGetTxIterTuple ires = IterFunc(ipproto, alproto, alstate, tx_id_min, total_txs, &state);
1651 if (ires.tx_ptr == NULL)
1655 GetDetectTx(ipproto, alproto, ires.tx_id, ires.tx_ptr, tx_end_state, flow_flags);
1657 SCLogDebug(
"%p/%"PRIu64
" no transaction to inspect",
1663 tx_id_min = tx.
tx_id + 1;
1668 bool do_sort =
false;
1669 uint32_t array_idx = 0;
1679 SCLogDebug(
"%p/%"PRIu64
" rules added from prefilter: %u candidates",
1683 if (!(RuleMatchCandidateTxArrayHasSpace(det_ctx, total_rules))) {
1684 RuleMatchCandidateTxArrayExpand(det_ctx, total_rules);
1698 if (!(RuleMatchCandidateTxArrayHasSpace(det_ctx, total_rules))) {
1699 RuleMatchCandidateTxArrayExpand(det_ctx, total_rules);
1705 uint32_t x = array_idx;
1707 RuleMatchCandidateMergeStateRules(det_ctx, &array_idx);
1711 const uint32_t old = array_idx;
1716 if (have_new_file) {
1717 SCLogDebug(
"%p/%"PRIu64
" destate: need to consider new file",
1724 for (; tx_store != NULL; tx_store = tx_store->
next) {
1730 store_cnt++, state_cnt++)
1747 do_sort |= (old && old != array_idx);
1753 DetectRunTxSortHelper);
1765 for (uint32_t i = 0; i < array_idx; i++) {
1771 bool skip_fw_hook =
false;
1772 uint8_t skip_before_progress = 0;
1773 bool fw_next_progress_missing =
false;
1781 if (total_txs == tx.
tx_id + 1) {
1782 DetectRunAppendDefaultAccept(det_ctx, p);
1788 bool tx_fw_verdict =
false;
1790 for (uint32_t i = 0; i < array_idx; i++) {
1794 bool break_out_of_app_filter =
false;
1797 flow_flags & STREAM_TOSERVER ?
"toserver" :
"toclient", tx.
tx_progress,
1805 while ((i + 1) < array_idx &&
1807 SCLogDebug(
"%p/%" PRIu64
" inspecting SKIP NEXT: sid %u (%u), flags %08x",
1816 if (!tx_fw_verdict) {
1817 const bool accept_tx_applies_to_packet = total_txs == tx.
tx_id + 1;
1818 if (accept_tx_applies_to_packet) {
1819 SCLogDebug(
"accept:(tx|hook): should be applied to the packet");
1820 DetectRunAppendDefaultAccept(det_ctx, p);
1823 tx_fw_verdict =
true;
1826 SCLogDebug(
"APP_LAYER_TX_ACCEPT, so skip rule");
1833 SCLogDebug(
"%p/%"PRIu64
" inspecting: sid %u (%u), flags %08x",
1836 if (inspect_flags) {
1838 SCLogDebug(
"%p/%"PRIu64
" inspecting: sid %u (%u), flags %08x ALREADY COMPLETE",
1844 if (inspect_flags) {
1852 bool last_for_progress =
false;
1853 if (have_fw_rules) {
1854 int fw_r = DetectRunTxCheckFirewallPolicy(det_ctx, p, f, &tx, s, i, array_idx,
1855 &skip_fw_hook, skip_before_progress, &last_for_progress,
1856 &fw_next_progress_missing);
1865 const int r = DetectRunTxInspectRule(
tv,
de_ctx, det_ctx, p, f, flow_flags,
1866 alstate, &tx, s, inspect_flags, can, scratch);
1869 DetectRunPostMatch(
tv, det_ctx, p, s);
1874 const bool fw_accept_to_packet = ApplyAcceptToPacket(total_txs, &tx, s);
1877 if (fw_accept_to_packet) {
1878 SCLogDebug(
"accept:(tx|hook): should be applied to the packet");
1886 tx_fw_verdict =
true;
1892 skip_fw_hook =
true;
1897 if (fw_next_progress_missing) {
1899 flow_flags & STREAM_TOSERVER ?
"toserver" :
"toclient");
1902 break_out_of_app_filter =
true;
1906 skip_fw_hook =
true;
1907 skip_before_progress = (uint8_t)tx_end_state + 1;
1908 SCLogDebug(
"accept:tx applied, skip_fw_hook, skip_before_progress %u",
1909 skip_before_progress);
1911 break_out_of_app_filter =
true;
1913 break_out_of_app_filter =
true;
1916 }
else if (last_for_progress) {
1917 SCLogDebug(
"sid %u: not a match: %s rule, last_for_progress %s", s->
id,
1922 flow_flags & STREAM_TOSERVER ?
"toserver" :
"toclient");
1927 break_out_of_app_filter =
true;
1928 tx_fw_verdict =
true;
1931 DetectVarProcessList(det_ctx, p->
flow, p);
1940 uint32_t prev_array_idx = array_idx;
1943 if (
ts->app_inspect != NULL) {
1951 SCLogDebug(
"%p/%" PRIu64
" rule %u (%u) added from 'post match' prefilter",
1955 SCLogDebug(
"%p/%" PRIu64
" rules added from 'post match' prefilter: %u", tx.
tx_ptr,
1956 tx.
tx_id, array_idx - prev_array_idx);
1957 if (prev_array_idx != array_idx) {
1960 DetectRunTxSortHelper);
1966 if (break_out_of_app_filter)
1981 flow_flags & STREAM_TOSERVER ?
"toserver" :
"toclient");
1982 const uint8_t inspected_flag = (flow_flags & STREAM_TOSERVER)
1986 SCLogDebug(
"%p/%" PRIu64
" tx is done for direction %s. Progress %02x", tx.
tx_ptr,
1987 tx.
tx_id, flow_flags & STREAM_TOSERVER ?
"toserver" :
"toclient",
2010 SCLogDebug(
"packet %" PRIu64
": tx_inspected %u fw_verdicted %u", p->
pcap_cnt, tx_inspected,
2012 if (tx_inspected && have_fw_rules && tx_inspected != fw_verdicted) {
2014 flow_flags & STREAM_TOSERVER ?
"toserver" :
"toclient");
2020 if (tx_inspected == 0 && fw_verdicted == 0 && have_fw_rules) {
2021 DetectRunAppendDefaultAccept(det_ctx, p);
2036 SCLogDebug(
"pcap_cnt %" PRIu64
": %s: skip frame inspection for TCP w/o APP UPDATE",
2041 if (frames_container == NULL) {
2046 frames = &frames_container->
toserver;
2048 frames = &frames_container->
toclient;
2051 for (uint32_t idx = 0; idx < frames->
cnt; idx++) {
2054 if (frame == NULL) {
2059 uint32_t array_idx = 0;
2067 SCLogDebug(
"%p/%" PRIi64
" rules added from prefilter: %u candidates", frame, frame->
id,
2072 if (!(RuleMatchCandidateTxArrayHasSpace(
2073 det_ctx, total_rules))) {
2074 RuleMatchCandidateTxArrayExpand(det_ctx, total_rules);
2089 uint32_t x = array_idx;
2100 SCLogDebug(
"%p/%" PRIi64
" rule %u (%u) added from 'match' list", frame, frame->
id,
2104 SCLogDebug(
"%p/%" PRIi64
" rules added from 'match' list: %u", frame, frame->
id,
2109 for (uint32_t i = 0; i < array_idx; i++) {
2116 while ((i + 1) < array_idx &&
2120 SCLogDebug(
"%p/%" PRIi64
" inspecting: sid %u (%u)", frame, frame->
id, s->
id, s->
num);
2123 SCLogDebug(
"%p/%" PRIi64
" Start sid %u", frame, frame->
id, s->
id);
2127 bool r = DetectRunInspectRuleHeader(p, f, s, s->
flags, s->
proto.
flags);
2132 DetectRunPostMatch(
tv, det_ctx, p, s);
2137 "%p/%" PRIi64
" sig %u (%u) matched", frame, frame->
id, s->
id, s->
num);
2144 DetectVarProcessList(det_ctx, p->
flow, p);
2155 "frame->inspect_progress: %" PRIu64
" -> not updated", frame->
inspect_progress);
2158 SCLogDebug(
"%p/%" PRIi64
" rules inspected, running cleanup", frame, frame->
id);
2209 SCLogDebug(
"p->pcap %"PRIu64
": no detection on packet, "
2210 "PKT_NOPACKET_INSPECTION is set", p->
pcap_cnt);
2246 if (det_ctx == NULL) {
2247 printf(
"ERROR: Detect has no thread ctx\n");
2253 SCLogDebug(
"Detect Engine using new det_ctx - %p",
2264 if (tenant_id > 0 && tenant_id < det_ctx->mt_det_ctxs_cnt) {
2267 if (det_ctx == NULL)
2275 SCLogDebug(
"MT de_ctx %p det_ctx %p (tenant %u)",
de_ctx, det_ctx, tenant_id);
2286 DetectFlow(
tv,
de_ctx, det_ctx, p);
2288 DetectNoFlow(
tv,
de_ctx, det_ctx, p);
2291 #ifdef PROFILE_RULES
2294 gettimeofday(&
ts, NULL);
2295 if (
ts.tv_sec != det_ctx->rule_perf_last_sync) {
2296 SCProfilingRuleThreatAggregate(det_ctx);
2297 det_ctx->rule_perf_last_sync =
ts.tv_sec;
2311 DetectPostInspectFileFlagsUpdate(f, NULL , STREAM_TOSERVER);
2312 DetectPostInspectFileFlagsUpdate(f, NULL , STREAM_TOCLIENT);
2323 DetectFlow(
tv,
de_ctx, det_ctx, p);
2325 DetectNoFlow(
tv,
de_ctx, det_ctx, p);