virtual void* get_hi_msg_section(const Flow*)
{ return nullptr; }
virtual void set_hi_msg_section(Flow*, void*) { }
- virtual AppId get_appid_from_stream(const Flow*) { return APP_ID_NONE; }
+ virtual AppId get_appid_from_stream(const Flow*) = 0;
// Stream based flows should override this interface to return parent flow
// when child flow is passed as input
virtual Flow* get_stream_parent_flow(Flow* cflow) { return cflow; }
{
stream_id = 0;
}
+ AppId get_appid_from_stream(const Flow*) override
+ {
+ return APP_ID_QUIC;
+ }
};
static QuicStreamIntf quic_stream_intf;
return 0;
}
// Stubs for AppIdInspector
-static ServiceDNSData dd;
+static ServiceDNSData dns_data;
static bool return_null_data = false;
ServiceDNSDoQData* dns_doq_data = nullptr;
AppIdConfig test_app_config;
AppIdFlowData* AppIdDetector::data_get(const AppIdSession&)
{
- return return_null_data ? nullptr : ⅆ
+ return return_null_data ? nullptr : &dns_data;
}
-int ServiceDetector::fail_service(AppIdSession& asd, const Packet* pkt, AppidSessionDirection dir) { return 1; }
+int ServiceDetector::fail_service(AppIdSession& asd, const Packet* pkt, AppidSessionDirection dir)
+{
+ return 1;
+}
TEST_GROUP(detector_dns_doq_tests)
{
- DnsTcpServiceDetector* test_detector = nullptr;
+ DnsTcpServiceDetector* const test_detector = nullptr;
void setup() override
{
- test_detector = new DnsTcpServiceDetector(&test_discovery);
+ const_cast<DnsTcpServiceDetector*&>(test_detector) = new DnsTcpServiceDetector(&test_discovery);
}
void teardown() override
{
delete test_detector;
- test_detector = nullptr;
- dd.free_dns_cache();
+ const_cast<DnsTcpServiceDetector*&>(test_detector) = nullptr;
+ dns_data.free_dns_cache();
}
};
OdpContext test_odp_ctxt(test_app_config, nullptr);
AppIdModule test_module;
AppIdInspector test_inspector(test_module);
- dd.state = DNS_STATE_QUERY;
+ dns_data.state = DNS_STATE_QUERY;
AppIdSession test_asd(IpProtocol::TCP, nullptr, (uint16_t)0, test_inspector, test_odp_ctxt, (uint32_t)0, 0);
Flow* flow = new Flow;
test_asd.flow = flow;
AppidChangeBits change_bits;
AppIdDiscoveryArgs args(dns_tcp_packet, sizeof(dns_tcp_packet), APP_ID_FROM_INITIATOR, test_asd, nullptr, change_bits);
auto result = test_detector->validate_doq(args);
- dd.free_dns_cache();
+ dns_data.free_dns_cache();
CHECK_EQUAL(APPID_INPROCESS, result);
// Now send a response packet
- dd.state = DNS_STATE_RESPONSE;
- dd.id = 13330;
+ dns_data.state = DNS_STATE_RESPONSE;
+ dns_data.id = 13330;
uint8_t dns_tcp_response[] = {
0x00, 0x25, // TCP length (37 bytes)
0x12, 0x34, // id
OdpContext test_odp_ctxt(test_app_config, nullptr);
AppIdModule test_module;
AppIdInspector test_inspector(test_module);
- dd.state = DNS_STATE_QUERY;
+ dns_data.state = DNS_STATE_QUERY;
AppIdSession test_asd(IpProtocol::TCP, nullptr, (uint16_t)0, test_inspector, test_odp_ctxt, (uint32_t)0, 0);
Flow* flow = new Flow;
test_asd.flow = flow;
AppidChangeBits change_bits;
AppIdDiscoveryArgs args(dns_tcp_packet_1, sizeof(dns_tcp_packet_1), APP_ID_FROM_INITIATOR, test_asd, nullptr, change_bits);
auto result = test_detector->validate_doq(args);
- CHECK_EQUAL(6, dd.cached_len);
+ CHECK_EQUAL(6, dns_data.cached_len);
CHECK_EQUAL(APPID_INPROCESS, result);
uint8_t dns_tcp_packet_2[]= {
OdpContext test_odp_ctxt(test_app_config, nullptr);
AppIdModule test_module;
AppIdInspector test_inspector(test_module);
- dd.state = DNS_STATE_QUERY;
+ dns_data.state = DNS_STATE_QUERY;
AppIdSession test_asd(IpProtocol::TCP, nullptr, (uint16_t)0, test_inspector, test_odp_ctxt, (uint32_t)0, 0);
Flow* flow = new Flow;
test_asd.flow = flow;
OdpContext test_odp_ctxt(test_app_config, nullptr);
AppIdModule test_module;
AppIdInspector test_inspector(test_module);
- dd.state = DNS_STATE_QUERY;
+ dns_data.state = DNS_STATE_QUERY;
AppIdSession test_asd(IpProtocol::TCP, nullptr, (uint16_t)0, test_inspector, test_odp_ctxt, (uint32_t)0, 0);
Flow* flow = new Flow;
test_asd.flow = flow;
OdpContext test_odp_ctxt(test_app_config, nullptr);
AppIdModule test_module;
AppIdInspector test_inspector(test_module);
- dd.state = DNS_STATE_QUERY;
+ dns_data.state = DNS_STATE_QUERY;
AppIdSession test_asd(IpProtocol::TCP, nullptr, (uint16_t)0, test_inspector, test_odp_ctxt, (uint32_t)0, 0);
Flow* flow = new Flow;
test_asd.flow = flow;
#include "dns.h"
+#include "appid/application_ids.h"
#include "detection/detection_engine.h"
+#include "flow/stream_flow.h"
#include "log/messages.h"
#include "profiler/profiler.h"
#include "pub_sub/dns_events.h"
{ CountType::SUM, "packets", "total packets processed" },
{ CountType::SUM, "requests", "total dns requests" },
{ CountType::SUM, "responses", "total dns responses" },
+ { CountType::SUM, "dns_over_udp", "total dns packets over udp" },
+ { CountType::SUM, "dns_over_tcp", "total dns packets over tcp" },
+ { CountType::SUM, "dns_over_http1", "total dns packets over http/1.1" },
+ { CountType::SUM, "dns_over_http2", "total dns packets over http/2" },
+ { CountType::SUM, "dns_over_http3", "total dns packets over http/3" },
+ { CountType::SUM, "dns_over_quic", "total dns packets over quic" },
{ CountType::NOW, "concurrent_sessions", "total concurrent dns sessions" },
{ CountType::MAX, "max_concurrent_sessions", "maximum concurrent dns sessions" },
{ CountType::SUM, "aborted_sessions", "total dns sessions aborted" },
+
{ CountType::END, nullptr, nullptr }
};
return &udpSessionData;
}
- fd = (DnsFlowData*)((p->flow)->get_flow_data(DnsFlowData::inspector_id));
+ fd = static_cast<DnsFlowData*>((p->flow)->get_flow_data(DnsFlowData::inspector_id));
if (fd)
{
fd->session.dns_events.set_packet(p);
if (!dnsSessionData->curr_txt.dns_name.empty())
dnsSessionData->curr_txt.dns_name += ".";
- dnsSessionData->curr_txt.dns_name.append((const char*)data, bytes_required);
+ dnsSessionData->curr_txt.dns_name.append(reinterpret_cast<const char*>(data), bytes_required);
}
data += bytes_required;
static bool is_in_udp_flow(Packet* p, uint16_t trans_id)
{
bool found = false;
- DnsUdpFlowData* udp_flow_data = (DnsUdpFlowData*)((p->flow)->get_flow_data(DnsUdpFlowData::inspector_id));
+ DnsUdpFlowData* udp_flow_data = static_cast<DnsUdpFlowData*>((p->flow)->get_flow_data(DnsUdpFlowData::inspector_id));
if (udp_flow_data)
found = udp_flow_data->trans_ids.find(trans_id) != udp_flow_data->trans_ids.end();
return found;
// Add DNS transaction ID to the UDP packet's flow data object
static void add_to_udp_flow(Packet* p, uint16_t trans_id)
{
- DnsUdpFlowData* udp_flow_data = (DnsUdpFlowData*)((p->flow)->get_flow_data(DnsUdpFlowData::inspector_id));
+ DnsUdpFlowData* udp_flow_data = static_cast<DnsUdpFlowData*>((p->flow)->get_flow_data(DnsUdpFlowData::inspector_id));
if (!udp_flow_data)
{
udp_flow_data = new DnsUdpFlowData();
}
// Remove DNS transaction ID from the UDP packet's flow data object
-static void rm_from_udp_flow(Packet* p, uint16_t trans_id)
+static void rm_from_udp_flow(Packet* p, uint16_t trans_id, bool is_payload)
{
- DnsUdpFlowData* udp_flow_data = (DnsUdpFlowData*)((p->flow)->get_flow_data(DnsUdpFlowData::inspector_id));
+ DnsUdpFlowData* udp_flow_data = static_cast<DnsUdpFlowData*>((p->flow)->get_flow_data(DnsUdpFlowData::inspector_id));
bool should_close = true;
if (udp_flow_data)
{
udp_flow_data->trans_ids.erase(trans_id);
should_close = udp_flow_data->trans_ids.empty();
}
- if (should_close && !p->flow->is_proxied())
+ if (should_close && !is_payload)
{
// Mark the UDP flow as "closed" only when all trans_ids are matched
// and removed by DNS-reply packets, or if the flow data object is not found
config->show();
}
-void Dns::snort_dns(Packet* p, bool udp)
+void Dns::snort_dns(Packet* p, bool udp, bool is_payload)
{
// cppcheck-suppress unreadVariable
Profile profile(dnsPerfStats);
if (dnsSessionData->flags & DNS_FLAG_NOT_DNS)
return;
+ if (is_payload)
+ {
+ if (p->flow->stream_intf)
+ {
+ AppId appid = p->flow->stream_intf->get_appid_from_stream(p->flow);
+ switch (appid)
+ {
+ case APP_ID_QUIC:
+ dnsstats.dns_over_quic++;
+ break;
+ case APP_ID_HTTP3:
+ dnsstats.dns_over_http3++;
+ break;
+ case APP_ID_HTTP2:
+ dnsstats.dns_over_http2++;
+ break;
+ default:
+ break;
+ }
+ }
+ else
+ dnsstats.dns_over_http1++;
+ }
+ else
+ {
+ if (udp)
+ dnsstats.dns_over_udp++;
+ else
+ dnsstats.dns_over_tcp++;
+ }
+
dnsSessionData->dns_config = config;
if ( from_server )
{
}
if (udp)
- rm_from_udp_flow(p, trans_id);
+ rm_from_udp_flow(p, trans_id, is_payload);
}
else
{
assert((p->is_udp() and p->dsize and p->data) or p->has_tcp_data() or p->has_udp_quic_data());
assert(p->flow);
if (p->has_udp_quic_data()) // DNS over QUIC follows DNS over TCP
- snort_dns(p, false);
+ snort_dns(p, false, true);
else
snort_dns(p, p->is_udp());
}
static Inspector* dns_ctor(Module* m)
{
- DnsModule* mod = (DnsModule*)m;
+ DnsModule* mod = static_cast<DnsModule*>(m);
return new Dns(mod);
}
bool supports_no_ips() const override
{ return true; }
- void snort_dns(snort::Packet* p, bool udp);
+ void snort_dns(snort::Packet* p, bool udp, bool is_payload = false);
const DnsConfig* get_config() const
{ return config; }
PegCount packets;
PegCount requests;
PegCount responses;
+ PegCount dns_over_udp;
+ PegCount dns_over_tcp;
+ PegCount dns_over_http1;
+ PegCount dns_over_http2;
+ PegCount dns_over_http3;
+ PegCount dns_over_quic;
PegCount concurrent_sessions;
PegCount max_concurrent_sessions;
PegCount aborted_sessions;
}
if (is_udp)
- static_cast<Dns&>(inspector).snort_dns(p, true);
+ static_cast<Dns&>(inspector).snort_dns(p, true, true);
p->data = old_data;
p->dsize = old_dsize;