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