18e745fdaSopenharmony_ci/* 28e745fdaSopenharmony_ci * Copyright (C) 2023 Huawei Device Co., Ltd. 38e745fdaSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 48e745fdaSopenharmony_ci * you may not use this file except in compliance with the License. 58e745fdaSopenharmony_ci * You may obtain a copy of the License at 68e745fdaSopenharmony_ci * 78e745fdaSopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 88e745fdaSopenharmony_ci * 98e745fdaSopenharmony_ci * Unless required by applicable law or agreed to in writing, software 108e745fdaSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 118e745fdaSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 128e745fdaSopenharmony_ci * See the License for the specific language governing permissions and 138e745fdaSopenharmony_ci * limitations under the License. 148e745fdaSopenharmony_ci */ 158e745fdaSopenharmony_ci 168e745fdaSopenharmony_ci#include "mdns_packet_parser.h" 178e745fdaSopenharmony_ci#include "netmgr_ext_log_wrapper.h" 188e745fdaSopenharmony_ci#include <cstring> 198e745fdaSopenharmony_ci 208e745fdaSopenharmony_cinamespace OHOS { 218e745fdaSopenharmony_cinamespace NetManagerStandard { 228e745fdaSopenharmony_ci 238e745fdaSopenharmony_cinamespace { 248e745fdaSopenharmony_ci 258e745fdaSopenharmony_ciconstexpr size_t MDNS_STR_INITIAL_SIZE = 16; 268e745fdaSopenharmony_ci 278e745fdaSopenharmony_ciconstexpr uint8_t DNS_STR_PTR_U8_MASK = 0xc0; 288e745fdaSopenharmony_ciconstexpr uint16_t DNS_STR_PTR_U16_MASK = 0xc000; 298e745fdaSopenharmony_ciconstexpr uint16_t DNS_STR_PTR_LENGTH = 0x3f; 308e745fdaSopenharmony_ciconstexpr uint8_t DNS_STR_EOL = '\0'; 318e745fdaSopenharmony_ci 328e745fdaSopenharmony_citemplate <class T> void WriteRawData(const T &data, MDnsPayload &payload) 338e745fdaSopenharmony_ci{ 348e745fdaSopenharmony_ci const uint8_t *begin = reinterpret_cast<const uint8_t *>(&data); 358e745fdaSopenharmony_ci payload.insert(payload.end(), begin, begin + sizeof(T)); 368e745fdaSopenharmony_ci} 378e745fdaSopenharmony_ci 388e745fdaSopenharmony_citemplate <class T> void WriteRawData(const T &data, uint8_t *ptr) 398e745fdaSopenharmony_ci{ 408e745fdaSopenharmony_ci const uint8_t *begin = reinterpret_cast<const uint8_t *>(&data); 418e745fdaSopenharmony_ci for (size_t i = 0; i < sizeof(T); ++i) { 428e745fdaSopenharmony_ci ptr[i] = *begin++; 438e745fdaSopenharmony_ci } 448e745fdaSopenharmony_ci} 458e745fdaSopenharmony_ci 468e745fdaSopenharmony_citemplate <class T> const uint8_t *ReadRawData(const uint8_t *raw, T &data) 478e745fdaSopenharmony_ci{ 488e745fdaSopenharmony_ci data = *reinterpret_cast<const T *>(raw); 498e745fdaSopenharmony_ci return raw + sizeof(T); 508e745fdaSopenharmony_ci} 518e745fdaSopenharmony_ci 528e745fdaSopenharmony_ciconst uint8_t *ReadNUint16(const uint8_t *raw, uint16_t &data) 538e745fdaSopenharmony_ci{ 548e745fdaSopenharmony_ci const uint8_t *tmp = ReadRawData(raw, data); 558e745fdaSopenharmony_ci data = ntohs(data); 568e745fdaSopenharmony_ci return tmp; 578e745fdaSopenharmony_ci} 588e745fdaSopenharmony_ci 598e745fdaSopenharmony_ciconst uint8_t *ReadNUint32(const uint8_t *raw, uint32_t &data) 608e745fdaSopenharmony_ci{ 618e745fdaSopenharmony_ci const uint8_t *tmp = ReadRawData(raw, data); 628e745fdaSopenharmony_ci data = ntohl(data); 638e745fdaSopenharmony_ci return tmp; 648e745fdaSopenharmony_ci} 658e745fdaSopenharmony_ci 668e745fdaSopenharmony_cistd::string UnDotted(const std::string &name) 678e745fdaSopenharmony_ci{ 688e745fdaSopenharmony_ci return EndsWith(name, MDNS_DOMAIN_SPLITER_STR) ? name.substr(0, name.size() - 1) : name; 698e745fdaSopenharmony_ci} 708e745fdaSopenharmony_ci 718e745fdaSopenharmony_ci} // namespace 728e745fdaSopenharmony_ci 738e745fdaSopenharmony_ciMDnsMessage MDnsPayloadParser::FromBytes(const MDnsPayload &payload) 748e745fdaSopenharmony_ci{ 758e745fdaSopenharmony_ci MDnsMessage msg; 768e745fdaSopenharmony_ci errorFlags_ = PARSE_OK; 778e745fdaSopenharmony_ci pos_ = Parse(payload.data(), payload, msg); 788e745fdaSopenharmony_ci return msg; 798e745fdaSopenharmony_ci} 808e745fdaSopenharmony_ci 818e745fdaSopenharmony_ciMDnsPayload MDnsPayloadParser::ToBytes(const MDnsMessage &msg) 828e745fdaSopenharmony_ci{ 838e745fdaSopenharmony_ci MDnsPayload payload; 848e745fdaSopenharmony_ci MDnsPayload *cachedPayload = &payload; 858e745fdaSopenharmony_ci std::map<std::string, uint16_t> strCacheMap; 868e745fdaSopenharmony_ci Serialize(msg, payload, cachedPayload, strCacheMap); 878e745fdaSopenharmony_ci return payload; 888e745fdaSopenharmony_ci} 898e745fdaSopenharmony_ci 908e745fdaSopenharmony_ciconst uint8_t *MDnsPayloadParser::Parse(const uint8_t *begin, const MDnsPayload &payload, MDnsMessage &msg) 918e745fdaSopenharmony_ci{ 928e745fdaSopenharmony_ci begin = ParseHeader(begin, payload, msg.header); 938e745fdaSopenharmony_ci if ((errorFlags_ & PARSE_ERROR) != PARSE_OK) { 948e745fdaSopenharmony_ci return begin; 958e745fdaSopenharmony_ci } 968e745fdaSopenharmony_ci for (int i = 0; i < msg.header.qdcount; ++i) { 978e745fdaSopenharmony_ci begin = ParseQuestion(begin, payload, msg.questions); 988e745fdaSopenharmony_ci if ((errorFlags_ & PARSE_ERROR) != PARSE_OK) { 998e745fdaSopenharmony_ci return begin; 1008e745fdaSopenharmony_ci } 1018e745fdaSopenharmony_ci } 1028e745fdaSopenharmony_ci for (int i = 0; i < msg.header.ancount; ++i) { 1038e745fdaSopenharmony_ci begin = ParseRR(begin, payload, msg.answers); 1048e745fdaSopenharmony_ci if ((errorFlags_ & PARSE_ERROR) != PARSE_OK) { 1058e745fdaSopenharmony_ci return begin; 1068e745fdaSopenharmony_ci } 1078e745fdaSopenharmony_ci } 1088e745fdaSopenharmony_ci for (int i = 0; i < msg.header.nscount; ++i) { 1098e745fdaSopenharmony_ci begin = ParseRR(begin, payload, msg.authorities); 1108e745fdaSopenharmony_ci if ((errorFlags_ & PARSE_ERROR) != PARSE_OK) { 1118e745fdaSopenharmony_ci return begin; 1128e745fdaSopenharmony_ci } 1138e745fdaSopenharmony_ci } 1148e745fdaSopenharmony_ci for (int i = 0; i < msg.header.arcount; ++i) { 1158e745fdaSopenharmony_ci begin = ParseRR(begin, payload, msg.additional); 1168e745fdaSopenharmony_ci if ((errorFlags_ & PARSE_ERROR) != PARSE_OK) { 1178e745fdaSopenharmony_ci return begin; 1188e745fdaSopenharmony_ci } 1198e745fdaSopenharmony_ci } 1208e745fdaSopenharmony_ci return begin; 1218e745fdaSopenharmony_ci} 1228e745fdaSopenharmony_ci 1238e745fdaSopenharmony_ciconst uint8_t *MDnsPayloadParser::ParseHeader(const uint8_t *begin, const MDnsPayload &payload, 1248e745fdaSopenharmony_ci DNSProto::Header &header) 1258e745fdaSopenharmony_ci{ 1268e745fdaSopenharmony_ci const uint8_t *end = payload.data() + payload.size(); 1278e745fdaSopenharmony_ci if (end - begin < static_cast<int>(sizeof(DNSProto::Header))) { 1288e745fdaSopenharmony_ci errorFlags_ |= PARSE_ERROR_BAD_SIZE; 1298e745fdaSopenharmony_ci return begin; 1308e745fdaSopenharmony_ci } 1318e745fdaSopenharmony_ci 1328e745fdaSopenharmony_ci begin = ReadNUint16(begin, header.id); 1338e745fdaSopenharmony_ci begin = ReadNUint16(begin, header.flags); 1348e745fdaSopenharmony_ci begin = ReadNUint16(begin, header.qdcount); 1358e745fdaSopenharmony_ci begin = ReadNUint16(begin, header.ancount); 1368e745fdaSopenharmony_ci begin = ReadNUint16(begin, header.nscount); 1378e745fdaSopenharmony_ci begin = ReadNUint16(begin, header.arcount); 1388e745fdaSopenharmony_ci return begin; 1398e745fdaSopenharmony_ci} 1408e745fdaSopenharmony_ci 1418e745fdaSopenharmony_ciconst uint8_t *MDnsPayloadParser::ParseQuestion(const uint8_t *begin, const MDnsPayload &payload, 1428e745fdaSopenharmony_ci std::vector<DNSProto::Question> &questions) 1438e745fdaSopenharmony_ci{ 1448e745fdaSopenharmony_ci questions.emplace_back(); 1458e745fdaSopenharmony_ci begin = ParseDnsString(begin, payload, questions.back().name); 1468e745fdaSopenharmony_ci questions.back().name = UnDotted(questions.back().name); 1478e745fdaSopenharmony_ci if ((errorFlags_ & PARSE_ERROR) != PARSE_OK) { 1488e745fdaSopenharmony_ci questions.pop_back(); 1498e745fdaSopenharmony_ci return begin; 1508e745fdaSopenharmony_ci } 1518e745fdaSopenharmony_ci 1528e745fdaSopenharmony_ci const uint8_t *end = payload.data() + payload.size(); 1538e745fdaSopenharmony_ci if (static_cast<ssize_t>(end - begin) < static_cast<ssize_t>(sizeof(uint16_t) + sizeof(uint16_t))) { 1548e745fdaSopenharmony_ci errorFlags_ |= PARSE_ERROR_BAD_SIZE; 1558e745fdaSopenharmony_ci questions.pop_back(); 1568e745fdaSopenharmony_ci return begin; 1578e745fdaSopenharmony_ci } 1588e745fdaSopenharmony_ci 1598e745fdaSopenharmony_ci begin = ReadNUint16(begin, questions.back().qtype); 1608e745fdaSopenharmony_ci begin = ReadNUint16(begin, questions.back().qclass); 1618e745fdaSopenharmony_ci return begin; 1628e745fdaSopenharmony_ci} 1638e745fdaSopenharmony_ci 1648e745fdaSopenharmony_ciconst uint8_t *MDnsPayloadParser::ParseRR(const uint8_t *begin, const MDnsPayload &payload, 1658e745fdaSopenharmony_ci std::vector<DNSProto::ResourceRecord> &answers) 1668e745fdaSopenharmony_ci{ 1678e745fdaSopenharmony_ci answers.emplace_back(); 1688e745fdaSopenharmony_ci begin = ParseDnsString(begin, payload, answers.back().name); 1698e745fdaSopenharmony_ci answers.back().name = UnDotted(answers.back().name); 1708e745fdaSopenharmony_ci if ((errorFlags_ & PARSE_ERROR) != PARSE_OK) { 1718e745fdaSopenharmony_ci answers.pop_back(); 1728e745fdaSopenharmony_ci return begin; 1738e745fdaSopenharmony_ci } 1748e745fdaSopenharmony_ci 1758e745fdaSopenharmony_ci const uint8_t *end = payload.data() + payload.size(); 1768e745fdaSopenharmony_ci if (static_cast<ssize_t>(end - begin) < 1778e745fdaSopenharmony_ci static_cast<ssize_t>(sizeof(uint16_t) + sizeof(uint16_t) + sizeof(uint32_t) + sizeof(uint16_t))) { 1788e745fdaSopenharmony_ci errorFlags_ |= PARSE_ERROR_BAD_SIZE; 1798e745fdaSopenharmony_ci answers.pop_back(); 1808e745fdaSopenharmony_ci return begin; 1818e745fdaSopenharmony_ci } 1828e745fdaSopenharmony_ci begin = ReadNUint16(begin, answers.back().rtype); 1838e745fdaSopenharmony_ci begin = ReadNUint16(begin, answers.back().rclass); 1848e745fdaSopenharmony_ci begin = ReadNUint32(begin, answers.back().ttl); 1858e745fdaSopenharmony_ci begin = ReadNUint16(begin, answers.back().length); 1868e745fdaSopenharmony_ci return ParseRData(begin, payload, answers.back().rtype, answers.back().length, answers.back().rdata); 1878e745fdaSopenharmony_ci} 1888e745fdaSopenharmony_ci 1898e745fdaSopenharmony_ciconst uint8_t *MDnsPayloadParser::ParseRData(const uint8_t *begin, const MDnsPayload &payload, int type, int length, 1908e745fdaSopenharmony_ci std::any &data) 1918e745fdaSopenharmony_ci{ 1928e745fdaSopenharmony_ci switch (type) { 1938e745fdaSopenharmony_ci case DNSProto::RRTYPE_A: { 1948e745fdaSopenharmony_ci const uint8_t *end = payload.data() + payload.size(); 1958e745fdaSopenharmony_ci if (static_cast<size_t>(end - begin) < sizeof(in_addr) || length != sizeof(in_addr)) { 1968e745fdaSopenharmony_ci errorFlags_ |= PARSE_ERROR_BAD_SIZE; 1978e745fdaSopenharmony_ci return begin; 1988e745fdaSopenharmony_ci } 1998e745fdaSopenharmony_ci in_addr addr; 2008e745fdaSopenharmony_ci begin = ReadRawData(begin, addr); 2018e745fdaSopenharmony_ci data = addr; 2028e745fdaSopenharmony_ci return begin; 2038e745fdaSopenharmony_ci } 2048e745fdaSopenharmony_ci case DNSProto::RRTYPE_AAAA: { 2058e745fdaSopenharmony_ci const uint8_t *end = payload.data() + payload.size(); 2068e745fdaSopenharmony_ci if ((static_cast<ssize_t>(end - begin) < 2078e745fdaSopenharmony_ci static_cast<ssize_t>(sizeof(in6_addr))) || (length != sizeof(in6_addr))) { 2088e745fdaSopenharmony_ci errorFlags_ |= PARSE_ERROR_BAD_SIZE; 2098e745fdaSopenharmony_ci return begin; 2108e745fdaSopenharmony_ci } 2118e745fdaSopenharmony_ci in6_addr addr; 2128e745fdaSopenharmony_ci begin = ReadRawData(begin, addr); 2138e745fdaSopenharmony_ci data = addr; 2148e745fdaSopenharmony_ci return begin; 2158e745fdaSopenharmony_ci } 2168e745fdaSopenharmony_ci case DNSProto::RRTYPE_PTR: { 2178e745fdaSopenharmony_ci std::string str; 2188e745fdaSopenharmony_ci begin = ParseDnsString(begin, payload, str); 2198e745fdaSopenharmony_ci str = UnDotted(str); 2208e745fdaSopenharmony_ci if ((errorFlags_ & PARSE_ERROR) != PARSE_OK) { 2218e745fdaSopenharmony_ci return begin; 2228e745fdaSopenharmony_ci } 2238e745fdaSopenharmony_ci data = str; 2248e745fdaSopenharmony_ci return begin; 2258e745fdaSopenharmony_ci } 2268e745fdaSopenharmony_ci case DNSProto::RRTYPE_SRV: { 2278e745fdaSopenharmony_ci return ParseSrv(begin, payload, data); 2288e745fdaSopenharmony_ci } 2298e745fdaSopenharmony_ci case DNSProto::RRTYPE_TXT: { 2308e745fdaSopenharmony_ci return ParseTxt(begin, payload, length, data); 2318e745fdaSopenharmony_ci } 2328e745fdaSopenharmony_ci default: { 2338e745fdaSopenharmony_ci errorFlags_ |= PARSE_WARNING_BAD_RRTYPE; 2348e745fdaSopenharmony_ci return begin + length; 2358e745fdaSopenharmony_ci } 2368e745fdaSopenharmony_ci } 2378e745fdaSopenharmony_ci} 2388e745fdaSopenharmony_ci 2398e745fdaSopenharmony_ciconst uint8_t *MDnsPayloadParser::ParseSrv(const uint8_t *begin, const MDnsPayload &payload, std::any &data) 2408e745fdaSopenharmony_ci{ 2418e745fdaSopenharmony_ci const uint8_t *end = payload.data() + payload.size(); 2428e745fdaSopenharmony_ci if (static_cast<ssize_t>(end - begin) < 2438e745fdaSopenharmony_ci static_cast<ssize_t>(sizeof(uint16_t) + sizeof(uint16_t) + sizeof(uint16_t))) { 2448e745fdaSopenharmony_ci errorFlags_ |= PARSE_ERROR_BAD_SIZE; 2458e745fdaSopenharmony_ci return begin; 2468e745fdaSopenharmony_ci } 2478e745fdaSopenharmony_ci 2488e745fdaSopenharmony_ci DNSProto::RDataSrv srv; 2498e745fdaSopenharmony_ci begin = ReadNUint16(begin, srv.priority); 2508e745fdaSopenharmony_ci begin = ReadNUint16(begin, srv.weight); 2518e745fdaSopenharmony_ci begin = ReadNUint16(begin, srv.port); 2528e745fdaSopenharmony_ci begin = ParseDnsString(begin, payload, srv.name); 2538e745fdaSopenharmony_ci srv.name = UnDotted(srv.name); 2548e745fdaSopenharmony_ci if ((errorFlags_ & PARSE_ERROR) != PARSE_OK) { 2558e745fdaSopenharmony_ci return begin; 2568e745fdaSopenharmony_ci } 2578e745fdaSopenharmony_ci data = srv; 2588e745fdaSopenharmony_ci return begin; 2598e745fdaSopenharmony_ci} 2608e745fdaSopenharmony_ci 2618e745fdaSopenharmony_ciconst uint8_t *MDnsPayloadParser::ParseTxt(const uint8_t *begin, const MDnsPayload &payload, int length, std::any &data) 2628e745fdaSopenharmony_ci{ 2638e745fdaSopenharmony_ci const uint8_t *end = payload.data() + payload.size(); 2648e745fdaSopenharmony_ci if (end - begin < length) { 2658e745fdaSopenharmony_ci errorFlags_ |= PARSE_ERROR_BAD_SIZE; 2668e745fdaSopenharmony_ci return begin; 2678e745fdaSopenharmony_ci } 2688e745fdaSopenharmony_ci 2698e745fdaSopenharmony_ci data = TxtRecordEncoded(begin, begin + length); 2708e745fdaSopenharmony_ci return begin + length; 2718e745fdaSopenharmony_ci} 2728e745fdaSopenharmony_ci 2738e745fdaSopenharmony_ciconst uint8_t *MDnsPayloadParser::ParseDnsString(const uint8_t *begin, const MDnsPayload &payload, std::string &str) 2748e745fdaSopenharmony_ci{ 2758e745fdaSopenharmony_ci const uint8_t *end = payload.data() + payload.size(); 2768e745fdaSopenharmony_ci const uint8_t *p = begin; 2778e745fdaSopenharmony_ci str.reserve(MDNS_STR_INITIAL_SIZE); 2788e745fdaSopenharmony_ci while (p && p < end) { 2798e745fdaSopenharmony_ci if (*p == 0) { 2808e745fdaSopenharmony_ci return p + 1; 2818e745fdaSopenharmony_ci } 2828e745fdaSopenharmony_ci if (*p <= MDNS_MAX_DOMAIN_LABEL && p + *p < end) { 2838e745fdaSopenharmony_ci str.append(reinterpret_cast<const char *>(p) + 1, *p); 2848e745fdaSopenharmony_ci str.push_back(MDNS_DOMAIN_SPLITER); 2858e745fdaSopenharmony_ci p += (*p + 1); 2868e745fdaSopenharmony_ci } else if ((*p & DNS_STR_PTR_U8_MASK) == DNS_STR_PTR_U8_MASK) { 2878e745fdaSopenharmony_ci if (end - p < static_cast<int>(sizeof(uint16_t))) { 2888e745fdaSopenharmony_ci errorFlags_ |= PARSE_ERROR_BAD_SIZE; 2898e745fdaSopenharmony_ci return begin; 2908e745fdaSopenharmony_ci } 2918e745fdaSopenharmony_ci 2928e745fdaSopenharmony_ci uint16_t offset; 2938e745fdaSopenharmony_ci const uint8_t *tmp = ReadNUint16(p, offset); 2948e745fdaSopenharmony_ci offset = offset & ~DNS_STR_PTR_U16_MASK; 2958e745fdaSopenharmony_ci const uint8_t *next = payload.data() + (offset & ~DNS_STR_PTR_U16_MASK); 2968e745fdaSopenharmony_ci 2978e745fdaSopenharmony_ci if (next >= end || next >= begin) { 2988e745fdaSopenharmony_ci errorFlags_ |= PARSE_ERROR_BAD_STRPTR; 2998e745fdaSopenharmony_ci return begin; 3008e745fdaSopenharmony_ci } 3018e745fdaSopenharmony_ci ParseDnsString(next, payload, str); 3028e745fdaSopenharmony_ci if ((errorFlags_ & PARSE_ERROR) != PARSE_OK) { 3038e745fdaSopenharmony_ci return begin; 3048e745fdaSopenharmony_ci } 3058e745fdaSopenharmony_ci return tmp; 3068e745fdaSopenharmony_ci } else { 3078e745fdaSopenharmony_ci errorFlags_ |= PARSE_ERROR_BAD_STR; 3088e745fdaSopenharmony_ci return p; 3098e745fdaSopenharmony_ci } 3108e745fdaSopenharmony_ci } 3118e745fdaSopenharmony_ci return p; 3128e745fdaSopenharmony_ci} 3138e745fdaSopenharmony_ci 3148e745fdaSopenharmony_civoid MDnsPayloadParser::Serialize(const MDnsMessage &msg, MDnsPayload &payload, MDnsPayload *cachedPayload, 3158e745fdaSopenharmony_ci std::map<std::string, uint16_t> &strCacheMap) 3168e745fdaSopenharmony_ci{ 3178e745fdaSopenharmony_ci payload.reserve(sizeof(DNSProto::Message)); 3188e745fdaSopenharmony_ci DNSProto::Header header = msg.header; 3198e745fdaSopenharmony_ci header.qdcount = msg.questions.size(); 3208e745fdaSopenharmony_ci header.ancount = msg.answers.size(); 3218e745fdaSopenharmony_ci header.nscount = msg.authorities.size(); 3228e745fdaSopenharmony_ci header.arcount = msg.additional.size(); 3238e745fdaSopenharmony_ci SerializeHeader(header, msg, payload); 3248e745fdaSopenharmony_ci for (uint16_t i = 0; i < header.qdcount; ++i) { 3258e745fdaSopenharmony_ci SerializeQuestion(msg.questions[i], payload, cachedPayload, strCacheMap); 3268e745fdaSopenharmony_ci } 3278e745fdaSopenharmony_ci for (uint16_t i = 0; i < header.ancount; ++i) { 3288e745fdaSopenharmony_ci SerializeRR(msg.answers[i], payload, cachedPayload, strCacheMap); 3298e745fdaSopenharmony_ci } 3308e745fdaSopenharmony_ci for (uint16_t i = 0; i < header.nscount; ++i) { 3318e745fdaSopenharmony_ci SerializeRR(msg.authorities[i], payload, cachedPayload, strCacheMap); 3328e745fdaSopenharmony_ci } 3338e745fdaSopenharmony_ci for (uint16_t i = 0; i < header.arcount; ++i) { 3348e745fdaSopenharmony_ci SerializeRR(msg.additional[i], payload, cachedPayload, strCacheMap); 3358e745fdaSopenharmony_ci } 3368e745fdaSopenharmony_ci} 3378e745fdaSopenharmony_ci 3388e745fdaSopenharmony_civoid MDnsPayloadParser::SerializeHeader(const DNSProto::Header &header, const MDnsMessage &msg, MDnsPayload &payload) 3398e745fdaSopenharmony_ci{ 3408e745fdaSopenharmony_ci WriteRawData(htons(header.id), payload); 3418e745fdaSopenharmony_ci WriteRawData(htons(header.flags), payload); 3428e745fdaSopenharmony_ci WriteRawData(htons(header.qdcount), payload); 3438e745fdaSopenharmony_ci WriteRawData(htons(header.ancount), payload); 3448e745fdaSopenharmony_ci WriteRawData(htons(header.nscount), payload); 3458e745fdaSopenharmony_ci WriteRawData(htons(header.arcount), payload); 3468e745fdaSopenharmony_ci} 3478e745fdaSopenharmony_ci 3488e745fdaSopenharmony_civoid MDnsPayloadParser::SerializeQuestion(const DNSProto::Question &question, MDnsPayload &payload, 3498e745fdaSopenharmony_ci MDnsPayload *cachedPayload, std::map<std::string, uint16_t> &strCacheMap) 3508e745fdaSopenharmony_ci{ 3518e745fdaSopenharmony_ci SerializeDnsString(question.name, payload, cachedPayload, strCacheMap); 3528e745fdaSopenharmony_ci WriteRawData(htons(question.qtype), payload); 3538e745fdaSopenharmony_ci WriteRawData(htons(question.qclass), payload); 3548e745fdaSopenharmony_ci} 3558e745fdaSopenharmony_ci 3568e745fdaSopenharmony_civoid MDnsPayloadParser::SerializeRR(const DNSProto::ResourceRecord &rr, MDnsPayload &payload, 3578e745fdaSopenharmony_ci MDnsPayload *cachedPayload, std::map<std::string, uint16_t> &strCacheMap) 3588e745fdaSopenharmony_ci{ 3598e745fdaSopenharmony_ci SerializeDnsString(rr.name, payload, cachedPayload, strCacheMap); 3608e745fdaSopenharmony_ci WriteRawData(htons(rr.rtype), payload); 3618e745fdaSopenharmony_ci WriteRawData(htons(rr.rclass), payload); 3628e745fdaSopenharmony_ci WriteRawData(htonl(rr.ttl), payload); 3638e745fdaSopenharmony_ci size_t lenStart = payload.size(); 3648e745fdaSopenharmony_ci WriteRawData(htons(rr.length), payload); 3658e745fdaSopenharmony_ci SerializeRData(rr.rdata, payload, cachedPayload, strCacheMap); 3668e745fdaSopenharmony_ci uint16_t len = payload.size() - lenStart - sizeof(uint16_t); 3678e745fdaSopenharmony_ci WriteRawData(htons(len), payload.data() + lenStart); 3688e745fdaSopenharmony_ci} 3698e745fdaSopenharmony_ci 3708e745fdaSopenharmony_civoid MDnsPayloadParser::SerializeRData(const std::any &rdata, MDnsPayload &payload, MDnsPayload *cachedPayload, 3718e745fdaSopenharmony_ci std::map<std::string, uint16_t> &strCacheMap) 3728e745fdaSopenharmony_ci{ 3738e745fdaSopenharmony_ci if (std::any_cast<const in_addr>(&rdata)) { 3748e745fdaSopenharmony_ci WriteRawData(*std::any_cast<const in_addr>(&rdata), payload); 3758e745fdaSopenharmony_ci } else if (std::any_cast<const in6_addr>(&rdata)) { 3768e745fdaSopenharmony_ci WriteRawData(*std::any_cast<const in6_addr>(&rdata), payload); 3778e745fdaSopenharmony_ci } else if (std::any_cast<const std::string>(&rdata)) { 3788e745fdaSopenharmony_ci SerializeDnsString(*std::any_cast<const std::string>(&rdata), payload, cachedPayload, strCacheMap); 3798e745fdaSopenharmony_ci } else if (std::any_cast<const DNSProto::RDataSrv>(&rdata)) { 3808e745fdaSopenharmony_ci const DNSProto::RDataSrv *srv = std::any_cast<const DNSProto::RDataSrv>(&rdata); 3818e745fdaSopenharmony_ci WriteRawData(htons(srv->priority), payload); 3828e745fdaSopenharmony_ci WriteRawData(htons(srv->weight), payload); 3838e745fdaSopenharmony_ci WriteRawData(htons(srv->port), payload); 3848e745fdaSopenharmony_ci SerializeDnsString(srv->name, payload, cachedPayload, strCacheMap); 3858e745fdaSopenharmony_ci } else if (std::any_cast<TxtRecordEncoded>(&rdata)) { 3868e745fdaSopenharmony_ci const auto *txt = std::any_cast<TxtRecordEncoded>(&rdata); 3878e745fdaSopenharmony_ci payload.insert(payload.end(), txt->begin(), txt->end()); 3888e745fdaSopenharmony_ci } 3898e745fdaSopenharmony_ci} 3908e745fdaSopenharmony_ci 3918e745fdaSopenharmony_civoid MDnsPayloadParser::SerializeDnsString(const std::string &str, MDnsPayload &payload, MDnsPayload *cachedPayload, 3928e745fdaSopenharmony_ci std::map<std::string, uint16_t> &strCacheMap) 3938e745fdaSopenharmony_ci{ 3948e745fdaSopenharmony_ci size_t pos = 0; 3958e745fdaSopenharmony_ci while (pos < str.size()) { 3968e745fdaSopenharmony_ci if ((cachedPayload == &payload) && (strCacheMap.find(str.substr(pos)) != strCacheMap.end())) { 3978e745fdaSopenharmony_ci return WriteRawData(htons(strCacheMap[str.substr(pos)]), payload); 3988e745fdaSopenharmony_ci } 3998e745fdaSopenharmony_ci 4008e745fdaSopenharmony_ci size_t nextDot = str.find(MDNS_DOMAIN_SPLITER, pos); 4018e745fdaSopenharmony_ci if (nextDot == std::string::npos) { 4028e745fdaSopenharmony_ci nextDot = str.size(); 4038e745fdaSopenharmony_ci } 4048e745fdaSopenharmony_ci uint8_t segLen = (nextDot - pos) & DNS_STR_PTR_LENGTH; 4058e745fdaSopenharmony_ci 4068e745fdaSopenharmony_ci uint16_t strptr = payload.size(); 4078e745fdaSopenharmony_ci WriteRawData(segLen, payload); 4088e745fdaSopenharmony_ci for (int i = 0; i < segLen; ++i) { 4098e745fdaSopenharmony_ci WriteRawData(str[pos + i], payload); 4108e745fdaSopenharmony_ci } 4118e745fdaSopenharmony_ci strCacheMap[str.substr(pos)] = strptr | DNS_STR_PTR_U16_MASK; 4128e745fdaSopenharmony_ci pos = nextDot + 1; 4138e745fdaSopenharmony_ci } 4148e745fdaSopenharmony_ci WriteRawData(DNS_STR_EOL, payload); 4158e745fdaSopenharmony_ci} 4168e745fdaSopenharmony_ci 4178e745fdaSopenharmony_ciuint32_t MDnsPayloadParser::GetError() const 4188e745fdaSopenharmony_ci{ 4198e745fdaSopenharmony_ci return errorFlags_ & PARSE_ERROR; 4208e745fdaSopenharmony_ci} 4218e745fdaSopenharmony_ci 4228e745fdaSopenharmony_ci} // namespace NetManagerStandard 4238e745fdaSopenharmony_ci} // namespace OHOS 424