Commit b78c4dad authored by Pavel Doležal's avatar Pavel Doležal

Merge branch 'dnstap_input' into 'devel'

Implement support for dnstap input

See merge request !9
parents c149bfee 7a779596
Pipeline #75598 passed with stage
in 2 minutes and 58 seconds
......@@ -10,6 +10,7 @@ set(BUILD_DOC ON CACHE BOOL "Generate Sphinx and Doxygen documentation")
set(PROBE_CRYPTOPANT ON CACHE BOOL "Enable IP anonymization with cryptopANT library")
set(PROBE_PARQUET ON CACHE BOOL "Enable export to Parquet format with Apache Arrow library")
set(PROBE_CDNS ON CACHE BOOL "Enable export to C-DNS format with C-DNS library")
set(PROBE_DNSTAP ON CACHE BOOL "Enable support for dnstap as input data format")
set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake)
set(CMAKE_CXX_STANDARD 14)
......@@ -85,6 +86,20 @@ if (PROBE_CRYPTOPANT)
target_compile_definitions(DNSProbe INTERFACE PROBE_CRYPTOPANT)
endif()
if (PROBE_DNSTAP)
find_package(Protobuf REQUIRED)
find_package(Fstrm REQUIRED)
execute_process(COMMAND protoc --cpp_out=${CMAKE_CURRENT_BINARY_DIR} --proto_path=${CMAKE_SOURCE_DIR}/src/dnstap dnstap.proto)
add_library(dnstap_proto ${CMAKE_CURRENT_BINARY_DIR}/dnstap.pb.h ${CMAKE_CURRENT_BINARY_DIR}/dnstap.pb.cc)
target_link_libraries(dnstap_proto PUBLIC ${PROTOBUF_LIBRARIES})
target_include_directories(dnstap_proto PUBLIC ${PROTOBUF_INCLUDE_DIRS} ${CMAKE_CURRENT_BINARY_DIR})
target_link_libraries(DNSProbe INTERFACE ${PROTOBUF_LIBRARIES} dnstap_proto Fstrm::Fstrm)
target_include_directories(DNSProbe INTERFACE ${PROTOBUF_INCLUDE_DIRS})
target_compile_definitions(DNSProbe INTERFACE PROBE_DNSTAP)
file(GLOB DNSTAP_HEADERS CONFIGURE_DEPENDS src/dnstap/*.h)
file(GLOB DNSTAP_SOURCES CONFIGURE_DEPENDS src/dnstap/*.cpp)
endif()
# Add warning flags
function(set_warning param)
check_cxx_compiler_flag(-W${param} WARNING_${param})
......@@ -105,7 +120,7 @@ if (AF_PACKET_BACKEND)
file(GLOB AF_PACKET_SOURCES CONFIGURE_DEPENDS src/non-dpdk/*.cpp)
set(AF_FILES ${AF_PACKET_HEADERS} ${AF_PACKET_SOURCES} ${PROBE_HEADERS} ${PROBE_SOURCES}
${PARQUET_HEADERS} ${PARQUET_SOURCES} ${CDNS_HEADERS} ${CDNS_SOURCES})
${PARQUET_HEADERS} ${PARQUET_SOURCES} ${CDNS_HEADERS} ${CDNS_SOURCES} ${DNSTAP_HEADERS} ${DNSTAP_SOURCES})
add_executable(dns-probe-af src/application/dp.cpp ${AF_FILES})
target_link_libraries(dns-probe-af PUBLIC DNSProbe)
install(TARGETS dns-probe-af RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
......@@ -127,7 +142,7 @@ if (DPDK_BACKEND)
file(GLOB DPDK_SOURCES CONFIGURE_DEPENDS src/dpdk/*.cpp)
set(DPDK_FILES ${DPDK_HEADERS} ${DPDK_SOURCES} ${PROBE_HEADERS} ${PROBE_SOURCES}
${PARQUET_HEADERS} ${PARQUET_SOURCES} ${CDNS_HEADERS} ${CDNS_SOURCES})
${PARQUET_HEADERS} ${PARQUET_SOURCES} ${CDNS_HEADERS} ${CDNS_SOURCES} ${DNSTAP_HEADERS} ${DNSTAP_SOURCES})
add_executable(dns-probe-dpdk src/application/ddp.cpp ${DPDK_FILES})
target_link_libraries(dns-probe-dpdk PUBLIC DNSProbe DPDK::DPDK)
target_compile_definitions(dns-probe-dpdk PUBLIC USE_DPDK)
......
include(utils)
FindLibrary(libfstrm Fstrm)
\ No newline at end of file
# Last revision: 2020-09-22
# Last revision: 2021-01-27
#
# Default instance configuration.
# This configuration is always loaded before other configuration specified by given instance's ID.
......@@ -13,6 +13,10 @@ default:
# List of PCAPs to process in addition to PCAPs passed with '-p' command line parameter.
pcap-list: []
# List of unix sockets to process dnstap data from in addition to sockets passed with '-d'
# command line parameter.
dnstap-socket-list: []
# Indicates RAW PCAPs as input in 'pcap-list' or from command line with '-p' parameter.
# Might get overriden by '-r' command line parameter.
# MUST be set to 'false' if 'interface-list' or '-i' command line parameter are used.
......
......@@ -50,6 +50,10 @@ and destination IP addresses, source and destination ports, and
transport protocol. The packet is then assigned to one of the RX queues
based on this hash value.
Unix sockets for `dnstap <https://dnstap.info/>`_ input are uniformly
distributed among available worker threads and all traffic from a given
socket is then processed by its assigned worker thread.
Backends
========
......
......@@ -24,6 +24,7 @@ DNS Probe uses local file in YAML format to load configuration at startup. Its s
+--rw <instance-id>?
+--rw coremask? <uint64>
+--rw dnstap-socket-list?* <string>
+--rw dns-ports?* <uint16>
+--rw export
| +--rw cdns-blocks-per-file? <uint64>
......@@ -157,6 +158,17 @@ Bitmask indicating which CPU cores should DNS Probe use. At least 3 CPU cores ar
The default value of 7 indicates that DNS Probe should use the first 3 CPU cores with IDs of 0, 1 and 2.
.. _dnstap-socket-list:
dnstap-socket-list
^^^^^^^^^^^^^^^^^^
:data node: ``<instance-id>/dnstap-socket-list``
:default: empty
List of unix sockets to process dnstap data from in addition to sockets passed with '-d'
command line parameter.
.. _dns-ports:
dns-ports
......
......@@ -89,6 +89,8 @@ distribution repositories:
- libpcap
- yaml-cpp
- OpenSSL (libssl-dev)
- fstrm
- Protocol Buffers (libprotobuf-dev, protobuf-compiler)
- DPDK (only for DPDK version)
Optionally, to build this user documentation (``make doc``) or manual pages (``make man``)
......@@ -164,6 +166,7 @@ DNS Probe
# For disabling DPDK BACKEND remove `-DDPDK_BACKEND=On`
# For building without IP anonymization support add `-DPROBE_CRYPTOPANT=Off`
# For building without support for one of the export formats add `-DPROBE_PARQUET=Off` or `-DPROBE_CDNS=Off`
# For building without support for dnstap input add `-DPROBE_DNSTAP=Off`
cmake <GIT_REPO> -DCMAKE_INSTALL_PREFIX="$DEP_DIR" -DCMAKE_BUILD_TYPE=Release -DAF_PACKET_BACKEND=On -DDPDK_BACKEND=On -DBUILD_COLLECTOR=On
make -j
make install
......@@ -4,7 +4,7 @@ Overview
DNS Probe is a high-speed DNS monitoring software developed as a part of the `ADAM <https://adam.nic.cz/en/>`_ project by CZ.NIC Laboratories in cooperation with Brno University of Technology, Faculty of Information Technology.
DNS Probe is able to extract DNS packets either from live network traffic or `pcap <https://en.wikipedia.org/wiki/Pcap>`_ traces, match client queries with the corresponding server responses and export consolidated records about individual DNS transactions.
DNS Probe is able to extract DNS packets from live network traffic, `pcap <https://en.wikipedia.org/wiki/Pcap>`_ traces or `dnstap <https://dnstap.info/>`_ data supplied by unix sockets, match client queries with the corresponding server responses and export consolidated records about individual DNS transactions.
DNS Probe is typically deployed together with a DNS server (autoritative or recursive), capturing and processing the traffic received and sent by the server.
......
......@@ -15,6 +15,13 @@ For changes in software see `version descriptions <https://gitlab.nic.cz/adam/dn
- Edition
- Segment
- Change description
* - **0.7.1**
- **1.0**
- :doc:`Architecture <Architecture>`, :doc:`Configuration <Configuration>`,
:doc:`Installation <Installation>`, :doc:`Overview <Overview>`,
:doc:`Default YAML file <YAMLfile>`, :doc:`AF manual pages <manpages/dns-probe-af>`,
:doc:`DPDK manual pages <manpages/dns-probe-dpdk>`
- Add dnstap as another input data format
* - **0.7**
- **1.0**
- :doc:`Architecture <Architecture>`, :doc:`Configuration <Configuration>`,
......
......@@ -9,7 +9,7 @@ It is also included in the project repository (`data-model/dns-probe.yml <https:
.. code-block:: yaml
# Last revision: 2020-09-22
# Last revision: 2021-01-27
#
# Default instance configuration.
# This configuration is always loaded before other configuration specified by given instance's ID.
......@@ -24,6 +24,10 @@ It is also included in the project repository (`data-model/dns-probe.yml <https:
# List of PCAPs to process in addition to PCAPs passed with '-p' command line parameter.
pcap-list: []
# List of unix sockets to process dnstap data from in addition to sockets passed with '-d'
# command line parameter.
dnstap-socket-list: []
# Indicates RAW PCAPs as input in 'pcap-list' or from command line with '-p' parameter.
# Might get overriden by '-r' command line parameter.
# MUST be set to 'false' if 'interface-list' or '-i' command line parameter are used.
......
......@@ -8,14 +8,14 @@ dns-probe-af
Synopsis
--------
:program:`dns-probe-af` [-i *interface* | -p *pcap* [-r]] [-l *logfile*] [-n *instance*] [-c *config_file*] [-h]
:program:`dns-probe-af` [-i *interface* | -p *pcap* [-r] | -d *socket*] [-l *logfile*] [-n *instance*] [-c *config_file*] [-h]
Description
-----------
:program:`dns-probe-af` is a network traffic probe that captures DNS queries and corresponding responses and exports them as configurable records about individual DNS transactions.
:program:`dns-probe-af` can either listen on an interface or read packets from a PCAP file. The :option:`-i` and :option:`-p` options are mutually incompatible but either of them can be used repeatedly.
:program:`dns-probe-af` can either listen on an interface or read packets from a PCAP file or read dnstap data from a unix socket. The :option:`-i`, :option:`-p` and :option:`-d` options are mutually incompatible but either of them can be used repeatedly.
Depending on the configuration, :program:`dns-probe-af` exports the transaction records in either Parquet or C-DNS format.
......@@ -34,6 +34,10 @@ Options
Indicates raw PCAP format.
.. option:: -d socket
Read dnstap input from given unix socket.
.. option:: -l logfile
Write logging messages to *logfile* instead of standard output.
......
......@@ -8,14 +8,14 @@ dns-probe-dpdk
Synopsis
--------
:program:`dns-probe-dpdk` [-i *interface* | -p *pcap* [-r]] [-l *logfile*] [-n *instance*] [-c *config_file*] [-h]
:program:`dns-probe-dpdk` [-i *interface* | -p *pcap* [-r] | -d *socket*] [-l *logfile*] [-n *instance*] [-c *config_file*] [-h]
Description
-----------
:program:`dns-probe-dpdk` is a network traffic probe that captures DNS queries and corresponding responses and exports them as configurable records about individual DNS transactions.
:program:`dns-probe-dpdk` can either listen on an interface or read packets from a PCAP file. The :option:`-i` and :option:`-p` options are mutually incompatible but either of them can be used repeatedly.
:program:`dns-probe-dpdk` can either listen on an interface or read packets from a PCAP file or read dnstap data from a unix socket. The :option:`-i`, :option:`-p` and :option:`-d` options are mutually incompatible but either of them can be used repeatedly.
Depending on the configuration, :program:`dns-probe-dpdk` exports the transaction records in either Parquet or C-DNS format.
......@@ -34,6 +34,10 @@ Options
Indicates raw PCAP format.
.. option:: -d socket
Read dnstap input from given unix socket.
.. option:: -l logfile
Write logging messages to *logfile* instead of standard output.
......
......@@ -40,6 +40,7 @@
#include "utils/Logger.h"
#include "dpdk/DpdkPort.h"
#include "dpdk/DpdkPcapPort.h"
#include "core/UnixSocket.h"
DDP::LogWriter logwriter;
......@@ -287,6 +288,7 @@ int main(int argc, char** argv)
}
std::vector<std::shared_ptr<DDP::Port>> ready_ports;
std::vector<std::shared_ptr<DDP::Port>> ready_sockets;
try {
// Port initialization
std::set<uint16_t> ports;
......@@ -318,6 +320,10 @@ int main(int argc, char** argv)
ready_ports.emplace_back(new DDP::DPDKPort(port, runner.slaves_cnt() - 1, interface_mempool));
}
for (auto& port : arguments.args.dnstap_sockets) {
ready_sockets.emplace_back(new DDP::UnixSocket(port.c_str()));
}
// Set up signal handlers to print stats on exit
struct sigaction sa{};
sa.sa_handler = &signal_handler;
......@@ -331,7 +337,7 @@ int main(int argc, char** argv)
// Poll on configuration core
try {
auto ret = static_cast<int>(runner.run(ready_ports));
auto ret = static_cast<int>(runner.run(ready_ports, ready_sockets));
try {
unbind_interfaces(arguments.args);
}
......
......@@ -31,6 +31,7 @@
#include "utils/Logger.h"
#include "non-dpdk/PcapPort.h"
#include "non-dpdk/AfPacketPort.h"
#include "core/UnixSocket.h"
constexpr int PCAP_THREADS = 3;
DDP::LogWriter logwriter;
......@@ -66,6 +67,7 @@ int main(int argc, char** argv)
}
std::vector<std::shared_ptr<DDP::Port>> ready_ports;
std::vector<std::shared_ptr<DDP::Port>> ready_sockets;
try {
// Port initialization
uint16_t id = 0;
......@@ -78,6 +80,10 @@ int main(int argc, char** argv)
ready_ports.emplace_back(new DDP::PCAPPort(port.c_str(), runner.slaves_cnt() - 1));
}
for (auto& port : arguments.args.dnstap_sockets) {
ready_sockets.emplace_back(new DDP::UnixSocket(port.c_str()));
}
// Set up signal handlers to print stats on exit
struct sigaction sa = {};
sa.sa_handler = &signal_handler;
......@@ -91,7 +97,7 @@ int main(int argc, char** argv)
// Poll on configuration core
try {
return static_cast<int>(runner.run(ready_ports));
return static_cast<int>(runner.run(ready_ports, ready_sockets));
} catch (std::exception &e) {
logwriter.log_lvl("ERROR", "Uncaught exception: ", e.what());
return static_cast<uint8_t>(DDP::Probe::ReturnValue::UNCAUGHT_ERROR);
......
......@@ -40,6 +40,7 @@ namespace DDP {
Config() : interface_list(),
pcap_list(),
raw_pcap(false),
dnstap_socket_list(),
log_file(),
coremask(0x7),
dns_ports({53}),
......@@ -74,6 +75,7 @@ namespace DDP {
ConfigItem<CList<std::string>> interface_list; //!< List of network interfaces to process traffic from
ConfigItem<CList<std::string>> pcap_list; //!< List of PCAP files to process
ConfigItem<bool> raw_pcap; //!< Defines if input PCAP files are without ethernet headers
ConfigItem<CList<std::string>> dnstap_socket_list; //!< List of unix sockets to process dnstap data from
ConfigItem<std::string> log_file; //!< Log file for storing probe's logs
ConfigItem<ThreadManager::MaskType> coremask; //!< Coremask used fo selecting cores where application will be running.
ConfigItem<CList<Port_t>> dns_ports; //!< TCP/UDP port list used for identifying DNS traffic
......
......@@ -66,6 +66,12 @@ void DDP::ConfigFile::load_instance(Config& cfg, YAML::Node node)
if (node["raw-pcap"] && node["raw-pcap"].IsScalar())
cfg.raw_pcap.add_value(node["raw-pcap"].as<bool>());
if (node["dnstap-socket-list"] && node["dnstap-socket-list"].IsSequence()) {
for (auto item : node["dnstap-socket-list"]) {
cfg.dnstap_socket_list.add_value(item.as<std::string>());
}
}
if (node["log-file"] && node["log-file"].IsScalar())
cfg.log_file.add_value(node["log-file"].as<std::string>());
......
......@@ -52,6 +52,7 @@ namespace DDP {
std::list<std::string> interfaces; //<! List of interfaces used for listening for incoming DNS data
std::list<PciDevice> devices; //<! List of PCI devices corresponding to interfaces list (used in DPDK version)
std::list<std::string> pcaps; //<! List of PCAPs with data for processing
std::list<std::string> dnstap_sockets; //<! List of unix sockets to process dnstap data from
std::string log_file; //!< Log file to store probe's logs
std::string instance_name = "default"; //!< Instance name used for getting YAML configuration
std::string conf_file = PROBE_CONFIG; //!< YAML file to load initial configuration from
......
/*
* Copyright (C) 2021 CZ.NIC, z. s. p. o.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* 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, see <http://www.gnu.org/licenses/>.
*
* In addition, as a special exception, the copyright holders give
* permission to link the code of portions of this program with the
* OpenSSL library under certain conditions as described in each
* individual source file, and distribute linked combinations including
* the two.
*/
#pragma once
#include <cstdint>
namespace DDP {
/**
* @brief Types of input data that can be stored in Packet structure
*/
enum class PacketType : uint8_t {
WIRE = 0, //!< wire format packet
DNSTAP, //!< dnstap message
NONE
};
}
......@@ -32,6 +32,10 @@
#include <netinet/udp.h>
#include <netinet/tcp.h>
#ifdef PROBE_DNSTAP
#include "dnstap.pb.h"
#endif
#include "utils/Logger.h"
#include "DnsParser.h"
......@@ -316,6 +320,133 @@ const uint8_t* DDP::DnsParser::parse_rr(const uint8_t* ptr, const uint8_t* pkt_e
return ptr;
}
#ifdef PROBE_DNSTAP
DDP::MemView<uint8_t> DDP::DnsParser::parse_dnstap_header(const dnstap::Dnstap& msg, DnsRecord& record, bool& drop)
{
MemView<uint8_t> dns = MemView<uint8_t>();
// Check if message contains everything necessary
if (!msg.has_message())
throw DnsParseException("Dnstap missing message content");
auto& hdr = msg.message();
if (!hdr.has_type())
throw DnsParseException("Missing type of dnstap message");
if (!hdr.has_socket_family() || !hdr.has_query_address() || !hdr.has_response_address())
throw DnsParseException("IP version or address missing in dnstap message");
if (!hdr.has_socket_protocol() || !hdr.has_query_port() || !hdr.has_response_port())
throw DnsParseException("Transport protocol or port missing in dnstap message");
// Parse L3 information
if (hdr.socket_family() == dnstap::SocketFamily::INET) {
record.m_addr_family = DnsRecord::AddrFamily::IP4;
drop = block_ipv4s(reinterpret_cast<const uint8_t*>(hdr.query_address().c_str()),
reinterpret_cast<const uint8_t*>(hdr.response_address().c_str()));
if (drop) {
put_back_record(record);
return MemView<uint8_t>();
}
set_ips(record, reinterpret_cast<const uint8_t*>(hdr.query_address().c_str()),
reinterpret_cast<const uint8_t*>(hdr.response_address().c_str()), IPV4_ADDRLEN);
}
else if (hdr.socket_family() == dnstap::SocketFamily::INET6) {
record.m_addr_family = DnsRecord::AddrFamily::IP6;
drop = block_ipv6s(reinterpret_cast<const uint8_t*>(hdr.query_address().c_str()),
reinterpret_cast<const uint8_t*>(hdr.response_address().c_str()));
if (drop) {
put_back_record(record);
return MemView<uint8_t>();
}
set_ips(record, reinterpret_cast<const uint8_t*>(hdr.query_address().c_str()),
reinterpret_cast<const uint8_t*>(hdr.response_address().c_str()), IPV6_ADDRLEN);
}
else {
put_back_record(record);
drop = true;
return MemView<uint8_t>();
}
// Parse L4 information
switch (hdr.socket_protocol()) {
case dnstap::SocketProtocol::UDP:
record.m_proto = DnsRecord::Proto::UDP;
break;
case dnstap::SocketProtocol::TCP:
case dnstap::SocketProtocol::DOT:
case dnstap::SocketProtocol::DOH:
record.m_proto = DnsRecord::Proto::TCP;
break;
default:
put_back_record(record);
drop = true;
return MemView<uint8_t>();
break;
}
if (!is_dns_ports(hdr.query_port(), hdr.response_port())) {
put_back_record(record);
drop = true;
return MemView<uint8_t>();
}
record.m_port[static_cast<int>(record.m_client_index)] = hdr.query_port();
record.m_port[!static_cast<int>(record.m_client_index)] = hdr.response_port();
// Parse additional information (DNS wire length, timestamps)
switch (hdr.type()) {
case dnstap::Message_Type::Message_Type_CLIENT_QUERY:
case dnstap::Message_Type::Message_Type_RESOLVER_QUERY:
case dnstap::Message_Type::Message_Type_AUTH_QUERY:
case dnstap::Message_Type::Message_Type_FORWARDER_QUERY:
case dnstap::Message_Type::Message_Type_STUB_QUERY:
case dnstap::Message_Type::Message_Type_TOOL_QUERY:
case dnstap::Message_Type::Message_Type_UPDATE_QUERY:
if (!hdr.has_query_message())
throw DnsParseException("dnstap message missing query DNS data");
record.m_dns_len = hdr.query_message().size();
dns = MemView<uint8_t>(reinterpret_cast<const uint8_t*>(hdr.query_message().c_str()), hdr.query_message().size());
if (hdr.has_query_time_sec() && hdr.has_query_time_nsec()) {
struct timespec tm;
tm.tv_sec = hdr.query_time_sec();
tm.tv_nsec = hdr.query_time_nsec();
record.m_timestamp = Time(tm);
}
else
record.m_timestamp = Time(Time::Clock::REALTIME);
break;
case dnstap::Message_Type::Message_Type_CLIENT_RESPONSE:
case dnstap::Message_Type::Message_Type_RESOLVER_RESPONSE:
case dnstap::Message_Type::Message_Type_AUTH_RESPONSE:
case dnstap::Message_Type::Message_Type_FORWARDER_RESPONSE:
case dnstap::Message_Type::Message_Type_STUB_RESPONSE:
case dnstap::Message_Type::Message_Type_TOOL_RESPONSE:
case dnstap::Message_Type::Message_Type_UPDATE_RESPONSE:
if (!hdr.has_response_message())
throw DnsParseException("dnstap message missing response DNS data");
record.m_dns_len = hdr.response_message().size();
dns = MemView<uint8_t>(reinterpret_cast<const uint8_t*>(hdr.response_message().c_str()), hdr.response_message().size());
if (hdr.has_response_time_sec() && hdr.has_response_time_nsec()) {
struct timespec tm;
tm.tv_sec = hdr.response_time_sec();
tm.tv_nsec = hdr.response_time_nsec();
record.m_timestamp = Time(tm);
}
else
record.m_timestamp = Time(Time::Clock::REALTIME);
break;
default:
throw DnsParseException("Invalid type of dnstap message");
break;
}
return dns;
}
#endif
DDP::MemView<uint8_t> DDP::DnsParser::parse_l2(const DDP::MemView<uint8_t>& pkt, DDP::DnsRecord& record, bool& drop)
{
// Check if packet is long enough to contain valid ethernet header
......@@ -373,44 +504,15 @@ DDP::MemView<uint8_t> DDP::DnsParser::parse_ipv4(const DDP::MemView<uint8_t>& pk
throw DnsParseException("Packet is too short. Probably missing part of IPv4 header.");
}
if (!m_ipv4_allowlist.empty()) {
bool deny = true;
for (auto& ipv4 : m_ipv4_allowlist) {
if ((std::memcmp(&(ipv4_header->saddr), &ipv4, IPV4_ADDRLEN) == 0) ||
(std::memcmp(&(ipv4_header->daddr), &ipv4, IPV4_ADDRLEN) == 0)) {
deny = false;
break;
}
}
if (deny) {
drop = true;
put_back_record(record);
return pkt;
}
}
else if (!m_ipv4_denylist.empty() && m_ipv4_allowlist.empty()) {
for (auto& ipv4 : m_ipv4_denylist) {
if ((std::memcmp(&(ipv4_header->saddr), &ipv4, IPV4_ADDRLEN) == 0) ||
(std::memcmp(&(ipv4_header->daddr), &ipv4, IPV4_ADDRLEN) == 0)) {
drop = true;
put_back_record(record);
return pkt;
}
}
drop = block_ipv4s(reinterpret_cast<const uint8_t*>(&(ipv4_header->saddr)),
reinterpret_cast<const uint8_t*>(&(ipv4_header->daddr)));
if (drop) {
put_back_record(record);
return pkt;
}
if(std::memcmp(&(ipv4_header->saddr), &(ipv4_header->daddr), IPV4_ADDRLEN) > 0) {
std::memcpy(&(record.m_addr[0]), &(ipv4_header->daddr), IPV4_ADDRLEN);
std::memcpy(&(record.m_addr[1]), &(ipv4_header->saddr), IPV4_ADDRLEN);
// Indicate location of src addr
record.m_client_index = DnsRecord::ClientIndex::CLIENT_HIGH;
}
else {
std::memcpy(&(record.m_addr[0]), &(ipv4_header->saddr), IPV4_ADDRLEN);
std::memcpy(&(record.m_addr[1]), &(ipv4_header->daddr), IPV4_ADDRLEN);
record.m_client_index = DnsRecord::ClientIndex::CLIENT_LOW;
}
set_ips(record, reinterpret_cast<const uint8_t*>(&ipv4_header->saddr),
reinterpret_cast<const uint8_t*>(&ipv4_header->daddr), IPV4_ADDRLEN);
record.m_addr_family = DnsRecord::AddrFamily::IP4;
record.m_ttl = ipv4_header->ttl;
......@@ -445,43 +547,15 @@ DDP::MemView<uint8_t> DDP::DnsParser::parse_ipv6(const DDP::MemView<uint8_t>& pk
auto ipv6_header = reinterpret_cast<const ip6_hdr*>(pkt.ptr());
if (!m_ipv6_allowlist.empty()) {
bool deny = true;
for (auto& ipv6 : m_ipv6_allowlist) {
if ((std::memcmp(&(ipv6_header->ip6_src), ipv6.data(), IPV6_ADDRLEN) == 0) ||
(std::memcmp(&(ipv6_header->ip6_dst), ipv6.data(), IPV6_ADDRLEN) == 0)) {
deny = false;
break;
}
}
if (deny) {
drop = true;
put_back_record(record);
return pkt;
}
}
else if (!m_ipv6_denylist.empty() && m_ipv6_allowlist.empty()) {
for (auto& ipv6 : m_ipv6_denylist) {
if ((std::memcmp(&(ipv6_header->ip6_src), ipv6.data(), IPV6_ADDRLEN) == 0) ||
(std::memcmp(&(ipv6_header->ip6_dst), ipv6.data(), IPV6_ADDRLEN) == 0)) {
drop = true;
put_back_record(record);
return pkt;
}
}
drop = block_ipv6s(reinterpret_cast<const uint8_t*>(&(ipv6_header->ip6_src)),
reinterpret_cast<const uint8_t*>(&(ipv6_header->ip6_dst)));
if (drop) {
put_back_record(record);
return pkt;
}
if(std::memcmp(&ipv6_header->ip6_src, &ipv6_header->ip6_dst, IPV6_ADDRLEN) > 0) {
std::memcpy(&(record.m_addr[0]), &ipv6_header->ip6_dst, IPV6_ADDRLEN);
std::memcpy(&(record.m_addr[1]), &ipv6_header->ip6_src, IPV6_ADDRLEN);
record.m_client_index = DnsRecord::ClientIndex::CLIENT_HIGH;
}