// See the file "COPYING" in the main distribution directory for copyright. #include "zeek/file_analysis/FileReassembler.h" #include "zeek/file_analysis/File.h" namespace zeek::file_analysis { class File; FileReassembler::FileReassembler(File *f, uint64_t starting_offset) : Reassembler(starting_offset, REASSEM_FILE), the_file(f), flushing(false) { } uint64_t FileReassembler::Flush() { if ( flushing ) return 0; if ( block_list.Empty() ) return 0; const auto& last_block = block_list.LastBlock(); // This is expected to call back into FileReassembler::Undelivered(). flushing = true; uint64_t rval = TrimToSeq(last_block.upper); flushing = false; return rval; } uint64_t FileReassembler::FlushTo(uint64_t sequence) { if ( flushing ) return 0; flushing = true; uint64_t rval = TrimToSeq(sequence); flushing = false; last_reassem_seq = sequence; return rval; } void FileReassembler::BlockInserted(DataBlockMap::const_iterator it) { const auto& start_block = it->second; if ( start_block.seq > last_reassem_seq || start_block.upper <= last_reassem_seq ) return; while ( it != block_list.End() ) { const auto& b = it->second; if ( b.seq > last_reassem_seq ) break; if ( b.seq == last_reassem_seq ) { // New stuff. uint64_t len = b.Size(); last_reassem_seq += len; the_file->DeliverStream(b.block, len); } ++it; } // Throw out forwarded data TrimToSeq(last_reassem_seq); } void FileReassembler::Undelivered(uint64_t up_to_seq) { // If we have blocks that begin below up_to_seq, deliver them. auto it = block_list.Begin(); while ( it != block_list.End() ) { const auto& b = it->second; if ( b.seq < last_reassem_seq ) { // Already delivered this block. ++it; continue; } if ( b.seq >= up_to_seq ) // Block is beyond what we need to process at this point. break; uint64_t gap_at_seq = last_reassem_seq; uint64_t gap_len = b.seq - last_reassem_seq; the_file->Gap(gap_at_seq, gap_len); last_reassem_seq += gap_len; BlockInserted(it); // Inserting a block may cause trimming of what's buffered, // so have to assume 'b' is invalid, hence re-assign to start. it = block_list.Begin(); } if ( up_to_seq > last_reassem_seq ) { the_file->Gap(last_reassem_seq, up_to_seq - last_reassem_seq); last_reassem_seq = up_to_seq; } } void FileReassembler::Overlap(const u_char* b1, const u_char* b2, uint64_t n) { // Not doing anything here yet. } } // end file_analysis