• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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