smb_events.h
ssh_events.h
ssl_events.h
+ dns_events.h
)
add_library( pub_sub OBJECT
${PUB_SUB_INCLUDES}
cip_events.cc
http_events.cc
+ dns_events.cc
http_request_body_event.cc
sip_events.cc
)
--- /dev/null
+//--------------------------------------------------------------------------
+// Copyright (C) 2022-2023 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.
+//--------------------------------------------------------------------------
+// dns_events.cc author Serhii Vlasiuk <svlasiuk@cisco.com>
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "dns_events.h"
+
+#include "service_inspectors/dns/dns.h"
+
+using namespace snort;
+
+void IPFqdnCacheItem::add_ip(const SfIp& ip)
+{
+ if (ip.is_set())
+ ips.emplace_back(ip);
+}
+
+void IPFqdnCacheItem::add_fqdn(const FqdnTtl& fqdn_ttl)
+{
+ if (fqdn_ttl.fqdn.empty())
+ return;
+
+ if (std::find_if(fqdns.cbegin(), fqdns.cend(),
+ [&fqdn_ttl](const FqdnTtl& i){ return i.fqdn == fqdn_ttl.fqdn; }) != fqdns.end())
+ return;
+
+ fqdns.emplace_back(fqdn_ttl);
+}
+
+void DnsResponseDataEvents::add_ip(const DnsResponseIp& ip)
+{
+ dns_ips.emplace_back(ip);
+}
+
+void DnsResponseDataEvents::add_fqdn(DnsResponseFqdn& fqdn, uint32_t ttl)
+{
+ fqdn.update_ttl(ttl);
+ dns_fqdns.emplace_back(fqdn);
+}
+
+void DnsResponseDataEvents::get_dns_data(IPFqdnCacheItem& ip_fqdn_cache_item)
+{
+ for (auto& it: dns_ips)
+ ip_fqdn_cache_item.add_ip(it.get_ip());
+
+ // don't add fqdns without ips
+ if (ip_fqdn_cache_item.ips.empty())
+ return;
+
+ for (auto& it: dns_fqdns)
+ ip_fqdn_cache_item.add_fqdn(it.get_fqdn());
+}
+
+bool DnsResponseDataEvents::empty() const
+{
+ return (dns_ips.empty() or dns_fqdns.empty());
+}
--- /dev/null
+//--------------------------------------------------------------------------
+// Copyright (C) 2022-2023 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.
+//--------------------------------------------------------------------------
+// dns_events.h author Serhii Vlasiuk <svlasiuk@cisco.com>
+
+#ifndef DNS_EVENTS_H
+#define DNS_EVENTS_H
+
+// This event allows the dns service inspector to publish dns response
+// for use by data bus subscribers
+
+#include "framework/data_bus.h"
+#include "sfip/sf_ip.h"
+
+struct FqdnTtl
+{
+ FqdnTtl(const std::string& fqdn, uint32_t ttl) :
+ fqdn(fqdn), ttl(ttl)
+ {}
+
+ std::string fqdn;
+ uint32_t ttl;
+};
+
+struct IPFqdnCacheItem
+{
+ void add_ip(const snort::SfIp& ip);
+ void add_fqdn(const FqdnTtl& fqdn_ttl);
+
+ std::vector<snort::SfIp> ips;
+ std::vector<FqdnTtl> fqdns;
+};
+
+struct DnsEventIds
+{
+ enum : unsigned
+ {
+ DNS_RESPONSE_DATA,
+ num_ids
+ };
+};
+
+const snort::PubKey dns_pub_key { "dns", DnsEventIds::num_ids };
+
+class DnsResponseIp;
+class DnsResponseFqdn;
+
+namespace snort
+{
+class SO_PUBLIC DnsResponseDataEvents : public snort::DataEvent
+{
+public:
+ void add_ip(const DnsResponseIp& event);
+ void add_fqdn(DnsResponseFqdn& event, uint32_t ttl);
+ void get_dns_data(IPFqdnCacheItem& ip_fqdn_cache_item);
+ bool empty() const;
+
+private:
+ std::vector<DnsResponseIp> dns_ips;
+ std::vector<DnsResponseFqdn> dns_fqdns;
+};
+}
+
+#endif
$<TARGET_OBJECTS:cip>
$<TARGET_OBJECTS:dce_rpc>
$<TARGET_OBJECTS:dnp3>
- $<TARGET_OBJECTS:dns>
$<TARGET_OBJECTS:ftp_telnet>
$<TARGET_OBJECTS:gtp_inspect>
$<TARGET_OBJECTS:iec104>
$<TARGET_OBJECTS:http2_inspect>
$<TARGET_OBJECTS:sip>
$<TARGET_OBJECTS:ssl>
+ $<TARGET_OBJECTS:dns>
${STATIC_INSPECTOR_OBJS}
CACHE INTERNAL "STATIC_SERVICE_INSPECTOR_PLUGINS"
)
set( FILE_LIST
dns.cc
dns.h
+ dns_config.cc
+ dns_config.h
dns_module.cc
dns_module.h
dns_splitter.cc
dns_splitter.h
)
-if (STATIC_INSPECTORS)
- add_library( dns OBJECT ${FILE_LIST})
+# if (STATIC_INSPECTORS)
+add_library( dns OBJECT ${FILE_LIST})
-else (STATIC_INSPECTORS)
- add_dynamic_module(dns inspectors ${FILE_LIST})
+# else (STATIC_INSPECTORS)
+# add_dynamic_module(dns inspectors ${FILE_LIST})
-endif (STATIC_INSPECTORS)
+# endif (STATIC_INSPECTORS)
#include "dns.h"
#include "detection/detection_engine.h"
+#include "dns_config.h"
#include "log/messages.h"
#include "profiler/profiler.h"
#include "protocols/packet.h"
#include "dns_module.h"
#include "dns_splitter.h"
+#include "pub_sub/dns_events.h"
using namespace snort;
/*
* Function prototype(s)
*/
-static void snort_dns(Packet* p);
+static void snort_dns(Packet* p, const DnsConfig* dns_config);
unsigned DnsFlowData::inspector_id = 0;
DnsFlowData::DnsFlowData() : FlowData(inspector_id)
{
- memset(&session, 0, sizeof(session));
dnsstats.concurrent_sessions++;
if(dnsstats.max_concurrent_sessions < dnsstats.concurrent_sessions)
dnsstats.max_concurrent_sessions = dnsstats.concurrent_sessions;
dnsstats.concurrent_sessions--;
}
+bool DNSData::publish_response() const
+{
+ return (dns_config->publish_response and state == DNS_RESP_STATE_ANS_RR);
+}
+
+bool DNSData::has_events() const
+{
+ return !dns_events.empty();
+}
+
static DNSData* SetNewDNSData(Packet* p)
{
DnsFlowData* fd;
return nullptr;
}
- memset(&udpSessionData, 0, sizeof(udpSessionData));
return &udpSessionData;
}
}
static uint16_t ParseDNSName(
- const unsigned char* data, uint16_t bytes_unused, DNSData* dnsSessionData)
+ const unsigned char* data, uint16_t bytes_unused, DNSData* dnsSessionData, bool parse_dns_name = false)
{
uint16_t bytes_required = dnsSessionData->curr_txt.txt_len -
dnsSessionData->curr_txt.txt_bytes_seen;
{
/* If this one is a relative offset, read that extra byte */
dnsSessionData->curr_txt.offset |= *data;
+ if (parse_dns_name)
+ {
+ // parse recursively relative name
+ dnsSessionData->curr_txt.name_state = DNS_RESP_STATE_NAME_SIZE;
+ return ParseDNSName(&dnsSessionData->data[0] + dnsSessionData->curr_txt.offset,
+ dnsSessionData->bytes_unused, dnsSessionData, parse_dns_name);
+ }
}
+
+ if (parse_dns_name)
+ {
+ if (!dnsSessionData->curr_txt.dns_name.empty())
+ dnsSessionData->curr_txt.dns_name += ".";
+
+ dnsSessionData->curr_txt.dns_name.append((const char*)data, bytes_required);
+ }
+
data += bytes_required;
dnsSessionData->bytes_seen_curr_rec += bytes_required;
dnsSessionData->curr_txt.txt_bytes_seen += bytes_required;
if (dnsSessionData->curr_txt.name_state == DNS_RESP_STATE_NAME_COMPLETE)
{
dnsSessionData->curr_rec_state = DNS_RESP_STATE_Q_TYPE;
- memset(&dnsSessionData->curr_txt, 0, sizeof(DNSNameState));
+ dnsSessionData->curr_txt = DNSNameState();
data = data + bytes_used;
bytes_unused = new_bytes_unused;
if (dnsSessionData->curr_rec_state < DNS_RESP_STATE_RR_NAME_COMPLETE)
{
+ if (dnsSessionData->publish_response())
+ dnsSessionData->cur_fqdn_event = DnsResponseFqdn(data, bytes_unused, dnsSessionData);
+
uint16_t new_bytes_unused = ParseDNSName(data, bytes_unused, dnsSessionData);
uint16_t bytes_used = bytes_unused - new_bytes_unused;
if (dnsSessionData->curr_txt.name_state == DNS_RESP_STATE_NAME_COMPLETE)
{
dnsSessionData->curr_rec_state = DNS_RESP_STATE_RR_TYPE;
- memset(&dnsSessionData->curr_txt, 0, sizeof(DNSNameState));
+ dnsSessionData->curr_txt = DNSNameState();
data = data + bytes_used;
}
bytes_unused = new_bytes_unused;
bytes_unused = SkipDNSRData(data, bytes_unused, dnsSessionData);
break;
case DNS_RR_TYPE_A:
- case DNS_RR_TYPE_NS:
+ case DNS_RR_TYPE_AAAA:
+ if (dnsSessionData->publish_response())
+ {
+ dnsSessionData->dns_events.add_fqdn(dnsSessionData->cur_fqdn_event, dnsSessionData->curr_rr.ttl);
+ dnsSessionData->dns_events.add_ip(DnsResponseIp(data, dnsSessionData->curr_rr.type));
+ }
+
+ bytes_unused = SkipDNSRData(data, bytes_unused, dnsSessionData);
+ break;
case DNS_RR_TYPE_CNAME:
+ if (dnsSessionData->publish_response())
+ dnsSessionData->dns_events.add_fqdn(dnsSessionData->cur_fqdn_event, dnsSessionData->curr_rr.ttl);
+
+ bytes_unused = SkipDNSRData(data, bytes_unused, dnsSessionData);
+ break;
+ case DNS_RR_TYPE_NS:
case DNS_RR_TYPE_SOA:
case DNS_RR_TYPE_WKS:
case DNS_RR_TYPE_PTR:
return bytes_unused;
}
-static void ParseDNSResponseMessage(Packet* p, DNSData* dnsSessionData)
+static void ParseDNSResponseMessage(Packet* p, DNSData* dnsSessionData, bool& needNextPacket)
{
uint16_t bytes_unused = p->dsize;
int i;
const unsigned char* data = p->data;
+ if (dnsSessionData->dns_config->publish_response and dnsSessionData->data.empty())
+ {
+ dnsSessionData->data.resize(bytes_unused);
+ memcpy((void*)&dnsSessionData->data[0], data, bytes_unused);
+ dnsSessionData->bytes_unused = bytes_unused;
+ }
while (bytes_unused)
{
}
else
{
- /* No more data */
+ needNextPacket = true;
return;
}
}
else
{
- /* No more data */
+ needNextPacket = true;
return;
}
}
if (bytes_unused == 0)
{
- /* No more data */
+ needNextPacket = true;
return;
}
bytes_unused = ParseDNSRData(data, bytes_unused, dnsSessionData);
if (dnsSessionData->curr_rec_state != DNS_RESP_STATE_RR_COMPLETE)
{
- /* Out of data, pick up on the next packet */
+ needNextPacket = true;
return;
}
else
if (dnsSessionData->curr_rr.type == DNS_RR_TYPE_TXT)
{
/* Reset the state tracking for this record */
- memset(&dnsSessionData->curr_txt, 0, sizeof(DNSNameState));
+ dnsSessionData->curr_txt = DNSNameState();
}
data = p->data + (p->dsize - bytes_unused);
}
if (dnsSessionData->curr_rr.type == DNS_RR_TYPE_TXT)
{
/* Reset the state tracking for this record */
- memset(&dnsSessionData->curr_txt, 0, sizeof(DNSNameState));
+ dnsSessionData->curr_txt = DNSNameState();
}
data = p->data + (p->dsize - bytes_unused);
}
if (dnsSessionData->curr_rr.type == DNS_RR_TYPE_TXT)
{
/* Reset the state tracking for this record */
- memset(&dnsSessionData->curr_txt, 0, sizeof(DNSNameState));
+ dnsSessionData->curr_txt = DNSNameState();
}
data = p->data + (p->dsize - bytes_unused);
}
}
}
-static void snort_dns(Packet* p)
+SfIp DnsResponseIp::get_ip()
+{
+ SfIp ip;
+ int family = 0;
+ switch (type)
+ {
+ case DNS_RR_TYPE_A:
+ family = AF_INET;
+ break;
+ case DNS_RR_TYPE_AAAA:
+ family = AF_INET6;
+ break;
+ }
+
+ if (family and strlen((const char*)data))
+ ip.set(data, family);
+
+ return ip;
+}
+
+FqdnTtl DnsResponseFqdn::get_fqdn()
+{
+ std::string dns_name;
+ ParseDNSName(data, bytes_unused, dnsSessionData.get(), true);
+
+ if (dnsSessionData->curr_txt.name_state == DNS_RESP_STATE_NAME_COMPLETE)
+ dnsSessionData->curr_txt.get_dns_name(dns_name);
+
+ return FqdnTtl(dns_name, dnsSessionData->curr_rr.ttl);
+}
+
+void DnsResponseFqdn::update_ttl(uint32_t ttl)
+{
+ dnsSessionData->curr_rr.ttl = ttl;
+}
+
+//-------------------------------------------------------------------------
+// class stuff
+//-------------------------------------------------------------------------
+
+class Dns : public Inspector
+{
+public:
+ Dns(DnsModule*);
+ ~Dns() override;
+
+ void eval(Packet*) override;
+ StreamSplitter* get_splitter(bool) override;
+ bool configure(snort::SnortConfig*) override;
+ void show(const snort::SnortConfig*) const override;
+ static unsigned get_pub_id() { return pub_id; }
+
+private:
+ const DnsConfig* config = nullptr;
+ static unsigned pub_id;
+};
+
+unsigned Dns::pub_id = 0;
+
+Dns::Dns(DnsModule* m)
+{
+ config = m->get_config();
+ assert(config);
+}
+
+Dns::~Dns()
+{
+ delete config;
+}
+
+void Dns::show(const SnortConfig*) const
+{
+ config->show();
+}
+
+void Dns::eval(Packet* p)
+{
+ // precondition - what we registered for
+ assert((p->is_udp() and p->dsize and p->data) or p->has_tcp_data());
+ assert(p->flow);
+
+ ++dnsstats.packets;
+ snort_dns(p, config);
+}
+
+bool Dns::configure(snort::SnortConfig*)
+{
+ pub_id = DataBus::get_id(dns_pub_key);
+ return true;
+}
+
+StreamSplitter* Dns::get_splitter(bool c2s)
+{
+ return new DnsSplitter(c2s);
+}
+
+static void snort_dns(Packet* p, const DnsConfig* dns_config)
{
Profile profile(dnsPerfStats);
if (dnsSessionData->flags & DNS_FLAG_NOT_DNS)
return;
+ dnsSessionData->dns_config = dns_config;
if ( from_server )
{
- ParseDNSResponseMessage(p, dnsSessionData);
+ bool needNextPacket = false;
+ ParseDNSResponseMessage(p, dnsSessionData, needNextPacket);
+
+ if (!needNextPacket and dnsSessionData->has_events())
+ DataBus::publish(Dns::get_pub_id(), DnsEventIds::DNS_RESPONSE_DATA, dnsSessionData->dns_events);
}
else
{
}
}
-//-------------------------------------------------------------------------
-// class stuff
-//-------------------------------------------------------------------------
-
-class Dns : public Inspector
-{
-public:
- Dns(DnsModule*);
-
- void eval(Packet*) override;
- StreamSplitter* get_splitter(bool) override;
-};
-
-Dns::Dns(DnsModule*)
-{ }
-
-void Dns::eval(Packet* p)
-{
- // precondition - what we registered for
- assert((p->is_udp() and p->dsize and p->data) or p->has_tcp_data());
- assert(p->flow);
-
- ++dnsstats.packets;
- snort_dns(p);
-}
-
-StreamSplitter* Dns::get_splitter(bool c2s)
-{
- return new DnsSplitter(c2s);
-}
-
//-------------------------------------------------------------------------
// api stuff
//-------------------------------------------------------------------------
#include "flow/flow.h"
+#include "pub_sub/dns_events.h"
+
// Implementation header with definitions, datatypes and flowdata class for
// DNS service inspector.
struct DNSHdr
{
- uint16_t id;
- uint16_t flags;
- uint16_t questions;
- uint16_t answers;
- uint16_t authorities;
- uint16_t additionals;
+ uint16_t id = 0;
+ uint16_t flags = 0;
+ uint16_t questions = 0;
+ uint16_t answers = 0;
+ uint16_t authorities = 0;
+ uint16_t additionals = 0;
};
#define DNS_HDR_FLAG_REPLY_CODE_MASK 0x000F
struct DNSQuestion
{
- uint16_t type;
- uint16_t dns_class;
+ uint16_t type = 0;
+ uint16_t dns_class = 0;
};
struct DNSRR
{
- uint16_t type;
- uint16_t dns_class;
- uint32_t ttl;
- uint16_t length;
+ uint16_t type = 0;
+ uint16_t dns_class = 0;
+ uint32_t ttl = 0;
+ uint16_t length = 0;
};
// FIXIT-L replace alerted/relative to bool?
struct DNSNameState
{
- uint32_t txt_count;
- uint32_t total_txt_len;
- uint8_t txt_len;
- uint8_t txt_bytes_seen;
- uint8_t name_state;
- uint8_t alerted;
- uint16_t offset;
- uint8_t relative;
+ uint32_t txt_count = 0;
+ uint32_t total_txt_len = 0;
+ uint8_t txt_len = 0;
+ uint8_t txt_bytes_seen = 0;
+ uint8_t name_state = 0;
+ uint8_t alerted = 0;
+ uint16_t offset = 0;
+ uint8_t relative = 0;
+ std::string dns_name;
+
+ void get_dns_name(std::string& name) const
+ {
+ if (dns_name.size())
+ name = dns_name;
+ }
};
// FIXIT-L remove obsolete flags?
#define DNS_RR_TYPE_MINFO 0x000e // experimental
#define DNS_RR_TYPE_MX 0x000f
#define DNS_RR_TYPE_TXT 0x0010
+#define DNS_RR_TYPE_AAAA 0x001c
#define DNS_FLAG_NOT_DNS 0x01
#define DNS_RESP_STATE_AUTH_RR 0x50
#define DNS_RESP_STATE_ADD_RR 0x60
+class DnsConfig;
+struct DNSData;
+
+class DnsResponseFqdn
+{
+public:
+ DnsResponseFqdn()
+ {}
+
+ DnsResponseFqdn(const unsigned char* data, uint16_t bytes_unused, DNSData* dnsSessionData) :
+ data(data), bytes_unused(bytes_unused), dnsSessionData(std::make_shared<DNSData>(*dnsSessionData))
+ {}
+
+ FqdnTtl get_fqdn();
+ void update_ttl(uint32_t ttl);
+
+private:
+ const unsigned char* data = nullptr;
+ uint16_t bytes_unused = 0;
+ std::shared_ptr<DNSData> dnsSessionData;
+};
+
// Per-session data block containing current state
// of the DNS inspector for the session.
struct DNSData
{
- uint32_t state; // The current state of the session.
- uint16_t curr_rec; // Record number for the current record
- uint16_t curr_rec_length;
- uint16_t bytes_seen_curr_rec;
- uint16_t length;
- uint8_t curr_rec_state;
+ uint32_t state = 0; // The current state of the session.
+ uint16_t curr_rec = 0; // Record number for the current record
+ uint16_t curr_rec_length = 0;
+ uint16_t bytes_seen_curr_rec = 0;
+ uint16_t length = 0;
+ uint16_t bytes_unused = 0;
+ uint8_t curr_rec_state = 0;
DNSHdr hdr; // Copy of the data from the DNS Header
DNSQuestion curr_q;
DNSRR curr_rr;
DNSNameState curr_txt;
- uint8_t flags;
+ uint8_t flags = 0;
+ std::vector<unsigned char> data;
+ const DnsConfig* dns_config = nullptr;
+ snort::DnsResponseDataEvents dns_events;
+ DnsResponseFqdn cur_fqdn_event;
+
+ bool publish_response() const;
+ bool has_events() const;
+};
+
+class DnsResponseIp
+{
+public:
+ DnsResponseIp()
+ {}
+
+ DnsResponseIp(const unsigned char* data, uint16_t type) :
+ data(data), type(type)
+ {}
+
+ snort::SfIp get_ip();
+
+private:
+ const unsigned char* data = nullptr;
+ uint16_t type = 0;
};
class DnsFlowData : public snort::FlowData
--- /dev/null
+//--------------------------------------------------------------------------
+// Copyright (C) 2015-2023 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.
+//--------------------------------------------------------------------------
+
+// dns_config.cc author Serhii Vlasiuk <svlasiuk@cisco.com>
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "dns_config.h"
+
+#include "log/messages.h"
+
+using namespace snort;
+
+void DnsConfig::show() const
+{
+ ConfigLogger::log_value("publish_response", publish_response);
+}
--- /dev/null
+//--------------------------------------------------------------------------
+// Copyright (C) 2015-2023 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.
+//--------------------------------------------------------------------------
+
+// dns_config.h author Serhii Vlasiuk <svlasiuk@cisco.com>
+
+#ifndef DNS_CONFIG_H
+#define DNS_CONFIG_H
+
+class DnsConfig
+{
+public:
+ DnsConfig() = default;
+ ~DnsConfig() = default;
+
+ void show() const;
+
+ bool publish_response = false;
+};
+
+#endif
#include "dns_module.h"
+#include "dns_config.h"
+
using namespace snort;
using namespace std;
static const Parameter s_params[] =
{
+ { "publish_response", Parameter::PT_BOOL, nullptr, "false", "parse and publish dns responses" },
+
{ nullptr, Parameter::PT_MAX, nullptr, nullptr, nullptr }
};
DnsModule::DnsModule() : Module(DNS_NAME, DNS_HELP, s_params)
{ }
+DnsModule::~DnsModule()
+{
+ delete config;
+}
+
+bool DnsModule::begin(const char*, int, SnortConfig*)
+{
+ if (!config)
+ config = new DnsConfig;
+
+ return true;
+}
+
+bool DnsModule::set(const char*, snort::Value& val, snort::SnortConfig*)
+{
+ if (val.is("publish_response"))
+ {
+ config->publish_response = val.get_bool();
+ }
+
+ return true;
+}
+
const RuleMap* DnsModule::get_rules() const
{ return dns_rules; }
ProfileStats* DnsModule::get_profile() const
{ return &dnsPerfStats; }
+const DnsConfig* DnsModule::get_config()
+{
+ DnsConfig* tmp = config;
+ config = nullptr;
+ return tmp;
+}
+
#define DNS_NAME "dns"
#define DNS_HELP "dns inspection"
+class DnsConfig;
struct DnsStats
{
{
public:
DnsModule();
+ ~DnsModule() override;
- bool set(const char*, snort::Value&, snort::SnortConfig*) override
- { return false; }
+ bool begin(const char*, int, snort::SnortConfig*) override;
+ bool set(const char*, snort::Value&, snort::SnortConfig*) override;
unsigned get_gid() const override
{ return GID_DNS; }
const PegInfo* get_pegs() const override;
PegCount* get_counts() const override;
snort::ProfileStats* get_profile() const override;
+ const DnsConfig* get_config();
Usage get_usage() const override
{ return INSPECT; }
bool is_bindable() const override
{ return true; }
+
+private:
+ DnsConfig* config = nullptr;
};
#endif