]> git.ipfire.org Git - thirdparty/snort3.git/commitdiff
Pull request #4691: file_api: multi instance snort related file cache sharing
authorShilpa Nagpal (shinagpa) <shinagpa@cisco.com>
Thu, 3 Jul 2025 09:57:05 +0000 (09:57 +0000)
committerLokesh Bevinamarad (lbevinam) <lbevinam@cisco.com>
Thu, 3 Jul 2025 09:57:05 +0000 (09:57 +0000)
Merge in SNORT/snort3 from ~SHINAGPA/snort3:mp_file to master

Squashed commit of the following:

commit 97add605a2d5f0f0cd1e0bbfebc07b418a9671b9
Author: Shilpa Nagpal <shinagpa@cisco.com>
Date:   Wed Apr 2 11:04:21 2025 +0530

    file_api: multi instance snort related file cache sharing

src/file_api/CMakeLists.txt
src/file_api/file_cache.cc
src/file_api/file_cache.h
src/file_api/file_cache_share.cc [new file with mode: 0644]
src/file_api/file_cache_share.h [new file with mode: 0644]
src/file_api/file_inspect.cc
src/file_api/file_lib.cc
src/file_api/file_lib.h
src/pub_sub/CMakeLists.txt
src/pub_sub/file_events.h [new file with mode: 0644]
src/pub_sub/file_events_ids.h [new file with mode: 0644]

index 9336330bd7e29414c52ba8d56a4a1d8c66939011..ef732bf6dbb59933e79ae12ab77fcbd591993ad7 100644 (file)
@@ -35,6 +35,8 @@ add_library ( file_api OBJECT
     file_service.cc
     file_stats.cc
     file_stats.h
+    file_cache_share.cc
+    file_cache_share.h
 )
 
 install (FILES ${FILE_API_INCLUDES}
index b27e400f77055d1e7e7bb0bac5c7913ac00476b2..d1cb1152833d35ff307b3496eb76a4b5cf39b66c 100644 (file)
 #include "packet_io/active.h"
 #include "packet_io/packet_tracer.h"
 #include "time/packet_time.h"
+#include "pub_sub/file_events.h"
 
 #include "file_flows.h"
 #include "file_module.h"
 #include "file_service.h"
 #include "file_stats.h"
+#include "file_cache_share.h"
 
 #define DEFAULT_FILE_LOOKUP_TIMEOUT_CACHED_ITEM 3600    // 1 hour
 
@@ -127,7 +129,6 @@ void FileCache::set_max_files(int64_t max)
 
 FileContext* FileCache::find_add(const FileHashKey& hashKey, int64_t timeout)
 {
-
     if ( !fileHash->get_num_nodes() )
         return nullptr;
 
@@ -162,7 +163,7 @@ FileContext* FileCache::find_add(const FileHashKey& hashKey, int64_t timeout)
     return node->file;
 }
 
-FileContext* FileCache::add(const FileHashKey& hashKey, int64_t timeout, bool &cache_full)
+FileContext* FileCache::add(const FileHashKey& hashKey, int64_t timeout, bool &cache_full, int64_t& cache_expire, FileInspect* ins)
 {
     FileNode new_node;
     /*
@@ -177,14 +178,19 @@ FileContext* FileCache::add(const FileHashKey& hashKey, int64_t timeout, bool &c
     struct timeval time_to_add = { static_cast<time_t>(timeout), 0 };
     timeradd(&now, &time_to_add, &new_node.cache_expire_time);
 
-    new_node.file = new FileContext;
-
     std::lock_guard<std::mutex> lock(cache_mutex);
-
     FileContext* file = find_add(hashKey, timeout);
 
-    if (!file) {
+    if (!file)
+    {
+        if (ins)
+            new_node.file = new FileContext(ins);
+        else
+            new_node.file = new FileContext;
+
         int ret = fileHash->insert((void*)&hashKey, &new_node);
+        cache_expire = new_node.cache_expire_time.tv_sec;
+
         if (ret != HASH_OK)
         {
             /* There is already a node or couldn't alloc space for key or cache is full.
@@ -196,24 +202,26 @@ FileContext* FileCache::add(const FileHashKey& hashKey, int64_t timeout, bool &c
                     PacketTracer::log("add:Insert failed in file cache, returning\n");
                 cache_full = true;
             }
-            FILE_DEBUG(file_trace, DEFAULT_TRACE_OPTION_ID, TRACE_CRITICAL_LEVEL, GET_CURRENT_PACKET,
-                "add:Insert failed in file cache, returning\n");
+            if (!ins)
+                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
     {
-        FILE_DEBUG(file_trace, DEFAULT_TRACE_OPTION_ID, TRACE_CRITICAL_LEVEL, GET_CURRENT_PACKET,
-            "add:file already found in file cache, returning\n");
-        delete new_node.file;
+        if (!ins)
+            FILE_DEBUG(file_trace, DEFAULT_TRACE_OPTION_ID, TRACE_CRITICAL_LEVEL, GET_CURRENT_PACKET,
+                "add:file already found in file cache, returning\n");
         return file;
     }
 }
 
-FileContext* FileCache::find(const FileHashKey& hashKey, int64_t timeout)
+FileContext* FileCache::find(const FileHashKey& hashKey, int64_t timeout, int64_t& cache_expire)
 {
     std::lock_guard<std::mutex> lock(cache_mutex);
 
@@ -233,7 +241,6 @@ FileContext* FileCache::find(const FileHashKey& hashKey, int64_t timeout)
 
     struct timeval now;
     packet_gettimeofday(&now);
-
     if ( timercmp(&node->cache_expire_time, &now, <) )
     {
         fileHash->release_node(hash_node);
@@ -248,11 +255,12 @@ FileContext* FileCache::find(const FileHashKey& hashKey, int64_t timeout)
     if (timercmp(&node->cache_expire_time, &next_expire_time, <))
         node->cache_expire_time = next_expire_time;
 
+    cache_expire = node->cache_expire_time.tv_sec;
     return node->file;
 }
 
 FileContext* FileCache::get_file(Flow* flow, uint64_t file_id, bool to_create,
-    int64_t timeout, bool using_cache_entry, bool &cache_full)
+    int64_t timeout, bool using_cache_entry, bool &cache_full, int64_t& cache_expire)
 {
     FileHashKey hashKey;
     hashKey.dip = flow->client_ip;
@@ -265,12 +273,12 @@ FileContext* FileCache::get_file(Flow* flow, uint64_t file_id, bool to_create,
     
     FileContext* file = nullptr;
     if (using_cache_entry)
-        file = find(hashKey, DEFAULT_FILE_LOOKUP_TIMEOUT_CACHED_ITEM);
+        file = find(hashKey, DEFAULT_FILE_LOOKUP_TIMEOUT_CACHED_ITEM, cache_expire);
     else
-        file = find(hashKey, timeout);
-    
+        file = find(hashKey, timeout, cache_expire);
+
     if (to_create and !file)
-        file = add(hashKey, timeout, cache_full);
+        file = add(hashKey, timeout, cache_full, cache_expire);
 
     return file;
 }
@@ -278,7 +286,8 @@ FileContext* FileCache::get_file(Flow* flow, uint64_t file_id, bool to_create,
 FileContext* FileCache::get_file(Flow* flow, uint64_t file_id, bool to_create, bool using_cache_entry)
 {
     bool cache_full = false;
-    return get_file(flow, file_id, to_create, lookup_timeout, using_cache_entry, cache_full);
+    int64_t cache_expire = 0;
+    return get_file(flow, file_id, to_create, lookup_timeout, using_cache_entry, cache_full, cache_expire);
 }
 
 FileVerdict FileCache::check_verdict(Packet* p, FileInfo* file,
@@ -311,10 +320,34 @@ FileVerdict FileCache::check_verdict(Packet* p, FileInfo* file,
     return verdict;
 }
 
+void FileCache::publish_file_cache_event(Flow* flow, FileInfo* file, int64_t timeout)
+{
+    if (SnortConfig::get_conf()->mp_dbus)
+    {      
+        FileHashKey hashkey;
+        hashkey.dip = flow->client_ip;
+        hashkey.sip = flow->server_ip;
+        hashkey.dgroup = flow->client_group;
+        hashkey.sgroup = flow->server_group;
+        hashkey.file_id = file->get_file_id();
+        hashkey.asid = flow->key->addressSpaceId;
+        hashkey.padding[0] = hashkey.padding[1] = hashkey.padding[2] = 0;
+
+
+        std::shared_ptr<FileMPEvent> fe = std::make_shared<FileMPEvent>(hashkey, timeout, *file);
+        unsigned file_pub_id = MPDataBus::get_id(file_pub_key);
+        MPDataBus::publish(file_pub_id, FileMPEvents::FILE_SHARE_SYNC, fe);
+
+        FILE_DEBUG(file_trace, DEFAULT_TRACE_OPTION_ID, TRACE_DEBUG_LEVEL, GET_CURRENT_PACKET,
+            "File Cache Sharing: Publish event with file_id %lu\n", hashkey.file_id);
+    }
+}
+
 int FileCache::store_verdict(Flow* flow, FileInfo* file, int64_t timeout, bool &cache_full)
 {
     assert(file);
     uint64_t file_id = file->get_file_id();
+    int64_t cache_expire = 0;
 
     if (!file_id)
     {
@@ -323,9 +356,10 @@ int FileCache::store_verdict(Flow* flow, FileInfo* file, int64_t timeout, bool &
         return 0;
     }
 
-    FileContext* file_got = get_file(flow, file_id, true, timeout, false, cache_full);
+    FileContext* file_got = get_file(flow, file_id, true, timeout, false, cache_full, cache_expire);
     if (file_got)
     {
+        publish_file_cache_event(flow, file, cache_expire);
         *((FileInfo*)(file_got)) = *file;
 
         if (FILE_VERDICT_PENDING == file->verdict and file != file_got)
index 78d7bd958718a03f8af8672607684f3a9a571949..0b805e74f222fd856f42fe09acf62ada77f88c98 100644 (file)
 
 class ExpectedFileCache;
 
-class FileCache
-{
-public:
-
 PADDING_GUARD_BEGIN
     struct FileHashKey
     {
@@ -47,6 +43,10 @@ PADDING_GUARD_BEGIN
     };
 PADDING_GUARD_END
 
+class FileCache
+{
+public:
+
     struct FileNode
     {
         struct timeval cache_expire_time = {0, 0};
@@ -59,21 +59,22 @@ PADDING_GUARD_END
     void set_block_timeout(int64_t);
     void set_lookup_timeout(int64_t);
     void set_max_files(int64_t);
-
+    snort::FileContext* add(const FileHashKey&, int64_t timeout, bool &cache_full, int64_t& cache_expire, FileInspect* ins = nullptr);
     snort::FileContext* get_file(snort::Flow*, uint64_t file_id, bool to_create, bool using_cache_entry);
     FileVerdict cached_verdict_lookup(snort::Packet*, snort::FileInfo*,
         snort::FilePolicyBase*,const uint8_t* current_data, uint32_t current_data_len);
     bool apply_verdict(snort::Packet*, snort::FileContext*, FileVerdict, bool resume,
         snort::FilePolicyBase*);
+    
 
-private:
-    snort::FileContext* add(const FileHashKey&, int64_t timeout, bool &cache_full);
-    snort::FileContext* find(const FileHashKey&, int64_t);
+private: 
+    snort::FileContext* find(const FileHashKey&, int64_t, int64_t& cache_expire);
     snort::FileContext* find_add(const FileHashKey&, int64_t);
     snort::FileContext* get_file(snort::Flow*, uint64_t file_id, bool to_create,
-        int64_t timeout, bool using_cache_entry, bool &cache_full);
+        int64_t timeout, bool using_cache_entry, bool &cache_full, int64_t& cache_expire);
     FileVerdict check_verdict(snort::Packet*, snort::FileInfo*, snort::FilePolicyBase*,const uint8_t* current_data, uint32_t current_data_len);
     int store_verdict(snort::Flow*, snort::FileInfo*, int64_t timeout, bool &cache_full);
+    void publish_file_cache_event(snort::Flow* flow, snort::FileInfo* file, int64_t timeout);
 
     /* The hash table of expected files */
     ExpectedFileCache* fileHash = nullptr;
diff --git a/src/file_api/file_cache_share.cc b/src/file_api/file_cache_share.cc
new file mode 100644 (file)
index 0000000..fb5ab14
--- /dev/null
@@ -0,0 +1,81 @@
+//--------------------------------------------------------------------------
+// Copyright (C) 2016-2025 Cisco and/or its affiliates. All rights reserved.
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License Version 2 as published
+// by the Free Software Foundation.  You may not use, modify or distribute
+// this program under any other version of the GNU General Public License.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+//--------------------------------------------------------------------------
+//  file_cache_share.cc author Shilpa Nagpal <shinagpa@cisco.com>
+
+
+#include "config.h"
+
+#include "file_cache_share.h"
+#include "file_service.h"
+#include "log/messages.h"
+
+using namespace snort;
+
+void FileCacheShare::handle(DataEvent& de, Flow*)
+{
+    FileMPEvent& fe = static_cast<FileMPEvent&>(de);
+    int64_t timeout = fe.get_timeout();
+    FileHashKey key = fe.get_hashkey();
+    FileInfo file = fe.get_file_ctx();
+
+    LogMessage("File Cache Sharing: Received event with file_id %lu\n", key.file_id);
+
+    FileCache* file_cache = FileService::get_file_cache();
+    if (file_cache)
+    {
+        bool cache_full = false;
+        int64_t cache_expire = 0;
+        FileContext* file_got = file_cache->add(key, timeout, cache_full, cache_expire, ins);
+        if (file_got)
+        {    
+            *((FileInfo*)(file_got)) = file;
+        }
+    }
+}
+
+bool serialize_file_event(snort::DataEvent* event, char*& buffer, uint16_t* len)
+{
+    if (!event)
+        return false;
+
+    snort::FileMPEvent* file_event = static_cast<snort::FileMPEvent*>(event);
+    uint16_t event_buffer_len = file_event->get_data_len();
+    if (event_buffer_len == 0)
+        return false;
+    
+    buffer = new char[event_buffer_len];
+    if (!buffer)
+        return false;
+
+    file_event->serialize(buffer, len);
+    return true;
+}
+
+bool deserialize_file_event(const char* buffer, uint16_t len, snort::DataEvent*& event)
+{
+    if (!buffer || len == 0)
+        return false;
+
+    snort::FileMPEvent* file_event = new snort::FileMPEvent();
+    if (!file_event)
+        return false;
+
+    file_event->deserialize(buffer, len);
+    event = file_event;
+    return true;
+}
diff --git a/src/file_api/file_cache_share.h b/src/file_api/file_cache_share.h
new file mode 100644 (file)
index 0000000..a8c5d44
--- /dev/null
@@ -0,0 +1,40 @@
+//--------------------------------------------------------------------------
+// Copyright (C) 2016-2025 Cisco and/or its affiliates. All rights reserved.
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License Version 2 as published
+// by the Free Software Foundation.  You may not use, modify or distribute
+// this program under any other version of the GNU General Public License.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+//--------------------------------------------------------------------------
+
+// file_cache.h author Shilpa Nagpal <shinagpa@cisco.com>
+
+#ifndef FILE_CACHE_SHARE_H
+#define FILE_CACHE_SHARE_H
+
+#include "framework/mp_data_bus.h"
+#include "pub_sub/file_events.h"
+
+class FileCacheShare : public snort::DataHandler
+{
+public:
+    FileCacheShare(FileInspect* fi) : DataHandler(FILE_ID_NAME) { ins = fi; }
+    void handle(snort::DataEvent&, snort::Flow*) override;
+private:
+    FileInspect* ins;
+};
+
+bool serialize_file_event(snort::DataEvent* event, char*& buffer, uint16_t* len);
+bool deserialize_file_event(const char* buffer, uint16_t len, snort::DataEvent*& event);
+
+#endif
+
index 1199f37e3a172b2e73faa01df944cf0671f5e61b..3b6e4d73a5f07cdf6b93134513261ebd996ae091 100644 (file)
@@ -36,6 +36,7 @@
 #include "file_flows.h"
 #include "file_module.h"
 #include "file_service.h"
+#include "file_cache_share.h"
 
 using namespace snort;
 
@@ -65,6 +66,14 @@ bool FileInspect::configure(SnortConfig* sc)
 
     FileService::set_max_file_depth(sc);
 
+    if(sc->mp_dbus)
+    {
+        MPSerializeFunc serialize_func = serialize_file_event;
+        MPDeserializeFunc deserialize_func = deserialize_file_event;
+
+        MPDataBus::register_event_helpers(file_pub_key, FileMPEvents::FILE_SHARE_SYNC, serialize_func, deserialize_func);
+        MPDataBus::subscribe(file_pub_key, FileMPEvents::FILE_SHARE_SYNC, new FileCacheShare(this));
+    }
     return true;
 }
 
index aef805a1cf2eaa17c3b062077fe9bd83a5f21f35..7de1d912f76479a4f6e6a8f64f3ff3e2fe5a2d50 100644 (file)
@@ -45,7 +45,6 @@
 #include "protocols/packet.h"
 #include "pub_sub/intrinsic_event_ids.h"
 #include "utils/util.h"
-
 #ifdef UNIT_TEST
 #include "catch/snort_catch.h"
 #endif
@@ -153,6 +152,104 @@ void FileInfo::copy(const FileInfo& other, bool clear_data)
     }
 }
 
+void FileInfo::serialize(char* buffer, uint16_t* len)
+{
+    int offset = *len;
+
+    auto write_bool = [&](bool val) {
+        memcpy(buffer + offset, &val, sizeof(val));
+        offset += sizeof(val);
+    };
+
+    auto write_string = [&](const std::string& str, bool is_set) {
+        write_bool(is_set);
+        if (is_set)
+        {
+            uint32_t len = static_cast<uint32_t>(str.length());
+            memcpy(buffer + offset, &len, sizeof(len));
+            offset += sizeof(len);
+            memcpy(buffer + offset, str.data(), len);
+            offset += len;
+        }
+    };
+
+    memcpy(buffer + offset,(uint16_t *) sha256, SHA256_HASH_SIZE); 
+    offset += SHA256_HASH_SIZE;
+    memcpy(buffer + offset, &verdict, sizeof(verdict)); 
+    offset += sizeof(verdict);
+    memcpy(buffer + offset, &file_size, sizeof(file_size)); 
+    offset += sizeof(file_size);
+    memcpy(buffer + offset, &direction, sizeof(direction)); 
+    offset += sizeof(direction);
+    memcpy(buffer + offset, &file_id, sizeof(file_id));
+    offset += sizeof(file_id);
+    memcpy(buffer + offset, &file_type_id, sizeof(file_type_id)); 
+    offset += sizeof(file_type_id);
+    memcpy(buffer + offset, &file_state.capture_state, sizeof(file_state.capture_state)); 
+    offset += sizeof(file_state.capture_state);
+    memcpy(buffer + offset, &file_state.sig_state, sizeof(file_state.sig_state)); 
+    offset += sizeof(file_state.sig_state);
+    memcpy(buffer + offset, &policy_id, sizeof(policy_id));
+    offset += sizeof(policy_id);
+    write_string(file_name, file_name_set);
+    write_string(url, url_set);
+    write_string(host_name, host_set);
+    write_bool(file_type_enabled);
+    write_bool(file_signature_enabled);
+    write_bool(file_capture_enabled);
+    write_bool(is_partial);
+
+    *len = offset;
+}
+
+void FileInfo::deserialize(const char* buffer, uint16_t& offset)
+{
+    auto read_bool = [&](bool& val) {
+        memcpy(&val, buffer + offset, sizeof(val));
+        offset += sizeof(val);
+    };
+
+    auto read_string = [&](std::string& str, bool& is_set) {
+        read_bool(is_set);
+        if (is_set)
+        {
+            uint32_t len = 0;
+            memcpy(&len, buffer + offset, sizeof(len));
+            offset += sizeof(len);
+            str.assign(buffer + offset, len);
+            offset += len;
+        }
+    };
+
+    if (!sha256)
+        sha256 = new uint8_t[SHA256_HASH_SIZE];  
+    memcpy(sha256, (const uint8_t *)(buffer + offset), SHA256_HASH_SIZE);
+    offset += SHA256_HASH_SIZE;
+    memcpy(&verdict, buffer + offset, sizeof(verdict)); 
+    offset += sizeof(verdict);
+    memcpy(&file_size, buffer + offset, sizeof(file_size)); 
+    offset += sizeof(file_size);
+    memcpy(&direction, buffer + offset, sizeof(direction)); 
+    offset += sizeof(direction);
+    memcpy(&file_id, buffer + offset, sizeof(file_id));
+    offset += sizeof(file_id);
+    memcpy(&file_type_id, buffer + offset, sizeof(file_type_id)); 
+    offset += sizeof(file_type_id);
+    memcpy(&file_state.capture_state, buffer + offset, sizeof(file_state.capture_state)); 
+    offset += sizeof(file_state.capture_state);
+    memcpy(&file_state.sig_state, buffer + offset, sizeof(file_state.sig_state)); 
+    offset += sizeof(file_state.sig_state);
+    memcpy(&policy_id, buffer + offset, sizeof(policy_id));
+    offset += sizeof(policy_id);
+    read_string(file_name, file_name_set);
+    read_string(url, url_set);
+    read_string(host_name, host_set);
+    read_bool(file_type_enabled);
+    read_bool(file_signature_enabled);
+    read_bool(file_capture_enabled);
+    read_bool(is_partial);
+}
+
 FileInfo::FileInfo(const FileInfo& other)
 {
     copy(other);
@@ -379,6 +476,17 @@ UserFileDataBase* FileInfo::get_file_data() const
     return user_file_data;
 }
 
+FileContext::FileContext (FileInspect* ins)
+{
+    file_type_context = nullptr;
+    file_signature_context = nullptr;
+    file_capture = nullptr;
+    file_segments = nullptr;
+    inspector = ins;
+    ins->add_global_ref();
+    config = ins->config;
+}
+
 FileContext::FileContext ()
 {
     file_type_context = nullptr;
index 063a99656c6ec418c08c5f804135b695a6895b6d..8a224da6a32cfb08ccf965854e70ec2f15553893 100644 (file)
@@ -115,6 +115,9 @@ public:
     void set_partial_flag(bool partial);
     bool is_partial_download() const;
 
+    void serialize(char* buffer, uint16_t* offset);
+    void deserialize(const char* buffer, uint16_t& offset);
+
 protected:
     std::string file_name;
     bool file_name_set = false;
@@ -146,6 +149,7 @@ class SO_PUBLIC FileContext : public FileInfo
 {
 public:
     FileContext();
+    FileContext (FileInspect* ins);
     ~FileContext() override;
 
     void check_policy(Flow*, FileDirection, FilePolicyBase*);
index d85449e2dec3d411b9270fc56dc8fd8ab255cb23..44db0cb218009be512bcce7d76a3a874c158f51a 100644 (file)
@@ -35,6 +35,8 @@ set (PUB_SUB_INCLUDES
     ssh_events.h
     ssl_events.h
     dns_events.h
+    file_events.h
+    file_events_ids.h
 )
 
 add_library( pub_sub OBJECT
diff --git a/src/pub_sub/file_events.h b/src/pub_sub/file_events.h
new file mode 100644 (file)
index 0000000..f36cfe0
--- /dev/null
@@ -0,0 +1,126 @@
+//--------------------------------------------------------------------------
+// Copyright (C) 2022-2025 Cisco and/or its affiliates. All rights reserved.
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License Version 2 as published
+// by the Free Software Foundation.  You may not use, modify or distribute
+// this program under any other version of the GNU General Public License.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+//--------------------------------------------------------------------------
+
+// http_event_ids.h author Shilpa Nagpal <shinagpa@cisco.com>
+
+// File events published by File Service for MP snort support.
+
+#ifndef FILE_MP_EVENTS_H
+#define FILE_MP_EVENTS_H
+
+#include "framework/mp_data_bus.h"
+#include "file_events_ids.h"
+#include "file_api/file_cache.h"
+#include "hash/hashes.h"
+
+namespace snort
+{
+
+class SO_PUBLIC FileMPEvent : public snort::DataEvent
+{
+    public:
+
+    FileMPEvent(const FileHashKey& key, int64_t tm, FileInfo& file) : timeout(tm), hashkey(key), file_ctx(file)
+    { 
+        len = sizeof(timeout) + sizeof(hashkey.sip) + sizeof(hashkey.sgroup) + 
+              sizeof(hashkey.dip) + sizeof(hashkey.dgroup) +
+              sizeof(hashkey.file_id) + sizeof(hashkey.asid) + sizeof(hashkey.padding) +
+              sizeof(file) + SHA256_HASH_SIZE;
+    }
+
+    FileMPEvent() : hashkey()
+    {
+       timeout = 0;
+        len = 0;
+    }
+
+    int64_t get_timeout()
+    {
+         return timeout;
+    }
+
+    FileInfo get_file_ctx()
+    {
+        return file_ctx;
+    }
+
+    FileHashKey get_hashkey()
+    {
+        return hashkey;
+    }
+
+    uint16_t get_data_len()
+    {
+        return len;
+    }
+
+    void deserialize(const char* d, uint16_t len)
+    {
+        uint16_t offset = 0;
+        memcpy(&timeout, d, sizeof(timeout));
+        offset += sizeof(timeout);
+        memcpy(&hashkey.sip, d + offset, sizeof(hashkey.sip));
+        offset += sizeof(hashkey.sip);
+        memcpy(&hashkey.sgroup, d + offset, sizeof(hashkey.sgroup));
+        offset += sizeof(hashkey.sgroup);
+        memcpy(&hashkey.dip, d + offset, sizeof(hashkey.dip));
+        offset += sizeof(hashkey.dip);
+        memcpy(&hashkey.dgroup, d + offset, sizeof(hashkey.dgroup));
+        offset += sizeof(hashkey.dgroup);
+        memcpy(&hashkey.file_id, d + offset, sizeof(hashkey.file_id));
+        offset += sizeof(hashkey.file_id);
+        memcpy(&hashkey.asid, d + offset, sizeof(hashkey.asid));
+        offset += sizeof(hashkey.asid);
+        memcpy(&hashkey.padding, d + offset, sizeof(hashkey.padding));
+        offset += sizeof(hashkey.padding);
+        file_ctx.deserialize(d, offset);
+        this->len = len;
+    }
+
+    void serialize(char* buffer, uint16_t* len)
+    {
+        uint16_t offset = 0;
+        memcpy(buffer, &timeout, sizeof(timeout));
+        offset += sizeof(timeout);
+        memcpy(buffer + offset, &hashkey.sip, sizeof(hashkey.sip));
+        offset += sizeof(hashkey.sip);
+        memcpy(buffer + offset, &hashkey.sgroup, sizeof(hashkey.sgroup));
+        offset += sizeof(hashkey.sgroup);
+        memcpy(buffer + offset, &hashkey.dip, sizeof(hashkey.dip));
+        offset += sizeof(hashkey.dip);
+        memcpy(buffer + offset, &hashkey.dgroup, sizeof(hashkey.dgroup));
+        offset += sizeof(hashkey.dgroup);
+        memcpy(buffer + offset, &hashkey.file_id, sizeof(hashkey.file_id));
+        offset += sizeof(hashkey.file_id);
+        memcpy(buffer + offset, &hashkey.asid, sizeof(hashkey.asid));
+        offset += sizeof(hashkey.asid);
+        memcpy(buffer + offset, &hashkey.padding, sizeof(hashkey.padding));
+        offset += sizeof(hashkey.padding);
+        file_ctx.serialize(buffer, &offset);
+        *len = offset;
+    }
+
+    private:
+        int64_t timeout;
+        FileHashKey hashkey;
+        FileInfo file_ctx;
+        uint16_t len;
+};
+
+}
+#endif
diff --git a/src/pub_sub/file_events_ids.h b/src/pub_sub/file_events_ids.h
new file mode 100644 (file)
index 0000000..c57f91f
--- /dev/null
@@ -0,0 +1,43 @@
+//--------------------------------------------------------------------------
+// Copyright (C) 2022-2025 Cisco and/or its affiliates. All rights reserved.
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License Version 2 as published
+// by the Free Software Foundation.  You may not use, modify or distribute
+// this program under any other version of the GNU General Public License.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+//--------------------------------------------------------------------------
+
+// http_event_ids.h author Shilpa Nagpal <shinagpa@cisco.com>
+
+// File events published by File Service for MP snort support.
+
+#ifndef FILE_MP_EVENTS_IDS_H
+#define FILE_MP_EVENTS_IDS_H
+
+#include "framework/mp_data_bus.h"
+
+namespace snort
+{
+
+struct FileMPEvents
+{ enum : unsigned {
+    
+    FILE_SHARE = 0,
+    FILE_SHARE_SYNC,
+    num_ids
+}; };
+
+const PubKey file_pub_key { "file_mp_events", FileMPEvents::num_ids };
+
+}
+#endif
+