1 // -*- mode: c++ -*- 2 #ifndef DNS_PROTO_H 3 #define DNS_PROTO_H 4 // Utilities for processing DNS packet contents 5 6 // Include ares internal file for DNS protocol constants 7 #include "nameser.h" 8 9 #include <memory> 10 #include <string> 11 #include <vector> 12 13 namespace ares { 14 15 typedef unsigned char byte; 16 17 std::string HexDump(std::vector<byte> data); 18 std::string HexDump(const byte *data, int len); 19 std::string HexDump(const char *data, int len); 20 21 std::string StatusToString(int status); 22 std::string RcodeToString(int rcode); 23 std::string RRTypeToString(int rrtype); 24 std::string ClassToString(int qclass); 25 std::string AddressToString(const void* addr, int len); 26 27 // Convert DNS protocol data to strings. 28 // Note that these functions are not defensive; they assume 29 // a validly formatted input, and so should not be used on 30 // externally-determined inputs. 31 std::string PacketToString(const std::vector<byte>& packet); 32 std::string QuestionToString(const std::vector<byte>& packet, 33 const byte** data, int* len); 34 std::string RRToString(const std::vector<byte>& packet, 35 const byte** data, int* len); 36 37 38 // Manipulate DNS protocol data. 39 void PushInt32(std::vector<byte>* data, int value); 40 void PushInt16(std::vector<byte>* data, int value); 41 std::vector<byte> EncodeString(const std::string& name); 42 43 struct DNSQuestion { DNSQuestionDNSQuestion44 DNSQuestion(const std::string& name, ns_type rrtype, ns_class qclass) 45 : name_(name), rrtype_(rrtype), qclass_(qclass) {} DNSQuestionDNSQuestion46 DNSQuestion(const std::string& name, ns_type rrtype) 47 : name_(name), rrtype_(rrtype), qclass_(ns_c_in) {} ~DNSQuestionDNSQuestion48 virtual ~DNSQuestion() {} 49 virtual std::vector<byte> data() const; 50 std::string name_; 51 ns_type rrtype_; 52 ns_class qclass_; 53 }; 54 55 struct DNSRR : public DNSQuestion { DNSRRDNSRR56 DNSRR(const std::string& name, ns_type rrtype, ns_class qclass, int ttl) 57 : DNSQuestion(name, rrtype, qclass), ttl_(ttl) {} DNSRRDNSRR58 DNSRR(const std::string& name, ns_type rrtype, int ttl) 59 : DNSQuestion(name, rrtype), ttl_(ttl) {} ~DNSRRDNSRR60 virtual ~DNSRR() {} 61 virtual std::vector<byte> data() const = 0; 62 int ttl_; 63 }; 64 65 struct DNSAddressRR : public DNSRR { DNSAddressRRDNSAddressRR66 DNSAddressRR(const std::string& name, ns_type rrtype, int ttl, 67 const byte* addr, int addrlen) 68 : DNSRR(name, rrtype, ttl), addr_(addr, addr + addrlen) {} DNSAddressRRDNSAddressRR69 DNSAddressRR(const std::string& name, ns_type rrtype, int ttl, 70 const std::vector<byte>& addr) 71 : DNSRR(name, rrtype, ttl), addr_(addr) {} 72 virtual std::vector<byte> data() const; 73 std::vector<byte> addr_; 74 }; 75 76 struct DNSARR : public DNSAddressRR { DNSARRDNSARR77 DNSARR(const std::string& name, int ttl, const byte* addr, int addrlen) 78 : DNSAddressRR(name, ns_t_a, ttl, addr, addrlen) {} DNSARRDNSARR79 DNSARR(const std::string& name, int ttl, const std::vector<byte>& addr) 80 : DNSAddressRR(name, ns_t_a, ttl, addr) {} 81 }; 82 83 struct DNSAaaaRR : public DNSAddressRR { DNSAaaaRRDNSAaaaRR84 DNSAaaaRR(const std::string& name, int ttl, const byte* addr, int addrlen) 85 : DNSAddressRR(name, ns_t_aaaa, ttl, addr, addrlen) {} DNSAaaaRRDNSAaaaRR86 DNSAaaaRR(const std::string& name, int ttl, const std::vector<byte>& addr) 87 : DNSAddressRR(name, ns_t_aaaa, ttl, addr) {} 88 }; 89 90 struct DNSSingleNameRR : public DNSRR { DNSSingleNameRRDNSSingleNameRR91 DNSSingleNameRR(const std::string& name, ns_type rrtype, int ttl, 92 const std::string& other) 93 : DNSRR(name, rrtype, ttl), other_(other) {} 94 virtual std::vector<byte> data() const; 95 std::string other_; 96 }; 97 98 struct DNSCnameRR : public DNSSingleNameRR { DNSCnameRRDNSCnameRR99 DNSCnameRR(const std::string& name, int ttl, const std::string& other) 100 : DNSSingleNameRR(name, ns_t_cname, ttl, other) {} 101 }; 102 103 struct DNSNsRR : public DNSSingleNameRR { DNSNsRRDNSNsRR104 DNSNsRR(const std::string& name, int ttl, const std::string& other) 105 : DNSSingleNameRR(name, ns_t_ns, ttl, other) {} 106 }; 107 108 struct DNSPtrRR : public DNSSingleNameRR { DNSPtrRRDNSPtrRR109 DNSPtrRR(const std::string& name, int ttl, const std::string& other) 110 : DNSSingleNameRR(name, ns_t_ptr, ttl, other) {} 111 }; 112 113 struct DNSTxtRR : public DNSRR { DNSTxtRRDNSTxtRR114 DNSTxtRR(const std::string& name, int ttl, const std::vector<std::string>& txt) 115 : DNSRR(name, ns_t_txt, ttl), txt_(txt) {} 116 virtual std::vector<byte> data() const; 117 std::vector<std::string> txt_; 118 }; 119 120 struct DNSMxRR : public DNSRR { DNSMxRRDNSMxRR121 DNSMxRR(const std::string& name, int ttl, int pref, const std::string& other) 122 : DNSRR(name, ns_t_mx, ttl), pref_(pref), other_(other) {} 123 virtual std::vector<byte> data() const; 124 int pref_; 125 std::string other_; 126 }; 127 128 struct DNSSrvRR : public DNSRR { DNSSrvRRDNSSrvRR129 DNSSrvRR(const std::string& name, int ttl, 130 int prio, int weight, int port, const std::string& target) 131 : DNSRR(name, ns_t_srv, ttl), prio_(prio), weight_(weight), port_(port), target_(target) {} 132 virtual std::vector<byte> data() const; 133 int prio_; 134 int weight_; 135 int port_; 136 std::string target_; 137 }; 138 139 struct DNSSoaRR : public DNSRR { DNSSoaRRDNSSoaRR140 DNSSoaRR(const std::string& name, int ttl, 141 const std::string& nsname, const std::string& rname, 142 int serial, int refresh, int retry, int expire, int minimum) 143 : DNSRR(name, ns_t_soa, ttl), nsname_(nsname), rname_(rname), 144 serial_(serial), refresh_(refresh), retry_(retry), 145 expire_(expire), minimum_(minimum) {} 146 virtual std::vector<byte> data() const; 147 std::string nsname_; 148 std::string rname_; 149 int serial_; 150 int refresh_; 151 int retry_; 152 int expire_; 153 int minimum_; 154 }; 155 156 struct DNSNaptrRR : public DNSRR { DNSNaptrRRDNSNaptrRR157 DNSNaptrRR(const std::string& name, int ttl, 158 int order, int pref, 159 const std::string& flags, 160 const std::string& service, 161 const std::string& regexp, 162 const std::string& replacement) 163 : DNSRR(name, ns_t_naptr, ttl), order_(order), pref_(pref), 164 flags_(flags), service_(service), regexp_(regexp), replacement_(replacement) {} 165 virtual std::vector<byte> data() const; 166 int order_; 167 int pref_; 168 std::string flags_; 169 std::string service_; 170 std::string regexp_; 171 std::string replacement_; 172 }; 173 174 struct DNSOption { 175 int code_; 176 std::vector<byte> data_; 177 }; 178 179 struct DNSOptRR : public DNSRR { DNSOptRRDNSOptRR180 DNSOptRR(int extrcode, int udpsize) 181 : DNSRR("", ns_t_opt, static_cast<ns_class>(udpsize), extrcode) {} 182 virtual std::vector<byte> data() const; 183 std::vector<DNSOption> opts_; 184 }; 185 186 struct DNSPacket { DNSPacketDNSPacket187 DNSPacket() 188 : qid_(0), response_(false), opcode_(ns_o_query), 189 aa_(false), tc_(false), rd_(false), ra_(false), 190 z_(false), ad_(false), cd_(false), rcode_(ns_r_noerror) {} 191 // Convenience functions that take ownership of given pointers. add_questionDNSPacket192 DNSPacket& add_question(DNSQuestion *q) { 193 questions_.push_back(std::unique_ptr<DNSQuestion>(q)); 194 return *this; 195 } add_answerDNSPacket196 DNSPacket& add_answer(DNSRR *q) { 197 answers_.push_back(std::unique_ptr<DNSRR>(q)); 198 return *this; 199 } add_authDNSPacket200 DNSPacket& add_auth(DNSRR *q) { 201 auths_.push_back(std::unique_ptr<DNSRR>(q)); 202 return *this; 203 } add_additionalDNSPacket204 DNSPacket& add_additional(DNSRR *q) { 205 adds_.push_back(std::unique_ptr<DNSRR>(q)); 206 return *this; 207 } 208 // Chainable setters. set_qidDNSPacket209 DNSPacket& set_qid(int qid) { qid_ = qid; return *this; } 210 DNSPacket& set_response(bool v = true) { response_ = v; return *this; } 211 DNSPacket& set_aa(bool v = true) { aa_ = v; return *this; } 212 DNSPacket& set_tc(bool v = true) { tc_ = v; return *this; } 213 DNSPacket& set_rd(bool v = true) { rd_ = v; return *this; } 214 DNSPacket& set_ra(bool v = true) { ra_ = v; return *this; } 215 DNSPacket& set_z(bool v = true) { z_ = v; return *this; } 216 DNSPacket& set_ad(bool v = true) { ad_ = v; return *this; } 217 DNSPacket& set_cd(bool v = true) { cd_ = v; return *this; } set_rcodeDNSPacket218 DNSPacket& set_rcode(ns_rcode rcode) { rcode_ = rcode; return *this; } 219 220 // Return the encoded packet. 221 std::vector<byte> data() const; 222 223 int qid_; 224 bool response_; 225 ns_opcode opcode_; 226 bool aa_; 227 bool tc_; 228 bool rd_; 229 bool ra_; 230 bool z_; 231 bool ad_; 232 bool cd_; 233 ns_rcode rcode_; 234 std::vector<std::unique_ptr<DNSQuestion>> questions_; 235 std::vector<std::unique_ptr<DNSRR>> answers_; 236 std::vector<std::unique_ptr<DNSRR>> auths_; 237 std::vector<std::unique_ptr<DNSRR>> adds_; 238 }; 239 240 } // namespace ares 241 242 #endif 243