1 /* MIT License 2 * 3 * Copyright (c) The c-ares project and its contributors 4 * 5 * Permission is hereby granted, free of charge, to any person obtaining a copy 6 * of this software and associated documentation files (the "Software"), to deal 7 * in the Software without restriction, including without limitation the rights 8 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 * copies of the Software, and to permit persons to whom the Software is 10 * furnished to do so, subject to the following conditions: 11 * 12 * The above copyright notice and this permission notice (including the next 13 * paragraph) shall be included in all copies or substantial portions of the 14 * Software. 15 * 16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 * SOFTWARE. 23 * 24 * SPDX-License-Identifier: MIT 25 */ 26 #ifndef DNS_PROTO_H 27 #define DNS_PROTO_H 28 // Utilities for processing DNS packet contents 29 30 #include "ares_setup.h" 31 #include "ares.h" 32 // Include ares internal file for DNS protocol constants 33 #include "ares_nameser.h" 34 35 #include <memory> 36 #include <string> 37 #include <vector> 38 39 extern "C" void arestest_strtolower(char *dest, const char *src, 40 size_t dest_size); 41 42 namespace ares { 43 44 typedef unsigned char byte; 45 46 std::string HexDump(std::vector<byte> data); 47 std::string HexDump(const byte *data, int len); 48 std::string HexDump(const char *data, int len); 49 50 std::string StatusToString(int status); 51 std::string RcodeToString(int rcode); 52 std::string RRTypeToString(int rrtype); 53 std::string ClassToString(int qclass); 54 std::string AddressToString(const void *addr, int len); 55 56 const ares_dns_rr_t *fetch_rr_opt(const ares_dns_record_t *rec); 57 58 // Convert DNS protocol data to strings. 59 // Note that these functions are not defensive; they assume 60 // a validly formatted input, and so should not be used on 61 // externally-determined inputs. 62 std::string PacketToString(const std::vector<byte> &packet); 63 std::string QuestionToString(const std::vector<byte> &packet, const byte **data, 64 int *len); 65 std::string RRToString(const std::vector<byte> &packet, const byte **data, 66 int *len); 67 68 69 // Manipulate DNS protocol data. 70 void PushInt32(std::vector<byte> *data, int value); 71 void PushInt16(std::vector<byte> *data, int value); 72 std::vector<byte> EncodeString(const std::string &name); 73 74 struct DNSQuestion { DNSQuestionDNSQuestion75 DNSQuestion(const std::string &name, int rrtype, int qclass) 76 : name_(name), rrtype_(rrtype), qclass_(qclass) 77 { 78 } 79 DNSQuestionDNSQuestion80 DNSQuestion(const std::string &name, int rrtype) 81 : name_(name), rrtype_(rrtype), qclass_(C_IN) 82 { 83 } 84 ~DNSQuestionDNSQuestion85 virtual ~DNSQuestion() 86 { 87 } 88 89 virtual std::vector<byte> data(const char *request_name, 90 const ares_dns_record_t *dnsrec) const; 91 dataDNSQuestion92 virtual std::vector<byte> data(const ares_dns_record_t *dnsrec) const 93 { 94 return data(nullptr, dnsrec); 95 } 96 dataDNSQuestion97 virtual std::vector<byte> data() const 98 { 99 return data(nullptr, nullptr); 100 } 101 102 std::string name_; 103 int rrtype_; 104 int qclass_; 105 }; 106 107 struct DNSRR : public DNSQuestion { DNSRRDNSRR108 DNSRR(const std::string &name, int rrtype, int qclass, int ttl) 109 : DNSQuestion(name, rrtype, qclass), ttl_(ttl) 110 { 111 } 112 DNSRRDNSRR113 DNSRR(const std::string &name, int rrtype, int ttl) 114 : DNSQuestion(name, rrtype), ttl_(ttl) 115 { 116 } 117 ~DNSRRDNSRR118 virtual ~DNSRR() 119 { 120 } 121 122 virtual std::vector<byte> data(const ares_dns_record_t *dnsrec) const = 0; 123 int ttl_; 124 }; 125 126 struct DNSAddressRR : public DNSRR { DNSAddressRRDNSAddressRR127 DNSAddressRR(const std::string &name, int rrtype, int ttl, const byte *addr, 128 int addrlen) 129 : DNSRR(name, rrtype, ttl), addr_(addr, addr + addrlen) 130 { 131 } 132 DNSAddressRRDNSAddressRR133 DNSAddressRR(const std::string &name, int rrtype, int ttl, 134 const std::vector<byte> &addr) 135 : DNSRR(name, rrtype, ttl), addr_(addr) 136 { 137 } 138 139 virtual std::vector<byte> data(const ares_dns_record_t *dnsrec) const; 140 std::vector<byte> addr_; 141 }; 142 143 struct DNSARR : public DNSAddressRR { DNSARRDNSARR144 DNSARR(const std::string &name, int ttl, const byte *addr, int addrlen) 145 : DNSAddressRR(name, T_A, ttl, addr, addrlen) 146 { 147 } 148 DNSARRDNSARR149 DNSARR(const std::string &name, int ttl, const std::vector<byte> &addr) 150 : DNSAddressRR(name, T_A, ttl, addr) 151 { 152 } 153 }; 154 155 struct DNSAaaaRR : public DNSAddressRR { DNSAaaaRRDNSAaaaRR156 DNSAaaaRR(const std::string &name, int ttl, const byte *addr, int addrlen) 157 : DNSAddressRR(name, T_AAAA, ttl, addr, addrlen) 158 { 159 } 160 DNSAaaaRRDNSAaaaRR161 DNSAaaaRR(const std::string &name, int ttl, const std::vector<byte> &addr) 162 : DNSAddressRR(name, T_AAAA, ttl, addr) 163 { 164 } 165 }; 166 167 struct DNSSingleNameRR : public DNSRR { DNSSingleNameRRDNSSingleNameRR168 DNSSingleNameRR(const std::string &name, int rrtype, int ttl, 169 const std::string &other) 170 : DNSRR(name, rrtype, ttl), other_(other) 171 { 172 } 173 174 virtual std::vector<byte> data(const ares_dns_record_t *dnsrec) const; 175 std::string other_; 176 }; 177 178 struct DNSCnameRR : public DNSSingleNameRR { DNSCnameRRDNSCnameRR179 DNSCnameRR(const std::string &name, int ttl, const std::string &other) 180 : DNSSingleNameRR(name, T_CNAME, ttl, other) 181 { 182 } 183 }; 184 185 struct DNSNsRR : public DNSSingleNameRR { DNSNsRRDNSNsRR186 DNSNsRR(const std::string &name, int ttl, const std::string &other) 187 : DNSSingleNameRR(name, T_NS, ttl, other) 188 { 189 } 190 }; 191 192 struct DNSPtrRR : public DNSSingleNameRR { DNSPtrRRDNSPtrRR193 DNSPtrRR(const std::string &name, int ttl, const std::string &other) 194 : DNSSingleNameRR(name, T_PTR, ttl, other) 195 { 196 } 197 }; 198 199 struct DNSTxtRR : public DNSRR { DNSTxtRRDNSTxtRR200 DNSTxtRR(const std::string &name, int ttl, 201 const std::vector<std::string> &txt) 202 : DNSRR(name, T_TXT, ttl), txt_(txt) 203 { 204 } 205 206 virtual std::vector<byte> data(const ares_dns_record_t *dnsrec) const; 207 std::vector<std::string> txt_; 208 }; 209 210 struct DNSMxRR : public DNSRR { DNSMxRRDNSMxRR211 DNSMxRR(const std::string &name, int ttl, int pref, const std::string &other) 212 : DNSRR(name, T_MX, ttl), pref_(pref), other_(other) 213 { 214 } 215 216 virtual std::vector<byte> data(const ares_dns_record_t *dnsrec) const; 217 int pref_; 218 std::string other_; 219 }; 220 221 struct DNSSrvRR : public DNSRR { DNSSrvRRDNSSrvRR222 DNSSrvRR(const std::string &name, int ttl, int prio, int weight, int port, 223 const std::string &target) 224 : DNSRR(name, T_SRV, ttl), prio_(prio), weight_(weight), port_(port), 225 target_(target) 226 { 227 } 228 229 virtual std::vector<byte> data(const ares_dns_record_t *dnsrec) const; 230 int prio_; 231 int weight_; 232 int port_; 233 std::string target_; 234 }; 235 236 struct DNSUriRR : public DNSRR { DNSUriRRDNSUriRR237 DNSUriRR(const std::string &name, int ttl, int prio, int weight, 238 const std::string &target) 239 : DNSRR(name, T_URI, ttl), prio_(prio), weight_(weight), target_(target) 240 { 241 } 242 243 virtual std::vector<byte> data(const ares_dns_record_t *dnsrec) const; 244 int prio_; 245 int weight_; 246 std::string target_; 247 }; 248 249 struct DNSSoaRR : public DNSRR { DNSSoaRRDNSSoaRR250 DNSSoaRR(const std::string &name, int ttl, const std::string &nsname, 251 const std::string &rname, int serial, int refresh, int retry, 252 int expire, int minimum) 253 : DNSRR(name, T_SOA, ttl), nsname_(nsname), rname_(rname), serial_(serial), 254 refresh_(refresh), retry_(retry), expire_(expire), minimum_(minimum) 255 { 256 } 257 258 virtual std::vector<byte> data(const ares_dns_record_t *dnsrec) const; 259 std::string nsname_; 260 std::string rname_; 261 int serial_; 262 int refresh_; 263 int retry_; 264 int expire_; 265 int minimum_; 266 }; 267 268 struct DNSNaptrRR : public DNSRR { DNSNaptrRRDNSNaptrRR269 DNSNaptrRR(const std::string &name, int ttl, int order, int pref, 270 const std::string &flags, const std::string &service, 271 const std::string ®exp, const std::string &replacement) 272 : DNSRR(name, T_NAPTR, ttl), order_(order), pref_(pref), flags_(flags), 273 service_(service), regexp_(regexp), replacement_(replacement) 274 { 275 } 276 277 virtual std::vector<byte> data(const ares_dns_record_t *dnsrec) const; 278 int order_; 279 int pref_; 280 std::string flags_; 281 std::string service_; 282 std::string regexp_; 283 std::string replacement_; 284 }; 285 286 struct DNSOption { 287 int code_; 288 std::vector<byte> data_; 289 }; 290 291 struct DNSOptRR : public DNSRR { DNSOptRRDNSOptRR292 DNSOptRR(unsigned char extrcode, unsigned char version, unsigned short flags, 293 int udpsize, std::vector<byte> client_cookie, 294 std::vector<byte> server_cookie, bool expect_server_cookie) 295 : DNSRR("", T_OPT, static_cast<int>(udpsize), 296 ((int)extrcode) << 24 | ((int)version) << 16 | 297 ((int)flags) /* ttl */) 298 { 299 client_cookie_ = client_cookie; 300 server_cookie_ = server_cookie; 301 expect_server_cookie_ = expect_server_cookie; 302 } 303 304 virtual std::vector<byte> data(const ares_dns_record_t *dnsrec) const; 305 std::vector<DNSOption> opts_; 306 std::vector<byte> client_cookie_; 307 std::vector<byte> server_cookie_; 308 bool expect_server_cookie_; 309 }; 310 311 struct DNSPacket { DNSPacketDNSPacket312 DNSPacket() 313 : qid_(0), response_(false), opcode_(O_QUERY), aa_(false), tc_(false), 314 rd_(false), ra_(false), z_(false), ad_(false), cd_(false), rcode_(NOERROR) 315 { 316 } 317 318 // Convenience functions that take ownership of given pointers. add_questionDNSPacket319 DNSPacket &add_question(DNSQuestion *q) 320 { 321 questions_.push_back(std::unique_ptr<DNSQuestion>(q)); 322 return *this; 323 } 324 add_answerDNSPacket325 DNSPacket &add_answer(DNSRR *q) 326 { 327 answers_.push_back(std::unique_ptr<DNSRR>(q)); 328 return *this; 329 } 330 add_authDNSPacket331 DNSPacket &add_auth(DNSRR *q) 332 { 333 auths_.push_back(std::unique_ptr<DNSRR>(q)); 334 return *this; 335 } 336 add_additionalDNSPacket337 DNSPacket &add_additional(DNSRR *q) 338 { 339 adds_.push_back(std::unique_ptr<DNSRR>(q)); 340 return *this; 341 } 342 343 // Chainable setters. set_qidDNSPacket344 DNSPacket &set_qid(int qid) 345 { 346 qid_ = qid; 347 return *this; 348 } 349 350 DNSPacket &set_response(bool v = true) 351 { 352 response_ = v; 353 return *this; 354 } 355 356 DNSPacket &set_aa(bool v = true) 357 { 358 aa_ = v; 359 return *this; 360 } 361 362 DNSPacket &set_tc(bool v = true) 363 { 364 tc_ = v; 365 return *this; 366 } 367 368 DNSPacket &set_rd(bool v = true) 369 { 370 rd_ = v; 371 return *this; 372 } 373 374 DNSPacket &set_ra(bool v = true) 375 { 376 ra_ = v; 377 return *this; 378 } 379 380 DNSPacket &set_z(bool v = true) 381 { 382 z_ = v; 383 return *this; 384 } 385 386 DNSPacket &set_ad(bool v = true) 387 { 388 ad_ = v; 389 return *this; 390 } 391 392 DNSPacket &set_cd(bool v = true) 393 { 394 cd_ = v; 395 return *this; 396 } 397 set_rcodeDNSPacket398 DNSPacket &set_rcode(int rcode) 399 { 400 rcode_ = rcode; 401 return *this; 402 } 403 404 // Return the encoded packet. 405 std::vector<byte> data(const char *request_name, 406 const ares_dns_record_t *dnsrec) const; 407 dataDNSPacket408 std::vector<byte> data() const 409 { 410 return data(nullptr, nullptr); 411 } 412 413 int qid_; 414 bool response_; 415 int opcode_; 416 bool aa_; 417 bool tc_; 418 bool rd_; 419 bool ra_; 420 bool z_; 421 bool ad_; 422 bool cd_; 423 int rcode_; 424 std::vector<std::unique_ptr<DNSQuestion>> questions_; 425 std::vector<std::unique_ptr<DNSRR>> answers_; 426 std::vector<std::unique_ptr<DNSRR>> auths_; 427 std::vector<std::unique_ptr<DNSRR>> adds_; 428 }; 429 430 } // namespace ares 431 432 #endif 433