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