C/C++ 提取DNS请求/响应数据包之中的 Quesion 内容

2024-06-20 08:36

本文主要是介绍C/C++ 提取DNS请求/响应数据包之中的 Quesion 内容,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

它主要是提取DNS数据包之中查询问题的信息,如:问题类型、问题类别、问题内容(域/IP),我们如果想要对于某个DNS数据包需要进行遥测的时,或者进行NS缓存生命周期管理,那么就需要类似这样的函数实现了。

例子:

                uint16_t queries_type = 0;uint16_t queries_clazz = 0;ppp::string domain = ppp::net::native::dns::ExtractHostY((Byte*)packet, packet_length,[&queries_type, &queries_clazz](ppp::net::native::dns::dns_hdr* h, ppp::string& domain, uint16_t type, uint16_t clazz) noexcept -> bool {queries_type = type;queries_clazz = clazz;return true;});

源声明:

#pragma pack(push, 1)struct dns_hdr {uint16_t                                                                usTransID;         // 标识符uint16_t                                                                usFlags;           // 各种标志位uint16_t                                                                usQuestionCount;   // Question字段个数 uint16_t                                                                usAnswerCount;     // Answer字段个数uint16_t                                                                usAuthorityCount;  // Authority字段个数uint16_t                                                                usAdditionalCount; // Additional字段个数};
#pragma pack(pop)static constexpr int MAX_DOMAINNAME_LEN                                     = 255; /* MAX: 253 +. ≈ 254 BYTE or 254 CHAR+. ≈ 255 BYTE */static constexpr int DNS_PORT                                               = PPP_DNS_SYS_PORT;static constexpr int DNS_TYPE_SIZE                                          = 2;static constexpr int DNS_CLASS_SIZE                                         = 2;static constexpr int DNS_TTL_SIZE                                           = 4;static constexpr int DNS_DATALEN_SIZE                                       = 2;static constexpr int DNS_TYPE_A                                             = 0x0001; //1 a host addressstatic constexpr int DNS_TYPE_AAAA                                          = 0x001c; //1 a host addressstatic constexpr int DNS_TYPE_CNAME                                         = 0x0005; //5 the canonical name for an aliasstatic constexpr int DNS_CLASS_IN                                           = 0x0001;static constexpr int DNS_PACKET_MAX_SIZE                                    = (sizeof(struct dns_hdr) + MAX_DOMAINNAME_LEN + DNS_TYPE_SIZE + DNS_CLASS_SIZE);ppp::string                                                                 ExtractHost(const Byte*                                                             szPacketStartPos, int                                                                     nPacketLength) noexcept;ppp::string                                                                 ExtractHostX(const Byte*                                                             szPacketStartPos, int                                                                     nPacketLength, const ppp::function<bool(dns_hdr*)>&                                    fPredicateB) noexcept;ppp::string                                                                 ExtractHostY(const Byte*                                                             szPacketStartPos, int                                                                     nPacketLength, const ppp::function<bool(dns_hdr*, ppp::string&, uint16_t, uint16_t)>&  fPredicateE) noexcept;ppp::string                                                                 ExtractHostZ(const Byte*                                                             szPacketStartPos, int                                                                     nPacketLength, const ppp::function<bool(dns_hdr*)>&                                    fPredicateB, const ppp::function<bool(dns_hdr*, ppp::string&, uint16_t, uint16_t)>&  fPredicateE) noexcept;

源实现:

                static bool ExtractName(char* szEncodedStr, uint16_t* pusEncodedStrLen, char* szDotStr, uint16_t nDotStrSize, char* szPacketStartPos, char* szPacketEndPos, char** ppDecodePos) noexcept{if (NULL == szEncodedStr || NULL == pusEncodedStrLen || NULL == szDotStr || szEncodedStr >= szPacketEndPos){return false;}char*& pDecodePos = *ppDecodePos;pDecodePos = szEncodedStr;uint16_t usPlainStrLen = 0;uint8_t nLabelDataLen = 0;*pusEncodedStrLen = 0;while ((nLabelDataLen = *pDecodePos) != 0x00){// Normal Format,LabelDataLen + Labelif ((nLabelDataLen & 0xc0) == 0) {if ((usPlainStrLen + nLabelDataLen + 1) > nDotStrSize || (pDecodePos + nLabelDataLen + 1) >= szPacketEndPos){return false;}memcpy(szDotStr + usPlainStrLen, pDecodePos + 1, nLabelDataLen);memcpy(szDotStr + usPlainStrLen + nLabelDataLen, ".", 1);pDecodePos += (nLabelDataLen + 1);usPlainStrLen += (nLabelDataLen + 1);*pusEncodedStrLen += (nLabelDataLen + 1);}else  {// Message compression format is 11000000 00000000, consisting of two bytes. // The first two bits are the jump flag, and the last 14 bits are the offset of the jump。if (NULL == szPacketStartPos){return false;}uint16_t usJumpPos = ntohs(*(uint16_t*)(pDecodePos)) & 0x3fff;uint16_t nEncodeStrLen = 0;if (!ExtractName(szPacketStartPos + usJumpPos, &nEncodeStrLen, szDotStr + usPlainStrLen, nDotStrSize - usPlainStrLen, szPacketStartPos, szPacketEndPos, ppDecodePos)){return false;}else{*pusEncodedStrLen += 2;return true;}}}++pDecodePos;szDotStr[usPlainStrLen - 1] = '\0';*pusEncodedStrLen += 1;return true;}static bool ExtractHost_DefaultPredicateB(dns_hdr* h) noexcept{uint16_t usFlags = htons(h->usFlags) & htons(DNS_TYPE_A);return usFlags != 0;}ppp::string ExtractHost(const Byte* szPacketStartPos, int nPacketLength) noexcept{ppp::function<bool(dns_hdr*)> predicate = ExtractHost_DefaultPredicateB;return ExtractHostX(szPacketStartPos, nPacketLength, predicate);}ppp::string ExtractHostX(const Byte* szPacketStartPos, int nPacketLength, const ppp::function<bool(dns_hdr*)>& fPredicateB) noexcept{ppp::function<bool(dns_hdr*, ppp::string&, uint16_t, uint16_t)> fPredicateE =[](dns_hdr* h, ppp::string& domain, uint16_t type, uint16_t clazz) noexcept -> bool{return true;};return ExtractHostZ(szPacketStartPos, nPacketLength, fPredicateB, fPredicateE);}ppp::string ExtractHostY(const Byte* szPacketStartPos, int nPacketLength, const ppp::function<bool(dns_hdr*, ppp::string&, uint16_t, uint16_t)>& fPredicateE) noexcept{ppp::function<bool(dns_hdr*)> fPredicateB = ExtractHost_DefaultPredicateB;return ExtractHostZ(szPacketStartPos, nPacketLength, fPredicateB, fPredicateE);}ppp::string ExtractHostZ(const Byte*                                        szPacketStartPos, int                                                                     nPacketLength, const ppp::function<bool(dns_hdr*)>&                                    fPredicateB, const ppp::function<bool(dns_hdr*, ppp::string&, uint16_t, uint16_t)>&  fPredicateE) noexcept{static constexpr int MAX_DOMAINNAME_LEN_STR = MAX_DOMAINNAME_LEN + 1;if (NULL == fPredicateB || NULL == fPredicateE){return ppp::string();}struct dns_hdr* pDNSHeader = (struct dns_hdr*)szPacketStartPos;if (NULL == pDNSHeader || nPacketLength < sizeof(pDNSHeader)){return ppp::string();}if (!fPredicateB(pDNSHeader)){return ppp::string();}int nQuestionCount = htons(pDNSHeader->usQuestionCount);if (nQuestionCount < 1){return ppp::string();}std::shared_ptr<Byte> pioBuffers = make_shared_alloc<Byte>(MAX_DOMAINNAME_LEN_STR);if (NULL == pioBuffers) {return ppp::string();}uint16_t pusEncodedStrLen = 0;char* pDecodePos = NULL;char* szDomainDotStr = (char*)pioBuffers.get();if (!ExtractName((char*)(pDNSHeader + 1), &pusEncodedStrLen, szDomainDotStr,(uint16_t)MAX_DOMAINNAME_LEN_STR, (char*)szPacketStartPos, (char*)szPacketStartPos + nPacketLength, &pDecodePos)){return ppp::string();}while (pusEncodedStrLen > 0 && szDomainDotStr[pusEncodedStrLen - 1] == '\x0'){pusEncodedStrLen--;}if (pusEncodedStrLen == 0){return ppp::string();}uint16_t* pusDecodePos = (uint16_t*)pDecodePos;uint16_t usQueriesType = ntohs(pusDecodePos[0]);uint16_t usQueriesClass = ntohs(pusDecodePos[1]);ppp::string strDomianStr(szDomainDotStr, pusEncodedStrLen);if (!fPredicateE(pDNSHeader, strDomianStr, usQueriesType, usQueriesClass)){return ppp::string();}return strDomianStr.data();}

这篇关于C/C++ 提取DNS请求/响应数据包之中的 Quesion 内容的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1077634

相关文章

C++中RAII资源获取即初始化

《C++中RAII资源获取即初始化》RAII通过构造/析构自动管理资源生命周期,确保安全释放,本文就来介绍一下C++中的RAII技术及其应用,具有一定的参考价值,感兴趣的可以了解一下... 目录一、核心原理与机制二、标准库中的RAII实现三、自定义RAII类设计原则四、常见应用场景1. 内存管理2. 文件操

C++中零拷贝的多种实现方式

《C++中零拷贝的多种实现方式》本文主要介绍了C++中零拷贝的实现示例,旨在在减少数据在内存中的不必要复制,从而提高程序性能、降低内存使用并减少CPU消耗,零拷贝技术通过多种方式实现,下面就来了解一下... 目录一、C++中零拷贝技术的核心概念二、std::string_view 简介三、std::stri

C++高效内存池实现减少动态分配开销的解决方案

《C++高效内存池实现减少动态分配开销的解决方案》C++动态内存分配存在系统调用开销、碎片化和锁竞争等性能问题,内存池通过预分配、分块管理和缓存复用解决这些问题,下面就来了解一下... 目录一、C++内存分配的性能挑战二、内存池技术的核心原理三、主流内存池实现:TCMalloc与Jemalloc1. TCM

Python实现精准提取 PDF中的文本,表格与图片

《Python实现精准提取PDF中的文本,表格与图片》在实际的系统开发中,处理PDF文件不仅限于读取整页文本,还有提取文档中的表格数据,图片或特定区域的内容,下面我们来看看如何使用Python实... 目录安装 python 库提取 PDF 文本内容:获取整页文本与指定区域内容获取页面上的所有文本内容获取

C++ 函数 strftime 和时间格式示例详解

《C++函数strftime和时间格式示例详解》strftime是C/C++标准库中用于格式化日期和时间的函数,定义在ctime头文件中,它将tm结构体中的时间信息转换为指定格式的字符串,是处理... 目录C++ 函数 strftipythonme 详解一、函数原型二、功能描述三、格式字符串说明四、返回值五

C++作用域和标识符查找规则详解

《C++作用域和标识符查找规则详解》在C++中,作用域(Scope)和标识符查找(IdentifierLookup)是理解代码行为的重要概念,本文将详细介绍这些规则,并通过实例来说明它们的工作原理,需... 目录作用域标识符查找规则1. 普通查找(Ordinary Lookup)2. 限定查找(Qualif

Python实现自动化Word文档样式复制与内容生成

《Python实现自动化Word文档样式复制与内容生成》在办公自动化领域,高效处理Word文档的样式和内容复制是一个常见需求,本文将展示如何利用Python的python-docx库实现... 目录一、为什么需要自动化 Word 文档处理二、核心功能实现:样式与表格的深度复制1. 表格复制(含样式与内容)2

C/C++ chrono简单使用场景示例详解

《C/C++chrono简单使用场景示例详解》:本文主要介绍C/C++chrono简单使用场景示例详解,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友... 目录chrono使用场景举例1 输出格式化字符串chrono使用场景China编程举例1 输出格式化字符串示

C++/类与对象/默认成员函数@构造函数的用法

《C++/类与对象/默认成员函数@构造函数的用法》:本文主要介绍C++/类与对象/默认成员函数@构造函数的用法,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录名词概念默认成员函数构造函数概念函数特征显示构造函数隐式构造函数总结名词概念默认构造函数:不用传参就可以

C++类和对象之默认成员函数的使用解读

《C++类和对象之默认成员函数的使用解读》:本文主要介绍C++类和对象之默认成员函数的使用方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、默认成员函数有哪些二、各默认成员函数详解默认构造函数析构函数拷贝构造函数拷贝赋值运算符三、默认成员函数的注意事项总结一