pub updated_tc: bool,
pub updated_ts: bool,
+ flags: u8,
+
/// logger flags for tx logging api
logged: LoggerFlags,
/// not using application layer keywords
pub guessed_applayer_logged: u8,
- /// detection engine flags for use by detection engine
- detect_flags_ts: u64,
- detect_flags_tc: u64,
+ /// detection engine progress tracking for use by detection engine
+ /// Reflects the "progress" of prefilter engines into this TX, where
+ /// the value is offset by 1. So if for progress state 0 the engines
+ /// are done, the value here will be 1. So a value of 0 means, no
+ /// progress tracked yet.
+ ///
+ detect_progress_ts: u8,
+ detect_progress_tc: u8,
de_state: *mut DetectEngineState,
pub events: *mut core::AppLayerDecoderEvents,
guessed_applayer_logged: 0,
updated_tc: true,
updated_ts: true,
- detect_flags_ts: 0,
- detect_flags_tc: 0,
+ flags: 0,
+ detect_progress_ts: 0,
+ detect_progress_tc: 0,
de_state: std::ptr::null_mut(),
events: std::ptr::null_mut(),
}
/// Create new AppLayerTxData for a transaction in a single
/// direction.
pub fn for_direction(direction: Direction) -> Self {
- let (detect_flags_ts, detect_flags_tc, updated_ts, updated_tc) = match direction {
- Direction::ToServer => (0, APP_LAYER_TX_SKIP_INSPECT_FLAG, true, false),
- Direction::ToClient => (APP_LAYER_TX_SKIP_INSPECT_FLAG, 0, false, true),
+ let (flags, updated_ts, updated_tc) = match direction {
+ Direction::ToServer => (APP_LAYER_TX_SKIP_INSPECT_TC, true, false),
+ Direction::ToClient => (APP_LAYER_TX_SKIP_INSPECT_TS, false, true),
};
Self {
config: AppLayerTxConfig::new(),
guessed_applayer_logged: 0,
updated_tc,
updated_ts,
- detect_flags_ts,
- detect_flags_tc,
+ detect_progress_ts: 0,
+ detect_progress_tc: 0,
+ flags,
de_state: std::ptr::null_mut(),
events: std::ptr::null_mut(),
}
pub const APP_LAYER_PARSER_OPT_ACCEPT_GAPS: u32 = BIT_U32!(0);
-pub const APP_LAYER_TX_SKIP_INSPECT_FLAG: u64 = BIT_U64!(62);
+pub const APP_LAYER_TX_SKIP_INSPECT_TS: u8 = BIT_U8!(0);
+pub const APP_LAYER_TX_SKIP_INSPECT_TC: u8 = BIT_U8!(1);
+pub const _APP_LAYER_TX_INSPECTED_TS: u8 = BIT_U8!(2);
+pub const _APP_LAYER_TX_INSPECTED_TC: u8 = BIT_U8!(3);
/// cbindgen:ignore
extern {
pub const IPPROTO_TCP : u8 = 6;
pub const IPPROTO_UDP : u8 = 17;
-/*
+
macro_rules!BIT_U8 {
($x:expr) => (1 << $x);
}
-*/
+
macro_rules!BIT_U16 {
($x:expr) => (1 << $x);
}
tx->tx_num = dnp3->transaction_max;
tx->is_request = request;
if (tx->is_request) {
- tx->tx_data.detect_flags_tc |= APP_LAYER_TX_SKIP_INSPECT_FLAG;
+ tx->tx_data.flags = APP_LAYER_TX_SKIP_INSPECT_TC;
} else {
- tx->tx_data.detect_flags_ts |= APP_LAYER_TX_SKIP_INSPECT_FLAG;
+ tx->tx_data.flags = APP_LAYER_TX_SKIP_INSPECT_TS;
}
TAILQ_INIT(&tx->objects);
TAILQ_INSERT_TAIL(&dnp3->tx_list, tx, next);
SCReturnCT(0ULL, "uint64_t");
}
-inline uint64_t AppLayerParserGetTxDetectFlags(AppLayerTxData *txd, const uint8_t dir)
+inline uint8_t AppLayerParserGetTxDetectProgress(AppLayerTxData *txd, const uint8_t dir)
{
- uint64_t detect_flags =
- (dir & STREAM_TOSERVER) ? txd->detect_flags_ts : txd->detect_flags_tc;
- return detect_flags;
-}
-
-static inline void SetTxDetectFlags(AppLayerTxData *txd, const uint8_t dir, const uint64_t detect_flags)
-{
- if (dir & STREAM_TOSERVER) {
- txd->detect_flags_ts = detect_flags;
- } else {
- txd->detect_flags_tc = detect_flags;
- }
+ uint8_t p = (dir & STREAM_TOSERVER) ? txd->detect_progress_ts : txd->detect_progress_tc;
+ return p;
}
static inline uint32_t GetTxLogged(AppLayerTxData *txd)
AppLayerTxData *txd = AppLayerParserGetTxData(ipproto, alproto, tx);
if (txd && tag_txs_as_inspected) {
- uint64_t detect_flags = AppLayerParserGetTxDetectFlags(txd, flags);
- if ((detect_flags & APP_LAYER_TX_INSPECTED_FLAG) == 0) {
- detect_flags |= APP_LAYER_TX_INSPECTED_FLAG;
- SetTxDetectFlags(txd, flags, detect_flags);
- SCLogDebug("%p/%"PRIu64" in-order tx is done for direction %s. Flag %016"PRIx64,
- tx, idx, flags & STREAM_TOSERVER ? "toserver" : "toclient", detect_flags);
+ const uint8_t inspected_flag = (flags & STREAM_TOSERVER) ? APP_LAYER_TX_INSPECTED_TS
+ : APP_LAYER_TX_INSPECTED_TC;
+ if (txd->flags & inspected_flag) {
+ txd->flags |= inspected_flag;
+ SCLogDebug("%p/%" PRIu64 " in-order tx is done for direction %s. Flags %02x", tx,
+ idx, flags & STREAM_TOSERVER ? "toserver" : "toclient", txd->flags);
}
}
idx++;
/* txd can be NULL for HTTP sessions where the user data alloc failed */
AppLayerTxData *txd = AppLayerParserGetTxData(ipproto, alproto, tx);
if (likely(txd)) {
- uint64_t detect_flags = AppLayerParserGetTxDetectFlags(txd, flags);
- if ((detect_flags & APP_LAYER_TX_INSPECTED_FLAG) == 0) {
- detect_flags |= APP_LAYER_TX_INSPECTED_FLAG;
- SetTxDetectFlags(txd, flags, detect_flags);
- SCLogDebug("%p/%"PRIu64" out of order tx is done for direction %s. Flag %016"PRIx64,
- tx, idx, flags & STREAM_TOSERVER ? "toserver" : "toclient", detect_flags);
+ const uint8_t inspected_flag = (flags & STREAM_TOSERVER)
+ ? APP_LAYER_TX_INSPECTED_TS
+ : APP_LAYER_TX_INSPECTED_TC;
+ if (txd->flags & inspected_flag) {
+ txd->flags |= inspected_flag;
+ SCLogDebug("%p/%" PRIu64 " out of order tx is done for direction %s. Flag %02x",
+ tx, idx, flags & STREAM_TOSERVER ? "toserver" : "toclient", txd->flags);
SCLogDebug("%p/%"PRIu64" out of order tx. Update inspect_id? %"PRIu64,
tx, idx, pstate->inspect_id[direction]);
if (txd && has_tx_detect_flags) {
if (!IS_DISRUPTED(ts_disrupt_flags) &&
(f->sgh_toserver != NULL || (f->flags & FLOW_SGH_TOSERVER) == 0)) {
- uint64_t detect_flags_ts = AppLayerParserGetTxDetectFlags(txd, STREAM_TOSERVER);
- if (!(detect_flags_ts &
- (APP_LAYER_TX_INSPECTED_FLAG | APP_LAYER_TX_SKIP_INSPECT_FLAG))) {
- SCLogDebug("%p/%" PRIu64 " skipping: TS inspect not done: ts:%" PRIx64, tx, i,
- detect_flags_ts);
+ if ((txd->flags & (APP_LAYER_TX_INSPECTED_TS | APP_LAYER_TX_SKIP_INSPECT_TS)) ==
+ 0) {
+ SCLogDebug("%p/%" PRIu64 " skipping: TS inspect not done: ts:%02x", tx, i,
+ txd->flags);
tx_skipped = true;
}
}
if (!IS_DISRUPTED(tc_disrupt_flags) &&
(f->sgh_toclient != NULL || (f->flags & FLOW_SGH_TOCLIENT) == 0)) {
- uint64_t detect_flags_tc = AppLayerParserGetTxDetectFlags(txd, STREAM_TOCLIENT);
- if (!(detect_flags_tc &
- (APP_LAYER_TX_INSPECTED_FLAG | APP_LAYER_TX_SKIP_INSPECT_FLAG))) {
- SCLogDebug("%p/%" PRIu64 " skipping: TC inspect not done: ts:%" PRIx64, tx, i,
- detect_flags_tc);
+ if ((txd->flags & (APP_LAYER_TX_INSPECTED_TC | APP_LAYER_TX_SKIP_INSPECT_TC)) ==
+ 0) {
+ SCLogDebug("%p/%" PRIu64 " skipping: TC inspect not done: ts:%02x", tx, i,
+ txd->flags);
tx_skipped = true;
}
}
#define APP_LAYER_PARSER_INT_STREAM_DEPTH_SET BIT_U32(0)
-/* applies to DetectFlags uint64_t field */
-
-/** reserved for future use */
-#define APP_LAYER_TX_RESERVED1_FLAG BIT_U64(48)
-#define APP_LAYER_TX_RESERVED2_FLAG BIT_U64(49)
-#define APP_LAYER_TX_RESERVED3_FLAG BIT_U64(50)
-#define APP_LAYER_TX_RESERVED4_FLAG BIT_U64(51)
-#define APP_LAYER_TX_RESERVED5_FLAG BIT_U64(52)
-#define APP_LAYER_TX_RESERVED6_FLAG BIT_U64(53)
-#define APP_LAYER_TX_RESERVED7_FLAG BIT_U64(54)
-#define APP_LAYER_TX_RESERVED8_FLAG BIT_U64(55)
-#define APP_LAYER_TX_RESERVED9_FLAG BIT_U64(56)
-#define APP_LAYER_TX_RESERVED10_FLAG BIT_U64(57)
-#define APP_LAYER_TX_RESERVED11_FLAG BIT_U64(58)
-#define APP_LAYER_TX_RESERVED12_FLAG BIT_U64(59)
-#define APP_LAYER_TX_RESERVED13_FLAG BIT_U64(60)
-#define APP_LAYER_TX_RESERVED14_FLAG BIT_U64(61)
-
-#define APP_LAYER_TX_RESERVED_FLAGS \
- (APP_LAYER_TX_RESERVED1_FLAG | APP_LAYER_TX_RESERVED2_FLAG | APP_LAYER_TX_RESERVED3_FLAG | \
- APP_LAYER_TX_RESERVED4_FLAG | APP_LAYER_TX_RESERVED5_FLAG | \
- APP_LAYER_TX_RESERVED6_FLAG | APP_LAYER_TX_RESERVED7_FLAG | \
- APP_LAYER_TX_RESERVED8_FLAG | APP_LAYER_TX_RESERVED9_FLAG | \
- APP_LAYER_TX_RESERVED10_FLAG | APP_LAYER_TX_RESERVED11_FLAG | \
- APP_LAYER_TX_RESERVED12_FLAG | APP_LAYER_TX_RESERVED13_FLAG | \
- APP_LAYER_TX_RESERVED14_FLAG)
+/* for use with the detect_progress_ts|detect_progress_tc fields */
/** should inspection be skipped in that direction */
-#define APP_LAYER_TX_SKIP_INSPECT_FLAG BIT_U64(62)
+#define APP_LAYER_TX_SKIP_INSPECT_TS BIT_U8(0)
+#define APP_LAYER_TX_SKIP_INSPECT_TC BIT_U8(1)
/** is tx fully inspected? */
-#define APP_LAYER_TX_INSPECTED_FLAG BIT_U64(63)
-/** other 63 bits are for tracking which prefilter engine is already
- * completely inspected */
-#define APP_LAYER_TX_PREFILTER_MASK ~(APP_LAYER_TX_INSPECTED_FLAG | APP_LAYER_TX_RESERVED_FLAGS)
+#define APP_LAYER_TX_INSPECTED_TS BIT_U8(2)
+#define APP_LAYER_TX_INSPECTED_TC BIT_U8(3)
/** parser has successfully processed in the input, and has consumed
* all of it. */
bool AppLayerParserSupportsFiles(uint8_t ipproto, AppProto alproto);
AppLayerTxData *AppLayerParserGetTxData(uint8_t ipproto, AppProto alproto, void *tx);
-uint64_t AppLayerParserGetTxDetectFlags(AppLayerTxData *txd, const uint8_t dir);
+uint8_t AppLayerParserGetTxDetectProgress(AppLayerTxData *txd, const uint8_t dir);
AppLayerStateData *AppLayerParserGetStateData(uint8_t ipproto, AppProto alproto, void *state);
void AppLayerParserApplyTxConfig(uint8_t ipproto, AppProto alproto,
void *state, void *tx, enum ConfigAction mode, AppLayerTxConfig);
SCLogDebug("tx %p txd %p: log_flags %x", tx, txd, txd->config.log_flags);
txd->config.log_flags |= BIT_U8(config->type);
- uint64_t unidir = ((AppLayerParserGetTxDetectFlags(txd, STREAM_TOSERVER) |
- AppLayerParserGetTxDetectFlags(txd, STREAM_TOCLIENT)) &
- APP_LAYER_TX_SKIP_INSPECT_FLAG) != 0;
+ const bool unidir =
+ (txd->flags & (APP_LAYER_TX_SKIP_INSPECT_TS | APP_LAYER_TX_SKIP_INSPECT_TC)) !=
+ 0;
if (unidir) {
SCLogDebug("handle unidir tx");
AppLayerTxConfig req;
/* reset rule store */
det_ctx->pmq.rule_id_array_cnt = 0;
- SCLogDebug("packet %" PRIu64 " tx %p progress %d tx->prefilter_flags %" PRIx64, p->pcap_cnt,
- tx->tx_ptr, tx->tx_progress, tx->prefilter_flags);
+ SCLogDebug("packet %" PRIu64 " tx %p progress %d tx->detect_progress %02x", p->pcap_cnt,
+ tx->tx_ptr, tx->tx_progress, tx->detect_progress);
PrefilterEngine *engine = sgh->tx_engines;
do {
if (engine->ctx.tx_min_progress > tx->tx_progress)
break;
if (tx->tx_progress > engine->ctx.tx_min_progress) {
- if (tx->prefilter_flags & BIT_U64(engine->ctx.tx_min_progress)) {
+ /* if state value is at or beyond engine state, we can skip it. It means we ran at
+ * least once already. */
+ if (tx->detect_progress > engine->ctx.tx_min_progress) {
+ SCLogDebug("tx already marked progress as beyond engine: %u > %u",
+ tx->detect_progress, engine->ctx.tx_min_progress);
goto next;
}
}
PREFILTER_PROFILING_END(det_ctx, engine->gid);
if (tx->tx_progress > engine->ctx.tx_min_progress && engine->is_last_for_progress) {
- tx->prefilter_flags |= BIT_U64(engine->ctx.tx_min_progress);
+ /* track with an offset of one, so that tx->progress 0 complete is tracked
+ * as 1, progress 1 as 2, etc. This is to allow 0 to mean: nothing tracked, even
+ * though a parser may use 0 as a valid value. */
+ tx->detect_progress = engine->ctx.tx_min_progress + 1;
+ SCLogDebug("tx->tx_progress %d engine->ctx.tx_min_progress %d "
+ "engine->is_last_for_progress %d => tx->detect_progress updated to %02x",
+ tx->tx_progress, engine->ctx.tx_min_progress, engine->is_last_for_progress,
+ tx->detect_progress);
}
next:
if (engine->is_last)
const uint64_t tx_id;
struct AppLayerTxData *tx_data_ptr;
DetectEngineStateDirection *de_state;
- const uint64_t detect_flags; /* detect flags get/set from/to applayer */
- uint64_t prefilter_flags; /* prefilter flags for direction, to be updated by prefilter code */
- const uint64_t
- prefilter_flags_orig; /* prefilter flags for direction, before prefilter has run */
+
+ /* tracking detect progress. Holds the value of
+ * the last completed "progress" + 1. */
+ uint8_t detect_progress;
+ /* original value to track changes. */
+ const uint8_t detect_progress_orig;
+
const int tx_progress;
const int tx_end_state;
} DetectTransaction;
if (tx) {
AppLayerTxData *txd = AppLayerParserGetTxData(f->proto, f->alproto, tx);
// test if the other tx is unidirectional in the other way
- if (txd &&
- (AppLayerParserGetTxDetectFlags(txd, dir) & APP_LAYER_TX_SKIP_INSPECT_FLAG)) {
+ if (txd && ((dir == STREAM_TOSERVER && (txd->flags & APP_LAYER_TX_SKIP_INSPECT_TS)) ||
+ (dir == STREAM_TOCLIENT &&
+ (txd->flags & APP_LAYER_TX_SKIP_INSPECT_TC)))) {
return true;
}
}
#define NO_TX \
{ \
- NULL, 0, NULL, NULL, 0, 0, 0, 0, 0, \
+ NULL, 0, NULL, NULL, 0, 0, 0, 0, \
}
/** \internal
DetectTransaction no_tx = NO_TX;
return no_tx;
}
- uint64_t detect_flags =
- (flow_flags & STREAM_TOSERVER) ? txd->detect_flags_ts : txd->detect_flags_tc;
- if (unlikely(detect_flags & APP_LAYER_TX_INSPECTED_FLAG)) {
- SCLogDebug("%"PRIu64" tx already fully inspected for %s. Flags %016"PRIx64,
- tx_id, flow_flags & STREAM_TOSERVER ? "toserver" : "toclient",
- detect_flags);
+ const uint8_t inspected_flag =
+ (flow_flags & STREAM_TOSERVER) ? APP_LAYER_TX_INSPECTED_TS : APP_LAYER_TX_INSPECTED_TC;
+ if (unlikely(txd->flags & inspected_flag)) {
+ SCLogDebug("%" PRIu64 " tx already fully inspected for %s. Flags %02x", tx_id,
+ flow_flags & STREAM_TOSERVER ? "toserver" : "toclient", txd->flags);
DetectTransaction no_tx = NO_TX;
return no_tx;
}
- if (unlikely(detect_flags & APP_LAYER_TX_SKIP_INSPECT_FLAG)) {
- SCLogDebug("%" PRIu64 " tx should not be inspected in direction %s. Flags %016" PRIx64,
- tx_id, flow_flags & STREAM_TOSERVER ? "toserver" : "toclient", detect_flags);
+ const uint8_t skip_flag = (flow_flags & STREAM_TOSERVER) ? APP_LAYER_TX_SKIP_INSPECT_TS
+ : APP_LAYER_TX_SKIP_INSPECT_TC;
+ if (unlikely(txd->flags & skip_flag)) {
+ SCLogDebug("%" PRIu64 " tx should not be inspected in direction %s. Flags %02x", tx_id,
+ flow_flags & STREAM_TOSERVER ? "toserver" : "toclient", txd->flags);
DetectTransaction no_tx = NO_TX;
return no_tx;
}
+ const uint8_t detect_progress =
+ (flow_flags & STREAM_TOSERVER) ? txd->detect_progress_ts : txd->detect_progress_tc;
+
const int dir_int = (flow_flags & STREAM_TOSERVER) ? 0 : 1;
DetectEngineState *tx_de_state = txd->de_state;
- DetectEngineStateDirection *tx_dir_state = tx_de_state ? &tx_de_state->dir_state[dir_int] : NULL;
- uint64_t prefilter_flags = detect_flags & APP_LAYER_TX_PREFILTER_MASK;
- DEBUG_VALIDATE_BUG_ON(prefilter_flags & APP_LAYER_TX_RESERVED_FLAGS);
-
+ DetectEngineStateDirection *tx_dir_state =
+ tx_de_state ? &tx_de_state->dir_state[dir_int] : NULL;
DetectTransaction tx = {
- .tx_ptr = tx_ptr,
- .tx_id = tx_id,
- .tx_data_ptr = (struct AppLayerTxData *)txd,
- .de_state = tx_dir_state,
- .detect_flags = detect_flags,
- .prefilter_flags = prefilter_flags,
- .prefilter_flags_orig = prefilter_flags,
- .tx_progress = tx_progress,
- .tx_end_state = tx_end_state,
- };
+ .tx_ptr = tx_ptr,
+ .tx_id = tx_id,
+ .tx_data_ptr = (struct AppLayerTxData *)txd,
+ .de_state = tx_dir_state,
+ .detect_progress = detect_progress,
+ .detect_progress_orig = detect_progress,
+ .tx_progress = tx_progress,
+ .tx_end_state = tx_end_state,
+ };
return tx;
}
-static inline void StoreDetectFlags(
- DetectTransaction *tx, const uint8_t flow_flags, const uint64_t detect_flags)
+static inline void StoreDetectProgress(
+ DetectTransaction *tx, const uint8_t flow_flags, const uint8_t progress)
{
AppLayerTxData *txd = (AppLayerTxData *)tx->tx_data_ptr;
if (likely(txd != NULL)) {
if (flow_flags & STREAM_TOSERVER) {
- txd->detect_flags_ts = detect_flags;
+ txd->detect_progress_ts = progress;
} else {
- txd->detect_flags_tc = detect_flags;
+ txd->detect_progress_tc = progress;
}
}
}
/* see if we have any updated state to store in the tx */
- uint64_t new_detect_flags = 0;
/* this side of the tx is done */
if (tx.tx_progress >= tx.tx_end_state) {
- new_detect_flags |= APP_LAYER_TX_INSPECTED_FLAG;
- SCLogDebug("%p/%"PRIu64" tx is done for direction %s. Flag %016"PRIx64,
- tx.tx_ptr, tx.tx_id,
- flow_flags & STREAM_TOSERVER ? "toserver" : "toclient",
- new_detect_flags);
- }
- if (tx.prefilter_flags != tx.prefilter_flags_orig) {
- new_detect_flags |= tx.prefilter_flags;
- DEBUG_VALIDATE_BUG_ON(new_detect_flags & APP_LAYER_TX_RESERVED_FLAGS);
- SCLogDebug("%p/%"PRIu64" updated prefilter flags %016"PRIx64" "
- "(was: %016"PRIx64") for direction %s. Flag %016"PRIx64,
- tx.tx_ptr, tx.tx_id, tx.prefilter_flags, tx.prefilter_flags_orig,
- flow_flags & STREAM_TOSERVER ? "toserver" : "toclient",
- new_detect_flags);
+ SCLogDebug("%" PRIu64 ": %s tx done", p->pcap_cnt,
+ flow_flags & STREAM_TOSERVER ? "toserver" : "toclient");
+ const uint8_t inspected_flag = (flow_flags & STREAM_TOSERVER)
+ ? APP_LAYER_TX_INSPECTED_TS
+ : APP_LAYER_TX_INSPECTED_TC;
+ tx.tx_data_ptr->flags |= inspected_flag;
+ SCLogDebug("%p/%" PRIu64 " tx is done for direction %s. Progress %02x", tx.tx_ptr,
+ tx.tx_id, flow_flags & STREAM_TOSERVER ? "toserver" : "toclient",
+ tx.detect_progress);
}
- if (new_detect_flags != 0 &&
- (new_detect_flags | tx.detect_flags) != tx.detect_flags)
- {
- new_detect_flags |= tx.detect_flags;
- DEBUG_VALIDATE_BUG_ON(new_detect_flags & APP_LAYER_TX_RESERVED_FLAGS);
- SCLogDebug("%p/%"PRIu64" Storing new flags %016"PRIx64" (was %016"PRIx64")",
- tx.tx_ptr, tx.tx_id, new_detect_flags, tx.detect_flags);
- StoreDetectFlags(&tx, flow_flags, new_detect_flags);
+ if (tx.detect_progress != tx.detect_progress_orig) {
+ SCLogDebug("%p/%" PRIu64 " Storing new progress %02x (was %02x)", tx.tx_ptr, tx.tx_id,
+ tx.detect_progress, tx.detect_progress_orig);
+
+ StoreDetectProgress(&tx, flow_flags, tx.detect_progress);
}
+
InspectionBufferClean(det_ctx);
next: