]> git.ipfire.org Git - thirdparty/snort3.git/commitdiff
Merge pull request #2605 in SNORT/snort3 from ~SATHIRKA/snort3:rna_dhcp_fp_framework...
authorShravan Rangarajuvenkata (shrarang) <shrarang@cisco.com>
Mon, 16 Nov 2020 23:20:46 +0000 (23:20 +0000)
committerShravan Rangarajuvenkata (shrarang) <shrarang@cisco.com>
Mon, 16 Nov 2020 23:20:46 +0000 (23:20 +0000)
Squashed commit of the following:

commit 1b3cbac56c1965b568232d886c6bb5913c18e5c9
Author: Sreeja Athirkandathil Narayanan <sathirka@cisco.com>
Date:   Mon Sep 21 17:29:55 2020 -0400

    rna: Support DHCP fingerprint matching and event generation

26 files changed:
src/host_tracker/host_tracker.cc
src/host_tracker/host_tracker.h
src/network_inspectors/appid/appid_session.h
src/network_inspectors/appid/service_plugins/service_bootp.cc
src/network_inspectors/appid/service_plugins/service_bootp.h
src/network_inspectors/rna/CMakeLists.txt
src/network_inspectors/rna/dev_notes.txt
src/network_inspectors/rna/rna_config.h
src/network_inspectors/rna/rna_event_handler.cc
src/network_inspectors/rna/rna_event_handler.h
src/network_inspectors/rna/rna_fingerprint.h
src/network_inspectors/rna/rna_fingerprint_udp.cc [new file with mode: 0644]
src/network_inspectors/rna/rna_fingerprint_udp.h [new file with mode: 0644]
src/network_inspectors/rna/rna_inspector.cc
src/network_inspectors/rna/rna_inspector.h
src/network_inspectors/rna/rna_logger.cc
src/network_inspectors/rna/rna_logger.h
src/network_inspectors/rna/rna_logger_common.h
src/network_inspectors/rna/rna_module.cc
src/network_inspectors/rna/rna_module.h
src/network_inspectors/rna/rna_pnd.cc
src/network_inspectors/rna/rna_pnd.h
src/network_inspectors/rna/test/rna_module_mock.h
src/network_inspectors/rna/test/rna_module_test.cc
src/pub_sub/CMakeLists.txt
src/pub_sub/dhcp_events.h [new file with mode: 0644]

index 8a3322ee24d2a64e43c065f1527b67a131cb7f91..478b2e01613b30245bc48e1c21c00606b7828301 100644 (file)
@@ -769,6 +769,13 @@ bool HostTracker::add_tcp_fingerprint(uint32_t fpid)
     return result.second;
 }
 
+bool HostTracker::add_udp_fingerprint(uint32_t fpid)
+{
+    lock_guard<mutex> lck(host_tracker_lock);
+    auto result = udp_fpids.emplace(fpid);
+    return result.second;
+}
+
 bool HostTracker::set_visibility(bool v)
 {
     std::lock_guard<std::mutex> lck(host_tracker_lock);
@@ -1183,4 +1190,12 @@ void HostTracker::stringify(string& str)
             str += string(")") + (--total ? ", " : "");
         }
     }
+
+    total = udp_fpids.size();
+    if ( total )
+    {
+        str += "\nudp fingerprint: ";
+        for ( const auto& fpid : udp_fpids )
+            str += to_string(fpid) + (--total ? ", " : "");
+    }
 }
index e8c59329737e0429886d7a93ce7e280b8a8c6606..ea8f8793454bb800b7a625bbd7ad201890425568 100644 (file)
@@ -335,6 +335,7 @@ public:
     bool add_tcp_fingerprint(uint32_t fpid);
     bool add_ua_fingerprint(uint32_t fpid, uint32_t fp_type, bool jail_broken,
         const char* device_info, uint8_t max_devices);
+    bool add_udp_fingerprint(uint32_t fpid);
 
     //  This should be updated whenever HostTracker data members are changed
     void stringify(std::string& str);
@@ -425,6 +426,7 @@ private:
     std::vector<HostApplication, HostAppAllocator> services;
     std::vector<HostClient, HostClientAllocator> clients;
     std::set<uint32_t, std::less<uint32_t>, HostCacheAllocIp<uint32_t>> tcp_fpids;
+    std::set<uint32_t, std::less<uint32_t>, HostCacheAllocIp<uint32_t>> udp_fpids;
     std::vector<DeviceFingerprint, HostDeviceFpAllocator> ua_fps;
 
     bool vlan_tag_present = false;
index 31ad3525d949a3ca6926d9f01b91c8329f982242..c0407c64c106fe7e97c6d40a93616b71c21adc06 100644 (file)
@@ -65,9 +65,7 @@ const uint8_t* service_strstr(const uint8_t* haystack, unsigned haystack_len,
 #define MAX_SFTP_PACKET_COUNT   55
 
 #define APPID_SESSION_DATA_NONE                  0
-#define APPID_SESSION_DATA_DHCP_FP_DATA          2
 #define APPID_SESSION_DATA_SMB_DATA              4
-#define APPID_SESSION_DATA_DHCP_INFO             5
 #define APPID_SESSION_DATA_SERVICE_MODSTATE_BIT  0x20000000
 #define APPID_SESSION_DATA_CLIENT_MODSTATE_BIT   0x40000000
 #define APPID_SESSION_DATA_DETECTOR_MODSTATE_BIT 0x80000000
index 156a04033cdb16ad10ba2cec12b0d9ac8250d7b8..5051dcd6ec46b3145ab6d7417c8b437ba89fa1e4 100644 (file)
 
 #include "service_bootp.h"
 
+#include "detection/detection_engine.h"
+#include "protocols/eth.h"
+#include "protocols/packet.h"
+#include "pub_sub/dhcp_events.h"
 #include "app_info_table.h"
 #include "appid_config.h"
 #include "appid_inspector.h"
 #include "appid_utils/ip_funcs.h"
-#include "protocols/eth.h"
-#include "protocols/packet.h"
 
 using namespace snort;
 
@@ -160,8 +162,7 @@ int BootpServiceDetector::validate(AppIdDiscoveryArgs& args)
 
                         if (option53 && op55_len && (memcmp(eh->ether_src, bh->chaddr, 6) == 0))
                         {
-                            if (add_dhcp_info(args.asd, op55_len, op55, op60_len, op60, bh->chaddr))
-                                return APPID_ENOMEM;
+                            add_dhcp_info(args.asd, op55_len, op55, op60_len, op60, bh->chaddr);
                         }
                         goto inprocess;
                     }
@@ -306,39 +307,19 @@ not_compatible:
     return APPID_NOT_COMPATIBLE;
 }
 
-void BootpServiceDetector::AppIdFreeDhcpData(DHCPData* dd)
-{
-    snort_free(dd);
-}
-
-void BootpServiceDetector::AppIdFreeDhcpInfo(DHCPInfo* dd)
-{
-    snort_free(dd);
-}
-
-int BootpServiceDetector::add_dhcp_info(AppIdSession& asd, unsigned op55_len, const uint8_t* op55,
+void BootpServiceDetector::add_dhcp_info(AppIdSession& asd, unsigned op55_len, const uint8_t* op55,
     unsigned op60_len, const uint8_t* op60, const uint8_t* mac)
 {
     if (op55_len && op55_len <= DHCP_OPTION55_LEN_MAX
         && !asd.get_session_flags(APPID_SESSION_HAS_DHCP_FP))
     {
-        DHCPData* rdd = (DHCPData*)snort_calloc(sizeof(*rdd));
-        if (asd.add_flow_data(rdd, APPID_SESSION_DATA_DHCP_FP_DATA,
-            (AppIdFreeFCN)BootpServiceDetector::AppIdFreeDhcpData))
-        {
-            BootpServiceDetector::AppIdFreeDhcpData(rdd);
-            return -1;
-        }
-
         asd.set_session_flags(APPID_SESSION_HAS_DHCP_FP);
-        rdd->op55_len = (op55_len > DHCP_OP55_MAX_SIZE) ? DHCP_OP55_MAX_SIZE : op55_len;
-        memcpy(rdd->op55, op55, rdd->op55_len);
-        rdd->op60_len =  (op60_len > DHCP_OP60_MAX_SIZE) ? DHCP_OP60_MAX_SIZE : op60_len;
-        if (op60_len)
-            memcpy(rdd->op60, op60, rdd->op60_len);
-        memcpy(rdd->eth_addr, mac, sizeof(rdd->eth_addr));
+        unsigned op55_length = (op55_len > DHCP_OP55_MAX_SIZE) ? DHCP_OP55_MAX_SIZE : op55_len;
+        unsigned op60_length = (op60_len > DHCP_OP60_MAX_SIZE) ? DHCP_OP60_MAX_SIZE : op60_len;
+        Packet* p = DetectionEngine::get_current_packet();
+        DHCPDataEvent event(p, op55_length, op60_length, op55, op60, mac);
+        DataBus::publish(DHCP_DATA_EVENT, event, p->flow);
     }
-    return 0;
 }
 
 static unsigned isIPv4HostMonitored(uint32_t, int32_t)
@@ -351,8 +332,6 @@ void BootpServiceDetector::add_new_dhcp_lease(AppIdSession& asd, const uint8_t*
     int32_t zone,
     uint32_t subnetmask, uint32_t leaseSecs, uint32_t router)
 {
-    DHCPInfo* info;
-
     if (memcmp(mac, zeromac, 6) == 0 || ip == 0)
         return;
 
@@ -364,19 +343,9 @@ void BootpServiceDetector::add_new_dhcp_lease(AppIdSession& asd, const uint8_t*
     if (!(flags & IPFUNCS_HOSTS_IP))
         return;
 
-    info = (DHCPInfo*)snort_calloc(sizeof(DHCPInfo));
-
-    if (asd.add_flow_data(info, APPID_SESSION_DATA_DHCP_INFO,
-        (AppIdFreeFCN)BootpServiceDetector::AppIdFreeDhcpInfo))
-    {
-        BootpServiceDetector::AppIdFreeDhcpInfo(info);
-        return;
-    }
     asd.set_session_flags(APPID_SESSION_HAS_DHCP_INFO);
-    info->ipAddr = ip;
-    memcpy(info->eth_addr, mac, sizeof(info->eth_addr));
-    info->subnetmask = subnetmask;
-    info->leaseSecs = leaseSecs;
-    info->router = router;
+    Packet* p = DetectionEngine::get_current_packet();
+    DHCPInfoEvent event(p, ip, mac, subnetmask, leaseSecs, router);
+    DataBus::publish(DHCP_INFO_EVENT,  event, p->flow);
 }
 
index 2e098af764e0daa5a5da37a78f0de5e700839c50..32aa6a211d6ea124636046d795257dc00cffee9f 100644 (file)
 
 #include "service_detector.h"
 
-#define DHCP_OP55_MAX_SIZE  64
-#define DHCP_OP60_MAX_SIZE  64
-
 class AppIdSession;
 class ServiceDiscovery;
 
-struct DHCPData
-{
-    DHCPData* next;
-    unsigned op55_len;
-    unsigned op60_len;
-    uint8_t op55[DHCP_OP55_MAX_SIZE];
-    uint8_t op60[DHCP_OP60_MAX_SIZE];
-    uint8_t eth_addr[6];
-};
-
-struct DHCPInfo
-{
-    DHCPInfo* next;
-    uint32_t ipAddr;
-    uint8_t eth_addr[6];
-    uint32_t subnetmask;
-    uint32_t leaseSecs;
-    uint32_t router;
-};
-
 class BootpServiceDetector : public ServiceDetector
 {
 public:
@@ -57,12 +34,8 @@ public:
 
     int validate(AppIdDiscoveryArgs&) override;
 
-    // FIXIT-L - move to service discovery class
-    static void AppIdFreeDhcpData(DHCPData*);
-    static void AppIdFreeDhcpInfo(DHCPInfo*);
-
 private:
-    int add_dhcp_info(AppIdSession&, unsigned op55_len, const uint8_t* op55, unsigned
+    void add_dhcp_info(AppIdSession&, unsigned op55_len, const uint8_t* op55, unsigned
         op60_len, const uint8_t* op60, const uint8_t* mac);
     void add_new_dhcp_lease(AppIdSession&, const uint8_t* mac, uint32_t ip, int32_t zone,
         uint32_t subnetmask, uint32_t leaseSecs, uint32_t router);
index 800fec670cb942f75bbf711ed5eef853fd8ecbc6..7cd8fc478b0f3f2ac40188833a0e9c4197af89ec 100644 (file)
@@ -2,6 +2,7 @@ set (RNA_INCLUDES
     rna_fingerprint.h
     rna_fingerprint_tcp.h
     rna_fingerprint_ua.h
+    rna_fingerprint_udp.h
     rna_inspector.h
     rna_logger.h
     rna_name.h
@@ -17,6 +18,7 @@ set ( RNA_SOURCES
     rna_fingerprint.h
     rna_fingerprint_tcp.cc
     rna_fingerprint_ua.cc
+    rna_fingerprint_udp.cc
     rna_inspector.cc
     rna_inspector.h
     rna_logger.cc
index 2f59c2cbefce1a6a07fc5de56f884979400835f7..de7c2cbe2a08f999010b350ab3eaf4fc63886bf8 100644 (file)
@@ -82,8 +82,6 @@ not return prior to that to avoid leaking any host trackers.
 Fingerprints
 
 Fingerprints are a sequence of features in network traffic used to identify a host's operating system.
-Currently only tcp fingerprints are supported, but future work may include udp fingerprints and
-user agent fingerprints.
 
 Tcp fingerprints are specified in lua and read by snort at configure time.
 Only the SYN and SYN-ACK packets are used for fingerprint matching. We refer to the SYN packet
@@ -234,3 +232,20 @@ looks like this:
     user_agent = { { substring = "CPU" }, { substring = "OS 3_0" }, { substring = "My Company" } },
     device = "My Mobile",
 }
+
+UDP fingerprints are of two types, namely DHCP and SMB. Currently only DHCP fingerprints are
+supported. Similar to TCP and user-agent based fingerprints, fingerprint patterns can be specified
+in the lua configuration. DHCP fingerprint matching is based on option fields present in DHCP
+Request packet and the updated lease information is obtained from the DHCP ACK packet. Appid
+module processes the DHCP request packet, parses the option 55 and option 60 fields and publishes
+the DHCPDataEvent. This triggers RNA fingerprint matching and event generation. While processing
+DHCP ACK packet, appid extracts the leased IP, netmask and lease time and publishes the DHCPInfoEvent.
+RNA generates the CHANGE_FULL_DHCP_INFO event with updated lease information.
+A sample DHCP fingerprint is shown below:
+{
+    fpid = 111,
+    uuid = "12345678-1234-1234-1234-123456789111",
+    type = 4,
+    dhcp55 = "1 121 3 6 15 119 252",
+    dhcp60 = "dhcp 5.1.4",
+}
index 781802c1356338202a4dbf593f39142cb7002c88..8c99ba0b94083c8b747535b17128dd0e1b910a61 100644 (file)
@@ -25,6 +25,7 @@ namespace snort
 {
 class TcpFpProcessor;
 class UaFpProcessor;
+class UdpFpProcessor;
 }
 
 struct RnaModuleConfig
@@ -34,6 +35,7 @@ struct RnaModuleConfig
     bool log_when_idle;
     snort::TcpFpProcessor* tcp_processor = nullptr;
     snort::UaFpProcessor* ua_processor = nullptr;
+    snort::UdpFpProcessor* udp_processor = nullptr;
 };
 
 // Give default values so that RNA can work even if rna_conf_path is not provided
index 72f8c93cbb7d9b9e8dcd44003234e0309a49ec29..3eb818406d96be57adfd1995f691d72bca401058 100644 (file)
@@ -23,6 +23,7 @@
 #endif
 
 #include "rna_event_handler.h"
+#include "pub_sub/dhcp_events.h"
 
 using namespace snort;
 
@@ -103,3 +104,17 @@ void RnaIdleEventHandler::handle(DataEvent& event, Flow*)
     ++rna_stats.change_host_update;
     pnd.generate_change_host_update();
 }
+
+void RnaDHCPInfoEventHandler::handle(DataEvent& event, Flow*)
+{
+    Profile profile(rna_perf_stats);
+    ++rna_stats.dhcp_info;
+    pnd.add_dhcp_info(event);
+}
+
+void RnaDHCPDataEventHandler::handle(DataEvent& event, Flow*)
+{
+    Profile profile(rna_perf_stats);
+    ++rna_stats.dhcp_data;
+    pnd.analyze_dhcp_fingerprint(event);
+}
index 980842bc28143be033430e5c8227c466461705ac..8bfb59600d4663d915f46b6f61b14bd1b5f51f4a 100644 (file)
@@ -126,4 +126,22 @@ private:
     RnaPnd& pnd;
 };
 
+class RnaDHCPInfoEventHandler : public snort::DataHandler
+{
+public:
+    RnaDHCPInfoEventHandler(RnaPnd& nd) : DataHandler(RNA_NAME), pnd(nd) { }
+    void handle(snort::DataEvent&, snort::Flow*) override;
+private:
+    RnaPnd& pnd;
+};
+
+class RnaDHCPDataEventHandler : public snort::DataHandler
+{
+public:
+    RnaDHCPDataEventHandler(RnaPnd& nd) : DataHandler(RNA_NAME), pnd(nd) { }
+    void handle(snort::DataEvent&, snort::Flow*) override;
+private:
+    RnaPnd& pnd;
+};
+
 #endif
index 3bb35452f53cf6ad3d42af34de7f2c102e93de36..73041d42676602b4d4d43860c9bf7f9e0b097e17 100644 (file)
@@ -144,6 +144,9 @@ public:
     std::string host_name;
     std::string device;
 
+    std::string dhcp55;
+    std::string dhcp60;
+
     void clear()
     {
         fpid = 0;
@@ -160,6 +163,8 @@ public:
         user_agent.clear();
         host_name.clear();
         device.clear();
+        dhcp55.clear();
+        dhcp60.clear();
     }
 };
 
diff --git a/src/network_inspectors/rna/rna_fingerprint_udp.cc b/src/network_inspectors/rna/rna_fingerprint_udp.cc
new file mode 100644 (file)
index 0000000..b27b4d9
--- /dev/null
@@ -0,0 +1,151 @@
+//--------------------------------------------------------------------------
+// Copyright (C) 2020-2020 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.
+//--------------------------------------------------------------------------
+
+// rna_fingerprint_udp.cc author Sreeja Athirkandathil Narayanan <sathirka@cisco.com>
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "rna_fingerprint_udp.h"
+
+#include <sstream>
+
+#ifdef UNIT_TEST
+#include "catch/snort_catch.h"
+#endif
+
+#include "main/thread.h"
+#include "pub_sub/dhcp_events.h"
+
+using namespace snort;
+using namespace std;
+
+static THREAD_LOCAL UdpFpProcessor* udp_fp_processor = nullptr;
+
+void set_udp_fp_processor(UdpFpProcessor* processor)
+{
+    udp_fp_processor = processor;
+}
+
+UdpFpProcessor* get_udp_fp_processor()
+{
+    return udp_fp_processor;
+}
+
+static void parse_fp_element(const string& data, vector<FpElement>& fpe)
+{
+    istringstream in(data);
+    string tok;
+    while ( in >> tok )
+        fpe.emplace_back(tok);
+}
+
+DHCPFingerprint::DHCPFingerprint(const RawFingerprint& rfp)
+{
+    fpid = rfp.fpid;
+    fpuuid = rfp.fpuuid;
+    fp_type = rfp.fp_type;
+    if (!rfp.dhcp55.empty())
+        parse_fp_element(rfp.dhcp55, dhcp55);
+    if (!rfp.dhcp60.empty())
+        dhcp60 = rfp.dhcp60;
+}
+
+void UdpFpProcessor::push(const RawFingerprint& rfp)
+{
+    if (rfp.fp_type == FpFingerprint::FpType::FP_TYPE_DHCP)
+    {
+        DHCPFingerprint dhcp_fp(rfp);
+        if (dhcp_fp.dhcp55.size() > DHCP_OP55_MAX_SIZE)
+            return;
+        push_dhcp_fp(dhcp_fp);   
+    }
+}
+
+static bool match_dhcp_options(const vector<FpElement>& options, const uint8_t* key_options)
+{
+    for (const auto& op : options)
+    {
+        if (op.d.value != *key_options++)
+            return false;
+    }
+    return true;
+}
+
+const DHCPFingerprint* UdpFpProcessor::match_dhcp_fingerprint(const FpDHCPKey& key) const
+{
+    if (key.dhcp55_len == 0 || key.dhcp55_len > DHCP_OP55_MAX_SIZE)
+        return nullptr;
+    uint32_t fptype = FpFingerprint::FpType::FP_TYPE_DHCP;
+    for (const auto& fp: dhcp_fps)
+    {
+        if (fptype == fp.fp_type && fp.dhcp55.size() == key.dhcp55_len and
+            match_dhcp_options(fp.dhcp55, key.dhcp55))
+        {
+            if (key.dhcp60 and !fp.dhcp60.empty())
+            {
+                if(fp.dhcp60.size() == key.dhcp60_len and
+                    !fp.dhcp60.compare((const char*) (key.dhcp60)))
+                    return &fp;
+            }
+            else if (fp.dhcp60.empty())
+                return &fp;
+        }
+    }
+    return nullptr;
+}
+
+#ifdef UNIT_TEST
+
+TEST_CASE("match_dhcp_fingerprint", "[rna_fingerprint_udp]")
+{
+    set_udp_fp_processor(new UdpFpProcessor);
+    UdpFpProcessor* processor = get_udp_fp_processor();
+
+    RawFingerprint rawfp;
+    rawfp.fpid = 111;
+    rawfp.fp_type = 4;
+    rawfp.fpuuid = "12345678-1234-1234-1234-123456789111";
+    rawfp.dhcp55 = "1 3 15 28 225";
+    rawfp.dhcp60 = "dhcp 5.1.2";
+    processor->push(rawfp);
+
+    FpDHCPKey key;
+    key.dhcp55_len = 0;
+    key.dhcp60 = (const uint8_t*) "dhcp 5.1.2";
+    key.dhcp60_len = 10;
+    // no dhcp55, only dhcp60 option, returns null
+    CHECK(processor->match_dhcp_fingerprint(key) == nullptr);
+
+    rawfp.fpid = 222;
+    rawfp.fp_type = 4;
+    rawfp.fpuuid = "12345678-1234-1234-1234-123456789222";
+    rawfp.dhcp55 = "1 2 45 121";
+    rawfp.dhcp60 = "dhcp 5.1.3";
+    processor->push(rawfp);
+
+    uint8_t op55[] = {1, 2, 45, 121};
+    key.dhcp55 = op55;
+    key.dhcp55_len = 4;
+    key.dhcp60 = (const uint8_t*) "dhcp 5.0";
+    key.dhcp60_len = 8;
+    //dhcp60 doesn't match, returns null
+    CHECK(processor->match_dhcp_fingerprint(key) == nullptr);
+}
+#endif
diff --git a/src/network_inspectors/rna/rna_fingerprint_udp.h b/src/network_inspectors/rna/rna_fingerprint_udp.h
new file mode 100644 (file)
index 0000000..6d4a3f2
--- /dev/null
@@ -0,0 +1,73 @@
+//--------------------------------------------------------------------------
+// Copyright (C) 2020-2020 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.
+//--------------------------------------------------------------------------
+
+// rna_fingerprint_udp.h author Sreeja Athirkandathil Narayanan <sathirka@cisco.com>
+
+#ifndef RNA_FINGERPRINT_UDP_H
+#define RNA_FINGERPRINT_UDP_H
+
+#include <string>
+#include <vector>
+
+#include "rna_fingerprint.h"
+
+namespace snort
+{
+class SO_PUBLIC DHCPFingerprint : public FpFingerprint
+{
+public:
+    DHCPFingerprint() = default;
+    DHCPFingerprint(const RawFingerprint& rfp);
+    std::vector<FpElement> dhcp55;
+    std::string dhcp60;
+
+    void clear() override
+    {
+        FpFingerprint::clear();
+        dhcp55.clear();
+        dhcp60.clear();
+    }
+};
+
+struct FpDHCPKey
+{
+    unsigned dhcp55_len;
+    unsigned dhcp60_len;
+    const uint8_t* dhcp55;
+    const uint8_t* dhcp60;
+};
+
+class SO_PUBLIC UdpFpProcessor
+{
+public:
+    void push(const RawFingerprint& rfp);
+    const DHCPFingerprint* match_dhcp_fingerprint(const FpDHCPKey&) const;
+
+    void push_dhcp_fp(DHCPFingerprint& dhcp_fp)
+    {
+        dhcp_fps.emplace_back(dhcp_fp);
+    }
+private:
+    std::vector<DHCPFingerprint> dhcp_fps;
+};
+
+}
+
+snort::UdpFpProcessor* get_udp_fp_processor();
+SO_PUBLIC void set_udp_fp_processor(snort::UdpFpProcessor*);
+#endif
index 3f4221fc38932e24304fe33c2a9f522e386c0dfd..4fbab04cefd136419053d3b495ff7b86d452562a 100644 (file)
 #include "main/snort.h"
 #include "managers/inspector_manager.h"
 #include "protocols/packet.h"
+#include "pub_sub/dhcp_events.h"
 
 #include "rna_event_handler.h"
 #include "rna_fingerprint_tcp.h"
 #include "rna_fingerprint_ua.h"
+#include "rna_fingerprint_udp.h"
 #include "rna_module.h"
 #include "rna_pnd.h"
 
@@ -72,6 +74,7 @@ RnaInspector::~RnaInspector()
     {
         delete mod_conf->tcp_processor;
         delete mod_conf->ua_processor;
+        delete mod_conf->udp_processor;
         delete mod_conf;
     }
 }
@@ -79,6 +82,8 @@ RnaInspector::~RnaInspector()
 bool RnaInspector::configure(SnortConfig* sc)
 {
     DataBus::subscribe_global( APPID_EVENT_ANY_CHANGE, new RnaAppidEventHandler(*pnd), sc );
+    DataBus::subscribe_global( DHCP_INFO_EVENT, new RnaDHCPInfoEventHandler(*pnd), sc);
+    DataBus::subscribe_global( DHCP_DATA_EVENT, new RnaDHCPDataEventHandler(*pnd), sc);
 
     DataBus::subscribe_global( STREAM_ICMP_NEW_FLOW_EVENT, new RnaIcmpNewFlowEventHandler(*pnd), sc );
     DataBus::subscribe_global( STREAM_ICMP_BIDIRECTIONAL_EVENT, new RnaIcmpBidirectionalEventHandler(*pnd), sc );
@@ -139,6 +144,7 @@ void RnaInspector::tinit()
     // thread local initialization
     set_tcp_fp_processor(mod_conf->tcp_processor);
     set_ua_fp_processor(mod_conf->ua_processor);
+    set_udp_fp_processor(mod_conf->udp_processor);
 }
 
 void RnaInspector::tterm()
@@ -199,7 +205,8 @@ void RnaInspector::load_rna_conf()
     in_stream.close();
 }
 
-void RnaInspector::get_or_create_fp_processor(TcpFpProcessor*& tfp, UaFpProcessor*& uafp)
+void RnaInspector::get_or_create_fp_processor(TcpFpProcessor*& tfp, UaFpProcessor*& uafp,
+    UdpFpProcessor*& udpfp)
 {
     if ( !mod_conf )
         return;
@@ -208,12 +215,15 @@ void RnaInspector::get_or_create_fp_processor(TcpFpProcessor*& tfp, UaFpProcesso
         mod_conf->tcp_processor = new TcpFpProcessor;
     if ( !mod_conf->ua_processor )
         mod_conf->ua_processor = new UaFpProcessor;
+    if ( !mod_conf->udp_processor )
+        mod_conf->udp_processor = new UdpFpProcessor;
 
     tfp = mod_conf->tcp_processor;
     uafp = mod_conf->ua_processor;
+    udpfp = mod_conf->udp_processor;
 }
 
-void RnaInspector::set_fp_processor(TcpFpProcessor* tfp, UaFpProcessor* uafp)
+void RnaInspector::set_fp_processor(TcpFpProcessor* tfp, UaFpProcessor* uafp, UdpFpProcessor* udpfp)
 {
     if ( !mod_conf )
         return;
@@ -223,6 +233,9 @@ void RnaInspector::set_fp_processor(TcpFpProcessor* tfp, UaFpProcessor* uafp)
 
     delete mod_conf->ua_processor;
     mod_conf->ua_processor = uafp;
+
+    delete mod_conf->udp_processor;
+    mod_conf->udp_processor = udpfp;
 }
 
 //-------------------------------------------------------------------------
@@ -307,10 +320,12 @@ TEST_CASE("RNA inspector", "[rna_inspector]")
         RnaInspector ins(&mod);
         TcpFpProcessor* tfp = nullptr;
         UaFpProcessor* uafp = nullptr;
-        ins.set_fp_processor(tfp, uafp);
-        ins.get_or_create_fp_processor(tfp, uafp);
+        UdpFpProcessor* udpfp = nullptr;
+        ins.set_fp_processor(tfp, uafp, udpfp);
+        ins.get_or_create_fp_processor(tfp, uafp, udpfp);
         CHECK(tfp != nullptr);
         CHECK(uafp != nullptr);
+        CHECK(udpfp != nullptr);
     }
 }
 #endif
index 77a4ecff4007026d42469d91b3f5efa5f98a1970..227e34419096ff36dcecd6bdde48eeae16438f7b 100644 (file)
@@ -30,6 +30,7 @@ namespace snort
 struct Packet;
 class TcpFpProcessor;
 class UaFpProcessor;
+class UdpFpProcessor;
 }
 
 struct RnaConfig;
@@ -49,8 +50,9 @@ public:
     void tinit() override;
     void tterm() override;
 
-    void get_or_create_fp_processor(snort::TcpFpProcessor*&, snort::UaFpProcessor*&);
-    void set_fp_processor(snort::TcpFpProcessor*, snort::UaFpProcessor*);
+    void get_or_create_fp_processor(snort::TcpFpProcessor*&, snort::UaFpProcessor*&,
+        snort::UdpFpProcessor*&);
+    void set_fp_processor(snort::TcpFpProcessor*, snort::UaFpProcessor*, snort::UdpFpProcessor*);
 
 private:
     void load_rna_conf();
index e8ce65b4bd68903ab81c51b0e38bf0c6ae9fe06f..0aa52d041e9f80b454c5a190ac893f364defc85e 100644 (file)
@@ -60,8 +60,21 @@ static inline void rna_logger_message(const RnaLoggerEvent& rle, const Packet* p
         SfIpString ipbuf;
         ip.set(rle.ip); // using this instead of packet's ip to support ARP
         if ( rle.mac )
-            debug_logf(rna_trace, p, "RNA log: type %u, subtype %u, mac %s, ip %s\n",
-                rle.type, rle.subtype, macbuf, ip.ntop(ipbuf));
+        {
+            if (rle.type == RNA_EVENT_CHANGE and rle.subtype == CHANGE_FULL_DHCP_INFO)
+            {
+                SfIp router;
+                SfIpString routerbuf;
+                router.set(rle.router);
+                debug_logf(rna_trace, p, "RNA DHCP full information log: type %u, "
+                    "subtype %u, mac %s, ip %s, lease time %u, netmask %x, router %s\n",
+                    rle.type, rle.subtype, macbuf, ip.ntop(ipbuf), rle.lease,
+                    rle.netmask, router.ntop(routerbuf));
+            }
+            else
+                debug_logf(rna_trace, p, "RNA log: type %u, subtype %u, mac %s, ip %s\n",
+                    rle.type, rle.subtype, macbuf, ip.ntop(ipbuf));
+        }
         else
             debug_logf(rna_trace, p, "RNA log: type %u, subtype %u, ip %s\n",
                 rle.type, rle.subtype, ip.ntop(ipbuf));
@@ -170,11 +183,20 @@ void RnaLogger::log(uint16_t type, uint16_t subtype, const Packet* p, const uint
         nullptr, nullptr, nullptr, cond_var);
 }
 
+void RnaLogger::log(uint16_t type, uint16_t subtype, const snort::Packet* p, RnaTracker* ht,
+    const struct in6_addr* src_ip, const uint8_t* src_mac, uint32_t lease, uint32_t netmask,
+    const struct in6_addr* router)
+{
+    log(type, subtype, src_ip, src_mac, ht, p, 0, 0, nullptr, nullptr, nullptr, nullptr,
+        nullptr, nullptr, APP_ID_NONE, nullptr, false, lease, netmask, router);
+}
+
 bool RnaLogger::log(uint16_t type, uint16_t subtype, const struct in6_addr* src_ip,
     const uint8_t* src_mac, RnaTracker* ht, const Packet* p, uint32_t event_time,
     uint16_t proto, const HostMac* hm, const HostApplication* ha,
     const FpFingerprint* fp, void* cond_var, const HostClient* hc,
-    const char* user, AppId appid, const char* di, bool jb)
+    const char* user, AppId appid, const char* di, bool jb, uint32_t lease,
+    uint32_t netmask, const struct in6_addr* router)
 {
     if ( !enabled )
         return false;
@@ -182,7 +204,7 @@ bool RnaLogger::log(uint16_t type, uint16_t subtype, const struct in6_addr* src_
     assert(ht);
 
     RnaLoggerEvent rle(type, subtype, src_mac, ht, hm, proto, cond_var,
-        ha, fp, hc, user, appid, di, jb, p);
+        ha, fp, hc, user, appid, di, jb, lease, netmask, router, p);
     if ( src_ip and (!IN6_IS_ADDR_V4MAPPED(src_ip) or src_ip->s6_addr32[3]) )
         rle.ip = src_ip;
     else
index 5521ce47b0471d8c2057fe11ec834224bdf41fbb..ec68272546593f7c81943e8048baf3c22ec45fda 100644 (file)
@@ -38,9 +38,11 @@ struct RnaLoggerEvent : public Event
     RnaLoggerEvent (uint16_t t, uint16_t st, const uint8_t* mc, const RnaTracker* rt,
         const snort::HostMac* hmp, uint16_t pr, void* cv, const snort::HostApplication* hap,
         const snort::FpFingerprint* fpr, const snort::HostClient* hcp, const char* u,
-        int32_t app, const char* di, bool jb, const snort::Packet* p) : type(t), subtype(st),
+        int32_t app, const char* di, bool jb, uint32_t ls, uint32_t nm,
+        const struct in6_addr* rtr, const snort::Packet* p) : type(t), subtype(st),
         mac(mc), ht(rt), hm(hmp), proto(pr), cond_var(cv), ha(hap), fp(fpr), hc(hcp),
-        user(u), appid(app), device_info(di), jail_broken(jb), pkt(p) { }
+        user(u), appid(app), device_info(di), jail_broken(jb), lease(ls), netmask(nm),
+        router(rtr), pkt(p) { }
 
     uint32_t event_time = 0;
     uint16_t type;
@@ -58,6 +60,9 @@ struct RnaLoggerEvent : public Event
     AppId appid;
     const char* device_info;
     bool jail_broken;
+    uint32_t lease;
+    uint32_t netmask;
+    const struct in6_addr* router;
     const snort::Packet* pkt;
 };
 
@@ -101,6 +106,11 @@ public:
     void log(uint16_t type, uint16_t subtype, const snort::Packet* p, const uint8_t* src_mac,
         const struct in6_addr* src_ip, RnaTracker* ht, uint32_t event_time, void* cond_var);
 
+    // for dhcp info event
+    void log(uint16_t type, uint16_t subtype, const snort::Packet* p, RnaTracker* ht,
+        const struct in6_addr* src_ip, const uint8_t* src_mac, uint32_t lease, uint32_t netmask,
+        const struct in6_addr* router);
+
     // for all
     bool log(uint16_t type, uint16_t subtype, const struct in6_addr* src_ip,
         const uint8_t* src_mac, RnaTracker* ht, const snort::Packet* p = nullptr,
@@ -108,7 +118,8 @@ public:
         const snort::HostApplication* ha = nullptr, const snort::FpFingerprint* fp = nullptr,
         void* cond_var = nullptr, const snort::HostClient* hc = nullptr,
         const char* user = nullptr, AppId appid = APP_ID_NONE, const char* device_info = nullptr,
-        bool jail_broken = false);
+        bool jail_broken = false, uint32_t lease = 0, uint32_t netmask = 0,
+        const struct in6_addr* router = nullptr);
 
 private:
     const bool enabled;
index aee6625f803d2ea62573200cee25ad7b5d17173f..2792efeb6d04c33563a844f0239d634e5f9327b5 100644 (file)
@@ -41,6 +41,7 @@
     #define CHANGE_VLAN_TAG            18
     #define CHANGE_BANNER_UPDATE       24
     #define CHANGE_CLIENT_APP_UPDATE   32
+    #define CHANGE_FULL_DHCP_INFO      33
 
 #define RUA_EVENT         1004
     #define CHANGE_USER_LOGIN    2
index 0387ada9c0f009fef82f1a3fb9189ff1a2d9acb6..46d61e97e475f5b573097dfbd1285e267e0cb08a 100644 (file)
@@ -39,6 +39,7 @@
 
 #include "rna_fingerprint_tcp.h"
 #include "rna_fingerprint_ua.h"
+#include "rna_fingerprint_udp.h"
 #include "rna_mac_cache.h"
 
 #ifdef UNIT_TEST
@@ -82,6 +83,7 @@ bool FpProcReloadTuner::tinit()
 {
     set_tcp_fp_processor(mod_conf.tcp_processor);
     set_ua_fp_processor(mod_conf.ua_processor);
+    set_udp_fp_processor(mod_conf.udp_processor);
     return false;  // no work to do after this
 }
 
@@ -286,6 +288,12 @@ static const Parameter rna_fp_params[] =
     { "device", Parameter::PT_STRING, nullptr, nullptr,
       "device information" },
 
+    { "dhcp55", Parameter::PT_STRING, nullptr, nullptr,
+      "dhcp option 55 values" },
+
+    { "dhcp60", Parameter::PT_STRING, nullptr, nullptr,
+      "dhcp option 60 values" },
+
     { nullptr, Parameter::PT_MAX, nullptr, nullptr, nullptr }
 };
 
@@ -309,6 +317,9 @@ static const Parameter rna_params[] =
     { "ua_fingerprints", Parameter::PT_LIST, rna_fp_params, nullptr,
       "list of user agent fingerprints" },
 
+    { "udp_fingerprints", Parameter::PT_LIST, rna_fp_params, nullptr,
+      "list of udp fingerprints" },
+
     { nullptr, Parameter::PT_MAX, nullptr, nullptr, nullptr }
 };
 
@@ -326,6 +337,8 @@ static const PegInfo rna_pegs[] =
     { CountType::SUM, "tcp_midstream", "count of TCP midstream packets received" },
     { CountType::SUM, "other_packets", "count of packets received without session tracking" },
     { CountType::SUM, "change_host_update", "count number of change host update events" },
+    { CountType::SUM, "dhcp_data", "count of DHCP data events received" },
+    { CountType::SUM, "dhcp_info", "count of new DHCP lease events received" },
     { CountType::END, nullptr, nullptr},
 };
 
@@ -367,6 +380,12 @@ bool RnaModule::begin(const char* fqn, int, SnortConfig*)
         if (!mod_conf->ua_processor)
             mod_conf->ua_processor = new UaFpProcessor;
     }
+    else if (!strcmp(fqn, "rna.udp_fingerprints"))
+    {
+        fingerprint.clear();
+        if (!mod_conf->udp_processor)
+            mod_conf->udp_processor = new UdpFpProcessor;
+    }
 
     return true;
 }
@@ -386,7 +405,7 @@ bool RnaModule::set(const char* fqn, Value& v, SnortConfig*)
         dump_file = snort_strdup(v.get_string());
     }
     else if ( fqn and ( strstr(fqn, "rna.tcp_fingerprints") or
-        strstr(fqn, "rna.ua_fingerprints") ) )
+        strstr(fqn, "rna.ua_fingerprints") or strstr(fqn, "rna.udp_fingerprints") ) )
     {
         if (v.is("fpid"))
             fingerprint.fpid = v.get_uint32();
@@ -423,6 +442,10 @@ bool RnaModule::set(const char* fqn, Value& v, SnortConfig*)
                 return false;
             fingerprint.user_agent.emplace_back(ua_part);
         }
+        else if (v.is("dhcp55"))
+            fingerprint.dhcp55 = v.get_string();
+        else if (v.is("dhcp60"))
+            fingerprint.dhcp60 = v.get_string();
         else
             return false;
     }
@@ -469,6 +492,11 @@ bool RnaModule::end(const char* fqn, int index, SnortConfig* sc)
         mod_conf->ua_processor->push(fingerprint);
         fingerprint.clear();
     }
+    else if ( index > 0 and mod_conf->udp_processor and !strcmp(fqn, "rna.udp_fingerprints") )
+    {
+        mod_conf->udp_processor->push(fingerprint);
+        fingerprint.clear();
+    }
 
     return true;
 }
@@ -544,7 +572,8 @@ bool RnaModule::log_mac_cache(const char* outfile)
 bool RnaModule::is_valid_fqn(const char* fqn) const
 {
     return !strcmp(fqn, RNA_NAME) or !strcmp(fqn, "rna.tcp_fingerprints") or
-        !strcmp(fqn, "rna.ua_fingerprints") or !strcmp(fqn, "rna.ua_fingerprints.user_agent");
+        !strcmp(fqn, "rna.ua_fingerprints") or !strcmp(fqn, "rna.ua_fingerprints.user_agent") or
+        !strcmp(fqn, "rna.udp_fingerprints");
 }
 
 
index 4fbcd0baee65c07815368cfce6b917f6d75abc56..a3638b8f10f6739621f3553e740ee49f79a9765a 100644 (file)
@@ -44,6 +44,8 @@ struct RnaStats
     PegCount tcp_midstream;
     PegCount other_packets;
     PegCount change_host_update;
+    PegCount dhcp_data;
+    PegCount dhcp_info;
 };
 
 extern THREAD_LOCAL RnaStats rna_stats;
index 020ccef1a14e2cfb912dcceeaac4fba58cfb0a28..c63ddeb350e071403adb1c741dacb64569f1edd2 100644 (file)
@@ -37,6 +37,7 @@
 
 #include "rna_app_discovery.h"
 #include "rna_fingerprint_tcp.h"
+#include "rna_fingerprint_udp.h"
 #include "rna_logger_common.h"
 
 #ifdef UNIT_TEST
@@ -215,6 +216,83 @@ void RnaPnd::discover_network(const Packet* p, uint8_t ttl)
     }
 }
 
+void RnaPnd::analyze_dhcp_fingerprint(DataEvent& event)
+{
+    const Packet* p = event.get_packet();
+    const DHCPDataEvent& dhcp_data_event = static_cast<DHCPDataEvent&>(event);
+    const uint8_t* src_mac = dhcp_data_event.get_eth_addr();
+    bool new_host = false;
+    bool new_mac = false;
+    const auto& src_ip = p->ptrs.ip_api.get_src();
+    auto ht = host_cache.find_else_create(*src_ip, &new_host);
+    if (!new_host)
+        ht->update_last_seen();
+
+    MacKey mk(src_mac);
+    auto hm_ptr = host_cache_mac.find_else_create(mk, &new_mac);
+    if (new_mac)
+    {
+        ht->add_mac(mk.mac_addr, p->ptrs.ip_api.ttl(), 0);
+        logger.log(RNA_EVENT_NEW, NEW_HOST, p, &ht, nullptr, mk.mac_addr);
+        hm_ptr->update_last_event(p->pkth->ts.tv_sec);
+    }
+    else
+        hm_ptr->update_last_seen(p->pkth->ts.tv_sec);
+
+    const UdpFpProcessor* processor = get_udp_fp_processor();
+    if (!processor)
+        return;
+
+    FpDHCPKey key;
+    key.dhcp55_len = dhcp_data_event.get_op55_len();
+    key.dhcp55 = dhcp_data_event.get_op55();
+    key.dhcp60_len = dhcp_data_event.get_op60_len();
+    key.dhcp60 = dhcp_data_event.get_op60();
+
+    const DHCPFingerprint* dhcp_fp = processor->match_dhcp_fingerprint(key);
+    if (dhcp_fp and ht->add_udp_fingerprint(dhcp_fp->fpid))
+    {
+        const auto& src_ip_ptr = (const struct in6_addr*) src_ip->get_ip6_ptr();
+        logger.log(RNA_EVENT_NEW, NEW_OS, p, &ht, src_ip_ptr, src_mac, dhcp_fp, packet_time());
+    }
+}
+
+/* called for processing information extracted from DHCP Ack.
+   It is called only for IPv4 since DHCPv6 is not implemented.*/
+void RnaPnd::add_dhcp_info(DataEvent& event)
+{
+    const DHCPInfoEvent& dhcp_info_event = static_cast<DHCPInfoEvent&>(event);
+    const uint8_t* src_mac = dhcp_info_event.get_eth_addr();
+    uint32_t ip_address = dhcp_info_event.get_ip_address();
+    uint32_t net_mask = dhcp_info_event.get_subnet_mask();
+    uint32_t lease = dhcp_info_event.get_lease_secs();
+    uint32_t router = dhcp_info_event.get_router();
+    const Packet* p = event.get_packet();
+
+    SfIp leased_ip = {(void*)&ip_address, AF_INET};
+    SfIp router_ip = {(void*)&router, AF_INET};
+    bool new_host = false;
+    bool new_mac = false;
+    auto ht = host_cache.find_else_create(leased_ip, &new_host);
+    if (!new_host)
+        ht->update_last_seen();
+
+    MacKey mk(src_mac);
+    auto hm_ptr = host_cache_mac.find_else_create(mk, &new_mac);
+    if (new_mac)
+    {
+        ht->add_mac(mk.mac_addr, p->ptrs.ip_api.ttl(), 0);
+        logger.log(RNA_EVENT_NEW, NEW_HOST, p, &ht, nullptr, mk.mac_addr);
+        hm_ptr->update_last_event(p->pkth->ts.tv_sec);
+    }
+    else
+        hm_ptr->update_last_seen(p->pkth->ts.tv_sec);
+
+    logger.log(RNA_EVENT_CHANGE, CHANGE_FULL_DHCP_INFO, p, &ht,
+        (const struct in6_addr*) leased_ip.get_ip6_ptr(), src_mac,
+        lease, net_mask, (const struct in6_addr*) router_ip.get_ip6_ptr());
+}
+
 inline void RnaPnd::update_vlan(const Packet* p, HostTrackerMac& hm)
 {
     if ( !(p->proto_bits & PROTO_BIT__VLAN) )
index 591ddd44067641a69eb8be0e8d11cca328c8f637..6c70b0a6f14d4e03cebea539e04ffb95a8f4d380 100644 (file)
@@ -30,6 +30,7 @@
 #include "protocols/tcp.h"
 #include "protocols/vlan.h"
 #include "pub_sub/appid_events.h"
+#include "pub_sub/dhcp_events.h"
 #include "sfip/sf_ip.h"
 
 #include "rna_config.h"
@@ -126,6 +127,8 @@ public:
     void analyze_flow_non_ip(const snort::Packet*);
     void analyze_flow_tcp(const snort::Packet*, TcpPacketType);
     void analyze_flow_udp(const snort::Packet*);
+    void analyze_dhcp_fingerprint(snort::DataEvent&);
+    void add_dhcp_info(snort::DataEvent&);
 
     // generate change event for all hosts in the ip cache
     void generate_change_host_update();
index a80c4c1afc945e4b073d0a78862b627251b8f116..2bf28df521c1214b37a052d05ef9b0ea3f94307b 100644 (file)
@@ -72,6 +72,8 @@ UaFpProcessor::~UaFpProcessor() { }
 void UaFpProcessor::make_mpse(SnortConfig*) { }
 void UaFpProcessor::push(RawFingerprint const&) { }
 
+void UdpFpProcessor::push(RawFingerprint const&) { }
+
 // inspector
 class RnaInspector
 {
index 586adbca2d8634fc8a80e3af102140aa4ad4aa34..9a397595017a6f634b0c3492bec810fee81190af 100644 (file)
@@ -38,6 +38,7 @@
 
 void set_tcp_fp_processor(TcpFpProcessor*) { }
 void set_ua_fp_processor(UaFpProcessor*) { }
+void set_udp_fp_processor(UdpFpProcessor*) { }
 
 namespace snort
 {
index fe4a0ccdd1f9476adb864e2e3106e0ab8e5a089b..f319a71e817dd18e995edc3ac20692d8a22e3366 100644 (file)
@@ -4,6 +4,7 @@ set (PUB_SUB_INCLUDES
     data_decrypt_event.h
     daq_message_event.h
     dcerpc_events.h
+    dhcp_events.h
     expect_events.h
     finalize_packet_event.h
     http_events.h
diff --git a/src/pub_sub/dhcp_events.h b/src/pub_sub/dhcp_events.h
new file mode 100644 (file)
index 0000000..a6abba3
--- /dev/null
@@ -0,0 +1,114 @@
+//--------------------------------------------------------------------------
+// Copyright (C) 2020-2020 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.
+//--------------------------------------------------------------------------
+// dhcp_events.h author Sreeja Athirkandathil Narayanan <sathirka@cisco.com>
+
+#ifndef DHCP_EVENTS_H
+#define DHCP_EVENTS_H
+
+#include <cstring>
+#include "framework/data_bus.h"
+
+#define DHCP_DATA_EVENT "dhcp_data_event"
+#define DHCP_INFO_EVENT "dhcp_info_event"
+#define DHCP_OP55_MAX_SIZE  64
+#define DHCP_OP60_MAX_SIZE  64
+
+namespace snort
+{
+
+class DHCPInfoEvent : public snort::DataEvent
+{
+public:
+    DHCPInfoEvent(const snort::Packet* p, uint32_t ip_address, const uint8_t* eth,
+        uint32_t subnet_mask, uint32_t lease_secs, uint32_t router) :
+        pkt(p), ip_address(ip_address), subnet_mask(subnet_mask),
+        lease_secs(lease_secs), router(router)
+    {
+        memcpy(eth_addr, eth, sizeof(eth_addr));
+    }
+
+    const snort::Packet* get_packet() override
+    { return pkt; }
+
+    uint32_t get_ip_address() const
+    { return ip_address; }
+
+    const uint8_t* get_eth_addr() const
+    { return eth_addr; }
+
+    uint32_t get_subnet_mask() const
+    { return subnet_mask; }
+
+    uint32_t get_lease_secs() const
+    { return lease_secs; }
+
+    uint32_t get_router() const
+    { return router; }
+
+private:
+    const snort::Packet* pkt;
+    uint32_t ip_address;
+    uint8_t eth_addr[6];
+    uint32_t subnet_mask;
+    uint32_t lease_secs;
+    uint32_t router;
+};
+
+class DHCPDataEvent : public snort::DataEvent
+{
+public:
+    DHCPDataEvent(const snort::Packet* p, unsigned op55_len, unsigned op60_len,
+        const uint8_t* op55_val, const uint8_t* op60_val, const uint8_t* eth) : pkt(p),
+        op55_len(op55_len), op60_len(op60_len)
+    {
+        memcpy(op55, op55_val, op55_len);
+        if (op60_len)
+            memcpy(op60, op60_val, op60_len);
+        memcpy(eth_addr, eth, sizeof(eth_addr));
+    }
+
+    const snort::Packet* get_packet() override
+    { return pkt; }
+
+    unsigned get_op55_len() const
+    { return op55_len; }
+
+    unsigned get_op60_len() const
+    { return op60_len; }
+
+    const uint8_t* get_op55() const
+    { return op55; }
+
+    const uint8_t* get_op60() const
+    { return op60; }
+
+    const uint8_t* get_eth_addr() const
+    { return eth_addr; }
+
+private:
+    const snort::Packet* pkt;
+    unsigned op55_len;
+    unsigned op60_len;
+    uint8_t op55[DHCP_OP55_MAX_SIZE] = {0};
+    uint8_t op60[DHCP_OP60_MAX_SIZE] = {0};
+    uint8_t eth_addr[6];
+};
+
+}
+
+#endif // DHCP_EVENTS_H