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