1 /* 2 * Copyright (C) 2023 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16 #ifndef MDNS_PACKET_PARSER_H 17 #define MDNS_PACKET_PARSER_H 18 19 #include <any> 20 #include <string> 21 #include <string_view> 22 #include <vector> 23 24 #include <netinet/in.h> 25 26 #include "mdns_common.h" 27 28 namespace OHOS { 29 namespace NetManagerStandard { 30 31 namespace DNSProto { 32 33 constexpr uint16_t HEADER_FLAGS_QR_MASK = 0x8000; 34 constexpr uint16_t HEADER_FLAGS_OPCODE_MASK = 0x7800; 35 constexpr uint16_t HEADER_FLAGS_AA_MASK = 0x0400; 36 constexpr uint16_t HEADER_FLAGS_TC_MASK = 0x0200; 37 constexpr uint16_t HEADER_FLAGS_RD_MASK = 0x0100; 38 constexpr uint16_t HEADER_FLAGS_RA_MASK = 0x0080; 39 constexpr uint16_t HEADER_FLAGS_Z_MASK = 0x0040; 40 constexpr uint16_t HEADER_FLAGS_AD_MASK = 0x0020; 41 constexpr uint16_t HEADER_FLAGS_CD_MASK = 0x0010; 42 constexpr uint16_t HEADER_FLAGS_RCODE_MASK = 0x000f; 43 44 constexpr uint16_t HEADER_FLAGS_QR_OFFSET = 15; 45 constexpr uint16_t HEADER_FLAGS_OPCODE_OFFSET = 11; 46 constexpr uint16_t HEADER_FLAGS_AA_OFFSET = 10; 47 constexpr uint16_t HEADER_FLAGS_TC_OFFSET = 9; 48 constexpr uint16_t HEADER_FLAGS_RD_OFFSET = 8; 49 constexpr uint16_t HEADER_FLAGS_RA_OFFSET = 7; 50 constexpr uint16_t HEADER_FLAGS_Z_OFFSET = 6; 51 constexpr uint16_t HEADER_FLAGS_AD_OFFSET = 5; 52 constexpr uint16_t HEADER_FLAGS_CD_OFFSET = 4; 53 constexpr uint16_t HEADER_FLAGS_RCODE_OFFSET = 0; 54 55 // QR = 1, AA = 1 56 static constexpr uint16_t MDNS_ANSWER_FLAGS = 0x8400; 57 58 // DNS Header format (https://www.rfc-editor.org/rfc/rfc1035#section-4.1.1) 59 // 1 1 1 1 1 1 60 // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 61 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ 62 // | ID | 63 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ 64 // |QR| OpCode |AA|TC|RD|RA| Z|AD|CD| RCODE | 65 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ 66 // | QDCOUNT/ZOCOUNT | 67 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ 68 // | ANCOUNT/PRCOUNT | 69 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ 70 // | NSCOUNT/UPCOUNT | 71 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ 72 // | ARCOUNT | 73 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ 74 struct Header { 75 uint16_t id = 0x0; 76 uint16_t flags = 0x0; 77 uint16_t qdcount = 0x0; 78 uint16_t ancount = 0x0; 79 uint16_t nscount = 0x0; 80 uint16_t arcount = 0x0; 81 }; 82 83 84 // RR Type (https://www.rfc-editor.org/rfc/rfc1035#section-3.2.2) 85 enum RRType { 86 RRTYPE_IGNORE = 0, 87 RRTYPE_A = 1, 88 RRTYPE_PTR = 12, 89 RRTYPE_TXT = 16, 90 RRTYPE_AAAA = 28, 91 RRTYPE_SRV = 33, 92 RRTYPE_ANY = 255 93 }; 94 95 // RR Class (https://www.rfc-editor.org/rfc/rfc1035#section-3.2.4) 96 enum RRClass { 97 RRCLASS_IN = 1, 98 RRCLASS_ANY = 255 99 }; 100 101 // DNS Question format (https://www.rfc-editor.org/rfc/rfc1035#section-4.1.2) 102 // 1 1 1 1 1 1 103 // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 104 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ 105 // | | 106 // / QNAME / 107 // / / 108 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ 109 // | QTYPE | 110 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ 111 // | QCLASS | 112 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ 113 struct Question { 114 std::string name; 115 uint16_t qtype; 116 uint16_t qclass; 117 }; 118 119 // DNS SRV RR format (https://www.rfc-editor.org/rfc/rfc2782) 120 struct RDataSrv { 121 uint16_t priority; 122 uint16_t weight; 123 uint16_t port; 124 std::string name; 125 }; 126 127 // DNS RR format (https://www.rfc-editor.org/rfc/rfc1035#section-3.2.1) 128 // 1 1 1 1 1 1 129 // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 130 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ 131 // | | 132 // / / 133 // / NAME / 134 // | | 135 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ 136 // | TYPE | 137 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ 138 // | CLASS | 139 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ 140 // | TTL | 141 // | | 142 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ 143 // | RDLENGTH | 144 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--| 145 // / RDATA / 146 // / / 147 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ 148 struct ResourceRecord { 149 std::string name; 150 uint16_t rtype; 151 uint16_t rclass; 152 uint32_t ttl; 153 uint16_t length; 154 std::any rdata; 155 }; 156 157 // Messages format (https://www.rfc-editor.org/rfc/rfc1035#section-4.1) 158 struct Message { 159 Header header; 160 std::vector<Question> questions; 161 std::vector<ResourceRecord> answers; 162 std::vector<ResourceRecord> authorities; 163 std::vector<ResourceRecord> additional; 164 }; 165 166 } // namespace DNSProto 167 168 using MDnsMessage = DNSProto::Message; 169 170 // Parse mDNS Message from UDP payload or serialize DNS Message to bytes 171 // This parser could record error location 172 class MDnsPayloadParser { 173 public: 174 enum { 175 PARSE_OK = 0, 176 PARSE_ERROR = 0xffff, 177 PARSE_ERROR_BAD_SIZE = 0x1, 178 PARSE_ERROR_BAD_STR = 0x2, 179 PARSE_ERROR_BAD_STRPTR = 0x4, 180 PARSE_WARNING = 0xffff0000, 181 PARSE_WARNING_BAD_ENTRY_SIZE = 0x40000000, 182 PARSE_WARNING_BAD_RRTYPE = 0x80000000, 183 }; 184 185 MDnsPayloadParser() = default; 186 ~MDnsPayloadParser() = default; 187 188 /** 189 * parse function 190 * 191 * @param udp payload as bytes 192 * @return dns message struct 193 */ 194 MDnsMessage FromBytes(const MDnsPayload &payload); 195 196 /** 197 * parse function 198 * 199 * @param dns message struct 200 * @return dns message as bytes for transmission 201 */ 202 MDnsPayload ToBytes(const MDnsMessage &msg); 203 204 /** 205 * get parse error function 206 * @return all error in uint32, use PARSE_ERROR_* to extract 207 */ 208 uint32_t GetError() const; 209 210 private: 211 const uint8_t *Parse(const uint8_t *begin, const MDnsPayload &payload, MDnsMessage &msg); 212 const uint8_t *ParseHeader(const uint8_t *begin, const MDnsPayload &payload, DNSProto::Header &header); 213 const uint8_t *ParseQuestion(const uint8_t *begin, const MDnsPayload &payload, 214 std::vector<DNSProto::Question> &questions); 215 const uint8_t *ParseRR(const uint8_t *begin, const MDnsPayload &payload, 216 std::vector<DNSProto::ResourceRecord> &answers); 217 const uint8_t *ParseRData(const uint8_t *begin, const MDnsPayload &payload, int type, int length, std::any &data); 218 const uint8_t *ParseSrv(const uint8_t *begin, const MDnsPayload &payload, std::any &data); 219 const uint8_t *ParseTxt(const uint8_t *begin, const MDnsPayload &payload, int length, std::any &data); 220 const uint8_t *ParseDnsString(const uint8_t *begin, const MDnsPayload &payload, std::string &str); 221 222 void Serialize(const MDnsMessage &msg, MDnsPayload &payload); 223 void SerializeHeader(const DNSProto::Header &header, const MDnsMessage &msg, MDnsPayload &payload); 224 void SerializeQuestion(const DNSProto::Question &question, const MDnsMessage &msg, MDnsPayload &payload); 225 void SerializeRR(const DNSProto::ResourceRecord &rr, const MDnsMessage &msg, MDnsPayload &payload); 226 void SerializeRData(const std::any &rdata, const MDnsMessage &msg, MDnsPayload &payload); 227 void SerializeDnsString(const std::string &str, const MDnsMessage &msg, MDnsPayload &payload); 228 229 uint32_t errorFlags_ = 0; 230 const uint8_t *pos_ = nullptr; 231 MDnsPayload *cachedPayload_ = nullptr; 232 std::map<std::string, uint16_t> strCacheMap_; 233 }; 234 235 } // namespace NetManagerStandard 236 } // namespace OHOS 237 #endif /* MDNS_PACKET_PARSER_H */ 238