• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* MIT License
2  *
3  * Copyright (c) The c-ares project and its contributors
4  *
5  * Permission is hereby granted, free of charge, to any person obtaining a copy
6  * of this software and associated documentation files (the "Software"), to deal
7  * in the Software without restriction, including without limitation the rights
8  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9  * copies of the Software, and to permit persons to whom the Software is
10  * furnished to do so, subject to the following conditions:
11  *
12  * The above copyright notice and this permission notice (including the next
13  * paragraph) shall be included in all copies or substantial portions of the
14  * Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22  * SOFTWARE.
23  *
24  * SPDX-License-Identifier: MIT
25  */
26 #ifndef DNS_PROTO_H
27 #define DNS_PROTO_H
28 // Utilities for processing DNS packet contents
29 
30 #include "ares_setup.h"
31 #include "ares.h"
32 // Include ares internal file for DNS protocol constants
33 #include "ares_nameser.h"
34 
35 #include <memory>
36 #include <string>
37 #include <vector>
38 
39 extern "C" void arestest_strtolower(char *dest, const char *src,
40                                     size_t dest_size);
41 
42 namespace ares {
43 
44 typedef unsigned char byte;
45 
46 std::string           HexDump(std::vector<byte> data);
47 std::string           HexDump(const byte *data, int len);
48 std::string           HexDump(const char *data, int len);
49 
50 std::string           StatusToString(int status);
51 std::string           RcodeToString(int rcode);
52 std::string           RRTypeToString(int rrtype);
53 std::string           ClassToString(int qclass);
54 std::string           AddressToString(const void *addr, int len);
55 
56 const ares_dns_rr_t  *fetch_rr_opt(const ares_dns_record_t *rec);
57 
58 // Convert DNS protocol data to strings.
59 // Note that these functions are not defensive; they assume
60 // a validly formatted input, and so should not be used on
61 // externally-determined inputs.
62 std::string           PacketToString(const std::vector<byte> &packet);
63 std::string QuestionToString(const std::vector<byte> &packet, const byte **data,
64                              int *len);
65 std::string RRToString(const std::vector<byte> &packet, const byte **data,
66                        int *len);
67 
68 
69 // Manipulate DNS protocol data.
70 void        PushInt32(std::vector<byte> *data, int value);
71 void        PushInt16(std::vector<byte> *data, int value);
72 std::vector<byte> EncodeString(const std::string &name);
73 
74 struct DNSQuestion {
DNSQuestionDNSQuestion75   DNSQuestion(const std::string &name, int rrtype, int qclass)
76     : name_(name), rrtype_(rrtype), qclass_(qclass)
77   {
78   }
79 
DNSQuestionDNSQuestion80   DNSQuestion(const std::string &name, int rrtype)
81     : name_(name), rrtype_(rrtype), qclass_(C_IN)
82   {
83   }
84 
~DNSQuestionDNSQuestion85   virtual ~DNSQuestion()
86   {
87   }
88 
89   virtual std::vector<byte> data(const char              *request_name,
90                                  const ares_dns_record_t *dnsrec) const;
91 
dataDNSQuestion92   virtual std::vector<byte> data(const ares_dns_record_t *dnsrec) const
93   {
94     return data(nullptr, dnsrec);
95   }
96 
dataDNSQuestion97   virtual std::vector<byte> data() const
98   {
99     return data(nullptr, nullptr);
100   }
101 
102   std::string name_;
103   int         rrtype_;
104   int         qclass_;
105 };
106 
107 struct DNSRR : public DNSQuestion {
DNSRRDNSRR108   DNSRR(const std::string &name, int rrtype, int qclass, int ttl)
109     : DNSQuestion(name, rrtype, qclass), ttl_(ttl)
110   {
111   }
112 
DNSRRDNSRR113   DNSRR(const std::string &name, int rrtype, int ttl)
114     : DNSQuestion(name, rrtype), ttl_(ttl)
115   {
116   }
117 
~DNSRRDNSRR118   virtual ~DNSRR()
119   {
120   }
121 
122   virtual std::vector<byte> data(const ares_dns_record_t *dnsrec) const = 0;
123   int                       ttl_;
124 };
125 
126 struct DNSAddressRR : public DNSRR {
DNSAddressRRDNSAddressRR127   DNSAddressRR(const std::string &name, int rrtype, int ttl, const byte *addr,
128                int addrlen)
129     : DNSRR(name, rrtype, ttl), addr_(addr, addr + addrlen)
130   {
131   }
132 
DNSAddressRRDNSAddressRR133   DNSAddressRR(const std::string &name, int rrtype, int ttl,
134                const std::vector<byte> &addr)
135     : DNSRR(name, rrtype, ttl), addr_(addr)
136   {
137   }
138 
139   virtual std::vector<byte> data(const ares_dns_record_t *dnsrec) const;
140   std::vector<byte>         addr_;
141 };
142 
143 struct DNSARR : public DNSAddressRR {
DNSARRDNSARR144   DNSARR(const std::string &name, int ttl, const byte *addr, int addrlen)
145     : DNSAddressRR(name, T_A, ttl, addr, addrlen)
146   {
147   }
148 
DNSARRDNSARR149   DNSARR(const std::string &name, int ttl, const std::vector<byte> &addr)
150     : DNSAddressRR(name, T_A, ttl, addr)
151   {
152   }
153 };
154 
155 struct DNSAaaaRR : public DNSAddressRR {
DNSAaaaRRDNSAaaaRR156   DNSAaaaRR(const std::string &name, int ttl, const byte *addr, int addrlen)
157     : DNSAddressRR(name, T_AAAA, ttl, addr, addrlen)
158   {
159   }
160 
DNSAaaaRRDNSAaaaRR161   DNSAaaaRR(const std::string &name, int ttl, const std::vector<byte> &addr)
162     : DNSAddressRR(name, T_AAAA, ttl, addr)
163   {
164   }
165 };
166 
167 struct DNSSingleNameRR : public DNSRR {
DNSSingleNameRRDNSSingleNameRR168   DNSSingleNameRR(const std::string &name, int rrtype, int ttl,
169                   const std::string &other)
170     : DNSRR(name, rrtype, ttl), other_(other)
171   {
172   }
173 
174   virtual std::vector<byte> data(const ares_dns_record_t *dnsrec) const;
175   std::string               other_;
176 };
177 
178 struct DNSCnameRR : public DNSSingleNameRR {
DNSCnameRRDNSCnameRR179   DNSCnameRR(const std::string &name, int ttl, const std::string &other)
180     : DNSSingleNameRR(name, T_CNAME, ttl, other)
181   {
182   }
183 };
184 
185 struct DNSNsRR : public DNSSingleNameRR {
DNSNsRRDNSNsRR186   DNSNsRR(const std::string &name, int ttl, const std::string &other)
187     : DNSSingleNameRR(name, T_NS, ttl, other)
188   {
189   }
190 };
191 
192 struct DNSPtrRR : public DNSSingleNameRR {
DNSPtrRRDNSPtrRR193   DNSPtrRR(const std::string &name, int ttl, const std::string &other)
194     : DNSSingleNameRR(name, T_PTR, ttl, other)
195   {
196   }
197 };
198 
199 struct DNSTxtRR : public DNSRR {
DNSTxtRRDNSTxtRR200   DNSTxtRR(const std::string &name, int ttl,
201            const std::vector<std::string> &txt)
202     : DNSRR(name, T_TXT, ttl), txt_(txt)
203   {
204   }
205 
206   virtual std::vector<byte> data(const ares_dns_record_t *dnsrec) const;
207   std::vector<std::string>  txt_;
208 };
209 
210 struct DNSMxRR : public DNSRR {
DNSMxRRDNSMxRR211   DNSMxRR(const std::string &name, int ttl, int pref, const std::string &other)
212     : DNSRR(name, T_MX, ttl), pref_(pref), other_(other)
213   {
214   }
215 
216   virtual std::vector<byte> data(const ares_dns_record_t *dnsrec) const;
217   int                       pref_;
218   std::string               other_;
219 };
220 
221 struct DNSSrvRR : public DNSRR {
DNSSrvRRDNSSrvRR222   DNSSrvRR(const std::string &name, int ttl, int prio, int weight, int port,
223            const std::string &target)
224     : DNSRR(name, T_SRV, ttl), prio_(prio), weight_(weight), port_(port),
225       target_(target)
226   {
227   }
228 
229   virtual std::vector<byte> data(const ares_dns_record_t *dnsrec) const;
230   int                       prio_;
231   int                       weight_;
232   int                       port_;
233   std::string               target_;
234 };
235 
236 struct DNSUriRR : public DNSRR {
DNSUriRRDNSUriRR237   DNSUriRR(const std::string &name, int ttl, int prio, int weight,
238            const std::string &target)
239     : DNSRR(name, T_URI, ttl), prio_(prio), weight_(weight), target_(target)
240   {
241   }
242 
243   virtual std::vector<byte> data(const ares_dns_record_t *dnsrec) const;
244   int                       prio_;
245   int                       weight_;
246   std::string               target_;
247 };
248 
249 struct DNSSoaRR : public DNSRR {
DNSSoaRRDNSSoaRR250   DNSSoaRR(const std::string &name, int ttl, const std::string &nsname,
251            const std::string &rname, int serial, int refresh, int retry,
252            int expire, int minimum)
253     : DNSRR(name, T_SOA, ttl), nsname_(nsname), rname_(rname), serial_(serial),
254       refresh_(refresh), retry_(retry), expire_(expire), minimum_(minimum)
255   {
256   }
257 
258   virtual std::vector<byte> data(const ares_dns_record_t *dnsrec) const;
259   std::string               nsname_;
260   std::string               rname_;
261   int                       serial_;
262   int                       refresh_;
263   int                       retry_;
264   int                       expire_;
265   int                       minimum_;
266 };
267 
268 struct DNSNaptrRR : public DNSRR {
DNSNaptrRRDNSNaptrRR269   DNSNaptrRR(const std::string &name, int ttl, int order, int pref,
270              const std::string &flags, const std::string &service,
271              const std::string &regexp, const std::string &replacement)
272     : DNSRR(name, T_NAPTR, ttl), order_(order), pref_(pref), flags_(flags),
273       service_(service), regexp_(regexp), replacement_(replacement)
274   {
275   }
276 
277   virtual std::vector<byte> data(const ares_dns_record_t *dnsrec) const;
278   int                       order_;
279   int                       pref_;
280   std::string               flags_;
281   std::string               service_;
282   std::string               regexp_;
283   std::string               replacement_;
284 };
285 
286 struct DNSOption {
287   int               code_;
288   std::vector<byte> data_;
289 };
290 
291 struct DNSOptRR : public DNSRR {
DNSOptRRDNSOptRR292   DNSOptRR(unsigned char extrcode, unsigned char version, unsigned short flags,
293            int udpsize, std::vector<byte> client_cookie,
294            std::vector<byte> server_cookie, bool expect_server_cookie)
295     : DNSRR("", T_OPT, static_cast<int>(udpsize),
296             ((int)extrcode) << 24 | ((int)version) << 16 |
297               ((int)flags) /* ttl */)
298   {
299     client_cookie_        = client_cookie;
300     server_cookie_        = server_cookie;
301     expect_server_cookie_ = expect_server_cookie;
302   }
303 
304   virtual std::vector<byte> data(const ares_dns_record_t *dnsrec) const;
305   std::vector<DNSOption>    opts_;
306   std::vector<byte>         client_cookie_;
307   std::vector<byte>         server_cookie_;
308   bool                      expect_server_cookie_;
309 };
310 
311 struct DNSPacket {
DNSPacketDNSPacket312   DNSPacket()
313     : qid_(0), response_(false), opcode_(O_QUERY), aa_(false), tc_(false),
314       rd_(false), ra_(false), z_(false), ad_(false), cd_(false), rcode_(NOERROR)
315   {
316   }
317 
318   // Convenience functions that take ownership of given pointers.
add_questionDNSPacket319   DNSPacket &add_question(DNSQuestion *q)
320   {
321     questions_.push_back(std::unique_ptr<DNSQuestion>(q));
322     return *this;
323   }
324 
add_answerDNSPacket325   DNSPacket &add_answer(DNSRR *q)
326   {
327     answers_.push_back(std::unique_ptr<DNSRR>(q));
328     return *this;
329   }
330 
add_authDNSPacket331   DNSPacket &add_auth(DNSRR *q)
332   {
333     auths_.push_back(std::unique_ptr<DNSRR>(q));
334     return *this;
335   }
336 
add_additionalDNSPacket337   DNSPacket &add_additional(DNSRR *q)
338   {
339     adds_.push_back(std::unique_ptr<DNSRR>(q));
340     return *this;
341   }
342 
343   // Chainable setters.
set_qidDNSPacket344   DNSPacket &set_qid(int qid)
345   {
346     qid_ = qid;
347     return *this;
348   }
349 
350   DNSPacket &set_response(bool v = true)
351   {
352     response_ = v;
353     return *this;
354   }
355 
356   DNSPacket &set_aa(bool v = true)
357   {
358     aa_ = v;
359     return *this;
360   }
361 
362   DNSPacket &set_tc(bool v = true)
363   {
364     tc_ = v;
365     return *this;
366   }
367 
368   DNSPacket &set_rd(bool v = true)
369   {
370     rd_ = v;
371     return *this;
372   }
373 
374   DNSPacket &set_ra(bool v = true)
375   {
376     ra_ = v;
377     return *this;
378   }
379 
380   DNSPacket &set_z(bool v = true)
381   {
382     z_ = v;
383     return *this;
384   }
385 
386   DNSPacket &set_ad(bool v = true)
387   {
388     ad_ = v;
389     return *this;
390   }
391 
392   DNSPacket &set_cd(bool v = true)
393   {
394     cd_ = v;
395     return *this;
396   }
397 
set_rcodeDNSPacket398   DNSPacket &set_rcode(int rcode)
399   {
400     rcode_ = rcode;
401     return *this;
402   }
403 
404   // Return the encoded packet.
405   std::vector<byte> data(const char              *request_name,
406                          const ares_dns_record_t *dnsrec) const;
407 
dataDNSPacket408   std::vector<byte> data() const
409   {
410     return data(nullptr, nullptr);
411   }
412 
413   int                                       qid_;
414   bool                                      response_;
415   int                                       opcode_;
416   bool                                      aa_;
417   bool                                      tc_;
418   bool                                      rd_;
419   bool                                      ra_;
420   bool                                      z_;
421   bool                                      ad_;
422   bool                                      cd_;
423   int                                       rcode_;
424   std::vector<std::unique_ptr<DNSQuestion>> questions_;
425   std::vector<std::unique_ptr<DNSRR>>       answers_;
426   std::vector<std::unique_ptr<DNSRR>>       auths_;
427   std::vector<std::unique_ptr<DNSRR>>       adds_;
428 };
429 
430 }  // namespace ares
431 
432 #endif
433