diff --git a/libs/CMakeLists.txt b/libs/CMakeLists.txt index e6480f56e..be74e90d1 100644 --- a/libs/CMakeLists.txt +++ b/libs/CMakeLists.txt @@ -2,6 +2,5 @@ message(STATUS "Custom Libraries") add_subdirectory(visor_test) add_subdirectory(visor_transaction) -add_subdirectory(visor_tcp) add_subdirectory(visor_dns) add_subdirectory(visor_utils) \ No newline at end of file diff --git a/libs/visor_dns/CMakeLists.txt b/libs/visor_dns/CMakeLists.txt index a7c4e8aec..e829e3c1b 100644 --- a/libs/visor_dns/CMakeLists.txt +++ b/libs/visor_dns/CMakeLists.txt @@ -2,9 +2,6 @@ message(STATUS "Visor Lib DNS Helper") add_library(VisorLibDns dns.cpp - DnsLayer.cpp - DnsResource.cpp - DnsResourceData.cpp ) add_library(Visor::Lib::Dns ALIAS VisorLibDns) @@ -15,7 +12,6 @@ target_include_directories(VisorLibDns target_link_libraries(VisorLibDns PUBLIC - Visor::Lib::Tcp ${CONAN_LIBS_PCAPPLUSPLUS} ${CONAN_LIBS_PTHREADS4W} ${CONAN_LIBS_LIBPCAP} diff --git a/libs/visor_dns/DnsAdditionalRecord.h b/libs/visor_dns/DnsAdditionalRecord.h index bb8dd932a..250d50c1a 100644 --- a/libs/visor_dns/DnsAdditionalRecord.h +++ b/libs/visor_dns/DnsAdditionalRecord.h @@ -9,8 +9,7 @@ #else #include #endif -#include "DnsResource.h" -#include "EndianPortable.h" +#include #include #include @@ -46,10 +45,10 @@ struct DnsAdditionalEcs { std::string client_subnet; }; -static std::unique_ptr parse_additional_records_ecs(DnsResource *additional) +static std::unique_ptr parse_additional_records_ecs(pcpp::DnsResource *additional) { - if (!additional || additional->getDnsType() != DnsType::DNS_TYPE_OPT || additional->getDataLength() == 0) { + if (!additional || additional->getDnsType() != pcpp::DnsType::DNS_TYPE_OPT || additional->getDataLength() == 0) { return nullptr; } diff --git a/libs/visor_dns/DnsLayer.cpp b/libs/visor_dns/DnsLayer.cpp deleted file mode 100644 index 006615f15..000000000 --- a/libs/visor_dns/DnsLayer.cpp +++ /dev/null @@ -1,770 +0,0 @@ -#define LOG_MODULE pcpp::PacketLogModuleDnsLayer - -#include "DnsLayer.h" -#include "EndianPortable.h" -#include -#ifdef __GNUC__ -#pragma GCC diagnostic push -#pragma clang diagnostic ignored "-Wgnu-zero-variadic-macro-arguments" -#endif -#include -#ifdef __GNUC__ -#pragma GCC diagnostic pop -#endif -#include -#include -#include -#include - -namespace visor::lib::dns { - -DnsLayer::DnsLayer(uint8_t *data, size_t dataLen, Layer *prevLayer, pcpp::Packet *packet) - : Layer(data, dataLen, prevLayer, packet) -{ - m_Protocol = pcpp::DNS; - m_ResourceList = NULL; - - m_FirstQuery = NULL; - m_FirstAnswer = NULL; - m_FirstAuthority = NULL; - m_FirstAdditional = NULL; -} - -DnsLayer::DnsLayer() -{ - const size_t headerLen = sizeof(dnshdr); - m_DataLen = headerLen; - m_Data = new uint8_t[headerLen]; - memset(m_Data, 0, headerLen); - m_Protocol = pcpp::DNS; - - m_ResourceList = NULL; - - m_FirstQuery = NULL; - m_FirstAnswer = NULL; - m_FirstAuthority = NULL; - m_FirstAdditional = NULL; -} - -DnsLayer::DnsLayer(const DnsLayer &other) - : Layer(other) -{ - m_Protocol = pcpp::DNS; - - m_ResourceList = NULL; - - m_FirstQuery = NULL; - m_FirstAnswer = NULL; - m_FirstAuthority = NULL; - m_FirstAdditional = NULL; -} - -DnsLayer &DnsLayer::operator=(const DnsLayer &other) -{ - Layer::operator=(other); - - IDnsResource *curResource = m_ResourceList; - while (curResource != NULL) { - IDnsResource *temp = curResource->getNextResource(); - delete curResource; - curResource = temp; - } - - m_ResourceList = NULL; - - m_FirstQuery = NULL; - m_FirstAnswer = NULL; - m_FirstAuthority = NULL; - m_FirstAdditional = NULL; - - return (*this); -} - -DnsLayer::~DnsLayer() -{ - IDnsResource *curResource = m_ResourceList; - while (curResource != NULL) { - IDnsResource *nextResource = curResource->getNextResource(); - delete curResource; - curResource = nextResource; - } -} - -bool DnsLayer::extendLayer(int offsetInLayer, size_t numOfBytesToExtend, IDnsResource *resource) -{ - if (!Layer::extendLayer(offsetInLayer, numOfBytesToExtend)) - return false; - - IDnsResource *curResource = resource->getNextResource(); - while (curResource != NULL) { - curResource->m_OffsetInLayer += numOfBytesToExtend; - curResource = curResource->getNextResource(); - } - return true; -} - -bool DnsLayer::shortenLayer(int offsetInLayer, size_t numOfBytesToShorten, IDnsResource *resource) -{ - if (!Layer::shortenLayer(offsetInLayer, numOfBytesToShorten)) - return false; - - IDnsResource *curResource = resource->getNextResource(); - while (curResource != NULL) { - curResource->m_OffsetInLayer -= numOfBytesToShorten; - curResource = curResource->getNextResource(); - } - return true; -} - -bool DnsLayer::parseResources(bool queryOnly, bool additionalOnly, bool forceParse) -{ - - if (m_ResourcesParsed && (!forceParse || !m_ResourcesParseResult)) { - return m_ResourcesParseResult; - } - - size_t offsetInPacket = sizeof(dnshdr); - IDnsResource *curResource = m_ResourceList; - - uint16_t numOfQuestions = be16toh(getDnsHeader()->numberOfQuestions); - uint16_t numOfAnswers = be16toh(getDnsHeader()->numberOfAnswers); - uint16_t numOfAuthority = be16toh(getDnsHeader()->numberOfAuthority); - uint16_t numOfAdditional = be16toh(getDnsHeader()->numberOfAdditional); - - uint32_t numOfOtherResources = numOfQuestions + numOfAnswers + numOfAuthority + numOfAdditional; - - if (numOfOtherResources > 100) { - // probably bad packet - m_ResourcesParsed = true; - m_ResourcesParseResult = false; - return m_ResourcesParseResult; - } - - for (uint32_t i = 0; i < numOfOtherResources; i++) { - DnsResourceType resType; - if (numOfQuestions > 0) { - resType = DnsQueryType; - numOfQuestions--; - } else if (numOfAnswers > 0) { - resType = DnsAnswerType; - numOfAnswers--; - } else if (numOfAuthority > 0) { - resType = DnsAuthorityType; - numOfAuthority--; - } else { - resType = DnsAdditionalType; - numOfAdditional--; - } - - DnsResource *newResource = NULL; - DnsQuery *newQuery = NULL; - IDnsResource *newGenResource = NULL; - if (resType == DnsQueryType) { - newQuery = new DnsQuery(this, offsetInPacket); - newGenResource = newQuery; - offsetInPacket += newQuery->getSize(); - } else { - newResource = new DnsResource(this, offsetInPacket, resType); - newGenResource = newResource; - offsetInPacket += newResource->getSize(); - } - - if (offsetInPacket > m_DataLen) { - // Parse packet failed, DNS resource is out of bounds. Probably a bad packet - delete newGenResource; - m_ResourcesParsed = true; - m_ResourcesParseResult = false; - return m_ResourcesParseResult; - } - - // this resource is the first resource - if (m_ResourceList == NULL) { - m_ResourceList = newGenResource; - curResource = m_ResourceList; - } else { - curResource->setNexResource(newGenResource); - curResource = curResource->getNextResource(); - } - - if (resType == DnsQueryType && m_FirstQuery == NULL) { - m_FirstQuery = newQuery; - if (queryOnly) { - break; - } - } else if (resType == DnsAnswerType && m_FirstAnswer == NULL) - m_FirstAnswer = newResource; - else if (resType == DnsAuthorityType && m_FirstAuthority == NULL) - m_FirstAuthority = newResource; - else if (resType == DnsAdditionalType && m_FirstAdditional == NULL) { - m_FirstAdditional = newResource; - if (additionalOnly) { - break; - } - } - } - - m_ResourcesParsed = true; - m_ResourcesParseResult = true; - return m_ResourcesParseResult; -} - -IDnsResource *DnsLayer::getResourceByName(IDnsResource *startFrom, size_t resourceCount, const std::string &name, bool exactMatch) const -{ - size_t index = 0; - while (index < resourceCount) { - if (startFrom == NULL) - return NULL; - - std::string resourceName = startFrom->getName(); - if (exactMatch && resourceName == name) - return startFrom; - else if (!exactMatch && resourceName.find(name) != std::string::npos) - return startFrom; - - startFrom = startFrom->getNextResource(); - - index++; - } - - return NULL; -} - -DnsQuery *DnsLayer::getQuery(const std::string &name, bool exactMatch) const -{ - uint16_t numOfQueries = be16toh(getDnsHeader()->numberOfQuestions); - IDnsResource *res = getResourceByName(m_FirstQuery, numOfQueries, name, exactMatch); - if (res != NULL) - return dynamic_cast(res); - return NULL; -} - -DnsQuery *DnsLayer::getFirstQuery() const -{ - return m_FirstQuery; -} - -DnsQuery *DnsLayer::getNextQuery(DnsQuery *query) const -{ - if (query == NULL - || query->getNextResource() == NULL - || query->getType() != DnsQueryType - || query->getNextResource()->getType() != DnsQueryType) - return NULL; - - return (DnsQuery *)(query->getNextResource()); -} - -size_t DnsLayer::getQueryCount() const -{ - return be16toh(getDnsHeader()->numberOfQuestions); -} - -DnsResource *DnsLayer::getAnswer(const std::string &name, bool exactMatch) const -{ - uint16_t numOfAnswers = be16toh(getDnsHeader()->numberOfAnswers); - IDnsResource *res = getResourceByName(m_FirstAnswer, numOfAnswers, name, exactMatch); - if (res != NULL) - return dynamic_cast(res); - return NULL; -} - -DnsResource *DnsLayer::getFirstAnswer() const -{ - return m_FirstAnswer; -} - -DnsResource *DnsLayer::getNextAnswer(DnsResource *answer) const -{ - if (answer == NULL - || answer->getNextResource() == NULL - || answer->getType() != DnsAnswerType - || answer->getNextResource()->getType() != DnsAnswerType) - return NULL; - - return (DnsResource *)(answer->getNextResource()); -} - -size_t DnsLayer::getAnswerCount() const -{ - return be16toh(getDnsHeader()->numberOfAnswers); -} - -DnsResource *DnsLayer::getAuthority(const std::string &name, bool exactMatch) const -{ - uint16_t numOfAuthorities = be16toh(getDnsHeader()->numberOfAuthority); - IDnsResource *res = getResourceByName(m_FirstAuthority, numOfAuthorities, name, exactMatch); - if (res != NULL) - return dynamic_cast(res); - return NULL; -} - -DnsResource *DnsLayer::getFirstAuthority() const -{ - return m_FirstAuthority; -} - -DnsResource *DnsLayer::getNextAuthority(DnsResource *authority) const -{ - if (authority == NULL - || authority->getNextResource() == NULL - || authority->getType() != DnsAuthorityType - || authority->getNextResource()->getType() != DnsAuthorityType) - return NULL; - - return (DnsResource *)(authority->getNextResource()); -} - -size_t DnsLayer::getAuthorityCount() const -{ - return be16toh(getDnsHeader()->numberOfAuthority); -} - -DnsResource *DnsLayer::getAdditionalRecord(const std::string &name, bool exactMatch) const -{ - uint16_t numOfAdditionalRecords = be16toh(getDnsHeader()->numberOfAdditional); - IDnsResource *res = getResourceByName(m_FirstAdditional, numOfAdditionalRecords, name, exactMatch); - if (res != NULL) - return dynamic_cast(res); - return NULL; -} - -DnsResource *DnsLayer::getFirstAdditionalRecord() const -{ - return m_FirstAdditional; -} - -DnsResource *DnsLayer::getNextAdditionalRecord(DnsResource *additionalRecord) const -{ - if (additionalRecord == NULL - || additionalRecord->getNextResource() == NULL - || additionalRecord->getType() != DnsAdditionalType - || additionalRecord->getNextResource()->getType() != DnsAdditionalType) - return NULL; - - return (DnsResource *)(additionalRecord->getNextResource()); -} - -size_t DnsLayer::getAdditionalRecordCount() const -{ - return be16toh(getDnsHeader()->numberOfAdditional); -} - -std::string DnsLayer::toString() const -{ - std::ostringstream tidAsString; - tidAsString << be16toh(getDnsHeader()->transactionID); - - std::ostringstream queryCount; - queryCount << getQueryCount(); - - std::ostringstream answerCount; - answerCount << getAnswerCount(); - - std::ostringstream authorityCount; - authorityCount << getAuthorityCount(); - - std::ostringstream additionalCount; - additionalCount << getAdditionalRecordCount(); - - if (getAnswerCount() > 0) { - return "DNS query response, ID: " + tidAsString.str() + ";" + " queries: " + queryCount.str() + ", answers: " + answerCount.str() + ", authorities: " + authorityCount.str() + ", additional record: " + additionalCount.str(); - } else if (getQueryCount() > 0) { - return "DNS query, ID: " + tidAsString.str() + ";" + " queries: " + queryCount.str() + ", answers: " + answerCount.str() + ", authorities: " + authorityCount.str() + ", additional record: " + additionalCount.str(); - - } else // not likely - a DNS with no answers and no queries - { - return "DNS record without queries and answers, ID: " + tidAsString.str() + ";" + " queries: " + queryCount.str() + ", answers: " + answerCount.str() + ", authorities: " + authorityCount.str() + ", additional record: " + additionalCount.str(); - } -} - -IDnsResource *DnsLayer::getFirstResource(DnsResourceType resType) const -{ - switch (resType) { - case DnsQueryType: { - return m_FirstQuery; - } - case DnsAnswerType: { - return m_FirstAnswer; - } - case DnsAuthorityType: { - return m_FirstAuthority; - } - case DnsAdditionalType: { - return m_FirstAdditional; - } - default: - return NULL; - } -} - -void DnsLayer::setFirstResource(DnsResourceType resType, IDnsResource *resource) -{ - switch (resType) { - case DnsQueryType: { - m_FirstQuery = dynamic_cast(resource); - break; - } - case DnsAnswerType: { - m_FirstAnswer = dynamic_cast(resource); - break; - } - case DnsAuthorityType: { - m_FirstAuthority = dynamic_cast(resource); - break; - } - case DnsAdditionalType: { - m_FirstAdditional = dynamic_cast(resource); - break; - } - default: - return; - } -} - -DnsResource *DnsLayer::addResource(DnsResourceType resType, const std::string &name, DnsType dnsType, DnsClass dnsClass, - uint32_t ttl, IDnsResourceData *data) -{ - // create new query on temporary buffer - uint8_t newResourceRawData[256]; - memset(newResourceRawData, 0, sizeof(newResourceRawData)); - - DnsResource *newResource = new DnsResource(newResourceRawData, resType); - - newResource->setDnsClass(dnsClass); - - newResource->setDnsType(dnsType); - - // cannot return false since layer shouldn't be extended or shortened in this stage - newResource->setName(name); - - newResource->setTTL(ttl); - - if (!newResource->setData(data)) { - delete newResource; - PCPP_LOG_ERROR("Couldn't set new resource data"); - return NULL; - } - - size_t newResourceOffsetInLayer = sizeof(dnshdr); - IDnsResource *curResource = m_ResourceList; - while (curResource != NULL && curResource->getType() <= resType) { - newResourceOffsetInLayer += curResource->getSize(); - IDnsResource *nextResource = curResource->getNextResource(); - if (nextResource == NULL || nextResource->getType() > resType) - break; - curResource = nextResource; - } - - // set next resource for new resource. This must happen here for extendLayer to succeed - if (curResource != NULL) { - if (curResource->getType() > newResource->getType()) - newResource->setNexResource(m_ResourceList); - else - newResource->setNexResource(curResource->getNextResource()); - } else // curResource != NULL - newResource->setNexResource(m_ResourceList); - - // extend layer to make room for the new resource - if (!extendLayer(newResourceOffsetInLayer, newResource->getSize(), newResource)) { - PCPP_LOG_ERROR("Couldn't extend DNS layer, addResource failed"); - delete newResource; - return NULL; - } - - // connect the new resource to layer - newResource->setDnsLayer(this, newResourceOffsetInLayer); - - // connect the new resource to the layer's resource list - if (curResource != NULL) { - curResource->setNexResource(newResource); - // this means the new resource is the first of it's type - if (curResource->getType() < newResource->getType()) { - setFirstResource(resType, newResource); - } - // this means the new resource should be the first resource in the packet - else if (curResource->getType() > newResource->getType()) { - m_ResourceList = newResource; - - setFirstResource(resType, newResource); - } - } else // curResource != NULL, meaning this is the first resource in layer - { - m_ResourceList = newResource; - - setFirstResource(resType, newResource); - } - - return newResource; -} - -DnsQuery *DnsLayer::addQuery(const std::string &name, DnsType dnsType, DnsClass dnsClass) -{ - // create new query on temporary buffer - uint8_t newQueryRawData[256]; - DnsQuery *newQuery = new DnsQuery(newQueryRawData); - - newQuery->setDnsClass(dnsClass); - newQuery->setDnsType(dnsType); - - // cannot return false since layer shouldn't be extended or shortened in this stage - newQuery->setName(name); - - // find the offset in the layer to insert the new query - size_t newQueryOffsetInLayer = sizeof(dnshdr); - DnsQuery *curQuery = getFirstQuery(); - while (curQuery != NULL) { - newQueryOffsetInLayer += curQuery->getSize(); - DnsQuery *nextQuery = getNextQuery(curQuery); - if (nextQuery == NULL) - break; - curQuery = nextQuery; - } - - // set next resource for new query. This must happen here for extendLayer to succeed - if (curQuery != NULL) - newQuery->setNexResource(curQuery->getNextResource()); - else - newQuery->setNexResource(m_ResourceList); - - // extend layer to make room for the new query - if (!extendLayer(newQueryOffsetInLayer, newQuery->getSize(), newQuery)) { - PCPP_LOG_ERROR("Couldn't extend DNS layer, addQuery failed"); - delete newQuery; - return NULL; - } - - // connect the new query to layer - newQuery->setDnsLayer(this, newQueryOffsetInLayer); - - // connect the new query to the layer's resource list - if (curQuery != NULL) - curQuery->setNexResource(newQuery); - else // curQuery == NULL, meaning this is the first query - { - m_ResourceList = newQuery; - m_FirstQuery = newQuery; - } - - // increase number of queries - getDnsHeader()->numberOfQuestions = htobe16(getQueryCount() + 1); - - return newQuery; -} - -DnsQuery *DnsLayer::addQuery(DnsQuery *const copyQuery) -{ - if (copyQuery == NULL) - return NULL; - - return addQuery(copyQuery->getName(), copyQuery->getDnsType(), copyQuery->getDnsClass()); -} - -bool DnsLayer::removeQuery(const std::string &queryNameToRemove, bool exactMatch) -{ - DnsQuery *queryToRemove = getQuery(queryNameToRemove, exactMatch); - if (queryToRemove == NULL) { - PCPP_LOG_DEBUG("Query not found"); - return false; - } - - return removeQuery(queryToRemove); -} - -bool DnsLayer::removeQuery(DnsQuery *queryToRemove) -{ - bool res = removeResource(queryToRemove); - if (res) { - // decrease number of query records - getDnsHeader()->numberOfQuestions = htobe16(getQueryCount() - 1); - } - - return res; -} - -DnsResource *DnsLayer::addAnswer(const std::string &name, DnsType dnsType, DnsClass dnsClass, uint32_t ttl, IDnsResourceData *data) -{ - DnsResource *res = addResource(DnsAnswerType, name, dnsType, dnsClass, ttl, data); - if (res != NULL) { - // increase number of answer records - getDnsHeader()->numberOfAnswers = htobe16(getAnswerCount() + 1); - } - - return res; -} - -DnsResource *DnsLayer::addAnswer(DnsResource *const copyAnswer) -{ - if (copyAnswer == NULL) - return NULL; - - return addAnswer(copyAnswer->getName(), copyAnswer->getDnsType(), copyAnswer->getDnsClass(), copyAnswer->getTTL(), copyAnswer->getData().get()); -} - -bool DnsLayer::removeAnswer(const std::string &answerNameToRemove, bool exactMatch) -{ - DnsResource *answerToRemove = getAnswer(answerNameToRemove, exactMatch); - if (answerToRemove == NULL) { - PCPP_LOG_DEBUG("Answer record not found"); - return false; - } - - return removeAnswer(answerToRemove); -} - -bool DnsLayer::removeAnswer(DnsResource *answerToRemove) -{ - bool res = removeResource(answerToRemove); - if (res) { - // decrease number of answer records - getDnsHeader()->numberOfAnswers = htobe16(getAnswerCount() - 1); - } - - return res; -} - -DnsResource *DnsLayer::addAuthority(const std::string &name, DnsType dnsType, DnsClass dnsClass, uint32_t ttl, IDnsResourceData *data) -{ - DnsResource *res = addResource(DnsAuthorityType, name, dnsType, dnsClass, ttl, data); - if (res != NULL) { - // increase number of authority records - getDnsHeader()->numberOfAuthority = htobe16(getAuthorityCount() + 1); - } - - return res; -} - -DnsResource *DnsLayer::addAuthority(DnsResource *const copyAuthority) -{ - if (copyAuthority == NULL) - return NULL; - - return addAuthority(copyAuthority->getName(), copyAuthority->getDnsType(), copyAuthority->getDnsClass(), copyAuthority->getTTL(), copyAuthority->getData().get()); -} - -bool DnsLayer::removeAuthority(const std::string &authorityNameToRemove, bool exactMatch) -{ - DnsResource *authorityToRemove = getAuthority(authorityNameToRemove, exactMatch); - if (authorityToRemove == NULL) { - PCPP_LOG_DEBUG("Authority not found"); - return false; - } - - return removeAuthority(authorityToRemove); -} - -bool DnsLayer::removeAuthority(DnsResource *authorityToRemove) -{ - bool res = removeResource(authorityToRemove); - if (res) { - // decrease number of authority records - getDnsHeader()->numberOfAuthority = htobe16(getAuthorityCount() - 1); - } - - return res; -} - -DnsResource *DnsLayer::addAdditionalRecord(const std::string &name, DnsType dnsType, DnsClass dnsClass, uint32_t ttl, IDnsResourceData *data) -{ - DnsResource *res = addResource(DnsAdditionalType, name, dnsType, dnsClass, ttl, data); - if (res != NULL) { - // increase number of authority records - getDnsHeader()->numberOfAdditional = htobe16(getAdditionalRecordCount() + 1); - } - - return res; -} - -DnsResource *DnsLayer::addAdditionalRecord(const std::string &name, DnsType dnsType, uint16_t customData1, uint32_t customData2, IDnsResourceData *data) -{ - DnsResource *res = addAdditionalRecord(name, dnsType, DNS_CLASS_ANY, customData2, data); - if (res != NULL) { - res->setCustomDnsClass(customData1); - } - - return res; -} - -DnsResource *DnsLayer::addAdditionalRecord(DnsResource *const copyAdditionalRecord) -{ - if (copyAdditionalRecord == NULL) - return NULL; - - return addAdditionalRecord(copyAdditionalRecord->getName(), copyAdditionalRecord->getDnsType(), copyAdditionalRecord->getCustomDnsClass(), copyAdditionalRecord->getTTL(), copyAdditionalRecord->getData().get()); -} - -bool DnsLayer::removeAdditionalRecord(const std::string &additionalRecordNameToRemove, bool exactMatch) -{ - DnsResource *additionalRecordToRemove = getAdditionalRecord(additionalRecordNameToRemove, exactMatch); - if (additionalRecordToRemove == NULL) { - PCPP_LOG_DEBUG("Additional record not found"); - return false; - } - - return removeAdditionalRecord(additionalRecordToRemove); -} - -bool DnsLayer::removeAdditionalRecord(DnsResource *additionalRecordToRemove) -{ - bool res = removeResource(additionalRecordToRemove); - if (res) { - // decrease number of additional records - getDnsHeader()->numberOfAdditional = htobe16(getAdditionalRecordCount() - 1); - } - - return res; -} - -bool DnsLayer::removeResource(IDnsResource *resourceToRemove) -{ - if (resourceToRemove == NULL) { - PCPP_LOG_DEBUG("resourceToRemove cannot be NULL"); - return false; - } - - // find the resource preceding resourceToRemove - IDnsResource *prevResource = m_ResourceList; - - if (m_ResourceList != resourceToRemove) { - while (prevResource != NULL) { - IDnsResource *temp = prevResource->getNextResource(); - if (temp == resourceToRemove) - break; - - prevResource = temp; - } - } - - if (prevResource == NULL) { - PCPP_LOG_DEBUG("Resource not found"); - return false; - } - - // shorten the layer and fix offset in layer for all next DNS resources in the packet - if (!shortenLayer(resourceToRemove->m_OffsetInLayer, resourceToRemove->getSize(), resourceToRemove)) { - PCPP_LOG_ERROR("Couldn't shorten the DNS layer, resource cannot be removed"); - return false; - } - - // remove resourceToRemove from the resources linked list - if (m_ResourceList != resourceToRemove) { - prevResource->setNexResource(resourceToRemove->getNextResource()); - } else { - m_ResourceList = resourceToRemove->getNextResource(); - } - - // check whether resourceToRemove was the first of its type - if (getFirstResource(resourceToRemove->getType()) == resourceToRemove) { - IDnsResource *nextResource = resourceToRemove->getNextResource(); - if (nextResource != NULL && nextResource->getType() == resourceToRemove->getType()) - setFirstResource(resourceToRemove->getType(), nextResource); - else - setFirstResource(resourceToRemove->getType(), NULL); - } - - // free resourceToRemove memory - delete resourceToRemove; - - return true; -} - -} // namespace visor diff --git a/libs/visor_dns/DnsLayer.h b/libs/visor_dns/DnsLayer.h deleted file mode 100644 index ba4567eb8..000000000 --- a/libs/visor_dns/DnsLayer.h +++ /dev/null @@ -1,504 +0,0 @@ -#ifndef PV_PACKETPP_DNS_LAYER -#define PV_PACKETPP_DNS_LAYER - -#ifdef __GNUC__ -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wold-style-cast" -#pragma GCC diagnostic ignored "-Wunused-parameter" -#pragma clang diagnostic ignored "-Wc99-extensions" -#endif -#include "DnsLayerEnums.h" -#include "DnsResource.h" -#include "DnsResourceData.h" -#include -#include -#ifdef __GNUC__ -#pragma GCC diagnostic pop -#endif -// forked code -#pragma GCC diagnostic ignored "-Wold-style-cast" - -/// @file - -/** - * \namespace visor - */ -namespace visor::lib::dns { - -/** - * @struct dnshdr - * Represents the fixed part of the DNS header, meaning the part that doesn't include the DNS data (queries, answers, authorities - * and additional records) - */ -#pragma pack(push, 1) -struct dnshdr { - /** DNS query identification */ - uint16_t transactionID; -#if (BYTE_ORDER == LITTLE_ENDIAN) - uint16_t - /** Recursion desired flag */ - recursionDesired:1, - /** Truncated flag */ - truncation:1, - /** Authoritative answer flag */ - authoritativeAnswer:1, - /** Operation Code */ - opcode:4, - /** Query/Response flag */ - queryOrResponse:1, - /** Response code */ - responseCode:4, - /** Checking disabled flag */ - checkingDisabled:1, - /** Authenticated data flag */ - authenticData:1, - /** Zero flag (Reserved) */ - zero:1, - /** Recursion available flag */ - recursionAvailable:1; -#elif (BYTE_ORDER == BIG_ENDIAN) - uint16_t - /** Query/Response flag */ - queryOrResponse:1, - /** Operation Code */ - opcode:4, - /** Authoritative answer flag */ - authoritativeAnswer:1, - /** Truncated flag */ - truncation:1, - /** Recursion desired flag */ - recursionDesired:1, - /** Recursion available flag */ - recursionAvailable:1, - /** Zero flag (Reserved) */ - zero:1, - /** Authenticated data flag */ - authenticData:1, - /** Checking disabled flag */ - checkingDisabled:1, - /** Response code */ - responseCode:4; -#endif - /** Number of DNS query records in packet */ - uint16_t numberOfQuestions; - /** Number of DNS answer records in packet */ - uint16_t numberOfAnswers; - /** Number of authority records in packet */ - uint16_t numberOfAuthority; - /** Number of additional records in packet */ - uint16_t numberOfAdditional; - }; -#pragma pack(pop) - - - // forward declarations - class DnsQuery; - class IDnsResource; - class DnsResource; - class IDnsResourceData; - - - /** - * @class DnsLayer - * Represents the DNS protocol layer.
- * CURRENTLY ONLY DNS PARSING IS AVAILABLE. CREATING AND EDITING DNS ATTRIBUTES WILL BE ADDED LATER - */ - class DnsLayer : public pcpp::Layer - { - friend class IDnsResource; - friend class DnsQuery; - friend class DnsResource; - - public: - - DnsLayer(pcpp::UdpLayer *udpLayer, pcpp::Packet *packet) - : DnsLayer(udpLayer->getData()+sizeof(pcpp::udphdr), udpLayer->getDataLen()-sizeof(pcpp::udphdr), udpLayer, packet) - { - } - - DnsLayer(pcpp::TcpLayer *tcpLayer, pcpp::Packet *packet) - : DnsLayer(tcpLayer->getData()+sizeof(pcpp::tcphdr), tcpLayer->getDataLen()-sizeof(pcpp::tcphdr), tcpLayer, packet) - { - } - - /** - * A constructor that creates the layer from an existing packet raw data - * @param[in] data A pointer to the raw data - * @param[in] dataLen Size of the data in bytes - * @param[in] prevLayer A pointer to the previous layer - * @param[in] packet A pointer to the Packet instance where layer will be stored in - */ - DnsLayer(uint8_t* data, size_t dataLen, pcpp::Layer* prevLayer, pcpp::Packet* packet); - - /** - * A constructor that creates an empty DNS layer: all members of dnshdr are set to 0 and layer will contain no records - */ - DnsLayer(); - - /** - * A copy constructor for this layer - */ - DnsLayer(const DnsLayer& other); - - /** - * An assignment operator for this layer - */ - DnsLayer& operator=(const DnsLayer& other); - - virtual ~DnsLayer(); - - /** - * Get a pointer to the DNS header (as opposed to the DNS data which is the queries, answers, etc. Data can be retrieved through the - * other methods of this layer. Notice the return value points directly to the data, so every change will change the actual packet data - * @return A pointer to the @ref dnshdr - */ - dnshdr* getDnsHeader() const { return (dnshdr*)m_Data; } - - /** - * Searches for a DNS query by its name field. Notice this method returns only a query which its name equals to the requested name. If - * several queries match the requested name, the first one will be returned. If no queries match the requested name, NULL will be returned - * @param[in] name The name of the query to search - * @param[in] exactMatch Indicate whether to match the whole name or just a part of it - * @return The first matching DNS query or NULL if no queries were found - */ - DnsQuery* getQuery(const std::string& name, bool exactMatch) const; - - /** - * @return The first DNS query in the packet or NULL if packet doesn't contain any queries - */ - DnsQuery* getFirstQuery() const; - - /** - * Get the DNS query following a certain query - * @param[in] query A pointer to a DNS query that exist in the packet - * @return The DNS query following 'query'. If 'query' is NULL or 'query' is the last query in the packet NULL will be returned - */ - DnsQuery* getNextQuery(DnsQuery* query) const; - - /** - * @return The number of DNS queries in the packet - */ - size_t getQueryCount() const; - - /** - * Add a new DNS query to the layer - * @param[in] name The value that shall be set in the name field of the query - * @param[in] dnsType The value that shall be set in the DNS type field of the query - * @param[in] dnsClass The value that shall be set in the DNS class field of the query - * @return A pointer to the newly created DNS query or NULL if query could not be created (an appropriate error log message will be - * printed in this case) - */ - DnsQuery* addQuery(const std::string& name, DnsType dnsType, DnsClass dnsClass); - - /** - * Add a new DNS query similar to an already existing DNS query. All query fields will be copied from the existing query - * param[in] copyQuery The record to create the new record from. copyQuery won't be changed in any way - * @return A pointer to the newly created DNS query or NULL if query could not be created (an appropriate error log message will be - * printed in this case) - */ - DnsQuery* addQuery(DnsQuery* const copyQuery); - - /** - * Remove an existing query by name. If several queries matches the name, the first match will be removed - * @param[in] queryNameToRemove The name of the query to remove - * @param[in] exactMatch Indicate whether to match the whole name or just a part of it - * @return True if query was found and successfully removed or false if query was not found or couldn't be removed - */ - bool removeQuery(const std::string& queryNameToRemove, bool exactMatch); - - /** - * Remove an existing query - * @param[in] queryToRemove A pointer to the query to remove - * @return True if query was found and successfully removed or false if query was not found or couldn't be removed - */ - bool removeQuery(DnsQuery* queryToRemove); - - /** - * Searches for a DNS answer by its name field. Notice this method returns only an answer which its name equals to the requested name. If - * several answers match the requested name, the first one will be returned. If no answers match the requested name, NULL will be returned - * @param[in] name The name of the answer to search - * @param[in] exactMatch Indicate whether to match the whole name or just a part of it - * @return The first matching DNS answer or NULL if no answers were found - */ - DnsResource* getAnswer(const std::string& name, bool exactMatch) const; - - /** - * @return The first DNS answer in the packet or NULL if packet doesn't contain any answers - */ - DnsResource* getFirstAnswer() const; - - /** - * Get the DNS answer following a certain answer - * @param[in] answer A pointer to a DNS answer that exist in the packet - * @return The DNS answer following 'answer'. If 'answer' is NULL or 'answer' is the last answer in the packet NULL will be returned - */ - DnsResource* getNextAnswer(DnsResource* answer) const; - - /** - * @return The number of DNS answers in the packet - */ - size_t getAnswerCount() const; - - /** - * Add a new DNS answer to the layer - * @param[in] name The value that shall be set in the name field of the answer - * @param[in] dnsType The value that shall be set in the DNS type field of the answer - * @param[in] dnsClass The value that shall be set in the DNS class field of the answer - * @param[in] ttl The value that shall be set in the 'time-to-leave' field of the answer - * @param[in] data The answer data to be set. The type of the data should match the type of the DNS record - * (for example: DNS record of type A should have data of type IPv4DnsResourceData. Please see DnsResource#setData() - * for more info on this - * @return A pointer to the newly created DNS answer or NULL if answer could not be created (an appropriate error log message will be - * printed in this case) - */ - DnsResource* addAnswer(const std::string& name, DnsType dnsType, DnsClass dnsClass, uint32_t ttl, IDnsResourceData* data); - - /** - * Add a new DNS answer similar to an already existing DNS answer. All answer fields will be copied from the existing answer - * param[in] copyAnswer The record to create the new record from. copyAnswer won't be changed in any way - * @return A pointer to the newly created DNS answer or NULL if query could not be created (an appropriate error log message will be - * printed in this case) - */ - DnsResource* addAnswer(DnsResource* const copyAnswer); - - /** - * Remove an existing answer by name. If several answers matches the name, the first match will be removed - * @param[in] answerNameToRemove The name of the answer to remove - * @param[in] exactMatch Indicate whether to match the whole name or just a part of it - * @return True if answer was found and successfully removed or false if answer was not found or couldn't be removed - */ - bool removeAnswer(const std::string& answerNameToRemove, bool exactMatch); - - /** - * Remove an existing answer - * @param[in] answerToRemove A pointer to the answer to remove - * @return True if answer was found and successfully removed or false if answer was not found or couldn't be removed - */ - bool removeAnswer(DnsResource* answerToRemove); - - - /** - * Searches for a DNS authority by its name field. Notice this method returns only an authority which its name equals to the requested name. If - * several authorities match the requested name, the first one will be returned. If no authorities match the requested name, NULL will be returned - * @param[in] name The name of the authority to search - * @param[in] exactMatch Indicate whether to match the whole name or just a part of it - * @return The first matching DNS authority or NULL if no authorities were found - */ - DnsResource* getAuthority(const std::string& name, bool exactMatch) const; - - /** - * @return The first DNS authority in the packet or NULL if packet doesn't contain any authorities - */ - DnsResource* getFirstAuthority() const; - - /** - * Get the DNS authority following a certain authority - * @param[in] authority A pointer to a DNS authority that exist in the packet - * @return The DNS authority following 'authority'. If 'authority' is NULL or 'authority' is the last authority in the packet NULL will be returned - */ - DnsResource* getNextAuthority(DnsResource* authority) const; - - /** - * @return The number of DNS authorities in the packet - */ - size_t getAuthorityCount() const; - - /** - * Add a new DNS authority to the layer - * @param[in] name The value that shall be set in the name field of the authority - * @param[in] dnsType The value that shall be set in the DNS type field of the authority - * @param[in] dnsClass The value that shall be set in the DNS class field of the authority - * @param[in] ttl The value that shall be set in the 'time-to-leave' field of the authority - * @param[in] data The authority data to be set. The type of the data should match the type of the DNS record - * (for example: DNS record of type A should have data of type IPv4DnsResourceData. Please see DnsResource#setData() - * for more info on this - * @return A pointer to the newly created DNS authority or NULL if authority could not be created (an appropriate error log message will be - * printed in this case) - */ - DnsResource* addAuthority(const std::string& name, DnsType dnsType, DnsClass dnsClass, uint32_t ttl, IDnsResourceData* data); - - /** - * Add a new DNS authority similar to an already existing DNS authority. All authority fields will be copied from the existing authority - * param[in] copyAuthority The record to create the new record from. copyAuthority won't be changed in any way - * @return A pointer to the newly created DNS authority or NULL if query could not be created (an appropriate error log message will be - * printed in this case) - */ - DnsResource* addAuthority(DnsResource* const copyAuthority); - - /** - * Remove an existing authority by name. If several authorities matches the name, the first match will be removed - * @param[in] authorityNameToRemove The name of the authority to remove - * @param[in] exactMatch Indicate whether to match the whole name or just a part of it - * @return True if authority was found and successfully removed or false if authority was not found or couldn't be removed - */ - bool removeAuthority(const std::string& authorityNameToRemove, bool exactMatch); - - /** - * Remove an existing authority - * @param[in] authorityToRemove A pointer to the authority to remove - * @return True if authority was found and successfully removed or false if authority was not found or couldn't be removed - */ - bool removeAuthority(DnsResource* authorityToRemove); - - - /** - * Searches for a DNS additional record by its name field. Notice this method returns only an additional record which its name equals to - * the requested name. If several additional records match the requested name, the first one will be returned. If no additional records - * match the requested name, NULL will be returned - * @param[in] name The name of the additional record to search - * @param[in] exactMatch Indicate whether to match the whole name or just a part of it - * @return The first matching DNS additional record or NULL if no additional records were found - */ - DnsResource* getAdditionalRecord(const std::string& name, bool exactMatch) const; - - /** - * @return The first DNS additional record in the packet or NULL if packet doesn't contain any additional records - */ - DnsResource* getFirstAdditionalRecord() const; - - /** - * Get the DNS additional record following a certain additional record - * @param[in] additionalRecord A pointer to a DNS additional record that exist in the packet - * @return The DNS additional record following 'additionalRecord'. If 'additionalRecord' is NULL or 'additionalRecord' is the - * last additional record in the packet NULL will be returned - */ - DnsResource* getNextAdditionalRecord(DnsResource* additionalRecord) const; - - /** - * @return The number of DNS additional records in the packet - */ - size_t getAdditionalRecordCount() const; - - /** - * Add a new DNS additional record to the layer - * @param[in] name The value that shall be set in the name field of the additional record - * @param[in] dnsType The value that shall be set in the DNS type field of the additional record - * @param[in] dnsClass The value that shall be set in the DNS class field of the additional record - * @param[in] ttl The value that shall be set in the 'time-to-leave' field of the additional record - * @param[in] data The additional record data to be set. The type of the data should match the type of the DNS record - * (for example: DNS record of type A should have data of type IPv4DnsResourceData. Please see DnsResource#setData() - * for more info on this - * @return A pointer to the newly created DNS additional record or NULL if additional record could not be created (an appropriate error - * log message will be printed in this case) - */ - DnsResource* addAdditionalRecord(const std::string& name, DnsType dnsType, DnsClass dnsClass, uint32_t ttl, IDnsResourceData* data); - - /** - * Add a new DNS additional record to the layer that doesn't have DNS class and TTL. Instead these bytes may contains some arbitrary - * data. In the future I may add support for these kinds of additional data records. For now, these bytes are set as raw - * @param[in] name The value that shall be set in the name field of the additional record - * @param[in] dnsType The value that shall be set in the DNS type field of the additional record - * @param[in] customData1 Two bytes of the arbitrary data that will be set in the offset usually used for the DNS class - * @param[in] customData2 Four bytes of the arbitrary data that will be set in the offset usually used for the TTL - * @param[in] data The additional record data to be set. The type of the data should match the type of the DNS record. - * (for example: DNS record of type A should have data of type IPv4DnsResourceData. Please see DnsResource#setData() - * for more info on this - * @return A pointer to the newly created DNS additional record or NULL if additional record could not be created (an appropriate error - * log message will be printed in this case) - */ - DnsResource* addAdditionalRecord(const std::string& name, DnsType dnsType, uint16_t customData1, uint32_t customData2, IDnsResourceData* data); - - /** - * Add a new DNS additional record similar to an already existing DNS additional record. All additional record fields will be copied from the - * existing additional record - * param[in] copyAdditionalRecord The record to create the new record from. copyAdditionalRecord won't be changed in any way - * @return A pointer to the newly created DNS additional record or NULL if query could not be created (an appropriate error log message will - * be printed in this case) - */ - DnsResource* addAdditionalRecord(DnsResource* const copyAdditionalRecord); - - /** - * Remove an existing additional record by name. If several additional records matches the name, the first match will be removed - * @param[in] additionalRecordNameToRemove The name of the additional record to remove - * @param[in] exactMatch Indicate whether to match the whole name or just a part of it - * @return True if additional record was found and successfully removed or false if additional record was not found or couldn't be removed - */ - bool removeAdditionalRecord(const std::string& additionalRecordNameToRemove, bool exactMatch); - - /** - * Remove an existing additional record - * @param[in] additionalRecordToRemove A pointer to the additional record to remove - * @return True if additional record was found and successfully removed or false if additional record was not found or couldn't be removed - */ - bool removeAdditionalRecord(DnsResource* additionalRecordToRemove); - - // implement abstract methods - - /** - * Does nothing for this layer (DnsLayer is always last) - */ - void parseNextLayer() {} - - /** - * Return the size of the DNS data in the packet including he DNS header and size of all queries, answers, authorities and additional - * records - */ - size_t getHeaderLen() const { return m_DataLen; } //No layer above DNS - - /** - * Does nothing for this layer - */ - void computeCalculateFields() {} - - std::string toString() const; - - bool parseResources(bool queryOnly, bool additionalOnly = false, bool force = false); - - pcpp::OsiModelLayer getOsiModelLayer() const - { - return pcpp::OsiModelApplicationLayer; - } - - /** - * A static method that checks whether the port is considered as DNS - * @param[in] port The port number to be checked - */ - static inline bool isDnsPort(uint16_t port); - - private: - bool m_ResourcesParsed{false}; - bool m_ResourcesParseResult{false}; - IDnsResource *m_ResourceList; - DnsQuery *m_FirstQuery; - DnsResource *m_FirstAnswer; - DnsResource *m_FirstAuthority; - DnsResource *m_FirstAdditional; - - IDnsResource *getFirstResource(DnsResourceType resType) const; - void setFirstResource(DnsResourceType resType, IDnsResource *resource); - - using Layer::extendLayer; - bool extendLayer(int offsetInLayer, size_t numOfBytesToExtend, IDnsResource *resource); - - using Layer::shortenLayer; - bool shortenLayer(int offsetInLayer, size_t numOfBytesToShorten, IDnsResource* resource); - - IDnsResource* getResourceByName(IDnsResource* startFrom, size_t resourceCount, const std::string& name, bool exactMatch) const; - - DnsResource* addResource(DnsResourceType resType, const std::string& name, DnsType dnsType, DnsClass dnsClass, - uint32_t ttl, IDnsResourceData* data); - - bool removeResource(IDnsResource* resourceToRemove); - - }; - - - // implementation of inline methods - - bool DnsLayer::isDnsPort(uint16_t port) - { - switch (port) - { - case 53: - case 5353: - case 5355: - case 53000: - return true; - default: - return false; - } - } - - } // namespace visor - -#endif /* PV_PACKETPP_DNS_LAYER */ diff --git a/libs/visor_dns/DnsLayerEnums.h b/libs/visor_dns/DnsLayerEnums.h deleted file mode 100644 index 59c3c43d2..000000000 --- a/libs/visor_dns/DnsLayerEnums.h +++ /dev/null @@ -1,156 +0,0 @@ -#ifndef PV_PACKETPP_DNS_LAYER_ENUMS -#define PV_PACKETPP_DNS_LAYER_ENUMS - -/// @file - -/** - * \namespace visor - */ -namespace visor::lib::dns { -/** - * An enum for all possible DNS record types - */ -enum DnsType { - /** IPv4 address record */ - DNS_TYPE_A = 1, - /** Name Server record */ - DNS_TYPE_NS, - /** Obsolete, replaced by MX */ - DNS_TYPE_MD, - /** Obsolete, replaced by MX */ - DNS_TYPE_MF, - /** Canonical name record */ - DNS_TYPE_CNAME, - /** Start of Authority record */ - DNS_TYPE_SOA, - /** mailbox domain name record */ - DNS_TYPE_MB, - /** mail group member record */ - DNS_TYPE_MG, - /** mail rename domain name record */ - DNS_TYPE_MR, - /** NULL record */ - DNS_TYPE_NULL_R, - /** well known service description record */ - DNS_TYPE_WKS, - /** Pointer record */ - DNS_TYPE_PTR, - /** Host information record */ - DNS_TYPE_HINFO, - /** mailbox or mail list information record */ - DNS_TYPE_MINFO, - /** Mail exchanger record */ - DNS_TYPE_MX, - /** Text record */ - DNS_TYPE_TXT, - /** Responsible person record */ - DNS_TYPE_RP, - /** AFS database record */ - DNS_TYPE_AFSDB, - /** DNS X25 resource record */ - DNS_TYPE_X25, - /** Integrated Services Digital Network record */ - DNS_TYPE_ISDN, - /** Route Through record */ - DNS_TYPE_RT, - /** network service access point address record */ - DNS_TYPE_NSAP, - /** network service access point address pointer record */ - DNS_TYPE_NSAP_PTR, - /** Signature record */ - DNS_TYPE_SIG, - /** Key record */ - DNS_TYPE_KEY, - /** Mail Mapping Information record */ - DNS_TYPE_PX, - /** DNS Geographical Position record */ - DNS_TYPE_GPOS, - /** IPv6 address record */ - DNS_TYPE_AAAA, - /** Location record */ - DNS_TYPE_LOC, - /** Obsolete record */ - DNS_TYPE_NXT, - /** DNS Endpoint Identifier record */ - DNS_TYPE_EID, - /** DNS Nimrod Locator record */ - DNS_TYPE_NIMLOC, - /** Service locator record */ - DNS_TYPE_SRV, - /** Asynchronous Transfer Mode address record */ - DNS_TYPE_ATMA, - /** Naming Authority Pointer record */ - DNS_TYPE_NAPTR, - /** Key eXchanger record */ - DNS_TYPE_KX, - /** Certificate record */ - DNS_TYPE_CERT, - /** Obsolete, replaced by AAAA type */ - DNS_TYPE_A6, - /** Delegation Name record */ - DNS_TYPE_DNAM, - /** Kitchen sink record */ - DNS_TYPE_SINK, - /** Option record */ - DNS_TYPE_OPT, - /** Address Prefix List record */ - DNS_TYPE_APL, - /** Delegation signer record */ - DNS_TYPE_DS, - /** SSH Public Key Fingerprint record */ - DNS_TYPE_SSHFP, - /** IPsec Key record */ - DNS_TYPE_IPSECKEY, - /** DNSSEC signature record */ - DNS_TYPE_RRSIG, - /** Next-Secure record */ - DNS_TYPE_NSEC, - /** DNS Key record */ - DNS_TYPE_DNSKEY, - /** DHCP identifier record */ - DNS_TYPE_DHCID, - /** NSEC record version 3 */ - DNS_TYPE_NSEC3, - /** NSEC3 parameters */ - DNS_TYPE_NSEC3PARAM, - /** All cached records */ - DNS_TYPE_ALL = 255 - }; - - - /** - * An enum for all possible DNS classes - */ - enum DnsClass - { - /** Internet class */ - DNS_CLASS_IN = 1, - /** Internet class with QU flag set to True */ - DNS_CLASS_IN_QU = 32769, - /** Chaos class */ - DNS_CLASS_CH = 3, - /** Hesiod class */ - DNS_CLASS_HS = 4, - /** ANY class */ - DNS_CLASS_ANY = 255 - }; - - - /** - * An enum for representing the 4 types of possible DNS records - */ - enum DnsResourceType - { - /** DNS query record */ - DnsQueryType = 0, - /** DNS answer record */ - DnsAnswerType = 1, - /** DNS authority record */ - DnsAuthorityType = 2, - /** DNS additional record */ - DnsAdditionalType = 3 - }; - -} - -#endif // PV_PACKETPP_DNS_LAYER_ENUMS diff --git a/libs/visor_dns/DnsResource.cpp b/libs/visor_dns/DnsResource.cpp deleted file mode 100644 index 8b329d6e5..000000000 --- a/libs/visor_dns/DnsResource.cpp +++ /dev/null @@ -1,447 +0,0 @@ -#define LOG_MODULE PacketLogModuleDnsLayer - -#include "DnsResource.h" -#include "EndianPortable.h" -#include "fmt/format.h" -#ifdef __GNUC__ -#pragma GCC diagnostic push -#pragma clang diagnostic ignored "-Wgnu-zero-variadic-macro-arguments" -#endif -#include -#ifdef __GNUC__ -#pragma GCC diagnostic pop -#endif -#include -#include - -namespace visor::lib::dns { - -IDnsResource::IDnsResource(DnsLayer *dnsLayer, size_t offsetInLayer) - : m_DnsLayer(dnsLayer) - , m_OffsetInLayer(offsetInLayer) - , m_NextResource(NULL) -{ - char decodedName[256]; - m_NameLength = decodeName((const char *)getRawData(), decodedName); - if (m_NameLength > 0) { - m_DecodedName = decodedName; - m_DecodedNameLower = m_DecodedName; - std::transform(m_DecodedNameLower.begin(), m_DecodedNameLower.end(), m_DecodedNameLower.begin(), - [](unsigned char c) { return std::tolower(c); }); - } -} - -IDnsResource::IDnsResource(uint8_t *emptyRawData) - : m_DnsLayer(NULL) - , m_OffsetInLayer(0) - , m_NextResource(NULL) - , m_DecodedName("") - , m_DecodedNameLower("") - , m_NameLength(0) - , m_ExternalRawData(emptyRawData) -{ -} - -uint8_t *IDnsResource::getRawData() const -{ - if (m_DnsLayer == NULL) - return m_ExternalRawData; - - return m_DnsLayer->m_Data + m_OffsetInLayer; -} - -size_t IDnsResource::decodeName(const char *encodedName, char *result, int iteration) -{ - size_t encodedNameLength = 0; - size_t decodedNameLength = 0; - char *resultPtr = result; - resultPtr[0] = 0; - - size_t curOffsetInLayer = (uint8_t *)encodedName - m_DnsLayer->m_Data; - if (curOffsetInLayer + 1 > m_DnsLayer->m_DataLen) - return encodedNameLength; - - if (iteration > 20) { - return encodedNameLength; - } - - uint8_t wordLength = encodedName[0]; - - // A string to parse - while (wordLength != 0) { - // A pointer to another place in the packet - if ((wordLength & 0xc0) == 0xc0) { - if (curOffsetInLayer + 2 > m_DnsLayer->m_DataLen || encodedNameLength > 255) - return encodedNameLength; - - uint16_t offsetInLayer = (wordLength & 0x3f) * 256 + (0xFF & encodedName[1]); - if (offsetInLayer < sizeof(dnshdr) || offsetInLayer >= m_DnsLayer->m_DataLen) { - PCPP_LOG_ERROR("DNS parsing error: name pointer is illegal"); - return 0; - } - - char tempResult[256]; - memset(tempResult, 0, 256); - int i = 0; - decodeName((const char *)(m_DnsLayer->m_Data + offsetInLayer), tempResult, iteration + 1); - while (tempResult[i] != 0 && decodedNameLength < 255) { - resultPtr[0] = tempResult[i++]; - resultPtr++; - decodedNameLength++; - } - - resultPtr[0] = 0; - - // in this case the length of the pointer is: 1 byte for 0xc0 + 1 byte for the offset itself - return encodedNameLength + sizeof(uint16_t); - } else { - // return if next word would be outside of the DNS layer or overflow the buffer behind resultPtr - if (curOffsetInLayer + wordLength + 1 > m_DnsLayer->m_DataLen || encodedNameLength + wordLength > 255) { - // add the last '\0' to the decoded string - if (encodedNameLength == 256) { - resultPtr--; - decodedNameLength--; - } else { - encodedNameLength++; - } - - resultPtr[0] = 0; - return encodedNameLength; - } - - memcpy(resultPtr, encodedName + 1, wordLength); - resultPtr += wordLength; - resultPtr[0] = '.'; - resultPtr++; - decodedNameLength += wordLength + 1; - encodedName += wordLength + 1; - encodedNameLength += wordLength + 1; - - curOffsetInLayer = (uint8_t *)encodedName - m_DnsLayer->m_Data; - if (curOffsetInLayer + 1 > m_DnsLayer->m_DataLen) { - // add the last '\0' to the decoded string - if (encodedNameLength == 256) { - decodedNameLength--; - resultPtr--; - } else { - encodedNameLength++; - } - - resultPtr[0] = 0; - return encodedNameLength; - } - - wordLength = encodedName[0]; - } - } - - // remove the last "." - if (resultPtr > result) { - result[resultPtr - result - 1] = 0; - } - - // add the last '\0' to encodedNameLength - resultPtr[0] = 0; - encodedNameLength++; - - return encodedNameLength; -} - -void IDnsResource::encodeName(const std::string &decodedName, char *result, size_t &resultLen) -{ - resultLen = 0; - std::stringstream strstream(decodedName); - std::string word; - while (getline(strstream, word, '.')) { - // pointer to a different hostname in the packet - if (word[0] == '#') { - // convert the number from string to int - std::stringstream stream(word.substr(1)); - int pointerInPacket = 0; - stream >> pointerInPacket; - - // verify it's indeed a number and that is in the range of [0-255] - if (stream.fail() || pointerInPacket < 0 || pointerInPacket > 0xff) { - PCPP_LOG_ERROR(fmt::format("Error encoding the string '{}'", decodedName)); - return; - } - - // set the pointer to the encoded string result - result[0] = (uint8_t)0xc0; - result[1] = (uint8_t)pointerInPacket; - result += 2; - resultLen += 2; - return; // pointer always comes last - } - - result[0] = word.length(); - result++; - memcpy(result, word.c_str(), word.length()); - result += word.length(); - resultLen += word.length() + 1; - } - - result[0] = 0; - resultLen++; -} - -DnsType IDnsResource::getDnsType() const -{ - uint16_t dnsType{0}; - memcpy(&dnsType, (getRawData() + m_NameLength), sizeof(dnsType)); - return (DnsType)be16toh(dnsType); -} - -void IDnsResource::setDnsType(DnsType newType) -{ - uint16_t newTypeAsInt = htobe16((uint16_t)newType); - memcpy(getRawData() + m_NameLength, &newTypeAsInt, sizeof(uint16_t)); -} - -DnsClass IDnsResource::getDnsClass() const -{ - uint16_t dnsClass = *(uint16_t *)(getRawData() + m_NameLength + sizeof(uint16_t)); - return (DnsClass)be16toh(dnsClass); -} - -void IDnsResource::setDnsClass(DnsClass newClass) -{ - uint16_t newClassAsInt = htobe16((uint16_t)newClass); - memcpy(getRawData() + m_NameLength + sizeof(uint16_t), &newClassAsInt, sizeof(uint16_t)); -} - -bool IDnsResource::setName(const std::string &newName) -{ - char encodedName[256]; - size_t encodedNameLen = 0; - encodeName(newName, encodedName, encodedNameLen); - if (m_DnsLayer != NULL) { - if (encodedNameLen > m_NameLength) { - if (!m_DnsLayer->extendLayer(m_OffsetInLayer, encodedNameLen - m_NameLength, this)) { - PCPP_LOG_ERROR("Couldn't set name for DNS query, unable to extend layer"); - return false; - } - } else if (encodedNameLen < m_NameLength) { - if (!m_DnsLayer->shortenLayer(m_OffsetInLayer, m_NameLength - encodedNameLen, this)) { - PCPP_LOG_ERROR("Couldn't set name for DNS query, unable to shorten layer"); - return false; - } - } - } else { - size_t size = getSize(); - char *tempData = new char[size]; - memcpy(tempData, m_ExternalRawData, size); - memcpy(m_ExternalRawData + encodedNameLen, tempData, size); - delete[] tempData; - } - - memcpy(getRawData(), encodedName, encodedNameLen); - m_NameLength = encodedNameLen; - m_DecodedName = newName; - m_DecodedNameLower = m_DecodedName; - std::transform(m_DecodedNameLower.begin(), m_DecodedNameLower.end(), m_DecodedNameLower.begin(), - [](unsigned char c) { return std::tolower(c); }); - - return true; -} - -void IDnsResource::setDnsLayer(DnsLayer *dnsLayer, size_t offsetInLayer) -{ - memcpy(dnsLayer->m_Data + offsetInLayer, m_ExternalRawData, getSize()); - m_DnsLayer = dnsLayer; - m_OffsetInLayer = offsetInLayer; - m_ExternalRawData = NULL; -} - -std::basic_string_view IDnsResource::getRawName() const -{ - if (m_NameLength == 0) { - // malformed name - return {}; - } - // scan starts at the domain name - auto scan = std::basic_string_view{m_DnsLayer->m_Data, m_DnsLayer->m_DataLen} - .substr(m_OffsetInLayer) // skip to the name offset - .substr(0, 255); // enforce name length limit - - // find the end of the scan - size_t pos = 0; - while (pos < scan.size()) { - if (scan[pos] == 0) { - // root label at the end - pos += 1; - break; - } else if (scan[pos] < 0xc0) { - // normal scan label - pos += scan[pos] + 1; - } else if (scan[pos] == 0xc0) { - // compression label at the end - pos += 3; - break; - } else { - // malformed name - pos = std::string_view::npos; - break; - } - } - - if (pos >= scan.size()) { - // malformed name - return {}; - } - - return scan.substr(0, pos); -} - -uint32_t DnsResource::getTTL() const -{ - uint32_t ttl = *(uint32_t *)(getRawData() + m_NameLength + 2 * sizeof(uint16_t)); - return be32toh(ttl); -} - -void DnsResource::setTTL(uint32_t newTTL) -{ - newTTL = htobe32(newTTL); - memcpy(getRawData() + m_NameLength + 2 * sizeof(uint16_t), &newTTL, sizeof(uint32_t)); -} - -size_t DnsResource::getDataLength() const -{ - uint16_t dataLength{0}; - memcpy(&dataLength, (getRawData() + m_NameLength + 2 * sizeof(uint16_t) + sizeof(uint32_t)), sizeof(dataLength)); - return be16toh(dataLength); -} - -DnsResourceDataPtr DnsResource::getData() const -{ - uint8_t *resourceRawData = getRawData() + m_NameLength + 3 * sizeof(uint16_t) + sizeof(uint32_t); - size_t dataLength = getDataLength(); - - switch (getDnsType()) { - case DNS_TYPE_A: { - return DnsResourceDataPtr(new IPv4DnsResourceData(resourceRawData, dataLength)); - } - - case DNS_TYPE_AAAA: { - return DnsResourceDataPtr(new IPv6DnsResourceData(resourceRawData, dataLength)); - } - - case DNS_TYPE_NS: - case DNS_TYPE_CNAME: - case DNS_TYPE_DNAM: - case DNS_TYPE_PTR: { - return DnsResourceDataPtr(new StringDnsResourceData(resourceRawData, dataLength, const_cast(static_cast(this)))); - } - - case DNS_TYPE_MX: { - return DnsResourceDataPtr(new MxDnsResourceData(resourceRawData, dataLength, const_cast(static_cast(this)))); - } - - default: { - return DnsResourceDataPtr(new GenericDnsResourceData(resourceRawData, dataLength)); - } - } -} - -size_t DnsResource::getDataOffset() const -{ - return (size_t)(m_OffsetInLayer + m_NameLength + 3 * sizeof(uint16_t) + sizeof(uint32_t)); -} - -bool DnsResource::setData(IDnsResourceData *data) -{ - // convert data to byte array according to the DNS type - size_t dataLength = 0; - uint8_t dataAsByteArr[256]; - - if (data == NULL) { - PCPP_LOG_ERROR("Given data is NULL"); - return false; - } - - switch (getDnsType()) { - case DNS_TYPE_A: { - if (!data->isTypeOf()) { - PCPP_LOG_ERROR("DNS record is of type A but given data isn't of type IPv4DnsResourceData"); - return false; - } - break; - } - - case DNS_TYPE_AAAA: { - if (!data->isTypeOf()) { - PCPP_LOG_ERROR("DNS record is of type AAAA but given data isn't of type IPv6DnsResourceData"); - return false; - } - break; - } - - case DNS_TYPE_NS: - case DNS_TYPE_CNAME: - case DNS_TYPE_DNAM: - case DNS_TYPE_PTR: { - if (!data->isTypeOf()) { - PCPP_LOG_ERROR("DNS record is of type NS, CNAME, DNAM or PTR but given data isn't of type StringDnsResourceData"); - return false; - } - break; - } - - case DNS_TYPE_MX: { - if (!data->isTypeOf()) { - PCPP_LOG_ERROR("DNS record is of type MX but given data isn't of type MxDnsResourceData"); - return false; - } - break; - } - - default: { - // do nothing - } - } - - // convert the IDnsResourceData to byte array - if (!data->toByteArr(dataAsByteArr, dataLength, this)) { - PCPP_LOG_ERROR("Cannot convert DNS resource data to byte array, data is probably invalid"); - return false; - } - - size_t dataLengthOffset = m_NameLength + (2 * sizeof(uint16_t)) + sizeof(uint32_t); - size_t dataOffset = dataLengthOffset + sizeof(uint16_t); - - if (m_DnsLayer != NULL) { - size_t curLength = getDataLength(); - if (dataLength > curLength) { - if (!m_DnsLayer->extendLayer(m_OffsetInLayer + dataOffset, dataLength - curLength, this)) { - PCPP_LOG_ERROR("Couldn't set data for DNS query, unable to extend layer"); - return false; - } - } else if (dataLength < curLength) { - if (!m_DnsLayer->shortenLayer(m_OffsetInLayer + dataOffset, curLength - dataLength, this)) { - PCPP_LOG_ERROR("Couldn't set data for DNS query, unable to shorten layer"); - return false; - } - } - } - - // write data to resource - memcpy(getRawData() + dataOffset, dataAsByteArr, dataLength); - // update data length in resource - dataLength = htobe16((uint16_t)dataLength); - memcpy(getRawData() + dataLengthOffset, &dataLength, sizeof(uint16_t)); - - return true; -} - -uint16_t DnsResource::getCustomDnsClass() const -{ - uint16_t value = *(uint16_t *)(getRawData() + m_NameLength + sizeof(uint16_t)); - return be16toh(value); -} - -void DnsResource::setCustomDnsClass(uint16_t customValue) -{ - memcpy(getRawData() + m_NameLength + sizeof(uint16_t), &customValue, sizeof(uint16_t)); -} - -} diff --git a/libs/visor_dns/DnsResource.h b/libs/visor_dns/DnsResource.h deleted file mode 100644 index 429c886c9..000000000 --- a/libs/visor_dns/DnsResource.h +++ /dev/null @@ -1,245 +0,0 @@ -#ifndef PV_PACKETPP_DNS_RESOURCE -#define PV_PACKETPP_DNS_RESOURCE - -#include "DnsLayer.h" -#include "DnsLayerEnums.h" -#include "DnsResourceData.h" -#include -#include -#include - -/// @file - -/** - * \namespace visor - */ -namespace visor::lib::dns { -// forward declarations -class DnsLayer; -class IDnsResourceData; -class DnsResourceDataPtr; - -/** - * @class IDnsResource - * An abstract class for representing all types of DNS records. This class gives access to all available record data such as DNS type, class, - * name, type of record, etc. The DnsLayer holds an instance of (inherited type of) this class for each DNS record in the DNS packet - */ -class IDnsResource - { - protected: - friend class DnsLayer; - friend class IDnsResourceData; - - protected: - DnsLayer* m_DnsLayer; - size_t m_OffsetInLayer; - IDnsResource* m_NextResource; - std::string m_DecodedName; - std::string m_DecodedNameLower; - size_t m_NameLength; - uint8_t* m_ExternalRawData; - - IDnsResource(DnsLayer* dnsLayer, size_t offsetInLayer); - - IDnsResource(uint8_t* emptyRawData); - - size_t decodeName(const char* encodedName, char* result, int iteration = 1); - void encodeName(const std::string& decodedName, char* result, size_t& resultLen); - - IDnsResource* getNextResource() const { return m_NextResource; } - void setNexResource(IDnsResource* next) { m_NextResource = next; } - - uint8_t* getRawData() const; - - void setDnsLayer(DnsLayer* dnsLayer, size_t offsetInLayer); - - public: - - virtual ~IDnsResource() {} - - /** - * @return The DNS type of this record - */ - DnsType getDnsType() const; - - /** - * Set DNS type for this record - * @param[in] newType The type to set - */ - void setDnsType(DnsType newType); - - /** - * @return The DNS class of this record - */ - DnsClass getDnsClass() const; - - /** - * Set DNS class for this record - * @param[in] newClass The class to set - */ - void setDnsClass(DnsClass newClass); - - /** - * @return The name of this record - */ - const std::string& getName() const { return m_DecodedName; } - - /** - * @return The name of this record in lower case - */ - const std::string& getNameLower() const { return m_DecodedNameLower; } - - /** - * @return The record name's offset in the packet - */ - size_t getNameOffset() const { return m_OffsetInLayer; } - - /** - * @return The raw name - */ - std::basic_string_view getRawName() const; - - /** - * Set the name of this record. The input name can be a standard hostname (e.g 'google.com'), or it may contain - * a pointer to another string in the packet (as explained here: http://www.zytrax.com/books/dns/ch15/#name). - * The pointer is used to reduce the DNS packet size and avoid unnecessary duplications. In case you - * want to use a pointer in your string you should use the following format: 'some.domain.#{offset}' where '#{offset}' - * is a the offset from the start of the layer. For example: if the string 'yahoo.com' already appears in offset - * 12 in the packet and you want to set the name of the current record to 'my.subdomain.yahoo.com' you may use - * the following string: 'my.subdomain.#12'. This will result in writing 'my.subdomain' and a pointer to offset 12.
- * Please notice the new name can be shorter or longer of the old name, so this method can cause the packet to be - * shorten or extended - * @param[in] newName The name to set - * @return True if name was set successfully or false if input string is malformed or if an error occurred - */ - bool setName(const std::string& newName); - - - // abstract methods - - /** - * @return The total size in bytes of this record - */ - virtual size_t getSize() const = 0; - - /** - * @return The type of this record (query, answer, authority, additional) - */ - virtual DnsResourceType getType() const = 0; - }; - - - /** - * @class DnsQuery - * Representing a DNS query record - */ - class DnsQuery : public IDnsResource - { - friend class DnsLayer; - - private: - DnsQuery(DnsLayer* dnsLayer, size_t offsetInLayer) : IDnsResource(dnsLayer, offsetInLayer) {} - - DnsQuery(uint8_t* emptyRawData) : IDnsResource(emptyRawData) {} - - public: - virtual ~DnsQuery() {} - - // implementation of abstract methods - virtual size_t getSize() const { return m_NameLength + 2 * sizeof(uint16_t); } - virtual DnsResourceType getType() const { return DnsQueryType; } - }; - - - /** - * @class DnsResource - * Representing DNS record other than DNS query - */ - class DnsResource : public IDnsResource - { - friend class DnsLayer; - - private: - DnsResourceType m_ResourceType; - - DnsResource(DnsLayer* dnsLayer, size_t offsetInLayer, DnsResourceType resourceType) : IDnsResource(dnsLayer, offsetInLayer) { m_ResourceType = resourceType; } - - DnsResource(uint8_t* emptyRawData, DnsResourceType resType) : IDnsResource(emptyRawData), m_ResourceType(resType) {} - - public: - virtual ~DnsResource() {} - - /** - * @return The time-to-leave value for this record - */ - uint32_t getTTL() const; - - /** - * Set time-to-leave value for this record - * @param[in] newTTL The new TTL value to set - */ - void setTTL(uint32_t newTTL); - - /** - * @return The data length value for this record (taken from the "data length" field of the record) - */ - size_t getDataLength() const; - - /** - * @return A smart pointer to an IDnsResourceData object that contains the DNS resource data. It is guaranteed that the - * smart pointer will always point to an object and never to NULL. The specific object type depends on the DNS type of this record:
- * - For type A (::DNS_TYPE_A): the return value is a smart pointer to IPv4DnsResourceData object that contains the IPv4 address
- * - For type AAAA (::DNS_TYPE_AAAA): the return value is a smart pointer to IPv6DnsResourceData object that contains the IPv6 address
- * - For types NS, CNAME, DNAME, PTR (::DNS_TYPE_NS, ::DNS_TYPE_CNAME, ::DNS_TYPE_DNAM, ::DNS_TYPE_PTR): the return value is - * a smart pointer to StringDnsResourceData object that contains the name
- * - For type MX (::DNS_TYPE_MX): the return value is a smart pointer to MxDnsResourceData object that contains the MX data (preference and - * mail exchange name)
- * - For all other types: the return value is a smart pointer to GenericDnsResourceData which contains a byte array of the data - */ - DnsResourceDataPtr getData() const; - - /** - * @return The offset of data in the DNS layer - */ - size_t getDataOffset() const; - - /** - * Set resource data. The given IDnsResourceData input object is validated against the DNS type of the resource. For example: if DNS type is A - * and data isn't of type IPv4DnsResourceData (which contains the IPv4 address) a log error will be printed and the method will return false. - * This method currently supports the following DNS types:
- * - ::DNS_TYPE_A (IPv4 address) - data is expected to be a pointer to IPv4DnsResourceData with a valid IPv4 address - * - ::DNS_TYPE_AAAA (IPv6 address) - data is expected to be a pointer to IPv6DnsResourceData with a valid IPv6 address - * - ::DNS_TYPE_NS, ::DNS_TYPE_CNAME, ::DNS_TYPE_DNAM, ::DNS_TYPE_PTR (name data) - data is expected to be a pointer to StringDnsResourceData - * object that contains a host name, e.g: 'www.google.com' - * - ::DNS_TYPE_MX (MX data) - data is expected to be a pointer to MxDnsResourceData object that contains the MX data - * - else: data is expected to be a pointer to GenericDnsResourceData object that contains a valid hex string (valid hex string means a string - * which has an even number of characters representing a valid hex data. e.g: '0d0a45569a9b') - * @param[in] data The pointer to the data object, as described above - * @return True if data was properly set or false if data is illegal or method couldn't extend or shorted the packet (appropriate error log is - * printed in all cases) - */ - bool setData(IDnsResourceData* data); - - /** - * Some records don't have a DNS class and the bytes used for storing the DNS class are used for other purpose. This method enables the - * user to receive these bytes - * @return The value stored in this place - */ - uint16_t getCustomDnsClass() const; - - /** - * Some records don't have a DNS class and the bytes used for storing the DNS class are used for other purpose. This method enables the - * user to set these bytes - * @param[in] customValue The value to set - */ - void setCustomDnsClass(uint16_t customValue); - - // implementation of abstract methods - virtual size_t getSize() const { return m_NameLength + 3 * sizeof(uint16_t) + sizeof(uint32_t) + getDataLength(); } - virtual DnsResourceType getType() const { return m_ResourceType; } - - }; - -} - -#endif // PV_PACKETPP_DNS_RESOURCE diff --git a/libs/visor_dns/DnsResourceData.cpp b/libs/visor_dns/DnsResourceData.cpp deleted file mode 100644 index 61ef5eb3e..000000000 --- a/libs/visor_dns/DnsResourceData.cpp +++ /dev/null @@ -1,215 +0,0 @@ -#define LOG_MODULE PacketLogModuleDnsLayer - -#include "DnsResourceData.h" -#include "EndianPortable.h" -#include -#include -#include -#ifdef __GNUC__ -#pragma GCC diagnostic push -#pragma clang diagnostic ignored "-Wgnu-zero-variadic-macro-arguments" -#endif -#include -#ifdef __GNUC__ -#pragma GCC diagnostic pop -#pragma GCC diagnostic ignored "-Wunused-parameter" -#endif - -// forked code -namespace visor::lib::dns { - -size_t IDnsResourceData::decodeName(const char *encodedName, char *result, IDnsResource *dnsResource) const -{ - if (dnsResource == NULL) { - PCPP_LOG_ERROR("Cannot decode name, DNS resource object is NULL"); - return 0; - } - - return dnsResource->decodeName(encodedName, result); -} - -void IDnsResourceData::encodeName(const std::string &decodedName, char *result, size_t &resultLen, IDnsResource *dnsResource) const -{ - if (dnsResource == NULL) { - PCPP_LOG_ERROR("Cannot encode name, DNS resource object is NULL"); - return; - } - - dnsResource->encodeName(decodedName, result, resultLen); -} - -StringDnsResourceData::StringDnsResourceData(const uint8_t *dataPtr, size_t dataLen, IDnsResource *dnsResource) -{ - char tempResult[256]; - decodeName((const char *)dataPtr, tempResult, dnsResource); - m_Data = tempResult; -} - -bool StringDnsResourceData::toByteArr(uint8_t *arr, size_t &arrLength, IDnsResource *dnsResource) const -{ - encodeName(m_Data, (char *)arr, arrLength, dnsResource); - return true; -} - -IPv4DnsResourceData::IPv4DnsResourceData(const uint8_t *dataPtr, size_t dataLen) -{ - if (dataLen != 4) { - PCPP_LOG_ERROR("DNS type is A but resource length is not 4 - malformed data"); - return; - } - - uint32_t addrAsInt = *(uint32_t *)dataPtr; - m_Data = pcpp::IPv4Address(addrAsInt); -} - -bool IPv4DnsResourceData::toByteArr(uint8_t *arr, size_t &arrLength, IDnsResource *dnsResource) const -{ - if (!m_Data.isValid()) { - PCPP_LOG_ERROR("Cannot convert IPv4 address to byte array because address is not valid"); - return false; - } - - arrLength = sizeof(uint32_t); - memcpy(arr, m_Data.toBytes(), sizeof(uint32_t)); - return true; -} - -IPv6DnsResourceData::IPv6DnsResourceData(const uint8_t *dataPtr, size_t dataLen) -{ - if (dataLen != 16) { - PCPP_LOG_ERROR("DNS type is AAAA but resource length is not 16 - malformed data"); - return; - } - - m_Data = pcpp::IPv6Address((uint8_t *)dataPtr); -} - -bool IPv6DnsResourceData::toByteArr(uint8_t *arr, size_t &arrLength, IDnsResource *dnsResource) const -{ - if (!m_Data.isValid()) { - PCPP_LOG_ERROR("Cannot convert IPv6 address to byte array because address is not valid"); - return false; - } - - arrLength = 16; - m_Data.copyTo(arr); - return true; -} - -MxDnsResourceData::MxDnsResourceData(uint8_t *dataPtr, size_t dataLen, IDnsResource *dnsResource) -{ - uint16_t preference = be16toh(*(uint16_t *)dataPtr); - char tempMX[256]; - decodeName((const char *)(dataPtr + sizeof(preference)), tempMX, dnsResource); - m_Data.preference = preference; - m_Data.mailExchange = tempMX; -} - -MxDnsResourceData::MxDnsResourceData(const uint16_t &preference, const std::string &mailExchange) -{ - m_Data.preference = preference; - m_Data.mailExchange = mailExchange; -} - -bool MxDnsResourceData::operator==(const MxDnsResourceData &other) const -{ - return (m_Data.preference == other.m_Data.preference) && (m_Data.mailExchange == other.m_Data.mailExchange); -} - -void MxDnsResourceData::setMxData(uint16_t preference, std::string mailExchange) -{ - m_Data.preference = preference; - m_Data.mailExchange = mailExchange; -} - -std::string MxDnsResourceData::toString() const -{ - std::stringstream result; - result << "pref: " << m_Data.preference << "; mx: " << m_Data.mailExchange; - return result.str(); -} - -bool MxDnsResourceData::toByteArr(uint8_t *arr, size_t &arrLength, IDnsResource *dnsResource) const -{ - uint16_t netOrderPreference = htobe16(m_Data.preference); - memcpy(arr, &netOrderPreference, sizeof(uint16_t)); - encodeName(m_Data.mailExchange, (char *)(arr + sizeof(uint16_t)), arrLength, dnsResource); - arrLength += sizeof(uint16_t); - - return true; -} - -GenericDnsResourceData::GenericDnsResourceData(uint8_t *dataPtr, size_t dataLen) -{ - m_Data = NULL; - m_DataLen = 0; - if (dataLen > 0 && dataPtr != NULL) { - m_DataLen = dataLen; - m_Data = new uint8_t[dataLen]; - memcpy(m_Data, dataPtr, dataLen); - } -} - -GenericDnsResourceData::GenericDnsResourceData(const std::string &dataAsHexString) -{ - m_Data = NULL; - uint8_t tempDataArr[2048]; - m_DataLen = pcpp::hexStringToByteArray(dataAsHexString, tempDataArr, 2048); - if (m_DataLen != 0) { - m_Data = new uint8_t[m_DataLen]; - memcpy(m_Data, tempDataArr, m_DataLen); - } -} - -GenericDnsResourceData::GenericDnsResourceData(const GenericDnsResourceData &other) - : IDnsResourceData() -{ - m_DataLen = other.m_DataLen; - - if (m_DataLen > 0 && other.m_Data != NULL) { - m_Data = new uint8_t[m_DataLen]; - memcpy(m_Data, other.m_Data, m_DataLen); - } -} - -GenericDnsResourceData &GenericDnsResourceData::operator=(const GenericDnsResourceData &other) -{ - if (m_Data != NULL) - delete[] m_Data; - - m_Data = NULL; - m_DataLen = other.m_DataLen; - if (m_DataLen > 0 && other.m_Data != NULL) { - m_Data = new uint8_t[m_DataLen]; - memcpy(m_Data, other.m_Data, m_DataLen); - } - - return (*this); -} - -bool GenericDnsResourceData::operator==(const GenericDnsResourceData &other) const -{ - if (m_DataLen != other.m_DataLen) - return false; - - return (memcmp(m_Data, other.m_Data, m_DataLen) == 0); -} - -std::string GenericDnsResourceData::toString() const -{ - return pcpp::byteArrayToHexString(m_Data, m_DataLen); -} - -bool GenericDnsResourceData::toByteArr(uint8_t *arr, size_t &arrLength, IDnsResource *dnsResource) const -{ - if (m_DataLen == 0 || m_Data == NULL) { - PCPP_LOG_ERROR("Input data is null or illegal"); - return false; - } - - arrLength = m_DataLen; - memcpy(arr, m_Data, m_DataLen); - return true; -} - -} diff --git a/libs/visor_dns/DnsResourceData.h b/libs/visor_dns/DnsResourceData.h deleted file mode 100644 index b7c683920..000000000 --- a/libs/visor_dns/DnsResourceData.h +++ /dev/null @@ -1,402 +0,0 @@ -#ifndef PV_PACKETPP_DNS_RESOURCE_DATA -#define PV_PACKETPP_DNS_RESOURCE_DATA - -#include "DnsResource.h" -#include -#include -#include -#include - - -/// @file - -/** - * \namespace visor - */ -namespace visor::lib::dns { - -//Visual studio has always been stupid about returning something useful for __cplusplus -//Only recently was this fixed - and even then it requires a specific hack to the command line during build -//Its easier/more consistent to test _MSC_VER in VS -//https://docs.microsoft.com/en-us/cpp/build/reference/zc-cplusplus?view=vs-2017 - -#if __cplusplus > 199711L || _MSC_VER >= 1800 //Maybe this can be 1600 for VS2010 -#define PCPP_SMART_PTR(T) std::unique_ptr -#else -#define PCPP_SMART_PTR(T) std::auto_ptr -#endif - - // forward declarations - class IDnsResource; - - /** - * @class IDnsResourceData - * A wrapper class for storing DNS RR (resource record) data. This is the base class which introduces several abstract - * methods for derived classes to implement for setting and retrieving the stored data. Each derived class will store - * different type of DNS RR data and implement these methods accordingly (for example: IPv4/IPv6 addresses, MX data, - * hostnames, raw byte data etc.) - */ - class IDnsResourceData - { - protected: - - // unimplemented private copy c'tor - IDnsResourceData(const IDnsResourceData& other); - IDnsResourceData() { } - - size_t decodeName(const char* encodedName, char* result, IDnsResource* dnsResource) const; - void encodeName(const std::string& decodedName, char* result, size_t& resultLen, IDnsResource* dnsResource) const; - - public: - /** - * A virtual d'tor, does nothing - */ - virtual ~IDnsResourceData() { } - - /** - * A templated method which takes a class that derives from IDnsResourceData as the template argument and - * checks whether this instance is of this type - * @return True if this instance is of the requested type, false otherwise - */ - template - bool isTypeOf() const { return dynamic_cast(this) != NULL; } - - /** - * A templated method which take a class that derives from IDnsResourceData as the template argument and tries to - * cast the current instance as that type - * @return A pointer to the current instance casted as the requested type or NULL if this instance isn't of this type - */ - template - IDnsResourceDataType* castAs() { return dynamic_cast(this); } - - /** - * @return A string that represents the current DNS RR data - */ - virtual std::string toString() const = 0; - - /** - * Convert the DNS RR data into a byte array - * @param[out] arr A pointer to a pre-allocated byte array where the result will be written to - * @param[out] arrLength A reference to a 2-byte number where the result array length will be written to - * @param[in] dnsResource A pointer to a DNS resource object where this DNS RR data will be stored - * @return True if the DNS RR data was successfully converted into a byte array and written to the given array or - * false if stored DNS RR data is invalid or if it could not be written to the given array - */ - virtual bool toByteArr(uint8_t* arr, size_t& arrLength, IDnsResource* dnsResource) const = 0; - }; - - - /** - * @class DnsResourceDataPtr - * A smart pointer class that holds pointers of type IDnsResourceData. This object is used in DnsResource#getData() - */ - class DnsResourceDataPtr : public PCPP_SMART_PTR(IDnsResourceData) - { - public: - - /** - * A c'tor to this class - * @param[in] ptr A pointer to IDnsResourceData - */ - DnsResourceDataPtr(IDnsResourceData* ptr) : PCPP_SMART_PTR(IDnsResourceData)(ptr) {} - - //Visual studio has always been stupid about returning something useful for __cplusplus - //Only recently was this fixed - and even then it requires a specific hack to the command line during build - //Its easier/more consistent to test _MSC_VER in VS - //https://docs.microsoft.com/en-us/cpp/build/reference/zc-cplusplus?view=vs-2017 - -#if __cplusplus <= 199711L && _MSC_VER < 1800 //Maybe this can be 1600 for VS2010 - DnsResourceDataPtr(const DnsResourceDataPtr& other) : PCPP_SMART_PTR(IDnsResourceData)((DnsResourceDataPtr&)other) {} -#endif - - /** - * A templated method which takes a class that derives from IDnsResourceData as the template argument and - * checks whether the pointer stored in this object is of this type - * @return True if the stored pointer is of the requested type, false otherwise - */ - template - bool isTypeOf() const { return get()->isTypeOf(); } - - /** - * A templated method which take a class that derives from IDnsResourceData as the template argument and tries to - * cast the pointer stored in this object as that type - * @return A pointer to the stored pointer casted as the requested type or NULL if it isn't of this type - */ - template - IDnsResourceDataType* castAs() { return get()->castAs();} - }; - - - /** - * @class StringDnsResourceData - * A class that represents DNS RR string data, mainly used in DNS RRs that store hostnames (like CNAME, DNAME, NS, etc.) - */ - class StringDnsResourceData : public IDnsResourceData - { - private: - std::string m_Data; - - public: - - /** - * A c'tor for this class - * @param[in] data The string data to store in this object. If this string represents a hostname it's possible - * to include a pointer to another string in the DNS layer (as explained here: http://www.zytrax.com/books/dns/ch15/#name). - * These pointers are often used to reduce the DNS packet size and avoid unnecessary duplications. The way to include pointers - * in a hostname string is to use the following format: 'some.domain.#{offset}' where '#{offset}' is the offset from the - * start of the DNS layer. For example: if the string 'yahoo.com' already appears in offset 12 in the packet and you want - * to set the DNS RR data as 'my.subdomain.yahoo.com' you may use the following string: 'my.subdomain.#12'. - * This will result in writing 'my.subdomain' and a pointer to offset 12 - */ - StringDnsResourceData(const std::string& data) { m_Data = data; } - - StringDnsResourceData(const uint8_t* dataPtr, size_t dataLen, IDnsResource* dnsResource); - - ~StringDnsResourceData() {} - - /** - * Equality operator overload for this class that compares the strings stored in each object - * @param[in] other The object to compare with - * @return True if the string data is the same in both objects, false otherwise - */ - bool operator==(const StringDnsResourceData& other) const { return m_Data == other.m_Data; } - - // implement abstract methods - - std::string toString() const { return m_Data; } - bool toByteArr(uint8_t* arr, size_t& arrLength, IDnsResource* dnsResource) const; - }; - - - /** - * @class IPv4DnsResourceData - * A class that represents DNS RR IPv4 data, mainly used in DNS RRs of type ::DNS_TYPE_A - */ - class IPv4DnsResourceData : public IDnsResourceData - { - private: - pcpp::IPv4Address m_Data; - - public: - - /** - * A c'tor for this class - * @param[in] dataPtr A byte array of size 4 that contains an IPv4 address (each byte represents 1 octet) - * @param[in] dataLen The byte array size, expected to be 4 - */ - IPv4DnsResourceData(const uint8_t* dataPtr, size_t dataLen); - - /** - * A c'tor for this class - * @param[in] addr The IPv4 address to store in this object - */ - IPv4DnsResourceData(const pcpp::IPv4Address& addr) : m_Data(addr) {} - - /** - * A c'tor for this class - * @param[in] addrAsString A string representation of an IPv4 address to store in this object - */ - IPv4DnsResourceData(const std::string& addrAsString) : m_Data(addrAsString) {} - - /** - * Equality operator overload for this class that compares the IPv4 addresses stored in each object - * @param[in] other The object to compare with - * @return True if IPv4 addresses are the same in both objects, false otherwise - */ - bool operator==(const IPv4DnsResourceData& other) const { return m_Data == other.m_Data; } - - /** - * @return The IPv4 address stored in this object - */ - pcpp::IPv4Address getIpAddress() const { return m_Data; } - - // implement abstract methods - - std::string toString() const { return m_Data.toString(); } - bool toByteArr(uint8_t* arr, size_t& arrLength, IDnsResource* dnsResource) const; - }; - - - /** - * @class IPv6DnsResourceData - * A class that represents DNS RR IPv6 data, mainly used in DNS RRs of type ::DNS_TYPE_AAAA - */ - class IPv6DnsResourceData : public IDnsResourceData - { - private: - pcpp::IPv6Address m_Data; - - public: - - /** - * A c'tor for this class - * @param[in] dataPtr A byte array of size 16 that contains an IPv6 address (each byte represents 1 octet) - * @param[in] dataLen The byte array size, expected to be 16 - */ - IPv6DnsResourceData(const uint8_t* dataPtr, size_t dataLen); - - /** - * A c'tor for this class - * @param[in] addr The IPv6 address to store in this object - */ - IPv6DnsResourceData(const pcpp::IPv6Address& addr) : m_Data(addr) {} - - /** - * A c'tor for this class - * @param[in] addrAsString A string representation of an IPv6 address to store in this object - */ - IPv6DnsResourceData(const std::string& addrAsString) : m_Data(addrAsString) {} - - /** - * Equality operator overload for this class that compares the IPv6 addresses stored in each object - * @param[in] other The object to compare with - * @return True if IPv6 addresses are the same in both objects, false otherwise - */ - bool operator==(const IPv6DnsResourceData& other) const { return m_Data == other.m_Data; } - - /** - * @return The IPv6 address stored in this object - */ - pcpp::IPv6Address getIpAddress() const { return m_Data; } - - // implement abstract methods - - std::string toString() const { return m_Data.toString(); } - bool toByteArr(uint8_t* arr, size_t& arrLength, IDnsResource* dnsResource) const; - }; - - - /** - * @class MxDnsResourceData - * A class that represents DNS RR mail exchange (MX) data, used in DNS RRs of type ::DNS_TYPE_MX - */ - class MxDnsResourceData : public IDnsResourceData - { - public: - - /** - * A struct that represents mail exchange (MX) data - */ - struct MxData - { - /** Preference value */ - uint16_t preference; - /** Mail exchange hostname */ - std::string mailExchange; - }; - - /** - * A c'tor for this class - * @param[in] dataPtr A byte array that contains the raw MX data (as written in the DNS packet) - * @param[in] dataLen The byte array size - * @param[in] dnsResource A pointer to a DNS resource object where this DNS RR data will be stored - */ - MxDnsResourceData(uint8_t* dataPtr, size_t dataLen, IDnsResource* dnsResource); - - /** - * A c'tor for this class - * @param[in] preference The MX preference value to store in this object - * @param[in] mailExchange The MX hostname value to store in this object. It's possible to include a pointer to - * another string in the DNS layer (as explained here: http://www.zytrax.com/books/dns/ch15/#name). These pointers - * are often used to reduce the DNS packet size and avoid unnecessary duplications. The way to include pointers - * in the hostname string is to use the following format: 'some.domain.#{offset}' where '#{offset}' is the offset - * from the start of the DNS layer. For example: if the string 'yahoo.com' already appears in offset 12 in the - * packet and you want to set the DNS RR data as 'my.subdomain.yahoo.com' you may use the following string: - * 'my.subdomain.#12'. This will result in writing 'my.subdomain' and a pointer to offset 12 - */ - MxDnsResourceData(const uint16_t& preference, const std::string& mailExchange); - - ~MxDnsResourceData() {} - - /** - * Equality operator overload for this class that compares the MX data stored in each object - * @param[in] other The object to compare with - * @return True if MX data is the same in both objects, meaning both preference and MX hostname are the same, - * false otherwise - */ - bool operator==(const MxDnsResourceData& other) const; - - /** - * @return The MX data stored in this object - */ - MxData getMxData() const { return m_Data; } - - /** - * Set the MX data stored in this object - * @param[in] preference The MX preference value to store in this object - * @param[in] mailExchange The MX hostname value to store in this object - */ - void setMxData(uint16_t preference, std::string mailExchange); - - // implement abstract methods - - /** - * A string representation of the MX data stored in this object. The string format is as follows: - * 'pref: {preference_value}; mx: {mail_exchange_hostname_value}' - */ - std::string toString() const; - - bool toByteArr(uint8_t* arr, size_t& arrLength, IDnsResource* dnsResource) const; - - private: - MxData m_Data; - }; - - - /** - * @class GenericDnsResourceData - * A class that represents generic DNS RR data which cannot be represented in any of the other classes. It stores the - * DNS RR data as byte array - */ - class GenericDnsResourceData : public IDnsResourceData - { - private: - uint8_t* m_Data; - size_t m_DataLen; - - public: - - /** - * A c'tor for this class - * @param[in] dataPtr A byte array that contains the raw data (as it written in the DNS packet). The data will be - * copied from this byte array to the object - * @param[in] dataLen The byte array size - */ - GenericDnsResourceData(uint8_t* dataPtr, size_t dataLen); - - /** - * A c'tor for this class - * @param[in] dataAsHexString A hex string that represents the DNS RR data - */ - GenericDnsResourceData(const std::string& dataAsHexString); - - /** - * A copy c'tor for this class - * @param[in] other The instance to copy from - */ - GenericDnsResourceData(const GenericDnsResourceData& other); - - ~GenericDnsResourceData() { if (m_Data != NULL) delete [] m_Data; } - - GenericDnsResourceData& operator=(const GenericDnsResourceData& other); - - /** - * Equality operator overload for this class that compares the raw data stored in each object - * @param[in] other The object to compare with - * @return True if data is the same in both objects, meaning byte streams are equal, false otherwise - */ - bool operator==(const GenericDnsResourceData& other) const; - - const uint8_t* getData() const { return m_Data; } - - size_t getDataLen() const { return m_DataLen; } - - // implement abstract methods - - std::string toString() const; - bool toByteArr(uint8_t* arr, size_t& arrLength, IDnsResource* dnsResource) const; - }; - -} - -#endif // PV_PACKETPP_DNS_RESOURCE_DATA diff --git a/libs/visor_dns/EndianPortable.h b/libs/visor_dns/EndianPortable.h deleted file mode 100644 index 2f0f19d29..000000000 --- a/libs/visor_dns/EndianPortable.h +++ /dev/null @@ -1,210 +0,0 @@ -/* - * librdkafka - Apache Kafka C library - * - * Copyright (c) 2012-2015 Magnus Edenhill - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ -#ifndef _ENDIANPORTABLE_H_ -#define _ENDIANPORTABLE_H_ - -/** - * Provides portable endian-swapping macros/functions. - * - * be64toh() - * htobe64() - * be32toh() - * htobe32() - * be16toh() - * htobe16() - * le64toh() - */ - -#ifdef __FreeBSD__ - #include -#elif defined __GLIBC__ - #include - #ifndef be64toh - /* Support older glibc (<2.9) which lack be64toh */ - #include - #if __BYTE_ORDER == __BIG_ENDIAN - #define be16toh(x) (x) - #define be32toh(x) (x) - #define be64toh(x) (x) - #define le64toh(x) __bswap_64 (x) - #define le32toh(x) __bswap_32 (x) - #else - #define be16toh(x) __bswap_16 (x) - #define be32toh(x) __bswap_32 (x) - #define be64toh(x) __bswap_64 (x) - #define le64toh(x) (x) - #define le32toh(x) (x) - #endif - #endif - -#elif defined __CYGWIN__ - #include -#elif defined(WIN32) || defined(WINx64) -#include - #if(BYTE_ORDER == LITTLE_ENDIAN) - #define htobe16(x) htons(x) - #define htole16(x) (x) - #define be16toh(x) ntohs(x) - #define le16toh(x) (x) - - #define htobe32(x) htonl(x) - #define htole32(x) (x) - #define be32toh(x) ntohl(x) - #define le32toh(x) (x) - - #define htobe64(x) htonll(x) - #define htole64(x) (x) - #define be64toh(x) ntohll(x) - #define le64toh(x) (x) - #else - #define htobe16(x) (x) - #define htole16(x) __builtin_bswap16(x) - #define be16toh(x) (x) - #define le16toh(x) __builtin_bswap16(x) - - #define htobe32(x) (x) - #define htole32(x) __builtin_bswap32(x) - #define be32toh(x) (x) - #define le32toh(x) __builtin_bswap32(x) - - #define htobe64(x) (x) - #define htole64(x) __builtin_bswap64(x) - #define be64toh(x) (x) - #define le64toh(x) __builtin_bswap64(x) - #endif -#elif defined __BSD__ - #include -#elif defined sun - #include - #include -#define __LITTLE_ENDIAN 1234 -#define __BIG_ENDIAN 4321 -#ifdef _BIG_ENDIAN -#define __BYTE_ORDER __BIG_ENDIAN -#define be64toh(x) (x) -#define be32toh(x) (x) -#define be16toh(x) (x) -#define le16toh(x) ((uint16_t)BSWAP_16(x)) -#define le32toh(x) BSWAP_32(x) -#define le64toh(x) BSWAP_64(x) -# else -#define __BYTE_ORDER __LITTLE_ENDIAN -#define be64toh(x) BSWAP_64(x) -#define be32toh(x) ntohl(x) -#define be16toh(x) ntohs(x) -#define le16toh(x) (x) -#define le32toh(x) (x) -#define le64toh(x) (x) -#define htole16(x) (x) -#define htole64(x) (x) -#endif /* sun */ - -#elif defined __APPLE__ - #include - #include -#if __DARWIN_BYTE_ORDER == __DARWIN_BIG_ENDIAN -#define be64toh(x) (x) -#define be32toh(x) (x) -#define be16toh(x) (x) -#define le16toh(x) OSSwapInt16(x) -#define le32toh(x) OSSwapInt32(x) -#define le64toh(x) OSSwapInt64(x) -#else -#define be64toh(x) OSSwapInt64(x) -#define be32toh(x) OSSwapInt32(x) -#define be16toh(x) OSSwapInt16(x) -#define le16toh(x) (x) -#define le32toh(x) (x) -#define le64toh(x) (x) -#endif - -#elif defined(_MSC_VER) -#include - -#define be64toh(x) _byteswap_uint64(x) -#define be32toh(x) _byteswap_ulong(x) -#define be16toh(x) _byteswap_ushort(x) -#define le16toh(x) (x) -#define le32toh(x) (x) -#define le64toh(x) (x) - -#elif defined _AIX /* AIX is always big endian */ -#define be64toh(x) (x) -#define be32toh(x) (x) -#define be16toh(x) (x) -#define le32toh(x) \ - ((((x) & 0xff) << 24) | \ - (((x) & 0xff00) << 8) | \ - (((x) & 0xff0000) >> 8) | \ - (((x) & 0xff000000) >> 24)) -#define le64toh(x) \ - ((((x) & 0x00000000000000ffL) << 56) | \ - (((x) & 0x000000000000ff00L) << 40) | \ - (((x) & 0x0000000000ff0000L) << 24) | \ - (((x) & 0x00000000ff000000L) << 8) | \ - (((x) & 0x000000ff00000000L) >> 8) | \ - (((x) & 0x0000ff0000000000L) >> 24) | \ - (((x) & 0x00ff000000000000L) >> 40) | \ - (((x) & 0xff00000000000000L) >> 56)) -#else - #include -#endif - - - -/* - * On Solaris, be64toh is a function, not a macro, so there's no need to error - * if it's not defined. - */ -#if !defined(__sun) && !defined(be64toh) -#error Missing definition for be64toh -#endif - -#ifndef be32toh -#define be32toh(x) ntohl(x) -#endif - -#ifndef be16toh -#define be16toh(x) ntohs(x) -#endif - -#ifndef htobe64 -#define htobe64(x) be64toh(x) -#endif -#ifndef htobe32 -#define htobe32(x) be32toh(x) -#endif -#ifndef htobe16 -#define htobe16(x) be16toh(x) -#endif - -#ifndef htole32 -#define htole32(x) le32toh(x) -#endif - -#endif /* _ENDIANPORTABLE_H_ */ diff --git a/libs/visor_dns/dns.h b/libs/visor_dns/dns.h index d3daea8a7..a8d105f1b 100644 --- a/libs/visor_dns/dns.h +++ b/libs/visor_dns/dns.h @@ -4,15 +4,36 @@ #pragma once -#include "DnsLayer.h" -#include "DnsResource.h" -#include "DnsResourceData.h" +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wpedantic" +#pragma GCC diagnostic ignored "-Wold-style-cast" +#pragma GCC diagnostic ignored "-Wunused-parameter" +#pragma clang diagnostic ignored "-Wc99-extensions" +#endif +#include +#include +#include +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif +#include #include #include #include namespace visor::lib::dns { +inline std::unique_ptr createDnsOverTcp(pcpp::TcpLayer *tcpLayer, pcpp::Packet *packet) +{ + return std::make_unique(tcpLayer->getData() + sizeof(pcpp::tcphdr), tcpLayer->getDataLen() - sizeof(pcpp::tcphdr), tcpLayer, packet); +} + +inline std::unique_ptr createDnsOverUdp(pcpp::UdpLayer *udpLayer, pcpp::Packet *packet) +{ + return std::make_unique(udpLayer->getData() + sizeof(pcpp::udphdr), udpLayer->getDataLen() - sizeof(pcpp::udphdr), udpLayer, packet); +} + typedef std::pair AggDomainResult; AggDomainResult aggregateDomain(const std::string &domain, size_t suffix_size = 0); diff --git a/libs/visor_tcp/CMakeLists.txt b/libs/visor_tcp/CMakeLists.txt deleted file mode 100644 index fd00d9d11..000000000 --- a/libs/visor_tcp/CMakeLists.txt +++ /dev/null @@ -1,19 +0,0 @@ -message(STATUS "Visor Lib TCP Helper") - -add_library(VisorLibTcp - VisorTcpLayer.cpp - ) -add_library(Visor::Lib::Tcp ALIAS VisorLibTcp) - -target_include_directories(VisorLibTcp - PUBLIC - $ - ) - -target_link_libraries(VisorLibTcp - PUBLIC - ${CONAN_LIBS_PCAPPLUSPLUS} - ${CONAN_LIBS_PTHREADS4W} - ${CONAN_LIBS_LIBPCAP} - ${CONAN_LIBS_NPCAP} - ) diff --git a/libs/visor_tcp/VisorTcpLayer.cpp b/libs/visor_tcp/VisorTcpLayer.cpp deleted file mode 100644 index 6e302416b..000000000 --- a/libs/visor_tcp/VisorTcpLayer.cpp +++ /dev/null @@ -1,6 +0,0 @@ -#include "VisorTcpLayer.h" - -namespace visor { - - -} diff --git a/libs/visor_tcp/VisorTcpLayer.h b/libs/visor_tcp/VisorTcpLayer.h deleted file mode 100644 index 414357fb8..000000000 --- a/libs/visor_tcp/VisorTcpLayer.h +++ /dev/null @@ -1,24 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public -* License, v. 2.0. If a copy of the MPL was not distributed with this -* file, You can obtain one at https://mozilla.org/MPL/2.0/. */ - -#pragma once - -#ifdef __GNUC__ -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wpedantic" -#endif -// TCPOPT_CC, TCPOPT_CCNEW and TCPOPT_CCECHO are defined in the MacOS's tcp.h. -#ifdef TCPOPT_CC -#undef TCPOPT_CC -#endif // TCPOPT_CC -#ifdef TCPOPT_CCNEW -#undef TCPOPT_CCNEW -#endif // TCPOPT_CCNEW -#ifdef TCPOPT_CCECHO -#undef TCPOPT_CCECHO -#endif // TCPOPT_CCECHO -#include -#ifdef __GNUC__ -#pragma GCC diagnostic pop -#endif diff --git a/src/handlers/dns/v1/DnsStreamHandler.cpp b/src/handlers/dns/v1/DnsStreamHandler.cpp index fff191de1..0a5615bf4 100644 --- a/src/handlers/dns/v1/DnsStreamHandler.cpp +++ b/src/handlers/dns/v1/DnsStreamHandler.cpp @@ -17,6 +17,7 @@ #endif #include #include +#include #include #ifdef __GNUC__ #pragma GCC diagnostic pop @@ -278,16 +279,16 @@ void DnsStreamHandler::process_udp_packet_cb(pcpp::Packet &payload, PacketDirect auto src_port = udpLayer->getSrcPort(); // note we want to capture metrics only when one of the ports is dns, // but metrics on the port which is _not_ the dns port - if (DnsLayer::isDnsPort(dst_port)) { + if (pcpp::DnsLayer::isDnsPort(dst_port)) { metric_port = src_port; - } else if (DnsLayer::isDnsPort(src_port)) { + } else if (pcpp::DnsLayer::isDnsPort(src_port)) { metric_port = dst_port; } if (metric_port) { if (flowkey != _cached_dns_layer.flowKey || stamp.tv_sec != _cached_dns_layer.timestamp.tv_sec || stamp.tv_nsec != _cached_dns_layer.timestamp.tv_nsec) { _cached_dns_layer.flowKey = flowkey; _cached_dns_layer.timestamp = stamp; - _cached_dns_layer.dnsLayer = std::make_unique(udpLayer, &payload); + _cached_dns_layer.dnsLayer = createDnsOverUdp(udpLayer, &payload); } auto dnsLayer = _cached_dns_layer.dnsLayer.get(); if (!_filtering(*dnsLayer, dir, l3, pcpp::UDP, metric_port, stamp) && _configs(*dnsLayer)) { @@ -312,16 +313,16 @@ void DnsStreamHandler::process_tcp_reassembled_packet_cb(pcpp::Packet &payload, auto src_port = tcpLayer->getSrcPort(); // note we want to capture metrics only when one of the ports is dns, // but metrics on the port which is _not_ the dns port - if (DnsLayer::isDnsPort(dst_port)) { + if (pcpp::DnsLayer::isDnsPort(dst_port)) { metric_port = src_port; - } else if (DnsLayer::isDnsPort(src_port)) { + } else if (pcpp::DnsLayer::isDnsPort(src_port)) { metric_port = dst_port; } if (metric_port) { if (flowkey != _cached_dns_layer.flowKey || stamp.tv_sec != _cached_dns_layer.timestamp.tv_sec || stamp.tv_nsec != _cached_dns_layer.timestamp.tv_nsec) { _cached_dns_layer.flowKey = flowkey; _cached_dns_layer.timestamp = stamp; - _cached_dns_layer.dnsLayer = std::make_unique(tcpLayer, &payload); + _cached_dns_layer.dnsLayer = createDnsOverTcp(tcpLayer, &payload); } auto dnsLayer = _cached_dns_layer.dnsLayer.get(); if (!_filtering(*dnsLayer, dir, l3, pcpp::TCP, metric_port, stamp) && _configs(*dnsLayer)) { @@ -384,9 +385,9 @@ void DnsStreamHandler::tcp_message_ready_cb(int8_t side, const pcpp::TcpStreamDa // note we want to capture metrics only when one of the ports is dns, // but metrics on the port which is _not_ the dns port uint16_t metric_port{0}; - if (DnsLayer::isDnsPort(tcpData.getConnectionData().dstPort)) { + if (pcpp::DnsLayer::isDnsPort(tcpData.getConnectionData().dstPort)) { metric_port = tcpData.getConnectionData().srcPort; - } else if (DnsLayer::isDnsPort(tcpData.getConnectionData().srcPort)) { + } else if (pcpp::DnsLayer::isDnsPort(tcpData.getConnectionData().srcPort)) { metric_port = tcpData.getConnectionData().dstPort; } if (metric_port) { @@ -405,10 +406,10 @@ void DnsStreamHandler::tcp_message_ready_cb(int8_t side, const pcpp::TcpStreamDa TIMEVAL_TO_TIMESPEC(&tcpData.getConnectionData().endTime, &stamp); auto got_dns_message = [this, &conn = tcpData.getConnectionData(), port, dir, l3Type, flowKey, stamp](std::unique_ptr data, size_t size) { - // this dummy packet prevents DnsLayer from owning and trying to free the data. it is otherwise unused by the DNS layer, + // this dummy packet prevents pcpp::DnsLayer from owning and trying to free the data. it is otherwise unused by the DNS layer, // instead using the packet meta data we pass in pcpp::Packet dummy_packet; - auto dnsLayer = new DnsLayer(data.release(), size, nullptr, nullptr); + auto dnsLayer = new pcpp::DnsLayer(data.release(), size, nullptr, nullptr); dummy_packet.addLayer(dnsLayer, true); if (!_filtering(*dnsLayer, dir, l3Type, pcpp::TCP, port, stamp) && _configs(*dnsLayer)) { _metrics->process_dns_layer(*dnsLayer, dir, l3Type, pcpp::TCP, flowKey, port, _static_suffix_size, stamp); @@ -444,9 +445,9 @@ void DnsStreamHandler::tcp_connection_start_cb(const pcpp::ConnectionData &conne // note we want to capture metrics only when one of the ports is dns, // but metrics on the port which is _not_ the dns port uint16_t metric_port{0}; - if (DnsLayer::isDnsPort(connectionData.dstPort)) { + if (pcpp::DnsLayer::isDnsPort(connectionData.dstPort)) { metric_port = connectionData.srcPort; - } else if (DnsLayer::isDnsPort(connectionData.srcPort)) { + } else if (pcpp::DnsLayer::isDnsPort(connectionData.srcPort)) { metric_port = connectionData.dstPort; } if (iter == _tcp_connections.end() && metric_port) { @@ -495,7 +496,8 @@ inline void DnsStreamHandler::_register_predicate_filter(Filters filter, std::st if (flowkey != cache.flowKey || stamp.tv_sec != cache.timestamp.tv_sec || stamp.tv_nsec != cache.timestamp.tv_nsec) { cache.flowKey = flowkey; cache.timestamp = stamp; - cache.dnsLayer = std::make_unique(udpLayer, &payload); + cache.dnsLayer = createDnsOverUdp(udpLayer, &payload); + ; } auto dnsLayer = cache.dnsLayer.get(); // return the 'jump key' for pcap to make O(1) call to appropriate signals @@ -512,14 +514,18 @@ inline void DnsStreamHandler::_register_predicate_filter(Filters filter, std::st if (flowkey != cache.flowKey || stamp.tv_sec != cache.timestamp.tv_sec || stamp.tv_nsec != cache.timestamp.tv_nsec) { cache.flowKey = flowkey; cache.timestamp = stamp; - cache.dnsLayer = std::make_unique(udpLayer, &payload); + cache.dnsLayer = createDnsOverUdp(udpLayer, &payload); + ; } auto dnsLayer = cache.dnsLayer.get(); // return the 'jump key' for pcap to make O(1) call to appropriate signals - if (!dnsLayer->parseResources(true) || dnsLayer->getFirstQuery() == nullptr) { + if (dnsLayer->getFirstQuery() == nullptr) { return std::string(DNS_SCHEMA) + "only_qname"; // invalid qname } - return std::string(DNS_SCHEMA) + "only_qname" + dnsLayer->getFirstQuery()->getNameLower(); + auto name = dnsLayer->getFirstQuery()->getName(); + std::transform(name.begin(), name.end(), name.begin(), + [](unsigned char c) { return std::tolower(c); }); + return std::string(DNS_SCHEMA) + "only_qname" + name; }; predicate = udp_qname_predicate; } @@ -536,7 +542,7 @@ inline void DnsStreamHandler::_register_predicate_filter(Filters filter, std::st _using_predicate_signals = true; } } -inline bool DnsStreamHandler::_filtering(DnsLayer &payload, [[maybe_unused]] PacketDirection dir, [[maybe_unused]] pcpp::ProtocolType l3, [[maybe_unused]] pcpp::ProtocolType l4, [[maybe_unused]] uint16_t port, timespec stamp) +inline bool DnsStreamHandler::_filtering(pcpp::DnsLayer &payload, [[maybe_unused]] PacketDirection dir, [[maybe_unused]] pcpp::ProtocolType l3, [[maybe_unused]] pcpp::ProtocolType l4, [[maybe_unused]] uint16_t port, timespec stamp) { if (_f_enabled[Filters::ExcludingRCode]) { auto rcode = payload.getDnsHeader()->responseCode; @@ -563,7 +569,7 @@ inline bool DnsStreamHandler::_filtering(DnsLayer &payload, [[maybe_unused]] Pac if ((payload.getDnsHeader()->queryOrResponse != QR::response) || !payload.getAnswerCount()) { goto will_filter; } - if (!payload.parseResources(false, true, true) || payload.getFirstAnswer() == nullptr) { + if (payload.getFirstAnswer() == nullptr) { goto will_filter; } bool has_ssig{false}; @@ -572,7 +578,7 @@ inline bool DnsStreamHandler::_filtering(DnsLayer &payload, [[maybe_unused]] Pac if (!dns_answer) { break; } - if (dns_answer->getDnsType() == DNS_TYPE_RRSIG) { + if (dns_answer->getDnsType() == pcpp::DNS_TYPE_RRSIG) { has_ssig = true; break; } @@ -583,7 +589,7 @@ inline bool DnsStreamHandler::_filtering(DnsLayer &payload, [[maybe_unused]] Pac } } if (_f_enabled[Filters::OnlyQtype]) { - if (!payload.parseResources(true) || payload.getFirstQuery() == nullptr) { + if (payload.getFirstQuery() == nullptr) { goto will_filter; } auto qtype = payload.getFirstQuery()->getDnsType(); @@ -592,20 +598,24 @@ inline bool DnsStreamHandler::_filtering(DnsLayer &payload, [[maybe_unused]] Pac } } if (_f_enabled[Filters::OnlyQName] && _predicate_filter_type != Filters::OnlyQName) { - if (!payload.parseResources(true) || payload.getFirstQuery() == nullptr) { + if (payload.getFirstQuery() == nullptr) { goto will_filter; } - std::string_view qname_ci = payload.getFirstQuery()->getNameLower(); + auto qname_ci = payload.getFirstQuery()->getName(); + std::transform(qname_ci.begin(), qname_ci.end(), qname_ci.begin(), + [](unsigned char c) { return std::tolower(c); }); if (std::none_of(_f_qnames.begin(), _f_qnames.end(), [&qname_ci](std::string fqn) { return qname_ci == fqn; })) { // checked the whole list and none of them matched: filter goto will_filter; } } if (_f_enabled[Filters::OnlyQNameSuffix]) { - if (!payload.parseResources(true) || payload.getFirstQuery() == nullptr) { + if (payload.getFirstQuery() == nullptr) { goto will_filter; } - std::string_view qname_ci = payload.getFirstQuery()->getNameLower(); + auto qname_ci = payload.getFirstQuery()->getName(); + std::transform(qname_ci.begin(), qname_ci.end(), qname_ci.begin(), + [](unsigned char c) { return std::tolower(c); }); if (std::none_of(_f_qnames_suffix.begin(), _f_qnames_suffix.end(), [this, &qname_ci](std::string fqn) { if (ends_with(qname_ci, fqn)) { _static_suffix_size = fqn.size(); @@ -621,7 +631,7 @@ inline bool DnsStreamHandler::_filtering(DnsLayer &payload, [[maybe_unused]] Pac if (!HandlerModulePlugin::city->enabled() || (payload.getDnsHeader()->queryOrResponse != QR::query) || !payload.getAdditionalRecordCount()) { goto will_filter; } - if (!payload.parseResources(false, true, true) || payload.getFirstAdditionalRecord() == nullptr) { + if (payload.getFirstAdditionalRecord() == nullptr) { goto will_filter; } auto ecs = parse_additional_records_ecs(payload.getFirstAdditionalRecord()); @@ -633,7 +643,7 @@ inline bool DnsStreamHandler::_filtering(DnsLayer &payload, [[maybe_unused]] Pac if (!HandlerModulePlugin::asn->enabled() || (payload.getDnsHeader()->queryOrResponse != QR::query) || !payload.getAdditionalRecordCount()) { goto will_filter; } - if (!payload.parseResources(false, true, true) || payload.getFirstAdditionalRecord() == nullptr) { + if (payload.getFirstAdditionalRecord() == nullptr) { goto will_filter; } auto ecs = parse_additional_records_ecs(payload.getFirstAdditionalRecord()); @@ -647,11 +657,14 @@ inline bool DnsStreamHandler::_filtering(DnsLayer &payload, [[maybe_unused]] Pac _metrics->process_filtered(stamp); return true; } -inline bool DnsStreamHandler::_configs(DnsLayer &payload) +inline bool DnsStreamHandler::_configs(pcpp::DnsLayer &payload) { // should only work if OnlyQNameSuffix is not enabled - if (_c_enabled[Configs::PublicSuffixList] && !_f_enabled[Filters::OnlyQNameSuffix] && payload.parseResources(true) && payload.getFirstQuery() != nullptr) { - _static_suffix_size = match_public_suffix(payload.getFirstQuery()->getNameLower()); + if (_c_enabled[Configs::PublicSuffixList] && !_f_enabled[Filters::OnlyQNameSuffix] && payload.getFirstQuery() != nullptr) { + auto lower_name = payload.getFirstQuery()->getName(); + std::transform(lower_name.begin(), lower_name.end(), lower_name.begin(), + [](unsigned char c) { return std::tolower(c); }); + _static_suffix_size = match_public_suffix(lower_name); } return true; @@ -894,21 +907,21 @@ void DnsMetricsBucket::process_dnstap(bool deep, const dnstap::Dnstap &payload) auto query = payload.message().query_message(); uint8_t *buf = new uint8_t[query.size()]; std::memcpy(buf, query.c_str(), query.size()); - // DnsLayer takes ownership of buf - DnsLayer dpayload(buf, query.size(), nullptr, nullptr); + // pcpp::DnsLayer takes ownership of buf + pcpp::DnsLayer dpayload(buf, query.size(), nullptr, nullptr); lock.unlock(); process_dns_layer(deep, dpayload, l3, l4, port); } else if (side == QR::response && payload.message().has_response_message()) { auto query = payload.message().response_message(); uint8_t *buf = new uint8_t[query.size()]; std::memcpy(buf, query.c_str(), query.size()); - // DnsLayer takes ownership of buf - DnsLayer dpayload(buf, query.size(), nullptr, nullptr); + // pcpp::DnsLayer takes ownership of buf + pcpp::DnsLayer dpayload(buf, query.size(), nullptr, nullptr); lock.unlock(); process_dns_layer(deep, dpayload, l3, l4, port); } } -void DnsMetricsBucket::process_dns_layer(bool deep, DnsLayer &payload, pcpp::ProtocolType l3, Protocol l4, uint16_t port, size_t suffix_size) +void DnsMetricsBucket::process_dns_layer(bool deep, pcpp::DnsLayer &payload, pcpp::ProtocolType l3, Protocol l4, uint16_t port, size_t suffix_size) { std::unique_lock lock(_mutex); @@ -974,11 +987,6 @@ void DnsMetricsBucket::process_dns_layer(bool deep, DnsLayer &payload, pcpp::Pro _dns_topUDPPort.update(port); } - auto success = payload.parseResources(true); - if (!success) { - return; - } - if (payload.getDnsHeader()->queryOrResponse == response) { _dns_topRCode.update(payload.getDnsHeader()->responseCode); } @@ -986,7 +994,9 @@ void DnsMetricsBucket::process_dns_layer(bool deep, DnsLayer &payload, pcpp::Pro auto query = payload.getFirstQuery(); if (query) { - auto name = query->getNameLower(); + auto name = query->getName(); + std::transform(name.begin(), name.end(), name.begin(), + [](unsigned char c) { return std::tolower(c); }); if (group_enabled(group::DnsMetrics::Cardinality)) { _dns_qnameCard.update(name); @@ -1028,7 +1038,6 @@ void DnsMetricsBucket::process_dns_layer(bool deep, DnsLayer &payload, pcpp::Pro if (payload.getDnsHeader()->queryOrResponse == QR::query && payload.getAdditionalRecordCount()) { auto additional = payload.getFirstAdditionalRecord(); if (!additional) { - payload.parseResources(false, true, true); additional = payload.getFirstAdditionalRecord(); } @@ -1091,7 +1100,7 @@ void DnsMetricsBucket::process_dns_layer(pcpp::ProtocolType l3, Protocol l4, QR } } -void DnsMetricsBucket::new_dns_transaction(bool deep, float to90th, float from90th, DnsLayer &dns, PacketDirection dir, DnsTransaction xact) +void DnsMetricsBucket::new_dns_transaction(bool deep, float to90th, float from90th, pcpp::DnsLayer &dns, PacketDirection dir, DnsTransaction xact) { uint64_t xactTime = ((xact.totalTS.tv_sec * 1'000'000'000L) + xact.totalTS.tv_nsec) / 1'000; // nanoseconds to microseconds @@ -1348,7 +1357,7 @@ void DnsMetricsBucket::process_filtered() } // the general metrics manager entry point (both UDP and TCP) -void DnsMetricsManager::process_dns_layer(DnsLayer &payload, PacketDirection dir, pcpp::ProtocolType l3, pcpp::ProtocolType l4, uint32_t flowkey, uint16_t port, size_t suffix_size, timespec stamp) +void DnsMetricsManager::process_dns_layer(pcpp::DnsLayer &payload, PacketDirection dir, pcpp::ProtocolType l3, pcpp::ProtocolType l4, uint32_t flowkey, uint16_t port, size_t suffix_size, timespec stamp) { // base event new_event(stamp); diff --git a/src/handlers/dns/v1/DnsStreamHandler.h b/src/handlers/dns/v1/DnsStreamHandler.h index da5d7ed56..1b0dc3ac4 100644 --- a/src/handlers/dns/v1/DnsStreamHandler.h +++ b/src/handlers/dns/v1/DnsStreamHandler.h @@ -227,11 +227,11 @@ class DnsMetricsBucket final : public visor::AbstractMetricsBucket } void process_filtered(); - void process_dns_layer(bool deep, DnsLayer &payload, pcpp::ProtocolType l3, Protocol l4, uint16_t port, size_t suffix_size = 0); + void process_dns_layer(bool deep, pcpp::DnsLayer &payload, pcpp::ProtocolType l3, Protocol l4, uint16_t port, size_t suffix_size = 0); void process_dns_layer(pcpp::ProtocolType l3, Protocol l4, QR side); void process_dnstap(bool deep, const dnstap::Dnstap &payload); - void new_dns_transaction(bool deep, float to90th, float from90th, DnsLayer &dns, PacketDirection dir, DnsTransaction xact); + void new_dns_transaction(bool deep, float to90th, float from90th, pcpp::DnsLayer &dns, PacketDirection dir, DnsTransaction xact); }; class DnsMetricsManager final : public visor::AbstractMetricsManager @@ -277,7 +277,7 @@ class DnsMetricsManager final : public visor::AbstractMetricsManager dnsLayer; + std::unique_ptr dnsLayer; }; static thread_local DnsCacheData _cached_dns_layer; @@ -407,8 +407,8 @@ class DnsStreamHandler final : public visor::StreamMetricsHandler -#include #include +#include #include "DnsStreamHandler.h" #include "GeoDB.h" @@ -18,7 +18,6 @@ #include #include #include -#include #ifdef __GNUC__ #pragma GCC diagnostic pop #pragma GCC diagnostic ignored "-Wold-style-cast" diff --git a/src/handlers/dns/v2/DnsStreamHandler.cpp b/src/handlers/dns/v2/DnsStreamHandler.cpp index 64cfb4905..333c71e3b 100644 --- a/src/handlers/dns/v2/DnsStreamHandler.cpp +++ b/src/handlers/dns/v2/DnsStreamHandler.cpp @@ -278,16 +278,16 @@ void DnsStreamHandler::process_udp_packet_cb(pcpp::Packet &payload, PacketDirect auto src_port = udpLayer->getSrcPort(); // note we want to capture metrics only when one of the ports is dns, // but metrics on the port which is _not_ the dns port - if (DnsLayer::isDnsPort(dst_port)) { + if (pcpp::DnsLayer::isDnsPort(dst_port)) { metric_port = src_port; - } else if (DnsLayer::isDnsPort(src_port)) { + } else if (pcpp::DnsLayer::isDnsPort(src_port)) { metric_port = dst_port; } if (metric_port) { if (flowkey != _cached_dns_layer.flowKey || stamp.tv_sec != _cached_dns_layer.timestamp.tv_sec || stamp.tv_nsec != _cached_dns_layer.timestamp.tv_nsec) { _cached_dns_layer.flowKey = flowkey; _cached_dns_layer.timestamp = stamp; - _cached_dns_layer.dnsLayer = std::make_unique(udpLayer, &payload); + _cached_dns_layer.dnsLayer = createDnsOverUdp(udpLayer, &payload); } auto dnsLayer = _cached_dns_layer.dnsLayer.get(); if (!_filtering(*dnsLayer, dir, flowkey, stamp) && _configs(*dnsLayer)) { @@ -312,16 +312,16 @@ void DnsStreamHandler::process_tcp_reassembled_packet_cb(pcpp::Packet &payload, auto src_port = tcpLayer->getSrcPort(); // note we want to capture metrics only when one of the ports is dns, // but metrics on the port which is _not_ the dns port - if (DnsLayer::isDnsPort(dst_port)) { + if (pcpp::DnsLayer::isDnsPort(dst_port)) { metric_port = src_port; - } else if (DnsLayer::isDnsPort(src_port)) { + } else if (pcpp::DnsLayer::isDnsPort(src_port)) { metric_port = dst_port; } if (metric_port) { if (flowkey != _cached_dns_layer.flowKey || stamp.tv_sec != _cached_dns_layer.timestamp.tv_sec || stamp.tv_nsec != _cached_dns_layer.timestamp.tv_nsec) { _cached_dns_layer.flowKey = flowkey; _cached_dns_layer.timestamp = stamp; - _cached_dns_layer.dnsLayer = std::make_unique(tcpLayer, &payload); + _cached_dns_layer.dnsLayer = createDnsOverTcp(tcpLayer, &payload); } auto dnsLayer = _cached_dns_layer.dnsLayer.get(); if (!_filtering(*dnsLayer, dir, flowkey, stamp) && _configs(*dnsLayer)) { @@ -384,9 +384,9 @@ void DnsStreamHandler::tcp_message_ready_cb(int8_t side, const pcpp::TcpStreamDa // note we want to capture metrics only when one of the ports is dns, // but metrics on the port which is _not_ the dns port uint16_t metric_port{0}; - if (DnsLayer::isDnsPort(tcpData.getConnectionData().dstPort)) { + if (pcpp::DnsLayer::isDnsPort(tcpData.getConnectionData().dstPort)) { metric_port = tcpData.getConnectionData().srcPort; - } else if (DnsLayer::isDnsPort(tcpData.getConnectionData().srcPort)) { + } else if (pcpp::DnsLayer::isDnsPort(tcpData.getConnectionData().srcPort)) { metric_port = tcpData.getConnectionData().dstPort; } if (metric_port) { @@ -405,10 +405,10 @@ void DnsStreamHandler::tcp_message_ready_cb(int8_t side, const pcpp::TcpStreamDa TIMEVAL_TO_TIMESPEC(&tcpData.getConnectionData().endTime, &stamp); auto got_dns_message = [this, &conn = tcpData.getConnectionData(), port, dir, l3Type, flowKey, stamp](std::unique_ptr data, size_t size) { - // this dummy packet prevents DnsLayer from owning and trying to free the data. it is otherwise unused by the DNS layer, + // this dummy packet prevents pcpp::DnsLayer from owning and trying to free the data. it is otherwise unused by the DNS layer, // instead using the packet meta data we pass in pcpp::Packet dummy_packet; - auto dnsLayer = new DnsLayer(data.release(), size, nullptr, nullptr); + auto dnsLayer = new pcpp::DnsLayer(data.release(), size, nullptr, nullptr); dummy_packet.addLayer(dnsLayer, true); if (!_filtering(*dnsLayer, dir, l3Type, stamp) && _configs(*dnsLayer)) { _metrics->process_dns_layer(*dnsLayer, dir, l3Type, pcpp::TCP, flowKey, port, _static_suffix_size, stamp); @@ -444,9 +444,9 @@ void DnsStreamHandler::tcp_connection_start_cb(const pcpp::ConnectionData &conne // note we want to capture metrics only when one of the ports is dns, // but metrics on the port which is _not_ the dns port uint16_t metric_port{0}; - if (DnsLayer::isDnsPort(connectionData.dstPort)) { + if (pcpp::DnsLayer::isDnsPort(connectionData.dstPort)) { metric_port = connectionData.srcPort; - } else if (DnsLayer::isDnsPort(connectionData.srcPort)) { + } else if (pcpp::DnsLayer::isDnsPort(connectionData.srcPort)) { metric_port = connectionData.dstPort; } if (iter == _tcp_connections.end() && metric_port) { @@ -482,7 +482,7 @@ void DnsStreamHandler::info_json(json &j) const j[schema_key()]["xact"]["open"] = _metrics->num_open_transactions(); } -inline bool DnsStreamHandler::_filtering(DnsLayer &payload, PacketDirection dir, uint32_t flowkey, timespec stamp) +inline bool DnsStreamHandler::_filtering(pcpp::DnsLayer &payload, PacketDirection dir, uint32_t flowkey, timespec stamp) { if (_f_enabled[Filters::DisableUndefDir] && dir == PacketDirection::unknown) { goto will_filter; @@ -514,7 +514,7 @@ inline bool DnsStreamHandler::_filtering(DnsLayer &payload, PacketDirection dir, if (!payload.getAnswerCount()) { goto will_filter; } - if (!payload.parseResources(false, true, true) || payload.getFirstAnswer() == nullptr) { + if (payload.getFirstAnswer() == nullptr) { goto will_filter; } bool has_ssig{false}; @@ -523,7 +523,7 @@ inline bool DnsStreamHandler::_filtering(DnsLayer &payload, PacketDirection dir, if (!dns_answer) { break; } - if (dns_answer->getDnsType() == DNS_TYPE_RRSIG) { + if (dns_answer->getDnsType() == pcpp::DNS_TYPE_RRSIG) { has_ssig = true; break; } @@ -534,7 +534,7 @@ inline bool DnsStreamHandler::_filtering(DnsLayer &payload, PacketDirection dir, } } if (_f_enabled[Filters::OnlyQtype]) { - if (!payload.parseResources(true) || payload.getFirstQuery() == nullptr) { + if (payload.getFirstQuery() == nullptr) { goto will_filter; } auto qtype = payload.getFirstQuery()->getDnsType(); @@ -553,7 +553,7 @@ inline bool DnsStreamHandler::_filtering(DnsLayer &payload, PacketDirection dir, if (!HandlerModulePlugin::city->enabled() || !payload.getAdditionalRecordCount()) { goto will_filter; } - if (!payload.parseResources(false, true, true) || payload.getFirstAdditionalRecord() == nullptr) { + if (payload.getFirstAdditionalRecord() == nullptr) { goto will_filter; } auto ecs = parse_additional_records_ecs(payload.getFirstAdditionalRecord()); @@ -565,7 +565,7 @@ inline bool DnsStreamHandler::_filtering(DnsLayer &payload, PacketDirection dir, if (!HandlerModulePlugin::asn->enabled() || !payload.getAdditionalRecordCount()) { goto will_filter; } - if (!payload.parseResources(false, true, true) || payload.getFirstAdditionalRecord() == nullptr) { + if (payload.getFirstAdditionalRecord() == nullptr) { goto will_filter; } auto ecs = parse_additional_records_ecs(payload.getFirstAdditionalRecord()); @@ -575,10 +575,12 @@ inline bool DnsStreamHandler::_filtering(DnsLayer &payload, PacketDirection dir, } if (_f_enabled[Filters::OnlyQName]) { - if (!payload.parseResources(true) || payload.getFirstQuery() == nullptr) { + if (payload.getFirstQuery() == nullptr) { goto will_filter; } - std::string_view qname_ci = payload.getFirstQuery()->getNameLower(); + auto qname_ci = payload.getFirstQuery()->getName(); + std::transform(qname_ci.begin(), qname_ci.end(), qname_ci.begin(), + [](unsigned char c) { return std::tolower(c); }); if (std::none_of(_f_qnames.begin(), _f_qnames.end(), [&qname_ci](std::string fqn) { return qname_ci == fqn; })) { // checked the whole list and none of them matched: filter goto will_filter; @@ -586,10 +588,12 @@ inline bool DnsStreamHandler::_filtering(DnsLayer &payload, PacketDirection dir, } if (_f_enabled[Filters::OnlyQNameSuffix]) { - if (!payload.parseResources(true) || payload.getFirstQuery() == nullptr) { + if (payload.getFirstQuery() == nullptr) { goto will_filter; } - std::string_view qname_ci = payload.getFirstQuery()->getNameLower(); + auto qname_ci = payload.getFirstQuery()->getName(); + std::transform(qname_ci.begin(), qname_ci.end(), qname_ci.begin(), + [](unsigned char c) { return std::tolower(c); }); if (std::none_of(_f_qnames_suffix.begin(), _f_qnames_suffix.end(), [this, &qname_ci](std::string fqn) { if (ends_with(qname_ci, fqn)) { _static_suffix_size = fqn.size(); @@ -608,11 +612,14 @@ inline bool DnsStreamHandler::_filtering(DnsLayer &payload, PacketDirection dir, _metrics->process_filtered(stamp, payload, dir, flowkey); return true; } -inline bool DnsStreamHandler::_configs(DnsLayer &payload) +inline bool DnsStreamHandler::_configs(pcpp::DnsLayer &payload) { // should only work if OnlyQNameSuffix is not enabled - if (_c_enabled[Configs::PublicSuffixList] && !_f_enabled[Filters::OnlyQNameSuffix] && payload.parseResources(true) && payload.getFirstQuery() != nullptr) { - _static_suffix_size = match_public_suffix(payload.getFirstQuery()->getNameLower()); + if (_c_enabled[Configs::PublicSuffixList] && !_f_enabled[Filters::OnlyQNameSuffix] && payload.getFirstQuery() != nullptr) { + auto lower_name = payload.getFirstQuery()->getName(); + std::transform(lower_name.begin(), lower_name.end(), lower_name.begin(), + [](unsigned char c) { return std::tolower(c); }); + _static_suffix_size = match_public_suffix(lower_name); } return true; @@ -654,7 +661,6 @@ void DnsMetricsBucket::specialized_merge(const AbstractMetricsBucket &o, Metric: _dns.at(dns.first).topNOERROR.merge(dns.second.topNOERROR); _dns.at(dns.first).topRCode.merge(dns.second.topRCode); } - if (group_enabled(group::DnsMetrics::TopQnames)) { _dns.at(dns.first).topQname2.merge(dns.second.topQname2); _dns.at(dns.first).topQname3.merge(dns.second.topQname3); @@ -923,7 +929,7 @@ void DnsMetricsBucket::to_opentelemetry(metrics::v1::ScopeMetrics &scope, timesp } } -void DnsMetricsBucket::new_dns_transaction(bool deep, float per90th, DnsLayer &payload, TransactionDirection dir, DnsTransaction xact, pcpp::ProtocolType l3, Protocol l4, uint16_t port, size_t suffix_size) +void DnsMetricsBucket::new_dns_transaction(bool deep, float per90th, pcpp::DnsLayer &payload, TransactionDirection dir, DnsTransaction xact, pcpp::ProtocolType l3, Protocol l4, uint16_t port, size_t suffix_size) { uint64_t xactTime = ((xact.totalTS.tv_sec * 1'000'000'000L) + xact.totalTS.tv_nsec) / 1'000; // nanoseconds to microseconds @@ -1020,11 +1026,6 @@ void DnsMetricsBucket::new_dns_transaction(bool deep, float per90th, DnsLayer &p data.dnsHistTimeUs.update(xactTime); } - auto success = payload.parseResources(true); - if (!success) { - return; - } - if (payload.getDnsHeader()->queryOrResponse == response) { data.topRCode.update(payload.getDnsHeader()->responseCode); } @@ -1032,7 +1033,9 @@ void DnsMetricsBucket::new_dns_transaction(bool deep, float per90th, DnsLayer &p auto query = payload.getFirstQuery(); if (query) { - auto name = query->getNameLower(); + auto name = query->getName(); + std::transform(name.begin(), name.end(), name.begin(), + [](unsigned char c) { return std::tolower(c); }); if (group_enabled(group::DnsMetrics::Cardinality)) { data.qnameCard.update(name); @@ -1098,7 +1101,7 @@ void DnsMetricsBucket::process_filtered() } // the general metrics manager entry point (both UDP and TCP) -void DnsMetricsManager::process_dns_layer(DnsLayer &payload, PacketDirection dir, pcpp::ProtocolType l3, pcpp::ProtocolType l4, uint32_t flowkey, uint16_t port, size_t suffix_size, timespec stamp) +void DnsMetricsManager::process_dns_layer(pcpp::DnsLayer &payload, PacketDirection dir, pcpp::ProtocolType l3, pcpp::ProtocolType l4, uint32_t flowkey, uint16_t port, size_t suffix_size, timespec stamp) { // base event new_event(stamp); @@ -1133,7 +1136,6 @@ void DnsMetricsManager::process_dns_layer(DnsLayer &payload, PacketDirection dir if (group_enabled(group::DnsMetrics::TopEcs) && payload.getAdditionalRecordCount()) { auto additional = payload.getFirstAdditionalRecord(); if (!additional) { - payload.parseResources(false, true, true); additional = payload.getFirstAdditionalRecord(); } if (auto ecs = parse_additional_records_ecs(additional); ecs) { @@ -1145,7 +1147,7 @@ void DnsMetricsManager::process_dns_layer(DnsLayer &payload, PacketDirection dir } } -void DnsMetricsManager::process_filtered(timespec stamp, DnsLayer &payload, PacketDirection dir, uint32_t flowkey) +void DnsMetricsManager::process_filtered(timespec stamp, pcpp::DnsLayer &payload, PacketDirection dir, uint32_t flowkey) { // base event, no sample new_event(stamp, false); @@ -1259,7 +1261,7 @@ void DnsMetricsManager::process_dnstap(const dnstap::Dnstap &payload, bool filte auto query = payload.message().response_message(); uint8_t *buf = new uint8_t[query.size()]; std::memcpy(buf, query.c_str(), query.size()); - DnsLayer dpayload(buf, query.size(), nullptr, nullptr); + pcpp::DnsLayer dpayload(buf, query.size(), nullptr, nullptr); auto xact = _pair_manager[xact_dir].xact_map->maybe_end_transaction(DnsXactID(dpayload.getDnsHeader()->transactionID, 2), stamp); live_bucket()->dir_setup(xact_dir); if (xact.first == Result::Valid) { @@ -1274,7 +1276,7 @@ void DnsMetricsManager::process_dnstap(const dnstap::Dnstap &payload, bool filte auto query = payload.message().query_message(); uint8_t *buf = new uint8_t[query.size()]; std::memcpy(buf, query.c_str(), query.size()); - DnsLayer dpayload(buf, query.size(), nullptr, nullptr); + pcpp::DnsLayer dpayload(buf, query.size(), nullptr, nullptr); _pair_manager[xact_dir].xact_map->start_transaction(DnsXactID(dpayload.getDnsHeader()->transactionID, 2), {{stamp, {0, 0}}, false, payload.message().query_message().size(), false, std::string()}); } } diff --git a/src/handlers/dns/v2/DnsStreamHandler.h b/src/handlers/dns/v2/DnsStreamHandler.h index 45a0cb3cd..d3721b1ce 100644 --- a/src/handlers/dns/v2/DnsStreamHandler.h +++ b/src/handlers/dns/v2/DnsStreamHandler.h @@ -378,7 +378,7 @@ class DnsMetricsBucket final : public visor::AbstractMetricsBucket } void process_filtered(); - void new_dns_transaction(bool deep, float per90th, DnsLayer &dns, TransactionDirection dir, DnsTransaction xact, pcpp::ProtocolType l3, Protocol l4, uint16_t port, size_t suffix_size = 0); + void new_dns_transaction(bool deep, float per90th, pcpp::DnsLayer &dns, TransactionDirection dir, DnsTransaction xact, pcpp::ProtocolType l3, Protocol l4, uint16_t port, size_t suffix_size = 0); }; class DnsMetricsManager final : public visor::AbstractMetricsManager @@ -445,8 +445,8 @@ class DnsMetricsManager final : public visor::AbstractMetricsManagerprocess_filtered(); } - void process_filtered(timespec stamp, DnsLayer &payload, PacketDirection dir, uint32_t flowkey); - void process_dns_layer(DnsLayer &payload, PacketDirection dir, pcpp::ProtocolType l3, pcpp::ProtocolType l4, uint32_t flowkey, uint16_t port, size_t suffix_size, timespec stamp); + void process_filtered(timespec stamp, pcpp::DnsLayer &payload, PacketDirection dir, uint32_t flowkey); + void process_dns_layer(pcpp::DnsLayer &payload, PacketDirection dir, pcpp::ProtocolType l3, pcpp::ProtocolType l4, uint32_t flowkey, uint16_t port, size_t suffix_size, timespec stamp); void process_dnstap(const dnstap::Dnstap &payload, bool filtered); }; @@ -472,7 +472,7 @@ class DnsStreamHandler final : public visor::StreamMetricsHandler dnsLayer; + std::unique_ptr dnsLayer; }; static thread_local DnsCacheData _cached_dns_layer; @@ -574,8 +574,8 @@ class DnsStreamHandler final : public visor::StreamMetricsHandler -#include #include +#include #include "DnsStreamHandler.h" #include "GeoDB.h" @@ -14,11 +14,9 @@ #pragma clang diagnostic ignored "-Wc99-extensions" #pragma clang diagnostic ignored "-Wrange-loop-analysis" #endif -#include "DnsLayer.h" #include #include #include -#include #ifdef __GNUC__ #pragma GCC diagnostic pop #pragma GCC diagnostic ignored "-Wold-style-cast" diff --git a/src/handlers/net/v1/CMakeLists.txt b/src/handlers/net/v1/CMakeLists.txt index e6e542480..3e3a45fe8 100644 --- a/src/handlers/net/v1/CMakeLists.txt +++ b/src/handlers/net/v1/CMakeLists.txt @@ -16,7 +16,6 @@ target_include_directories(VisorHandlerNet target_link_libraries(VisorHandlerNet PUBLIC - Visor::Lib::Tcp Visor::Input::Pcap Visor::Input::Dnstap Visor::Input::Mock diff --git a/src/handlers/net/v1/NetStreamHandler.cpp b/src/handlers/net/v1/NetStreamHandler.cpp index 48bf4d900..b009c3a7b 100644 --- a/src/handlers/net/v1/NetStreamHandler.cpp +++ b/src/handlers/net/v1/NetStreamHandler.cpp @@ -19,7 +19,7 @@ #include "IPv6Layer.h" #include "PacketUtils.h" #include "TimespecTimeval.h" -#include "VisorTcpLayer.h" +#include #ifdef __GNUC__ #pragma GCC diagnostic pop #endif diff --git a/src/handlers/net/v2/CMakeLists.txt b/src/handlers/net/v2/CMakeLists.txt index 38e017234..7ebd082bd 100644 --- a/src/handlers/net/v2/CMakeLists.txt +++ b/src/handlers/net/v2/CMakeLists.txt @@ -16,7 +16,6 @@ target_include_directories(VisorHandlerNetV2 target_link_libraries(VisorHandlerNetV2 PUBLIC - Visor::Lib::Tcp Visor::Input::Pcap Visor::Input::Dnstap Visor::Input::Mock diff --git a/src/handlers/net/v2/NetStreamHandler.cpp b/src/handlers/net/v2/NetStreamHandler.cpp index 64517dfef..8831dba7c 100644 --- a/src/handlers/net/v2/NetStreamHandler.cpp +++ b/src/handlers/net/v2/NetStreamHandler.cpp @@ -19,7 +19,7 @@ #include "IPv6Layer.h" #include "PacketUtils.h" #include "TimespecTimeval.h" -#include "VisorTcpLayer.h" +#include #ifdef __GNUC__ #pragma GCC diagnostic pop #endif diff --git a/src/handlers/netprobe/NetProbeStreamHandler.h b/src/handlers/netprobe/NetProbeStreamHandler.h index a12f7444d..9fe0ff2cf 100644 --- a/src/handlers/netprobe/NetProbeStreamHandler.h +++ b/src/handlers/netprobe/NetProbeStreamHandler.h @@ -16,7 +16,7 @@ #pragma GCC diagnostic ignored "-Wzero-as-null-pointer-constant" #endif #include -#include +#include #ifdef __GNUC__ #pragma GCC diagnostic pop #endif diff --git a/src/inputs/netprobe/CMakeLists.txt b/src/inputs/netprobe/CMakeLists.txt index 84246e4ee..21e57ce5a 100644 --- a/src/inputs/netprobe/CMakeLists.txt +++ b/src/inputs/netprobe/CMakeLists.txt @@ -20,7 +20,6 @@ target_include_directories(VisorInputNetProbe target_link_libraries(VisorInputNetProbe PUBLIC Visor::Core - Visor::Lib::Tcp ${CONAN_LIBS_LIBUV} ${CONAN_LIBS_UVW} ${CONAN_LIBS_PCAPPLUSPLUS} diff --git a/src/inputs/netprobe/TcpProbe.cpp b/src/inputs/netprobe/TcpProbe.cpp index 2cb61f978..7d28f00ac 100644 --- a/src/inputs/netprobe/TcpProbe.cpp +++ b/src/inputs/netprobe/TcpProbe.cpp @@ -7,7 +7,7 @@ #pragma GCC diagnostic ignored "-Wold-style-cast" #pragma GCC diagnostic ignored "-Wzero-as-null-pointer-constant" #endif -#include +#include #ifdef __GNUC__ #pragma GCC diagnostic pop #endif