]> git.ipfire.org Git - people/ms/suricata.git/commitdiff
rust/app-layer: provide generic implementation of iterator
authorJason Ish <jason.ish@oisf.net>
Thu, 14 Oct 2021 18:37:03 +0000 (12:37 -0600)
committerVictor Julien <vjulien@oisf.net>
Mon, 22 Nov 2021 09:20:22 +0000 (10:20 +0100)
Create traits for app-layer State and Transaction that allow
a generic implementation of a transaction iterator that parser
can use when the follow the common pattern for iterating
transactions.

Also convert DNS to use the generic for testing purposes.

rust/src/applayer.rs
rust/src/dns/dns.rs

index 9518606cef7e3676d2a9f8c0fe64cc9336f506f8..a9ac44394d28d62b90caaf825f53653e0b1b0823 100644 (file)
@@ -507,3 +507,43 @@ pub unsafe fn get_event_info_by_id<T: AppLayerEvent>(
     }
     return -1;
 }
+
+/// Transaction trait.
+///
+/// This trait defines methods that a Transaction struct must implement
+/// in order to define some generic helper functions.
+pub trait Transaction {
+    fn id(&self) -> u64;
+}
+
+pub trait State<Tx: Transaction> {
+    fn get_transactions(&self) -> &[Tx];
+
+    fn get_transaction_iterator(&self, min_tx_id: u64, state: &mut u64) -> AppLayerGetTxIterTuple {
+        let mut index = *state as usize;
+        let transactions = self.get_transactions();
+        let len = transactions.len();
+        while index < len {
+            let tx = &transactions[index];
+            if tx.id() < min_tx_id + 1 {
+                index += 1;
+                continue;
+            }
+            *state = index as u64;
+            return AppLayerGetTxIterTuple::with_values(
+                tx as *const _ as *mut _,
+                tx.id() - 1,
+                len - index > 1,
+            );
+        }
+        return AppLayerGetTxIterTuple::not_found();
+    }
+}
+
+pub unsafe extern "C" fn state_get_tx_iterator<S: State<Tx>, Tx: Transaction>(
+    _ipproto: u8, _alproto: AppProto, state: *mut std::os::raw::c_void, min_tx_id: u64,
+    _max_tx_id: u64, istate: &mut u64,
+) -> AppLayerGetTxIterTuple {
+    let state = cast_pointer!(state, S);
+    state.get_transaction_iterator(min_tx_id, istate)
+}
index ae7b06cf5866f9408a9b98b797710c57db66617b..16b67cfa9c1e357ab8a27a7194353aa03ce90863 100644 (file)
@@ -236,6 +236,12 @@ pub struct DNSTransaction {
     pub tx_data: AppLayerTxData,
 }
 
+impl Transaction for DNSTransaction {
+    fn id(&self) -> u64 {
+        self.id
+    }
+}
+
 impl DNSTransaction {
 
     pub fn new() -> Self {
@@ -336,6 +342,12 @@ pub struct DNSState {
     gap: bool,
 }
 
+impl State<DNSTransaction> for DNSState {
+    fn get_transactions(&self) -> &[DNSTransaction] {
+        &self.transactions
+    }
+}
+
 impl DNSState {
 
     pub fn new() -> Self {
@@ -991,7 +1003,7 @@ pub unsafe extern "C" fn rs_dns_udp_register_parser() {
         localstorage_new: None,
         localstorage_free: None,
         get_files: None,
-        get_tx_iterator: None,
+        get_tx_iterator: Some(crate::applayer::state_get_tx_iterator::<DNSState, DNSTransaction>),
         get_de_state: rs_dns_state_get_tx_detect_state,
         set_de_state: rs_dns_state_set_tx_detect_state,
         get_tx_data: rs_dns_state_get_tx_data,
@@ -1037,7 +1049,7 @@ pub unsafe extern "C" fn rs_dns_tcp_register_parser() {
         localstorage_new: None,
         localstorage_free: None,
         get_files: None,
-        get_tx_iterator: None,
+        get_tx_iterator: Some(crate::applayer::state_get_tx_iterator::<DNSState, DNSTransaction>),
         get_de_state: rs_dns_state_get_tx_detect_state,
         set_de_state: rs_dns_state_set_tx_detect_state,
         get_tx_data: rs_dns_state_get_tx_data,