赞
踩
它主要是提取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 address
- static constexpr int DNS_TYPE_AAAA = 0x001c; //1 a host address
- static constexpr int DNS_TYPE_CNAME = 0x0005; //5 the canonical name for an alias
- static 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 + Label
- if ((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();
- }

Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。