]> git.ipfire.org Git - thirdparty/suricata.git/commitdiff
rust/nfs: fix read reply handling
authorVictor Julien <victor@inliniac.net>
Thu, 25 Jan 2018 13:56:05 +0000 (14:56 +0100)
committerVictor Julien <victor@inliniac.net>
Mon, 12 Feb 2018 09:02:08 +0000 (10:02 +0100)
READ replies with large data chunks are processed partially to avoid
queuing too much data. When the final chunk was received however, the
start of the chunk would already tag the transaction as 'done'. The
more aggressive tx freeing that was recently merged would cause this
tx to be freed before the rest of the in-progress chunk was done.

This patch delays the tagging of the tx until the final data has been
received.

rust/src/filetracker.rs
rust/src/nfs/nfs.rs

index b1b7a4d5df22252dd098a7b1cd3a012686f708c6..9092599922752ef4cdfdf2df50b86bf430ad90b2 100644 (file)
@@ -89,6 +89,10 @@ impl FileTransferTracker {
         }
     }
 
+    pub fn is_done(&self) -> bool {
+        self.file_open == false
+    }
+
     fn open(&mut self, config: &'static SuricataFileContext,
             files: &mut FileContainer, flags: u16, name: &[u8]) -> i32
     {
index 41658d62ccc0fb25673b529366ca8a9b61c4434f..04426f54a7167f2b5ad7f4a315b5e58fa5aaa612 100644 (file)
@@ -1169,6 +1169,16 @@ impl NFSState {
 
                 tdf.chunk_count += 1;
                 let cs = tdf.file_tracker.update(files, flags, data, gap_size);
+                /* see if we need to close the tx */
+                if tdf.file_tracker.is_done() {
+                    if direction == STREAM_TOCLIENT {
+                        tx.response_done = true;
+                        SCLogDebug!("TX {} response is done now that the file track is ready", tx.id);
+                    } else {
+                        tx.request_done = true;
+                        SCLogDebug!("TX {} request is done now that the file track is ready", tx.id);
+                    }
+                }
                 cs
             },
             None => { 0 },
@@ -1230,6 +1240,9 @@ impl NFSState {
 
         }
 
+        let is_partial = reply.data.len() < reply.count as usize;
+        SCLogDebug!("partial data? {}", is_partial);
+
         let found = match self.get_file_tx_by_handle(&file_handle, STREAM_TOCLIENT) {
             Some((tx, files, flags)) => {
                 let ref mut tdf = match tx.type_data {
@@ -1246,7 +1259,13 @@ impl NFSState {
                     tx.nfs_response_status = reply.status;
                     tx.is_last = true;
                     tx.request_done = true;
-                    tx.response_done = true;
+
+                    /* if this is a partial record we will close the tx
+                     * when we've received the final data */
+                    if !is_partial {
+                        tx.response_done = true;
+                        SCLogDebug!("TX {} is DONE", tx.id);
+                    }
                 }
                 true
             },
@@ -1270,7 +1289,13 @@ impl NFSState {
                 tx.nfs_response_status = reply.status;
                 tx.is_last = true;
                 tx.request_done = true;
-                tx.response_done = true;
+
+                /* if this is a partial record we will close the tx
+                 * when we've received the final data */
+                if !is_partial {
+                    tx.response_done = true;
+                    SCLogDebug!("TX {} is DONE", tx.id);
+                }
             }
         }