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#ifndef MDNS_PACKET_PARSER_H
178e745fdaSopenharmony_ci#define MDNS_PACKET_PARSER_H
188e745fdaSopenharmony_ci
198e745fdaSopenharmony_ci#include <any>
208e745fdaSopenharmony_ci#include <string>
218e745fdaSopenharmony_ci#include <string_view>
228e745fdaSopenharmony_ci#include <vector>
238e745fdaSopenharmony_ci
248e745fdaSopenharmony_ci#include <netinet/in.h>
258e745fdaSopenharmony_ci
268e745fdaSopenharmony_ci#include "mdns_common.h"
278e745fdaSopenharmony_ci
288e745fdaSopenharmony_cinamespace OHOS {
298e745fdaSopenharmony_cinamespace NetManagerStandard {
308e745fdaSopenharmony_ci
318e745fdaSopenharmony_cinamespace DNSProto {
328e745fdaSopenharmony_ci
338e745fdaSopenharmony_ciconstexpr uint16_t HEADER_FLAGS_QR_MASK = 0x8000;
348e745fdaSopenharmony_ciconstexpr uint16_t HEADER_FLAGS_OPCODE_MASK = 0x7800;
358e745fdaSopenharmony_ciconstexpr uint16_t HEADER_FLAGS_AA_MASK = 0x0400;
368e745fdaSopenharmony_ciconstexpr uint16_t HEADER_FLAGS_TC_MASK = 0x0200;
378e745fdaSopenharmony_ciconstexpr uint16_t HEADER_FLAGS_RD_MASK = 0x0100;
388e745fdaSopenharmony_ciconstexpr uint16_t HEADER_FLAGS_RA_MASK = 0x0080;
398e745fdaSopenharmony_ciconstexpr uint16_t HEADER_FLAGS_Z_MASK = 0x0040;
408e745fdaSopenharmony_ciconstexpr uint16_t HEADER_FLAGS_AD_MASK = 0x0020;
418e745fdaSopenharmony_ciconstexpr uint16_t HEADER_FLAGS_CD_MASK = 0x0010;
428e745fdaSopenharmony_ciconstexpr uint16_t HEADER_FLAGS_RCODE_MASK = 0x000f;
438e745fdaSopenharmony_ci
448e745fdaSopenharmony_ciconstexpr uint16_t HEADER_FLAGS_QR_OFFSET = 15;
458e745fdaSopenharmony_ciconstexpr uint16_t HEADER_FLAGS_OPCODE_OFFSET = 11;
468e745fdaSopenharmony_ciconstexpr uint16_t HEADER_FLAGS_AA_OFFSET = 10;
478e745fdaSopenharmony_ciconstexpr uint16_t HEADER_FLAGS_TC_OFFSET = 9;
488e745fdaSopenharmony_ciconstexpr uint16_t HEADER_FLAGS_RD_OFFSET = 8;
498e745fdaSopenharmony_ciconstexpr uint16_t HEADER_FLAGS_RA_OFFSET = 7;
508e745fdaSopenharmony_ciconstexpr uint16_t HEADER_FLAGS_Z_OFFSET = 6;
518e745fdaSopenharmony_ciconstexpr uint16_t HEADER_FLAGS_AD_OFFSET = 5;
528e745fdaSopenharmony_ciconstexpr uint16_t HEADER_FLAGS_CD_OFFSET = 4;
538e745fdaSopenharmony_ciconstexpr uint16_t HEADER_FLAGS_RCODE_OFFSET = 0;
548e745fdaSopenharmony_ci
558e745fdaSopenharmony_ci// QR = 1, AA = 1
568e745fdaSopenharmony_cistatic constexpr uint16_t MDNS_ANSWER_FLAGS = 0x8400;
578e745fdaSopenharmony_ci
588e745fdaSopenharmony_ci// DNS Header format (https://www.rfc-editor.org/rfc/rfc1035#section-4.1.1)
598e745fdaSopenharmony_ci//                                 1  1  1  1  1  1
608e745fdaSopenharmony_ci//   0  1  2  3  4  5  6  7  8  9  0  1  2  3  4  5
618e745fdaSopenharmony_ci// +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
628e745fdaSopenharmony_ci// |                      ID                       |
638e745fdaSopenharmony_ci// +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
648e745fdaSopenharmony_ci// |QR|   OpCode  |AA|TC|RD|RA| Z|AD|CD|   RCODE   |
658e745fdaSopenharmony_ci// +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
668e745fdaSopenharmony_ci// |                QDCOUNT/ZOCOUNT                |
678e745fdaSopenharmony_ci// +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
688e745fdaSopenharmony_ci// |                ANCOUNT/PRCOUNT                |
698e745fdaSopenharmony_ci// +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
708e745fdaSopenharmony_ci// |                NSCOUNT/UPCOUNT                |
718e745fdaSopenharmony_ci// +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
728e745fdaSopenharmony_ci// |                    ARCOUNT                    |
738e745fdaSopenharmony_ci// +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
748e745fdaSopenharmony_cistruct Header {
758e745fdaSopenharmony_ci    uint16_t id = 0x0;
768e745fdaSopenharmony_ci    uint16_t flags = 0x0;
778e745fdaSopenharmony_ci    uint16_t qdcount = 0x0;
788e745fdaSopenharmony_ci    uint16_t ancount = 0x0;
798e745fdaSopenharmony_ci    uint16_t nscount = 0x0;
808e745fdaSopenharmony_ci    uint16_t arcount = 0x0;
818e745fdaSopenharmony_ci};
828e745fdaSopenharmony_ci
838e745fdaSopenharmony_ci// RR Type (https://www.rfc-editor.org/rfc/rfc1035#section-3.2.2)
848e745fdaSopenharmony_cienum RRType {
858e745fdaSopenharmony_ci    RRTYPE_IGNORE = 0,
868e745fdaSopenharmony_ci    RRTYPE_A = 1,
878e745fdaSopenharmony_ci    RRTYPE_PTR = 12,
888e745fdaSopenharmony_ci    RRTYPE_TXT = 16,
898e745fdaSopenharmony_ci    RRTYPE_AAAA = 28,
908e745fdaSopenharmony_ci    RRTYPE_SRV = 33,
918e745fdaSopenharmony_ci    RRTYPE_ANY = 255
928e745fdaSopenharmony_ci};
938e745fdaSopenharmony_ci
948e745fdaSopenharmony_ci// RR Class (https://www.rfc-editor.org/rfc/rfc1035#section-3.2.4)
958e745fdaSopenharmony_cienum RRClass {
968e745fdaSopenharmony_ci    RRCLASS_IN = 1,
978e745fdaSopenharmony_ci    RRCLASS_ANY = 255
988e745fdaSopenharmony_ci};
998e745fdaSopenharmony_ci
1008e745fdaSopenharmony_ci// DNS Question format (https://www.rfc-editor.org/rfc/rfc1035#section-4.1.2)
1018e745fdaSopenharmony_ci//                                 1  1  1  1  1  1
1028e745fdaSopenharmony_ci//   0  1  2  3  4  5  6  7  8  9  0  1  2  3  4  5
1038e745fdaSopenharmony_ci// +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1048e745fdaSopenharmony_ci// |                                               |
1058e745fdaSopenharmony_ci// /                     QNAME                     /
1068e745fdaSopenharmony_ci// /                                               /
1078e745fdaSopenharmony_ci// +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1088e745fdaSopenharmony_ci// |                     QTYPE                     |
1098e745fdaSopenharmony_ci// +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1108e745fdaSopenharmony_ci// |                     QCLASS                    |
1118e745fdaSopenharmony_ci// +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1128e745fdaSopenharmony_cistruct Question {
1138e745fdaSopenharmony_ci    std::string name;
1148e745fdaSopenharmony_ci    uint16_t qtype;
1158e745fdaSopenharmony_ci    uint16_t qclass;
1168e745fdaSopenharmony_ci};
1178e745fdaSopenharmony_ci
1188e745fdaSopenharmony_ci// DNS SRV RR format (https://www.rfc-editor.org/rfc/rfc2782)
1198e745fdaSopenharmony_cistruct RDataSrv {
1208e745fdaSopenharmony_ci    uint16_t priority;
1218e745fdaSopenharmony_ci    uint16_t weight;
1228e745fdaSopenharmony_ci    uint16_t port;
1238e745fdaSopenharmony_ci    std::string name;
1248e745fdaSopenharmony_ci};
1258e745fdaSopenharmony_ci
1268e745fdaSopenharmony_ci// DNS RR format (https://www.rfc-editor.org/rfc/rfc1035#section-3.2.1)
1278e745fdaSopenharmony_ci//                                 1  1  1  1  1  1
1288e745fdaSopenharmony_ci//   0  1  2  3  4  5  6  7  8  9  0  1  2  3  4  5
1298e745fdaSopenharmony_ci// +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1308e745fdaSopenharmony_ci// |                                               |
1318e745fdaSopenharmony_ci// /                                               /
1328e745fdaSopenharmony_ci// /                      NAME                     /
1338e745fdaSopenharmony_ci// |                                               |
1348e745fdaSopenharmony_ci// +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1358e745fdaSopenharmony_ci// |                      TYPE                     |
1368e745fdaSopenharmony_ci// +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1378e745fdaSopenharmony_ci// |                     CLASS                     |
1388e745fdaSopenharmony_ci// +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1398e745fdaSopenharmony_ci// |                      TTL                      |
1408e745fdaSopenharmony_ci// |                                               |
1418e745fdaSopenharmony_ci// +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1428e745fdaSopenharmony_ci// |                   RDLENGTH                    |
1438e745fdaSopenharmony_ci// +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--|
1448e745fdaSopenharmony_ci// /                     RDATA                     /
1458e745fdaSopenharmony_ci// /                                               /
1468e745fdaSopenharmony_ci// +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1478e745fdaSopenharmony_cistruct ResourceRecord {
1488e745fdaSopenharmony_ci    std::string name;
1498e745fdaSopenharmony_ci    uint16_t rtype;
1508e745fdaSopenharmony_ci    uint16_t rclass;
1518e745fdaSopenharmony_ci    uint32_t ttl;
1528e745fdaSopenharmony_ci    uint16_t length;
1538e745fdaSopenharmony_ci    std::any rdata;
1548e745fdaSopenharmony_ci};
1558e745fdaSopenharmony_ci
1568e745fdaSopenharmony_ci// Messages format (https://www.rfc-editor.org/rfc/rfc1035#section-4.1)
1578e745fdaSopenharmony_cistruct Message {
1588e745fdaSopenharmony_ci    Header header;
1598e745fdaSopenharmony_ci    std::vector<Question> questions;
1608e745fdaSopenharmony_ci    std::vector<ResourceRecord> answers;
1618e745fdaSopenharmony_ci    std::vector<ResourceRecord> authorities;
1628e745fdaSopenharmony_ci    std::vector<ResourceRecord> additional;
1638e745fdaSopenharmony_ci};
1648e745fdaSopenharmony_ci
1658e745fdaSopenharmony_ci} // namespace DNSProto
1668e745fdaSopenharmony_ci
1678e745fdaSopenharmony_ciusing MDnsMessage = DNSProto::Message;
1688e745fdaSopenharmony_ci
1698e745fdaSopenharmony_ci// Parse mDNS Message from UDP payload or serialize DNS Message to bytes
1708e745fdaSopenharmony_ci// This parser could record error location
1718e745fdaSopenharmony_ciclass MDnsPayloadParser {
1728e745fdaSopenharmony_cipublic:
1738e745fdaSopenharmony_ci    enum {
1748e745fdaSopenharmony_ci        PARSE_OK = 0,
1758e745fdaSopenharmony_ci        PARSE_ERROR = 0xffff,
1768e745fdaSopenharmony_ci        PARSE_ERROR_BAD_SIZE = 0x1,
1778e745fdaSopenharmony_ci        PARSE_ERROR_BAD_STR = 0x2,
1788e745fdaSopenharmony_ci        PARSE_ERROR_BAD_STRPTR = 0x4,
1798e745fdaSopenharmony_ci        PARSE_WARNING = 0xffff0000,
1808e745fdaSopenharmony_ci        PARSE_WARNING_BAD_ENTRY_SIZE = 0x40000000,
1818e745fdaSopenharmony_ci        PARSE_WARNING_BAD_RRTYPE = 0x80000000,
1828e745fdaSopenharmony_ci    };
1838e745fdaSopenharmony_ci
1848e745fdaSopenharmony_ci    MDnsPayloadParser() = default;
1858e745fdaSopenharmony_ci    ~MDnsPayloadParser() = default;
1868e745fdaSopenharmony_ci
1878e745fdaSopenharmony_ci    /**
1888e745fdaSopenharmony_ci     * parse function
1898e745fdaSopenharmony_ci     *
1908e745fdaSopenharmony_ci     * @param udp payload as bytes
1918e745fdaSopenharmony_ci     * @return dns message struct
1928e745fdaSopenharmony_ci     */
1938e745fdaSopenharmony_ci    MDnsMessage FromBytes(const MDnsPayload &payload);
1948e745fdaSopenharmony_ci
1958e745fdaSopenharmony_ci    /**
1968e745fdaSopenharmony_ci     * parse function
1978e745fdaSopenharmony_ci     *
1988e745fdaSopenharmony_ci     * @param dns message struct
1998e745fdaSopenharmony_ci     * @return dns message as bytes for transmission
2008e745fdaSopenharmony_ci     */
2018e745fdaSopenharmony_ci    MDnsPayload ToBytes(const MDnsMessage &msg);
2028e745fdaSopenharmony_ci
2038e745fdaSopenharmony_ci    /**
2048e745fdaSopenharmony_ci     * get parse error function
2058e745fdaSopenharmony_ci     * @return all error in uint32, use PARSE_ERROR_* to extract
2068e745fdaSopenharmony_ci     */
2078e745fdaSopenharmony_ci    uint32_t GetError() const;
2088e745fdaSopenharmony_ci
2098e745fdaSopenharmony_ciprivate:
2108e745fdaSopenharmony_ci    const uint8_t *Parse(const uint8_t *begin, const MDnsPayload &payload, MDnsMessage &msg);
2118e745fdaSopenharmony_ci    const uint8_t *ParseHeader(const uint8_t *begin, const MDnsPayload &payload, DNSProto::Header &header);
2128e745fdaSopenharmony_ci    const uint8_t *ParseQuestion(const uint8_t *begin, const MDnsPayload &payload,
2138e745fdaSopenharmony_ci                                 std::vector<DNSProto::Question> &questions);
2148e745fdaSopenharmony_ci    const uint8_t *ParseRR(const uint8_t *begin, const MDnsPayload &payload,
2158e745fdaSopenharmony_ci                           std::vector<DNSProto::ResourceRecord> &answers);
2168e745fdaSopenharmony_ci    const uint8_t *ParseRData(const uint8_t *begin, const MDnsPayload &payload, int type, int length, std::any &data);
2178e745fdaSopenharmony_ci    const uint8_t *ParseSrv(const uint8_t *begin, const MDnsPayload &payload, std::any &data);
2188e745fdaSopenharmony_ci    const uint8_t *ParseTxt(const uint8_t *begin, const MDnsPayload &payload, int length, std::any &data);
2198e745fdaSopenharmony_ci
2208e745fdaSopenharmony_ci    // Read https://www.rfc-editor.org/rfc/rfc1035#section-4.1.4
2218e745fdaSopenharmony_ci    const uint8_t *ParseDnsString(const uint8_t *begin, const MDnsPayload &payload, std::string &str);
2228e745fdaSopenharmony_ci
2238e745fdaSopenharmony_ci    void Serialize(const MDnsMessage &msg, MDnsPayload &payload, MDnsPayload *cachedPayload,
2248e745fdaSopenharmony_ci                   std::map<std::string, uint16_t> &strCacheMap);
2258e745fdaSopenharmony_ci    void SerializeHeader(const DNSProto::Header &header, const MDnsMessage &msg, MDnsPayload &payload);
2268e745fdaSopenharmony_ci    void SerializeQuestion(const DNSProto::Question &question, MDnsPayload &payload, MDnsPayload *cachedPayload,
2278e745fdaSopenharmony_ci                           std::map<std::string, uint16_t> &strCacheMap);
2288e745fdaSopenharmony_ci    void SerializeRR(const DNSProto::ResourceRecord &rr, MDnsPayload &payload, MDnsPayload *cachedPayload,
2298e745fdaSopenharmony_ci                     std::map<std::string, uint16_t> &strCacheMap);
2308e745fdaSopenharmony_ci    void SerializeRData(const std::any &rdata, MDnsPayload &payload, MDnsPayload *cachedPayload,
2318e745fdaSopenharmony_ci                        std::map<std::string, uint16_t> &strCacheMap);
2328e745fdaSopenharmony_ci    void SerializeDnsString(const std::string &str, MDnsPayload &payload, MDnsPayload *cachedPayload,
2338e745fdaSopenharmony_ci                            std::map<std::string, uint16_t> &strCacheMap);
2348e745fdaSopenharmony_ci
2358e745fdaSopenharmony_ci    uint32_t errorFlags_ = 0;
2368e745fdaSopenharmony_ci    const uint8_t *pos_ = nullptr;
2378e745fdaSopenharmony_ci};
2388e745fdaSopenharmony_ci
2398e745fdaSopenharmony_ci} // namespace NetManagerStandard
2408e745fdaSopenharmony_ci} // namespace OHOS
2418e745fdaSopenharmony_ci#endif /* MDNS_PACKET_PARSER_H */
242