From: Victor Julien Date: Thu, 25 Jan 2018 13:56:05 +0000 (+0100) Subject: rust/nfs: fix read reply handling X-Git-Tag: suricata-4.0.4~20 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=06c47a7bd79cdb007e009d3dedd733289d8b022a;p=thirdparty%2Fsuricata.git rust/nfs: fix read reply handling 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. --- diff --git a/rust/src/filetracker.rs b/rust/src/filetracker.rs index b1b7a4d5df..9092599922 100644 --- a/rust/src/filetracker.rs +++ b/rust/src/filetracker.rs @@ -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 { diff --git a/rust/src/nfs/nfs.rs b/rust/src/nfs/nfs.rs index 41658d62cc..04426f54a7 100644 --- a/rust/src/nfs/nfs.rs +++ b/rust/src/nfs/nfs.rs @@ -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); + } } }