| // -*- mode: c++ -*- |
| /* |
| * Copyright (C) The c-ares project |
| * |
| * Permission to use, copy, modify, and distribute this |
| * software and its documentation for any purpose and without |
| * fee is hereby granted, provided that the above copyright |
| * notice appear in all copies and that both that copyright |
| * notice and this permission notice appear in supporting |
| * documentation, and that the name of M.I.T. not be used in |
| * advertising or publicity pertaining to distribution of the |
| * software without specific, written prior permission. |
| * M.I.T. makes no representations about the suitability of |
| * this software for any purpose. It is provided "as is" |
| * without express or implied warranty. |
| * |
| * SPDX-License-Identifier: MIT |
| */ |
| #ifndef DNS_PROTO_H |
| #define DNS_PROTO_H |
| // Utilities for processing DNS packet contents |
| |
| #include "ares_setup.h" |
| #include "ares.h" |
| // Include ares internal file for DNS protocol constants |
| #include "ares_nameser.h" |
| |
| #include <memory> |
| #include <string> |
| #include <vector> |
| |
| namespace ares { |
| |
| typedef unsigned char byte; |
| |
| std::string HexDump(std::vector<byte> data); |
| std::string HexDump(const byte *data, int len); |
| std::string HexDump(const char *data, int len); |
| |
| std::string StatusToString(int status); |
| std::string RcodeToString(int rcode); |
| std::string RRTypeToString(int rrtype); |
| std::string ClassToString(int qclass); |
| std::string AddressToString(const void *addr, int len); |
| |
| // Convert DNS protocol data to strings. |
| // Note that these functions are not defensive; they assume |
| // a validly formatted input, and so should not be used on |
| // externally-determined inputs. |
| std::string PacketToString(const std::vector<byte> &packet); |
| std::string QuestionToString(const std::vector<byte> &packet, const byte **data, |
| int *len); |
| std::string RRToString(const std::vector<byte> &packet, const byte **data, |
| int *len); |
| |
| |
| // Manipulate DNS protocol data. |
| void PushInt32(std::vector<byte> *data, int value); |
| void PushInt16(std::vector<byte> *data, int value); |
| std::vector<byte> EncodeString(const std::string &name); |
| |
| struct DNSQuestion { |
| DNSQuestion(const std::string &name, int rrtype, int qclass) |
| : name_(name), rrtype_(rrtype), qclass_(qclass) |
| { |
| } |
| |
| DNSQuestion(const std::string &name, int rrtype) |
| : name_(name), rrtype_(rrtype), qclass_(C_IN) |
| { |
| } |
| |
| virtual ~DNSQuestion() |
| { |
| } |
| |
| virtual std::vector<byte> data() const; |
| std::string name_; |
| int rrtype_; |
| int qclass_; |
| }; |
| |
| struct DNSRR : public DNSQuestion { |
| DNSRR(const std::string &name, int rrtype, int qclass, int ttl) |
| : DNSQuestion(name, rrtype, qclass), ttl_(ttl) |
| { |
| } |
| |
| DNSRR(const std::string &name, int rrtype, int ttl) |
| : DNSQuestion(name, rrtype), ttl_(ttl) |
| { |
| } |
| |
| virtual ~DNSRR() |
| { |
| } |
| |
| virtual std::vector<byte> data() const = 0; |
| int ttl_; |
| }; |
| |
| struct DNSAddressRR : public DNSRR { |
| DNSAddressRR(const std::string &name, int rrtype, int ttl, const byte *addr, |
| int addrlen) |
| : DNSRR(name, rrtype, ttl), addr_(addr, addr + addrlen) |
| { |
| } |
| |
| DNSAddressRR(const std::string &name, int rrtype, int ttl, |
| const std::vector<byte> &addr) |
| : DNSRR(name, rrtype, ttl), addr_(addr) |
| { |
| } |
| |
| virtual std::vector<byte> data() const; |
| std::vector<byte> addr_; |
| }; |
| |
| struct DNSARR : public DNSAddressRR { |
| DNSARR(const std::string &name, int ttl, const byte *addr, int addrlen) |
| : DNSAddressRR(name, T_A, ttl, addr, addrlen) |
| { |
| } |
| |
| DNSARR(const std::string &name, int ttl, const std::vector<byte> &addr) |
| : DNSAddressRR(name, T_A, ttl, addr) |
| { |
| } |
| }; |
| |
| struct DNSAaaaRR : public DNSAddressRR { |
| DNSAaaaRR(const std::string &name, int ttl, const byte *addr, int addrlen) |
| : DNSAddressRR(name, T_AAAA, ttl, addr, addrlen) |
| { |
| } |
| |
| DNSAaaaRR(const std::string &name, int ttl, const std::vector<byte> &addr) |
| : DNSAddressRR(name, T_AAAA, ttl, addr) |
| { |
| } |
| }; |
| |
| struct DNSSingleNameRR : public DNSRR { |
| DNSSingleNameRR(const std::string &name, int rrtype, int ttl, |
| const std::string &other) |
| : DNSRR(name, rrtype, ttl), other_(other) |
| { |
| } |
| |
| virtual std::vector<byte> data() const; |
| std::string other_; |
| }; |
| |
| struct DNSCnameRR : public DNSSingleNameRR { |
| DNSCnameRR(const std::string &name, int ttl, const std::string &other) |
| : DNSSingleNameRR(name, T_CNAME, ttl, other) |
| { |
| } |
| }; |
| |
| struct DNSNsRR : public DNSSingleNameRR { |
| DNSNsRR(const std::string &name, int ttl, const std::string &other) |
| : DNSSingleNameRR(name, T_NS, ttl, other) |
| { |
| } |
| }; |
| |
| struct DNSPtrRR : public DNSSingleNameRR { |
| DNSPtrRR(const std::string &name, int ttl, const std::string &other) |
| : DNSSingleNameRR(name, T_PTR, ttl, other) |
| { |
| } |
| }; |
| |
| struct DNSTxtRR : public DNSRR { |
| DNSTxtRR(const std::string &name, int ttl, |
| const std::vector<std::string> &txt) |
| : DNSRR(name, T_TXT, ttl), txt_(txt) |
| { |
| } |
| |
| virtual std::vector<byte> data() const; |
| std::vector<std::string> txt_; |
| }; |
| |
| struct DNSMxRR : public DNSRR { |
| DNSMxRR(const std::string &name, int ttl, int pref, const std::string &other) |
| : DNSRR(name, T_MX, ttl), pref_(pref), other_(other) |
| { |
| } |
| |
| virtual std::vector<byte> data() const; |
| int pref_; |
| std::string other_; |
| }; |
| |
| struct DNSSrvRR : public DNSRR { |
| DNSSrvRR(const std::string &name, int ttl, int prio, int weight, int port, |
| const std::string &target) |
| : DNSRR(name, T_SRV, ttl), prio_(prio), weight_(weight), port_(port), |
| target_(target) |
| { |
| } |
| |
| virtual std::vector<byte> data() const; |
| int prio_; |
| int weight_; |
| int port_; |
| std::string target_; |
| }; |
| |
| struct DNSUriRR : public DNSRR { |
| DNSUriRR(const std::string &name, int ttl, int prio, int weight, |
| const std::string &target) |
| : DNSRR(name, T_URI, ttl), prio_(prio), weight_(weight), target_(target) |
| { |
| } |
| |
| virtual std::vector<byte> data() const; |
| int prio_; |
| int weight_; |
| std::string target_; |
| }; |
| |
| struct DNSSoaRR : public DNSRR { |
| DNSSoaRR(const std::string &name, int ttl, const std::string &nsname, |
| const std::string &rname, int serial, int refresh, int retry, |
| int expire, int minimum) |
| : DNSRR(name, T_SOA, ttl), nsname_(nsname), rname_(rname), serial_(serial), |
| refresh_(refresh), retry_(retry), expire_(expire), minimum_(minimum) |
| { |
| } |
| |
| virtual std::vector<byte> data() const; |
| std::string nsname_; |
| std::string rname_; |
| int serial_; |
| int refresh_; |
| int retry_; |
| int expire_; |
| int minimum_; |
| }; |
| |
| struct DNSNaptrRR : public DNSRR { |
| DNSNaptrRR(const std::string &name, int ttl, int order, int pref, |
| const std::string &flags, const std::string &service, |
| const std::string ®exp, const std::string &replacement) |
| : DNSRR(name, T_NAPTR, ttl), order_(order), pref_(pref), flags_(flags), |
| service_(service), regexp_(regexp), replacement_(replacement) |
| { |
| } |
| |
| virtual std::vector<byte> data() const; |
| int order_; |
| int pref_; |
| std::string flags_; |
| std::string service_; |
| std::string regexp_; |
| std::string replacement_; |
| }; |
| |
| struct DNSOption { |
| int code_; |
| std::vector<byte> data_; |
| }; |
| |
| struct DNSOptRR : public DNSRR { |
| DNSOptRR(int extrcode, int udpsize) |
| : DNSRR("", T_OPT, static_cast<int>(udpsize), extrcode) |
| { |
| } |
| |
| virtual std::vector<byte> data() const; |
| std::vector<DNSOption> opts_; |
| }; |
| |
| struct DNSPacket { |
| DNSPacket() |
| : qid_(0), response_(false), opcode_(O_QUERY), aa_(false), tc_(false), |
| rd_(false), ra_(false), z_(false), ad_(false), cd_(false), rcode_(NOERROR) |
| { |
| } |
| |
| // Convenience functions that take ownership of given pointers. |
| DNSPacket &add_question(DNSQuestion *q) |
| { |
| questions_.push_back(std::unique_ptr<DNSQuestion>(q)); |
| return *this; |
| } |
| |
| DNSPacket &add_answer(DNSRR *q) |
| { |
| answers_.push_back(std::unique_ptr<DNSRR>(q)); |
| return *this; |
| } |
| |
| DNSPacket &add_auth(DNSRR *q) |
| { |
| auths_.push_back(std::unique_ptr<DNSRR>(q)); |
| return *this; |
| } |
| |
| DNSPacket &add_additional(DNSRR *q) |
| { |
| adds_.push_back(std::unique_ptr<DNSRR>(q)); |
| return *this; |
| } |
| |
| // Chainable setters. |
| DNSPacket &set_qid(int qid) |
| { |
| qid_ = qid; |
| return *this; |
| } |
| |
| DNSPacket &set_response(bool v = true) |
| { |
| response_ = v; |
| return *this; |
| } |
| |
| DNSPacket &set_aa(bool v = true) |
| { |
| aa_ = v; |
| return *this; |
| } |
| |
| DNSPacket &set_tc(bool v = true) |
| { |
| tc_ = v; |
| return *this; |
| } |
| |
| DNSPacket &set_rd(bool v = true) |
| { |
| rd_ = v; |
| return *this; |
| } |
| |
| DNSPacket &set_ra(bool v = true) |
| { |
| ra_ = v; |
| return *this; |
| } |
| |
| DNSPacket &set_z(bool v = true) |
| { |
| z_ = v; |
| return *this; |
| } |
| |
| DNSPacket &set_ad(bool v = true) |
| { |
| ad_ = v; |
| return *this; |
| } |
| |
| DNSPacket &set_cd(bool v = true) |
| { |
| cd_ = v; |
| return *this; |
| } |
| |
| DNSPacket &set_rcode(int rcode) |
| { |
| rcode_ = rcode; |
| return *this; |
| } |
| |
| // Return the encoded packet. |
| std::vector<byte> data() const; |
| |
| int qid_; |
| bool response_; |
| int opcode_; |
| bool aa_; |
| bool tc_; |
| bool rd_; |
| bool ra_; |
| bool z_; |
| bool ad_; |
| bool cd_; |
| int rcode_; |
| std::vector<std::unique_ptr<DNSQuestion>> questions_; |
| std::vector<std::unique_ptr<DNSRR>> answers_; |
| std::vector<std::unique_ptr<DNSRR>> auths_; |
| std::vector<std::unique_ptr<DNSRR>> adds_; |
| }; |
| |
| } // namespace ares |
| |
| #endif |