]> 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, 29 Jan 2018 10:44:01 +0000 (11:44 +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 20b35575e41d98e3af5d48673423b8c2eea58a4e..ff0e0558f2108c040029a017c284dd3c92b521ea 100644 (file)
@@ -1174,6 +1174,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 },
@@ -1235,6 +1245,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 {
@@ -1251,7 +1264,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
             },
@@ -1275,7 +1294,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);
+                }
             }
         }