1 // -*- mode: c++ -*- 2 #ifndef DNS_PROTO_H 3 #define DNS_PROTO_H 4 // Utilities for processing DNS packet contents 5 6 #include "ares_setup.h" 7 #include "ares.h" 8 // Include ares internal file for DNS protocol constants 9 #include "ares_nameser.h" 10 11 #include <memory> 12 #include <string> 13 #include <vector> 14 15 namespace ares { 16 17 typedef unsigned char byte; 18 19 std::string HexDump(std::vector<byte> data); 20 std::string HexDump(const byte *data, int len); 21 std::string HexDump(const char *data, int len); 22 23 std::string StatusToString(int status); 24 std::string RcodeToString(int rcode); 25 std::string RRTypeToString(int rrtype); 26 std::string ClassToString(int qclass); 27 std::string AddressToString(const void* addr, int len); 28 29 // Convert DNS protocol data to strings. 30 // Note that these functions are not defensive; they assume 31 // a validly formatted input, and so should not be used on 32 // externally-determined inputs. 33 std::string PacketToString(const std::vector<byte>& packet); 34 std::string QuestionToString(const std::vector<byte>& packet, 35 const byte** data, int* len); 36 std::string RRToString(const std::vector<byte>& packet, 37 const byte** data, int* len); 38 39 40 // Manipulate DNS protocol data. 41 void PushInt32(std::vector<byte>* data, int value); 42 void PushInt16(std::vector<byte>* data, int value); 43 std::vector<byte> EncodeString(const std::string& name); 44 45 struct DNSQuestion { DNSQuestionDNSQuestion46 DNSQuestion(const std::string& name, int rrtype, int qclass) 47 : name_(name), rrtype_(rrtype), qclass_(qclass) {} DNSQuestionDNSQuestion48 DNSQuestion(const std::string& name, int rrtype) 49 : name_(name), rrtype_(rrtype), qclass_(C_IN) {} ~DNSQuestionDNSQuestion50 virtual ~DNSQuestion() {} 51 virtual std::vector<byte> data() const; 52 std::string name_; 53 int rrtype_; 54 int qclass_; 55 }; 56 57 struct DNSRR : public DNSQuestion { DNSRRDNSRR58 DNSRR(const std::string& name, int rrtype, int qclass, int ttl) 59 : DNSQuestion(name, rrtype, qclass), ttl_(ttl) {} DNSRRDNSRR60 DNSRR(const std::string& name, int rrtype, int ttl) 61 : DNSQuestion(name, rrtype), ttl_(ttl) {} ~DNSRRDNSRR62 virtual ~DNSRR() {} 63 virtual std::vector<byte> data() const = 0; 64 int ttl_; 65 }; 66 67 struct DNSAddressRR : public DNSRR { DNSAddressRRDNSAddressRR68 DNSAddressRR(const std::string& name, int rrtype, int ttl, 69 const byte* addr, int addrlen) 70 : DNSRR(name, rrtype, ttl), addr_(addr, addr + addrlen) {} DNSAddressRRDNSAddressRR71 DNSAddressRR(const std::string& name, int rrtype, int ttl, 72 const std::vector<byte>& addr) 73 : DNSRR(name, rrtype, ttl), addr_(addr) {} 74 virtual std::vector<byte> data() const; 75 std::vector<byte> addr_; 76 }; 77 78 struct DNSARR : public DNSAddressRR { DNSARRDNSARR79 DNSARR(const std::string& name, int ttl, const byte* addr, int addrlen) 80 : DNSAddressRR(name, T_A, ttl, addr, addrlen) {} DNSARRDNSARR81 DNSARR(const std::string& name, int ttl, const std::vector<byte>& addr) 82 : DNSAddressRR(name, T_A, ttl, addr) {} 83 }; 84 85 struct DNSAaaaRR : public DNSAddressRR { DNSAaaaRRDNSAaaaRR86 DNSAaaaRR(const std::string& name, int ttl, const byte* addr, int addrlen) 87 : DNSAddressRR(name, T_AAAA, ttl, addr, addrlen) {} DNSAaaaRRDNSAaaaRR88 DNSAaaaRR(const std::string& name, int ttl, const std::vector<byte>& addr) 89 : DNSAddressRR(name, T_AAAA, ttl, addr) {} 90 }; 91 92 struct DNSSingleNameRR : public DNSRR { DNSSingleNameRRDNSSingleNameRR93 DNSSingleNameRR(const std::string& name, int rrtype, int ttl, 94 const std::string& other) 95 : DNSRR(name, rrtype, ttl), other_(other) {} 96 virtual std::vector<byte> data() const; 97 std::string other_; 98 }; 99 100 struct DNSCnameRR : public DNSSingleNameRR { DNSCnameRRDNSCnameRR101 DNSCnameRR(const std::string& name, int ttl, const std::string& other) 102 : DNSSingleNameRR(name, T_CNAME, ttl, other) {} 103 }; 104 105 struct DNSNsRR : public DNSSingleNameRR { DNSNsRRDNSNsRR106 DNSNsRR(const std::string& name, int ttl, const std::string& other) 107 : DNSSingleNameRR(name, T_NS, ttl, other) {} 108 }; 109 110 struct DNSPtrRR : public DNSSingleNameRR { DNSPtrRRDNSPtrRR111 DNSPtrRR(const std::string& name, int ttl, const std::string& other) 112 : DNSSingleNameRR(name, T_PTR, ttl, other) {} 113 }; 114 115 struct DNSTxtRR : public DNSRR { DNSTxtRRDNSTxtRR116 DNSTxtRR(const std::string& name, int ttl, const std::vector<std::string>& txt) 117 : DNSRR(name, T_TXT, ttl), txt_(txt) {} 118 virtual std::vector<byte> data() const; 119 std::vector<std::string> txt_; 120 }; 121 122 struct DNSMxRR : public DNSRR { DNSMxRRDNSMxRR123 DNSMxRR(const std::string& name, int ttl, int pref, const std::string& other) 124 : DNSRR(name, T_MX, ttl), pref_(pref), other_(other) {} 125 virtual std::vector<byte> data() const; 126 int pref_; 127 std::string other_; 128 }; 129 130 struct DNSSrvRR : public DNSRR { DNSSrvRRDNSSrvRR131 DNSSrvRR(const std::string& name, int ttl, 132 int prio, int weight, int port, const std::string& target) 133 : DNSRR(name, T_SRV, ttl), prio_(prio), weight_(weight), port_(port), target_(target) {} 134 virtual std::vector<byte> data() const; 135 int prio_; 136 int weight_; 137 int port_; 138 std::string target_; 139 }; 140 141 struct DNSUriRR : public DNSRR { DNSUriRRDNSUriRR142 DNSUriRR(const std::string& name, int ttl, 143 int prio, int weight, const std::string& target) 144 : DNSRR(name, T_URI, ttl), prio_(prio), weight_(weight), target_(target) {} 145 virtual std::vector<byte> data() const; 146 int prio_; 147 int weight_; 148 std::string target_; 149 }; 150 151 struct DNSSoaRR : public DNSRR { DNSSoaRRDNSSoaRR152 DNSSoaRR(const std::string& name, int ttl, 153 const std::string& nsname, const std::string& rname, 154 int serial, int refresh, int retry, int expire, int minimum) 155 : DNSRR(name, T_SOA, ttl), nsname_(nsname), rname_(rname), 156 serial_(serial), refresh_(refresh), retry_(retry), 157 expire_(expire), minimum_(minimum) {} 158 virtual std::vector<byte> data() const; 159 std::string nsname_; 160 std::string rname_; 161 int serial_; 162 int refresh_; 163 int retry_; 164 int expire_; 165 int minimum_; 166 }; 167 168 struct DNSNaptrRR : public DNSRR { DNSNaptrRRDNSNaptrRR169 DNSNaptrRR(const std::string& name, int ttl, 170 int order, int pref, 171 const std::string& flags, 172 const std::string& service, 173 const std::string& regexp, 174 const std::string& replacement) 175 : DNSRR(name, T_NAPTR, ttl), order_(order), pref_(pref), 176 flags_(flags), service_(service), regexp_(regexp), replacement_(replacement) {} 177 virtual std::vector<byte> data() const; 178 int order_; 179 int pref_; 180 std::string flags_; 181 std::string service_; 182 std::string regexp_; 183 std::string replacement_; 184 }; 185 186 struct DNSOption { 187 int code_; 188 std::vector<byte> data_; 189 }; 190 191 struct DNSOptRR : public DNSRR { DNSOptRRDNSOptRR192 DNSOptRR(int extrcode, int udpsize) 193 : DNSRR("", T_OPT, static_cast<int>(udpsize), extrcode) {} 194 virtual std::vector<byte> data() const; 195 std::vector<DNSOption> opts_; 196 }; 197 198 struct DNSPacket { DNSPacketDNSPacket199 DNSPacket() 200 : qid_(0), response_(false), opcode_(O_QUERY), 201 aa_(false), tc_(false), rd_(false), ra_(false), 202 z_(false), ad_(false), cd_(false), rcode_(NOERROR) {} 203 // Convenience functions that take ownership of given pointers. add_questionDNSPacket204 DNSPacket& add_question(DNSQuestion *q) { 205 questions_.push_back(std::unique_ptr<DNSQuestion>(q)); 206 return *this; 207 } add_answerDNSPacket208 DNSPacket& add_answer(DNSRR *q) { 209 answers_.push_back(std::unique_ptr<DNSRR>(q)); 210 return *this; 211 } add_authDNSPacket212 DNSPacket& add_auth(DNSRR *q) { 213 auths_.push_back(std::unique_ptr<DNSRR>(q)); 214 return *this; 215 } add_additionalDNSPacket216 DNSPacket& add_additional(DNSRR *q) { 217 adds_.push_back(std::unique_ptr<DNSRR>(q)); 218 return *this; 219 } 220 // Chainable setters. set_qidDNSPacket221 DNSPacket& set_qid(int qid) { qid_ = qid; return *this; } 222 DNSPacket& set_response(bool v = true) { response_ = v; return *this; } 223 DNSPacket& set_aa(bool v = true) { aa_ = v; return *this; } 224 DNSPacket& set_tc(bool v = true) { tc_ = v; return *this; } 225 DNSPacket& set_rd(bool v = true) { rd_ = v; return *this; } 226 DNSPacket& set_ra(bool v = true) { ra_ = v; return *this; } 227 DNSPacket& set_z(bool v = true) { z_ = v; return *this; } 228 DNSPacket& set_ad(bool v = true) { ad_ = v; return *this; } 229 DNSPacket& set_cd(bool v = true) { cd_ = v; return *this; } set_rcodeDNSPacket230 DNSPacket& set_rcode(int rcode) { rcode_ = rcode; return *this; } 231 232 // Return the encoded packet. 233 std::vector<byte> data() const; 234 235 int qid_; 236 bool response_; 237 int opcode_; 238 bool aa_; 239 bool tc_; 240 bool rd_; 241 bool ra_; 242 bool z_; 243 bool ad_; 244 bool cd_; 245 int rcode_; 246 std::vector<std::unique_ptr<DNSQuestion>> questions_; 247 std::vector<std::unique_ptr<DNSRR>> answers_; 248 std::vector<std::unique_ptr<DNSRR>> auths_; 249 std::vector<std::unique_ptr<DNSRR>> adds_; 250 }; 251 252 } // namespace ares 253 254 #endif 255