fileHash->set_max_nodes(max_files);
}
+FileContext* FileCache::find_add(const FileHashKey& hashKey, int64_t timeout)
+{
+
+ if ( !fileHash->get_num_nodes() )
+ return nullptr;
+
+ HashNode* hash_node = fileHash->find_node(&hashKey);
+ if ( !hash_node )
+ return nullptr;
+
+ FileNode* node = (FileNode*)hash_node->data;
+ if ( !node )
+ {
+ fileHash->release_node(hash_node);
+ return nullptr;
+ }
+
+ struct timeval now;
+ packet_gettimeofday(&now);
+
+ if ( timercmp(&node->cache_expire_time, &now, <) )
+ {
+ fileHash->release_node(hash_node);
+ return nullptr;
+ }
+
+ struct timeval next_expire_time;
+ struct timeval time_to_add = { static_cast<time_t>(timeout), 0 };
+ timeradd(&now, &time_to_add, &next_expire_time);
+
+ // Refresh the timer on the cache.
+ if (timercmp(&node->cache_expire_time, &next_expire_time, <))
+ node->cache_expire_time = next_expire_time;
+
+ return node->file;
+}
+
FileContext* FileCache::add(const FileHashKey& hashKey, int64_t timeout)
{
FileNode new_node;
std::lock_guard<std::mutex> lock(cache_mutex);
- if (fileHash->insert((void*)&hashKey, &new_node) != HASH_OK)
+ FileContext* file = find_add(hashKey, timeout);
+
+ if (!file) {
+ if (fileHash->insert((void*)&hashKey, &new_node) != HASH_OK)
+ {
+ /* Uh, shouldn't get here...
+ * There is already a node or couldn't alloc space
+ * for key. This means bigger problems, but fail
+ * gracefully.
+ */
+ FILE_DEBUG(file_trace, DEFAULT_TRACE_OPTION_ID, TRACE_CRITICAL_LEVEL, GET_CURRENT_PACKET,
+ "add:Insert failed in file cache, returning\n");
+ file_counts.cache_add_fails++;
+ delete new_node.file;
+ return nullptr;
+ }
+ return new_node.file;
+ }
+ else
{
- /* Uh, shouldn't get here...
- * There is already a node or couldn't alloc space
- * for key. This means bigger problems, but fail
- * gracefully.
- */
FILE_DEBUG(file_trace, DEFAULT_TRACE_OPTION_ID, TRACE_CRITICAL_LEVEL, GET_CURRENT_PACKET,
- "add:Insert failed in file cache, returning\n");
+ "add:file already found in file cache, returning\n");
file_counts.cache_add_fails++;
delete new_node.file;
- return nullptr;
+ return file;
}
-
- return new_node.file;
}
FileContext* FileCache::find(const FileHashKey& hashKey, int64_t timeout)
{
if (file->get_file_data() and !file_got->get_file_data())
{
+ file_got->user_file_data_mutex.lock();
file_got->set_file_data(file->get_file_data());
file->set_file_data(nullptr);
+ file_got->user_file_data_mutex.unlock();
}
}
else
private:
snort::FileContext* add(const FileHashKey&, int64_t timeout);
snort::FileContext* find(const FileHashKey&, int64_t);
- snort::FileContext* get_file(snort::Flow*, uint64_t file_id, bool to_create, int64_t timeout);
+ snort::FileContext* find_add(const FileHashKey&, int64_t);
+ snort::FileContext* get_file(snort::Flow*, uint64_t file_id, bool to_create,
+ int64_t timeout);
FileVerdict check_verdict(snort::Packet*, snort::FileInfo*, snort::FilePolicyBase*);
int store_verdict(snort::Flow*, snort::FileInfo*, int64_t timeout);
{
if (file_cache)
file_got = file_cache->get_file(flow, pending_file_id, false);
- if (file_got and file_got->get_file_data())
+ if (file_got and file_got->get_file_data() and file_got->verdict == FILE_VERDICT_PENDING)
{
file_got->user_file_data_mutex.lock();
file->set_file_data(file_got->get_file_data());
file_got->user_file_data_mutex.unlock();
}
}
-
+ file->user_file_data_mutex.lock();
FileVerdict verdict = file_policy->signature_lookup(p, file);
+ file->user_file_data_mutex.unlock();
+
if (file_cache)
{
FILE_DEBUG(file_trace, DEFAULT_TRACE_OPTION_ID, TRACE_DEBUG_LEVEL, p,
FileContext* file_got = file_cache->get_file(flow, file_id, false);
if (file_got and file_got->verdict == FILE_VERDICT_PENDING and current_context != file_got)
{
+ file_got->user_file_data_mutex.lock();
delete(file_got->get_file_data());
file_got->set_file_data(nullptr);
+ file_got->user_file_data_mutex.unlock();
}
}
current_context = ctx;