rust: move AppLayerTxData definition to C

and bindgen it to rust

Will make easier the bindgen of RustParser structure which uses
a callback which uses AppLayerTxData

Move also the free function to C SCAppLayerTxDataCleanup
As suricata-sys crate defines AppLayerTxData for rust,
It must itself implement the Drop trait, and thus,
We need to define a feature surest
pull/14758/head
Philippe Antoine 6 months ago committed by Victor Julien
parent 8eaced3c1e
commit 8857b78f6a

@ -151,7 +151,9 @@ if HAVE_BINDGEN
--allowlist-type 'AppLayerStateData' \
--allowlist-type 'AppLayerGetTxIterTuple' \
--allowlist-type 'AppLayerResult' \
--allowlist-type 'AppLayerTxData' \
--allowlist-type 'StreamSlice' \
--no-copy 'AppLayerTxData' \
--allowlist-function 'SC.*' \
--allowlist-var 'SC.*' \
--opaque-type 'SCConfNode' \

@ -28,20 +28,16 @@ use std::ffi::CStr;
// AppLayerEvent from this module.
pub use suricata_derive::AppLayerEvent;
use suricata_sys::sys::{
AppLayerDecoderEvents, AppLayerGetTxIterState, AppLayerParserState, AppProto,
DetectEngineState, GenericVar,
AppLayerGetTxIterState, AppLayerParserState, AppProto,
};
pub use suricata_sys::sys::{
AppLayerGetFileState, AppLayerGetTxIterTuple, AppLayerResult, AppLayerStateData,
StreamSlice,
AppLayerTxConfig, StreamSlice,
};
#[cfg(not(test))]
use suricata_sys::sys::{
SCAppLayerDecoderEventsFreeEvents, SCAppLayerDecoderEventsSetEventRaw, SCDetectEngineStateFree,
SCGenericVarFree,
};
use suricata_sys::sys::SCAppLayerDecoderEventsSetEventRaw;
/// Cast pointer to a variable, as a mutable reference to an object
///
@ -101,123 +97,18 @@ impl StreamSliceRust for StreamSlice {
}
}
#[repr(C)]
#[derive(Default, Debug,PartialEq, Eq)]
pub struct AppLayerTxConfig {
/// config: log flags
log_flags: u8,
}
#[repr(C)]
#[derive(Debug, PartialEq, Eq)]
pub struct AppLayerTxData {
/// config: log flags
pub config: AppLayerTxConfig,
/// The tx has been updated and needs to be processed : detection, logging, cleaning
/// It can then be skipped until new data arrives.
/// There is a boolean for both directions : to server and to client
pub updated_tc: bool,
pub updated_ts: bool,
flags: u8,
/// logger flags for tx logging api
logged: u32,
/// track file open/logs so we can know how long to keep the tx
pub files_opened: u32,
pub files_logged: u32,
pub files_stored: u32,
pub file_flags: u16,
/// Indicated if a file tracking tx, and if so in which direction:
/// 0: not a file tx
/// STREAM_TOSERVER: file tx, files only in toserver dir
/// STREAM_TOCLIENT: file tx , files only in toclient dir
/// STREAM_TOSERVER|STREAM_TOCLIENT: files possible in both dirs
pub file_tx: u8,
/// Number of times this tx data has already been logged for signatures
/// not using application layer keywords
pub guessed_applayer_logged: u8,
/// 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 AppLayerDecoderEvents,
txbits: *mut GenericVar,
}
impl Default for AppLayerTxData {
fn default() -> Self {
Self::new()
}
}
impl Drop for AppLayerTxData {
fn drop(&mut self) {
self.cleanup();
}
}
#[no_mangle]
pub unsafe extern "C" fn SCAppLayerTxDataCleanup(txd: *mut AppLayerTxData) {
let txd = cast_pointer!(txd, AppLayerTxData);
txd.cleanup()
}
#[derive(Debug, Default, Eq, PartialEq)]
pub struct AppLayerTxData(pub suricata_sys::sys::AppLayerTxData);
impl AppLayerTxData {
#[cfg(not(test))]
pub fn cleanup(&mut self) {
if !self.de_state.is_null() {
unsafe {
SCDetectEngineStateFree(self.de_state);
}
}
if !self.events.is_null() {
unsafe {
SCAppLayerDecoderEventsFreeEvents(&mut self.events);
}
}
if !self.txbits.is_null() {
unsafe {
SCGenericVarFree(self.txbits);
}
}
}
#[cfg(test)]
pub fn cleanup(&mut self) {}
/// Create new AppLayerTxData for a transaction that covers both
/// directions.
pub fn new() -> Self {
Self {
config: AppLayerTxConfig::default(),
logged: 0,
files_opened: 0,
files_logged: 0,
files_stored: 0,
file_flags: 0,
file_tx: 0,
guessed_applayer_logged: 0,
Self (suricata_sys::sys::AppLayerTxData {
updated_tc: true,
updated_ts: true,
flags: 0,
detect_progress_ts: 0,
detect_progress_tc: 0,
de_state: std::ptr::null_mut(),
events: std::ptr::null_mut(),
txbits: std::ptr::null_mut(),
}
..Default::default()
})
}
/// Create new AppLayerTxData for a transaction in a single
@ -227,62 +118,49 @@ impl AppLayerTxData {
Direction::ToServer => (APP_LAYER_TX_SKIP_INSPECT_TC, true, false),
Direction::ToClient => (APP_LAYER_TX_SKIP_INSPECT_TS, false, true),
};
Self {
config: AppLayerTxConfig::default(),
logged: 0,
files_opened: 0,
files_logged: 0,
files_stored: 0,
file_flags: 0,
file_tx: 0,
guessed_applayer_logged: 0,
Self (suricata_sys::sys::AppLayerTxData{
updated_tc,
updated_ts,
detect_progress_ts: 0,
detect_progress_tc: 0,
flags,
de_state: std::ptr::null_mut(),
events: std::ptr::null_mut(),
txbits: std::ptr::null_mut(),
}
..Default::default()
})
}
pub fn init_files_opened(&mut self) {
self.files_opened = 1;
self.0.files_opened = 1;
}
pub fn incr_files_opened(&mut self) {
self.files_opened += 1;
self.0.files_opened += 1;
}
pub fn set_event(&mut self, _event: u8) {
#[cfg(not(test))]
unsafe {
SCAppLayerDecoderEventsSetEventRaw(&mut self.events, _event);
SCAppLayerDecoderEventsSetEventRaw(&mut self.0.events, _event);
}
}
pub fn update_file_flags(&mut self, state_flags: u16) {
if (self.file_flags & state_flags) != state_flags {
SCLogDebug!("updating tx file_flags {:04x} with state flags {:04x}", self.file_flags, state_flags);
let mut nf = state_flags;
// With keyword filestore:both,flow :
// There may be some opened unclosed file in one direction without filestore
// As such it has tx file_flags had FLOWFILE_NO_STORE_TS or TC
// But a new file in the other direction may trigger filestore:both,flow
// And thus set state_flags FLOWFILE_STORE_TS
// If the file was opened without storing it, do not try to store just the end of it
if (self.file_flags & FLOWFILE_NO_STORE_TS) != 0 && (state_flags & FLOWFILE_STORE_TS) != 0 {
nf &= !FLOWFILE_STORE_TS;
}
if (self.file_flags & FLOWFILE_NO_STORE_TC) != 0 && (state_flags & FLOWFILE_STORE_TC) != 0 {
nf &= !FLOWFILE_STORE_TC;
}
self.file_flags |= nf;
unsafe {
SCTxDataUpdateFileFlags(&mut self.0, state_flags);
}
}
}
#[cfg(not(test))]
use suricata_sys::sys::SCAppLayerTxDataCleanup;
impl Drop for AppLayerTxData {
fn drop(&mut self) {
#[cfg(not(test))]
unsafe {
SCAppLayerTxDataCleanup(&mut self.0);
}
}
}
// need to keep in sync with C flow.h
pub const FLOWFILE_NO_STORE_TS: u16 = BIT_U16!(2);
pub const FLOWFILE_NO_STORE_TC: u16 = BIT_U16!(3);
@ -290,18 +168,34 @@ pub const FLOWFILE_STORE_TS: u16 = BIT_U16!(12);
pub const FLOWFILE_STORE_TC: u16 = BIT_U16!(13);
#[no_mangle]
pub unsafe extern "C" fn SCTxDataUpdateFileFlags(txd: &mut AppLayerTxData, state_flags: u16) {
txd.update_file_flags(state_flags);
pub unsafe extern "C" fn SCTxDataUpdateFileFlags(txd: &mut suricata_sys::sys::AppLayerTxData, state_flags: u16) {
if (txd.file_flags & state_flags) != state_flags {
SCLogDebug!("updating tx file_flags {:04x} with state flags {:04x}", txd.file_flags, state_flags);
let mut nf = state_flags;
// With keyword filestore:both,flow :
// There may be some opened unclosed file in one direction without filestore
// As such it has tx file_flags had FLOWFILE_NO_STORE_TS or TC
// But a new file in the other direction may trigger filestore:both,flow
// And thus set state_flags FLOWFILE_STORE_TS
// If the file was opened without storing it, do not try to store just the end of it
if (txd.file_flags & FLOWFILE_NO_STORE_TS) != 0 && (state_flags & FLOWFILE_STORE_TS) != 0 {
nf &= !FLOWFILE_STORE_TS;
}
if (txd.file_flags & FLOWFILE_NO_STORE_TC) != 0 && (state_flags & FLOWFILE_STORE_TC) != 0 {
nf &= !FLOWFILE_STORE_TC;
}
txd.file_flags |= nf;
}
}
#[macro_export]
macro_rules!export_tx_data_get {
($name:ident, $type:ty) => {
unsafe extern "C" fn $name(tx: *mut std::os::raw::c_void)
-> *mut $crate::applayer::AppLayerTxData
-> *mut suricata_sys::sys::AppLayerTxData
{
let tx = &mut *(tx as *mut $type);
&mut tx.tx_data
&mut tx.tx_data.0
}
}
}
@ -485,7 +379,7 @@ pub type GetTxIteratorFn = unsafe extern "C" fn (ipproto: u8, alproto: AppPro
max_tx_id: u64,
istate: *mut AppLayerGetTxIterState)
-> AppLayerGetTxIterTuple;
pub type GetTxDataFn = unsafe extern "C" fn(*mut c_void) -> *mut AppLayerTxData;
pub type GetTxDataFn = unsafe extern "C" fn(*mut c_void) -> *mut suricata_sys::sys::AppLayerTxData;
pub type GetStateDataFn = unsafe extern "C" fn(*mut c_void) -> *mut AppLayerStateData;
pub type ApplyTxConfigFn = unsafe extern "C" fn (*mut c_void, *mut c_void, c_int, AppLayerTxConfig);
pub type GetFrameIdByName = unsafe extern "C" fn(*const c_char) -> c_int;

@ -210,7 +210,7 @@ impl TemplateState {
start = rem;
if let Some(tx) = self.find_request() {
tx.tx_data.updated_tc = true;
tx.tx_data.0.updated_tc = true;
tx.response = Some(response);
SCLogNotice!("Found response for request:");
SCLogNotice!("- Request: {:?}", tx.request);

@ -370,8 +370,8 @@ impl DCERPCState {
for tx_old in &mut self.transactions.range_mut(self.tx_index_completed..) {
index += 1;
if !tx_old.req_done || !tx_old.resp_done {
tx_old.tx_data.updated_tc = true;
tx_old.tx_data.updated_ts = true;
tx_old.tx_data.0.updated_tc = true;
tx_old.tx_data.0.updated_ts = true;
tx_old.req_done = true;
tx_old.resp_done = true;
break;
@ -457,8 +457,8 @@ impl DCERPCState {
}
}
}
tx.tx_data.updated_tc = true;
tx.tx_data.updated_ts = true;
tx.tx_data.0.updated_tc = true;
tx.tx_data.0.updated_ts = true;
return Some(tx);
}
}
@ -1054,10 +1054,10 @@ pub(super) unsafe extern "C" fn get_alstate_progress(tx: *mut std::os::raw::c_vo
unsafe extern "C" fn get_tx_data(
tx: *mut std::os::raw::c_void)
-> *mut AppLayerTxData
-> *mut suricata_sys::sys::AppLayerTxData
{
let tx = cast_pointer!(tx, DCERPCTransaction);
return &mut tx.tx_data;
return &mut tx.tx_data.0;
}
#[no_mangle]

@ -94,8 +94,8 @@ impl DCERPCUDPState {
for tx_old in &mut self.transactions.range_mut(self.tx_index_completed..) {
index += 1;
if !tx_old.req_done || !tx_old.resp_done {
tx_old.tx_data.updated_tc = true;
tx_old.tx_data.updated_ts = true;
tx_old.tx_data.0.updated_tc = true;
tx_old.tx_data.0.updated_ts = true;
tx_old.req_done = true;
tx_old.resp_done = true;
break;
@ -171,8 +171,8 @@ impl DCERPCUDPState {
}
if let Some(tx) = otx {
tx.tx_data.updated_tc = true;
tx.tx_data.updated_ts = true;
tx.tx_data.0.updated_tc = true;
tx.tx_data.0.updated_ts = true;
let done = (hdr.flags1 & PFCL1_FRAG) == 0 || (hdr.flags1 & PFCL1_LASTFRAG) != 0;
let max_size = cfg_max_stub_size() as usize;
@ -277,10 +277,10 @@ unsafe extern "C" fn state_transaction_free(
unsafe extern "C" fn get_tx_data(
tx: *mut std::os::raw::c_void)
-> *mut AppLayerTxData
-> *mut suricata_sys::sys::AppLayerTxData
{
let tx = cast_pointer!(tx, DCERPCTransaction);
return &mut tx.tx_data;
return &mut tx.tx_data.0;
}
unsafe extern "C" fn get_tx(

@ -675,7 +675,7 @@ impl DNSState {
if let Some(ref mut config) = &mut self.config {
if let Some(response) = &tx.response {
if let Some(config) = config.remove(&response.header.tx_id) {
tx.tx_data.config = config;
tx.tx_data.0.config = config;
}
}
}
@ -1022,9 +1022,9 @@ pub extern "C" fn SCDnsTxIsResponse(tx: &mut DNSTransaction) -> bool {
pub(crate) unsafe extern "C" fn state_get_tx_data(
tx: *mut std::os::raw::c_void,
) -> *mut AppLayerTxData {
) -> *mut suricata_sys::sys::AppLayerTxData {
let tx = cast_pointer!(tx, DNSTransaction);
return &mut tx.tx_data;
return &mut tx.tx_data.0;
}
pub(crate) unsafe extern "C" fn dns_get_state_data(

@ -207,8 +207,8 @@ impl EnipState {
fn purge_tx_flood(&mut self) {
let mut event_set = false;
for tx in self.transactions.iter_mut() {
tx.tx_data.updated_tc = true;
tx.tx_data.updated_ts = true;
tx.tx_data.0.updated_tc = true;
tx.tx_data.0.updated_ts = true;
tx.done = true;
if !event_set {
tx.tx_data.set_event(EnipEvent::TooManyTransactions as u8);
@ -222,8 +222,8 @@ impl EnipState {
if let Some(req) = &tx.request {
if tx.response.is_none() {
tx.done = true;
tx.tx_data.updated_tc = true;
tx.tx_data.updated_ts = true;
tx.tx_data.0.updated_tc = true;
tx.tx_data.0.updated_ts = true;
if response_matches_request(req, pdu) {
return Some(tx);
}

@ -685,7 +685,7 @@ impl HTTP2State {
for tx in &mut self.transactions {
if tx.tx_id == tx_id + 1 {
tx.tx_data.update_file_flags(self.state_data.file_flags);
tx.update_file_flags(tx.tx_data.file_flags);
tx.update_file_flags(tx.tx_data.0.file_flags);
return Some(tx);
}
}
@ -741,8 +741,8 @@ impl HTTP2State {
tx_old.set_event(HTTP2Event::TooManyStreams);
// use a distinct state, even if we do not log it
tx_old.state = HTTP2TransactionState::HTTP2StateTodrop;
tx_old.tx_data.updated_tc = true;
tx_old.tx_data.updated_ts = true;
tx_old.tx_data.0.updated_tc = true;
tx_old.tx_data.0.updated_ts = true;
}
return None;
}
@ -775,9 +775,9 @@ impl HTTP2State {
let tx = &mut self.transactions[index - 1];
tx.tx_data.update_file_flags(self.state_data.file_flags);
tx.update_file_flags(tx.tx_data.file_flags);
tx.tx_data.updated_tc = true;
tx.tx_data.updated_ts = true;
tx.update_file_flags(tx.tx_data.0.file_flags);
tx.tx_data.0.updated_tc = true;
tx.tx_data.0.updated_ts = true;
return Some(tx);
} else {
// do not use SETTINGS_MAX_CONCURRENT_STREAMS as it can grow too much
@ -790,8 +790,8 @@ impl HTTP2State {
tx_old.set_event(HTTP2Event::TooManyStreams);
// use a distinct state, even if we do not log it
tx_old.state = HTTP2TransactionState::HTTP2StateTodrop;
tx_old.tx_data.updated_tc = true;
tx_old.tx_data.updated_ts = true;
tx_old.tx_data.0.updated_tc = true;
tx_old.tx_data.0.updated_ts = true;
}
return None;
}
@ -801,8 +801,8 @@ impl HTTP2State {
tx.stream_id = sid;
tx.state = HTTP2TransactionState::HTTP2StateOpen;
tx.tx_data.update_file_flags(self.state_data.file_flags);
tx.update_file_flags(tx.tx_data.file_flags);
tx.tx_data.file_tx = STREAM_TOSERVER | STREAM_TOCLIENT; // might hold files in both directions
tx.update_file_flags(tx.tx_data.0.file_flags);
tx.tx_data.0.file_tx = STREAM_TOSERVER | STREAM_TOCLIENT; // might hold files in both directions
self.transactions.push_back(tx);
return Some(self.transactions.back_mut().unwrap());
}

@ -158,8 +158,8 @@ impl LdapState {
if self.transactions.len() > unsafe { LDAP_MAX_TX } {
for tx_old in &mut self.transactions {
if !tx_old.complete {
tx_old.tx_data.updated_tc = true;
tx_old.tx_data.updated_ts = true;
tx_old.tx_data.0.updated_tc = true;
tx_old.tx_data.0.updated_ts = true;
tx_old.complete = true;
tx_old
.tx_data
@ -311,7 +311,7 @@ impl LdapState {
if let Some(tx) = self.find_request(response.message_id) {
tx.complete |= tx_is_complete(&response.protocol_op, Direction::ToClient);
let tx_id = tx.id();
tx.tx_data.updated_tc = true;
tx.tx_data.0.updated_tc = true;
tx.responses.push(response.to_static());
sc_app_layer_parser_trigger_raw_stream_inspection(
flow,

@ -130,8 +130,8 @@ impl ModbusState {
for tx in &mut self.transactions {
if let Some(req) = &tx.request {
if tx.response.is_none() && resp.matches(req) {
tx.tx_data.updated_tc = true;
tx.tx_data.updated_ts = true;
tx.tx_data.0.updated_tc = true;
tx.tx_data.0.updated_ts = true;
return Some(tx);
}
}
@ -147,8 +147,8 @@ impl ModbusState {
for tx in &mut self.transactions {
if let Some(resp) = &tx.response {
if tx.request.is_none() && req.matches(resp) {
tx.tx_data.updated_tc = true;
tx.tx_data.updated_ts = true;
tx.tx_data.0.updated_tc = true;
tx.tx_data.0.updated_ts = true;
return Some(tx);
}
}
@ -196,8 +196,8 @@ impl ModbusState {
match self.find_response_and_validate(&mut msg) {
Some(tx) => {
tx.set_events_from_flags(&msg.error_flags);
tx.tx_data.updated_tc = true;
tx.tx_data.updated_ts = true;
tx.tx_data.0.updated_tc = true;
tx.tx_data.0.updated_ts = true;
tx.request = Some(msg);
if !flow.is_null() {
sc_app_layer_parser_trigger_raw_stream_inspection(
@ -236,8 +236,8 @@ impl ModbusState {
} else {
tx.set_events_from_flags(&msg.error_flags);
}
tx.tx_data.updated_tc = true;
tx.tx_data.updated_ts = true;
tx.tx_data.0.updated_tc = true;
tx.tx_data.0.updated_ts = true;
tx.response = Some(msg);
if !flow.is_null() {
sc_app_layer_parser_trigger_raw_stream_inspection(
@ -398,9 +398,9 @@ unsafe extern "C" fn modbus_tx_get_alstate_progress(
unsafe extern "C" fn modbus_state_get_tx_data(
tx: *mut std::os::raw::c_void,
) -> *mut AppLayerTxData {
) -> *mut suricata_sys::sys::AppLayerTxData {
let tx = cast_pointer!(tx, ModbusTransaction);
&mut tx.tx_data
&mut tx.tx_data.0
}
export_state_data_get!(modbus_get_state_data, ModbusState);

@ -178,8 +178,8 @@ impl MQTTState {
if !tx.complete {
if let Some(mpktid) = tx.pkt_id {
if mpktid == pkt_id {
tx.tx_data.updated_tc = true;
tx.tx_data.updated_ts = true;
tx.tx_data.0.updated_tc = true;
tx.tx_data.0.updated_ts = true;
return Some(tx);
}
}
@ -202,8 +202,8 @@ impl MQTTState {
for tx_old in &mut self.transactions.range_mut(self.tx_index_completed..) {
index += 1;
if !tx_old.complete {
tx_old.tx_data.updated_tc = true;
tx_old.tx_data.updated_ts = true;
tx_old.tx_data.0.updated_tc = true;
tx_old.tx_data.0.updated_ts = true;
tx_old.complete = true;
MQTTState::set_event(tx_old, MQTTEvent::TooManyTransactions);
break;

@ -263,8 +263,8 @@ impl NFSTransaction {
}
pub fn free(&mut self) {
debug_validate_bug_on!(self.tx_data.files_opened > 1);
debug_validate_bug_on!(self.tx_data.files_logged > 1);
debug_validate_bug_on!(self.tx_data.0.files_opened > 1);
debug_validate_bug_on!(self.tx_data.0.files_logged > 1);
}
}
@ -454,8 +454,8 @@ impl NFSState {
// set at least one another transaction to the drop state
for tx_old in &mut self.transactions {
if !tx_old.request_done || !tx_old.response_done {
tx_old.tx_data.updated_tc = true;
tx_old.tx_data.updated_ts = true;
tx_old.tx_data.0.updated_tc = true;
tx_old.tx_data.0.updated_ts = true;
tx_old.request_done = true;
tx_old.response_done = true;
tx_old.is_file_closed = true;
@ -515,8 +515,8 @@ impl NFSState {
&mut self, flow: *mut Flow, xid: u32, rpc_status: u32, nfs_status: u32, resp_handle: &[u8],
) {
if let Some(mytx) = self.get_tx_by_xid(xid) {
mytx.tx_data.updated_tc = true;
mytx.tx_data.updated_ts = true;
mytx.tx_data.0.updated_tc = true;
mytx.tx_data.0.updated_ts = true;
mytx.response_done = true;
mytx.rpc_response_status = rpc_status;
mytx.nfs_response_status = nfs_status;
@ -923,10 +923,10 @@ impl NFSState {
d.direction = direction;
d.file_tracker.tx_id = tx.id - 1;
tx.tx_data.update_file_flags(self.state_data.file_flags);
d.update_file_flags(tx.tx_data.file_flags);
d.update_file_flags(tx.tx_data.0.file_flags);
}
tx.tx_data.init_files_opened();
tx.tx_data.file_tx = if direction == Direction::ToServer {
tx.tx_data.0.file_tx = if direction == Direction::ToServer {
STREAM_TOSERVER
} else {
STREAM_TOCLIENT
@ -953,10 +953,10 @@ impl NFSState {
&& tx.file_handle == fh
{
tx.tx_data.update_file_flags(self.state_data.file_flags);
d.update_file_flags(tx.tx_data.file_flags);
d.update_file_flags(tx.tx_data.0.file_flags);
SCLogDebug!("Found NFS file TX with ID {} XID {:04X}", tx.id, tx.xid);
tx.tx_data.updated_tc = true;
tx.tx_data.updated_ts = true;
tx.tx_data.0.updated_tc = true;
tx.tx_data.0.updated_ts = true;
return Some(tx);
}
}
@ -2039,9 +2039,9 @@ unsafe extern "C" fn nfs_tx_get_alstate_progress(
}
}
unsafe extern "C" fn nfs_get_tx_data(tx: *mut std::os::raw::c_void) -> *mut AppLayerTxData {
unsafe extern "C" fn nfs_get_tx_data(tx: *mut std::os::raw::c_void) -> *mut suricata_sys::sys::AppLayerTxData {
let tx = cast_pointer!(tx, NFSTransaction);
return &mut tx.tx_data;
return &mut tx.tx_data.0;
}
export_state_data_get!(nfs_get_state_data, NFSState);

@ -231,8 +231,8 @@ impl PgsqlState {
for tx_old in &mut self.transactions.range_mut(self.tx_index_completed..) {
index += 1;
if tx_old.tx_res_state < PgsqlTxProgress::Done {
tx_old.tx_data.updated_tc = true;
tx_old.tx_data.updated_ts = true;
tx_old.tx_data.0.updated_tc = true;
tx_old.tx_data.0.updated_ts = true;
// we don't check for TxReqDone for the majority of requests are basically completed
// when they're parsed, as of now
tx_old.tx_req_state = PgsqlTxProgress::FlushedOut;
@ -413,7 +413,7 @@ impl PgsqlState {
// A simplified finite state machine for PostgreSQL v3 can be found at:
// https://samadhiweb.com/blog/2013.04.28.graphviz.postgresv3.html
if let Some(tx) = self.find_or_create_tx() {
tx.tx_data.updated_ts = true;
tx.tx_data.0.updated_ts = true;
if let Some(state) = new_state {
if state == PgsqlStateProgress::FirstCopyDataInReceived
|| state == PgsqlStateProgress::ConsolidatingCopyDataIn {
@ -629,7 +629,7 @@ impl PgsqlState {
self.state_progress = state;
}
if let Some(tx) = self.find_or_create_tx() {
tx.tx_data.updated_tc = true;
tx.tx_data.0.updated_tc = true;
if tx.tx_res_state == PgsqlTxProgress::Init {
tx.tx_res_state = PgsqlTxProgress::Received;
}

@ -197,8 +197,8 @@ impl POP3State {
if self.transactions.len() > unsafe { POP3_MAX_TX } {
for tx_old in &mut self.transactions {
if !tx_old.complete {
tx_old.tx_data.updated_tc = true;
tx_old.tx_data.updated_ts = true;
tx_old.tx_data.0.updated_tc = true;
tx_old.tx_data.0.updated_ts = true;
tx_old.complete = true;
tx_old
.tx_data

@ -177,8 +177,8 @@ impl RFBState {
let tx_id = self.tx_id;
let r = self.transactions.iter_mut().find(|tx| tx.tx_id == tx_id);
if let Some(tx) = r {
tx.tx_data.updated_tc = true;
tx.tx_data.updated_ts = true;
tx.tx_data.0.updated_tc = true;
tx.tx_data.0.updated_ts = true;
return Some(tx);
}
return None;

@ -168,8 +168,8 @@ impl SMBState {
_ => { false },
};
if found {
tx.tx_data.updated_tc = true;
tx.tx_data.updated_ts = true;
tx.tx_data.0.updated_tc = true;
tx.tx_data.0.updated_ts = true;
return Some(tx);
}
}

@ -97,10 +97,10 @@ impl SMBState {
d.file_name = file_name.to_vec();
d.file_tracker.tx_id = tx.id - 1;
tx.tx_data.update_file_flags(self.state_data.file_flags);
d.update_file_flags(tx.tx_data.file_flags);
d.update_file_flags(tx.tx_data.0.file_flags);
}
tx.tx_data.init_files_opened();
tx.tx_data.file_tx = if direction == Direction::ToServer { STREAM_TOSERVER } else { STREAM_TOCLIENT }; // TODO direction to flag func?
tx.tx_data.0.file_tx = if direction == Direction::ToServer { STREAM_TOSERVER } else { STREAM_TOCLIENT }; // TODO direction to flag func?
SCLogDebug!("SMB: new_file_tx: TX FILE created: ID {} NAME {}",
tx.id, String::from_utf8_lossy(file_name));
self.transactions.push_back(tx);
@ -126,10 +126,10 @@ impl SMBState {
SCLogDebug!("SMB: Found SMB file TX with ID {}", tx.id);
if let Some(SMBTransactionTypeData::FILE(ref mut d)) = tx.type_data {
tx.tx_data.update_file_flags(self.state_data.file_flags);
d.update_file_flags(tx.tx_data.file_flags);
d.update_file_flags(tx.tx_data.0.file_flags);
}
tx.tx_data.updated_tc = true;
tx.tx_data.updated_ts = true;
tx.tx_data.0.updated_tc = true;
tx.tx_data.0.updated_ts = true;
return Some(tx);
}
}
@ -154,10 +154,10 @@ impl SMBState {
SCLogDebug!("SMB: Found SMB file TX with ID {}", tx.id);
if let Some(SMBTransactionTypeData::FILE(ref mut d)) = tx.type_data {
tx.tx_data.update_file_flags(self.state_data.file_flags);
d.update_file_flags(tx.tx_data.file_flags);
d.update_file_flags(tx.tx_data.0.file_flags);
}
tx.tx_data.updated_tc = true;
tx.tx_data.updated_ts = true;
tx.tx_data.0.updated_tc = true;
tx.tx_data.0.updated_ts = true;
return Some(tx);
}
}

@ -61,8 +61,8 @@ impl SMBState {
_ => { false },
};
if hit {
tx.tx_data.updated_tc = true;
tx.tx_data.updated_ts = true;
tx.tx_data.0.updated_tc = true;
tx.tx_data.0.updated_ts = true;
return Some(tx);
}
}

@ -546,8 +546,8 @@ impl SMBTransaction {
pub fn free(&mut self) {
SCLogDebug!("SMB TX {:p} free ID {}", &self, self.id);
debug_validate_bug_on!(self.tx_data.files_opened > 1);
debug_validate_bug_on!(self.tx_data.files_logged > 1);
debug_validate_bug_on!(self.tx_data.0.files_opened > 1);
debug_validate_bug_on!(self.tx_data.0.files_logged > 1);
}
}
@ -844,8 +844,8 @@ impl SMBState {
for tx_old in &mut self.transactions.range_mut(self.tx_index_completed..) {
index += 1;
if !tx_old.request_done || !tx_old.response_done {
tx_old.tx_data.updated_tc = true;
tx_old.tx_data.updated_ts = true;
tx_old.tx_data.0.updated_tc = true;
tx_old.tx_data.0.updated_ts = true;
tx_old.request_done = true;
tx_old.response_done = true;
tx_old.set_event(SMBEvent::TooManyTransactions);
@ -904,7 +904,7 @@ impl SMBState {
/* hack: apply flow file flags to file tx here to make sure its propagated */
if let Some(SMBTransactionTypeData::FILE(ref mut d)) = tx.type_data {
tx.tx_data.update_file_flags(self.state_data.file_flags);
d.update_file_flags(tx.tx_data.file_flags);
d.update_file_flags(tx.tx_data.0.file_flags);
}
return Some(tx);
}
@ -964,8 +964,8 @@ impl SMBState {
false
};
if found {
tx.tx_data.updated_tc = true;
tx.tx_data.updated_ts = true;
tx.tx_data.0.updated_tc = true;
tx.tx_data.0.updated_ts = true;
return Some(tx);
}
}
@ -990,8 +990,8 @@ impl SMBState {
false
};
if found {
tx.tx_data.updated_tc = true;
tx.tx_data.updated_ts = true;
tx.tx_data.0.updated_tc = true;
tx.tx_data.0.updated_ts = true;
return Some(tx);
}
}
@ -1030,8 +1030,8 @@ impl SMBState {
_ => { false },
};
if found {
tx.tx_data.updated_tc = true;
tx.tx_data.updated_ts = true;
tx.tx_data.0.updated_tc = true;
tx.tx_data.0.updated_ts = true;
return Some(tx);
}
}
@ -1065,8 +1065,8 @@ impl SMBState {
_ => { false },
};
if hit {
tx.tx_data.updated_tc = true;
tx.tx_data.updated_ts = true;
tx.tx_data.0.updated_tc = true;
tx.tx_data.0.updated_ts = true;
return Some(tx);
}
}
@ -2261,10 +2261,10 @@ export_state_data_get!(smb_get_state_data, SMBState);
unsafe extern "C" fn smb_get_tx_data(
tx: *mut std::os::raw::c_void)
-> *mut AppLayerTxData
-> *mut suricata_sys::sys::AppLayerTxData
{
let tx = cast_pointer!(tx, SMBTransaction);
return &mut tx.tx_data;
return &mut tx.tx_data.0;
}
unsafe extern "C" fn smb_state_get_event_info_by_id(

@ -459,7 +459,7 @@ unsafe extern "C" fn ssh_parse_request(
let state = &mut cast_pointer!(state, SSHState);
let buf = stream_slice.as_slice();
let hdr = &mut state.transaction.cli_hdr;
state.transaction.tx_data.updated_ts = true;
state.transaction.tx_data.0.updated_ts = true;
if hdr.flags < SSHConnectionState::SshStateBannerDone {
return state.parse_banner(buf, false, pstate, flow, &stream_slice);
} else {
@ -474,7 +474,7 @@ unsafe extern "C" fn ssh_parse_response(
let state = &mut cast_pointer!(state, SSHState);
let buf = stream_slice.as_slice();
let hdr = &mut state.transaction.srv_hdr;
state.transaction.tx_data.updated_tc = true;
state.transaction.tx_data.0.updated_tc = true;
if hdr.flags < SSHConnectionState::SshStateBannerDone {
return state.parse_banner(buf, true, pstate, flow, &stream_slice);
} else {

@ -25,7 +25,7 @@ use nom8::combinator::map_res;
use nom8::bytes::streaming::{tag, take_while};
use nom8::number::streaming::be_u8;
use crate::applayer::{AppLayerTxData,AppLayerStateData};
use crate::applayer::{AppLayerTxData, AppLayerStateData};
const READREQUEST: u8 = 1;
const WRITEREQUEST: u8 = 2;
@ -176,10 +176,10 @@ pub unsafe extern "C" fn SCTftpParseRequest(state: &mut TFTPState,
#[no_mangle]
pub unsafe extern "C" fn SCTftpGetTxData(
tx: *mut std::os::raw::c_void)
-> *mut AppLayerTxData
-> *mut suricata_sys::sys::AppLayerTxData
{
let tx = cast_pointer!(tx, TFTPTransaction);
return &mut tx.tx_data;
return &mut tx.tx_data.0;
}
#[no_mangle]

@ -994,11 +994,6 @@ pub struct File_ {
_unused: [u8; 0],
}
pub type File = File_;
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct AppLayerTxData {
_unused: [u8; 0],
}
extern "C" {
#[doc = " \\brief Given a protocol name, checks if the parser is enabled in\n the conf file.\n\n \\param alproto_name Name of the app layer protocol.\n\n \\retval 1 If enabled.\n \\retval 0 If disabled."]
pub fn SCAppLayerParserConfParserEnabled(
@ -1080,6 +1075,52 @@ pub struct AppLayerResult {
pub consumed: u32,
pub needed: u32,
}
#[repr(C)]
#[derive(Debug, Default, Copy, Clone, PartialEq, Eq)]
pub struct AppLayerTxConfig {
#[doc = " config: log flags"]
pub log_flags: u8,
}
pub type GenericVar = GenericVar_;
#[repr(C)]
#[derive(Debug, PartialEq, Eq)]
pub struct AppLayerTxData {
#[doc = " config: log flags"]
pub config: AppLayerTxConfig,
#[doc = " The tx has been updated and needs to be processed : detection, logging, cleaning\n It can then be skipped until new data arrives.\n There is a boolean for both directions : to server and to client"]
pub updated_tc: bool,
pub updated_ts: bool,
pub flags: u8,
#[doc = " logger flags for tx logging api"]
pub logged: u32,
#[doc = " track file open/logs so we can know how long to keep the tx"]
pub files_opened: u32,
pub files_logged: u32,
pub files_stored: u32,
pub file_flags: u16,
#[doc = " Indicated if a file tracking tx, and if so in which direction:\n 0: not a file tx\n STREAM_TOSERVER: file tx, files only in toserver dir\n STREAM_TOCLIENT: file tx , files only in toclient dir\n STREAM_TOSERVER|STREAM_TOCLIENT: files possible in both dirs"]
pub file_tx: u8,
#[doc = " Number of times this tx data has already been logged for signatures\n not using application layer keywords"]
pub guessed_applayer_logged: u8,
#[doc = " detection engine progress tracking for use by detection engine\n Reflects the \"progress\" of prefilter engines into this TX, where\n the value is offset by 1. So if for progress state 0 the engines\n are done, the value here will be 1. So a value of 0 means, no\n progress tracked yet.\n"]
pub detect_progress_ts: u8,
pub detect_progress_tc: u8,
pub de_state: *mut DetectEngineState,
pub events: *mut AppLayerDecoderEvents,
pub txbits: *mut GenericVar,
}
impl Default for AppLayerTxData {
fn default() -> Self {
let mut s = ::std::mem::MaybeUninit::<Self>::uninit();
unsafe {
::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1);
s.assume_init()
}
}
}
extern "C" {
pub fn SCAppLayerTxDataCleanup(txd: *mut AppLayerTxData);
}
extern "C" {
pub fn SCAppLayerParserReallocCtx(alproto: AppProto) -> ::std::os::raw::c_int;
}
@ -1417,7 +1458,6 @@ impl Default for GenericVar_ {
}
}
}
pub type GenericVar = GenericVar_;
extern "C" {
pub fn SCGenericVarFree(arg1: *mut GenericVar);
}

@ -744,6 +744,19 @@ static inline uint32_t GetTxLogged(AppLayerTxData *txd)
return txd->logged;
}
void SCAppLayerTxDataCleanup(AppLayerTxData *txd)
{
if (txd->de_state) {
SCDetectEngineStateFree(txd->de_state);
}
if (txd->events) {
SCAppLayerDecoderEventsFreeEvents(&txd->events);
}
if (txd->txbits) {
SCGenericVarFree(txd->txbits);
}
}
void AppLayerParserSetTransactionInspectId(const Flow *f, AppLayerParserState *pstate,
void *alstate, const uint8_t flags,
bool tag_txs_as_inspected)

@ -27,6 +27,7 @@
#include "app-layer-protos.h"
#include "app-layer-events.h"
#include "detect-engine-state.h"
// Forward declarations for bindgen
enum ConfigAction;
typedef struct Flow_ Flow;
@ -40,8 +41,6 @@ typedef struct StreamSlice StreamSlice;
typedef struct AppLayerResult AppLayerResult;
typedef struct AppLayerGetTxIterTuple AppLayerGetTxIterTuple;
typedef struct AppLayerGetFileState AppLayerGetFileState;
typedef struct AppLayerTxData AppLayerTxData;
typedef struct AppLayerTxConfig AppLayerTxConfig;
/* Flags for AppLayerParserState. */
// flag available BIT_U16(0)
@ -171,6 +170,61 @@ typedef struct AppLayerResult {
uint32_t needed;
} AppLayerResult;
typedef struct AppLayerTxConfig {
/// config: log flags
uint8_t log_flags;
} AppLayerTxConfig;
typedef struct GenericVar_ GenericVar;
typedef struct AppLayerTxData {
/// config: log flags
AppLayerTxConfig config;
/// The tx has been updated and needs to be processed : detection, logging, cleaning
/// It can then be skipped until new data arrives.
/// There is a boolean for both directions : to server and to client
bool updated_tc;
bool updated_ts;
uint8_t flags;
/// logger flags for tx logging api
uint32_t logged;
/// track file open/logs so we can know how long to keep the tx
uint32_t files_opened;
uint32_t files_logged;
uint32_t files_stored;
uint16_t file_flags;
/// Indicated if a file tracking tx, and if so in which direction:
/// 0: not a file tx
/// STREAM_TOSERVER: file tx, files only in toserver dir
/// STREAM_TOCLIENT: file tx , files only in toclient dir
/// STREAM_TOSERVER|STREAM_TOCLIENT: files possible in both dirs
uint8_t file_tx;
/// Number of times this tx data has already been logged for signatures
/// not using application layer keywords
uint8_t guessed_applayer_logged;
/// 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.
///
uint8_t detect_progress_ts;
uint8_t detect_progress_tc;
DetectEngineState *de_state;
AppLayerDecoderEvents *events;
GenericVar *txbits;
} AppLayerTxData;
void SCAppLayerTxDataCleanup(AppLayerTxData *txd);
/** \brief tx iterator prototype */
typedef AppLayerGetTxIterTuple (*AppLayerGetTxIteratorFunc)
(const uint8_t ipproto, const AppProto alproto,

@ -35,6 +35,7 @@
#include "util-var.h"
#include "util-debug.h"
#include "rust.h"
#include "app-layer-parser.h"
static XBit *TxBitGet(AppLayerTxData *txd, uint32_t idx)
{

Loading…
Cancel
Save