libtins  4.0
dns.h
1 /*
2  * Copyright (c) 2017, Matias Fontanini
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are
7  * met:
8  *
9  * * Redistributions of source code must retain the above copyright
10  * notice, this list of conditions and the following disclaimer.
11  * * Redistributions in binary form must reproduce the above
12  * copyright notice, this list of conditions and the following disclaimer
13  * in the documentation and/or other materials provided with the
14  * distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27  *
28  */
29 
30 #ifndef TINS_DNS_H
31 #define TINS_DNS_H
32 
33 #include <stdint.h>
34 #include <vector>
35 #include <cstring>
36 #include <string>
37 #include <map>
38 #include <tins/macros.h>
39 #include <tins/pdu.h>
40 #include <tins/endianness.h>
41 
42 // Undefining some macros that conflict with some symbols here.
43 // Eventually, the conflicting names will be removed, but until then
44 // this is the best we can do.
45 // - IN is defined by winsock2.h
46 // - CERT is defined by openssl
47 #undef IN
48 #undef CERT
49 
50 namespace Tins {
51 namespace Memory {
52 
53 class InputMemoryStream;
54 
55 } // Memory
56 
57 class IPv4Address;
58 class IPv6Address;
59 
85 class TINS_API DNS : public PDU {
86 public:
90  static const PDU::PDUType pdu_flag = PDU::DNS;
91 
95  enum QRType {
96  QUERY = 0,
97  RESPONSE = 1
98  };
99 
103  enum QueryType {
104  A = 1,
105  NS,
106  MD,
107  MF,
108  CNAME,
109  SOA,
110  MB,
111  MG,
112  MR,
113  NULL_R,
114  WKS,
115  PTR,
116  HINFO,
117  MINFO,
118  MX,
119  TXT,
120  RP,
121  AFSDB,
122  X25,
123  ISDN,
124  RT,
125  NSAP,
126  NSAP_PTR,
127  SIG,
128  KEY,
129  PX,
130  GPOS,
131  AAAA,
132  LOC,
133  NXT,
134  EID,
135  NIMLOC,
136  SRV,
137  ATMA,
138  NAPTR,
139  KX,
140  CERTIFICATE,
141  A6,
142  DNAM,
143  SINK,
144  OPT,
145  APL,
146  DS,
147  SSHFP,
148  IPSECKEY,
149  RRSIG,
150  NSEC,
151  DNSKEY,
152  DHCID,
153  NSEC3,
154  NSEC3PARAM,
155  CERT = CERTIFICATE
156  };
157 
158  enum QueryClass {
159  INTERNET = 1,
160  CHAOS = 3,
161  HESIOD = 4,
165  IN = INTERNET,
166  CH = CHAOS,
167  HS = HESIOD,
171  ANY = 255
172  };
173 
177  class query {
178  public:
186  #if TINS_IS_CXX11
187  query(std::string nm, QueryType tp, QueryClass cl)
188  : name_(std::move(nm)), type_(tp), qclass_(cl) {}
189  #else
190  query(const std::string& nm, QueryType tp, QueryClass cl)
191  : name_(nm), type_(tp), qclass_(cl) {}
192  #endif
193 
197  query() : type_(), qclass_() {}
198 
204  void dname(const std::string& nm) {
205  name_ = nm;
206  }
207 
214  type_ = tp;
215  }
216 
225  TINS_DEPRECATED(void type(QueryType tp)) {
226  type_ = tp;
227  }
228 
234  void query_class(QueryClass cl) {
235  qclass_ = cl;
236  }
237 
241  const std::string& dname() const {
242  return name_;
243  }
244 
249  return type_;
250  }
251 
260  TINS_DEPRECATED(QueryType type() const) {
261  return type_;
262  }
263 
267  QueryClass query_class() const {
268  return qclass_;
269  }
270  private:
271  std::string name_;
272  QueryType type_;
273  QueryClass qclass_;
274  };
275 
276  class resource;
277 
281  class soa_record {
282  public:
286  soa_record();
287 
293 
299  soa_record(const uint8_t* buffer, uint32_t total_sz);
300 
312  soa_record(const std::string& mname,
313  const std::string& rname,
314  uint32_t serial,
315  uint32_t refresh,
316  uint32_t retry,
317  uint32_t expire,
318  uint32_t minimum_ttl);
319 
327  const std::string& mname() const {
328  return mname_;
329  }
330 
338  const std::string& rname() const {
339  return rname_;
340  }
341 
346  uint32_t serial() const {
347  return serial_;
348  }
349 
354  uint32_t refresh() const {
355  return refresh_;
356  }
357 
362  uint32_t retry() const {
363  return retry_;
364  }
365 
370  uint32_t expire() const {
371  return expire_;
372  }
373 
378  uint32_t minimum_ttl() const {
379  return minimum_ttl_;
380  }
381 
386  void mname(const std::string& value);
387 
392  void rname(const std::string& value);
393 
398  void serial(uint32_t value);
399 
404  void refresh(uint32_t value);
405 
410  void retry(uint32_t value);
411 
416  void expire(uint32_t value);
417 
422  void minimum_ttl(uint32_t value);
423 
428  PDU::serialization_type serialize() const;
429  private:
430  void init(const uint8_t* buffer, uint32_t total_sz);
431 
432  std::string mname_;
433  std::string rname_;
434  uint32_t serial_;
435  uint32_t refresh_;
436  uint32_t retry_;
437  uint32_t expire_;
438  uint32_t minimum_ttl_;
439  };
440 
444  class resource {
445  public:
456  #if TINS_IS_CXX11
457  resource(std::string dname,
458  std::string data,
459  uint16_t type,
460  uint16_t rclass,
461  uint32_t ttl,
462  uint16_t preference = 0)
463  : dname_(std::move(dname)), data_(std::move(data)), type_(type),
464  qclass_(rclass), ttl_(ttl), preference_(preference) {}
465  #else
466  resource(const std::string& dname,
467  const std::string& data,
468  uint16_t type,
469  uint16_t rclass,
470  uint32_t ttl,
471  uint16_t preference = 0)
472  : dname_(dname), data_(data), type_(type), qclass_(rclass),
473  ttl_(ttl), preference_(preference) {}
474  #endif
475 
476  resource() : type_(), qclass_(), ttl_(), preference_() {}
477 
484  const std::string& dname() const {
485  return dname_;
486  }
487 
491  const std::string& data() const {
492  return data_;
493  }
494 
498  uint16_t query_type() const {
499  return type_;
500  }
501 
510  TINS_DEPRECATED(uint16_t type() const) {
511  return type_;
512  }
513 
517  uint16_t query_class() const {
518  return qclass_;
519  }
520 
524  uint32_t ttl() const {
525  return ttl_;
526  }
527 
533  uint16_t preference() const {
534  return preference_;
535  }
536 
540  void dname(const std::string& data) {
541  dname_ = data;
542  }
543 
556  void data(const std::string& data) {
557  data_ = data;
558  }
559 
564  void data(const soa_record& data) {
565  serialization_type buffer = data.serialize();
566  data_.assign(buffer.begin(), buffer.end());
567  }
568 
572  void query_type(uint16_t data) {
573  type_ = data;
574  }
575 
584  TINS_DEPRECATED(void type(uint16_t data)) {
585  type_ = data;
586  }
587 
591  void query_class(uint16_t data) {
592  qclass_ = data;
593  }
594 
598  void ttl(uint32_t data) {
599  ttl_ = data;
600  }
601 
607  void preference(uint16_t data) {
608  preference_ = data;
609  }
610  private:
611  std::string dname_, data_;
612  uint16_t type_, qclass_;
613  uint32_t ttl_;
614  uint16_t preference_;
615  };
616 
617  TINS_DEPRECATED(typedef query Query);
618  TINS_DEPRECATED(typedef resource Resource);
619 
620  typedef std::vector<query> queries_type;
621  typedef std::vector<resource> resources_type;
622  typedef IPv4Address address_type;
624 
631  static metadata extract_metadata(const uint8_t *buffer, uint32_t total_sz);
632 
638  DNS();
639 
650  DNS(const uint8_t* buffer, uint32_t total_sz);
651 
652  // Getters
653 
659  uint16_t id() const {
660  return Endian::be_to_host(header_.id);
661  }
662 
669  QRType type() const {
670  return static_cast<QRType>(header_.qr);
671  }
672 
678  uint8_t opcode() const {
679  return header_.opcode;
680  }
681 
688  uint8_t authoritative_answer() const {
689  return header_.aa;
690  }
691 
697  uint8_t truncated() const {
698  return header_.tc;
699  }
700 
707  uint8_t recursion_desired() const {
708  return header_.rd;
709  }
710 
717  uint8_t recursion_available() const {
718  return header_.ra;
719  }
720 
726  uint8_t z() const {
727  return header_.z;
728  }
729 
736  uint8_t authenticated_data() const {
737  return header_.ad;
738  }
739 
746  uint8_t checking_disabled() const {
747  return header_.cd;
748  }
749 
755  uint8_t rcode() const {
756  return header_.rcode;
757  }
758 
764  uint16_t questions_count() const {
765  return Endian::be_to_host(header_.questions);
766  }
767 
773  uint16_t answers_count() const {
774  return Endian::be_to_host(header_.answers);
775  }
776 
782  uint16_t authority_count() const {
783  return Endian::be_to_host(header_.authority);
784  }
785 
791  uint16_t additional_count() const {
792  return Endian::be_to_host(header_.additional);
793  }
794 
800  PDUType pdu_type() const {
801  return pdu_flag;
802  }
803 
807  uint32_t header_size() const;
808 
809  // Setters
810 
816  void id(uint16_t new_id);
817 
823  void type(QRType new_qr);
824 
830  void opcode(uint8_t new_opcode);
831 
838  void authoritative_answer(uint8_t new_aa);
839 
846  void truncated(uint8_t new_tc);
847 
854  void recursion_desired(uint8_t new_rd);
855 
862  void recursion_available(uint8_t new_ra);
863 
869  void z(uint8_t new_z);
870 
877  void authenticated_data(uint8_t new_ad);
878 
884  void checking_disabled(uint8_t new_cd);
885 
891  void rcode(uint8_t new_rcode);
892 
893  // Methods
894 
900  void add_query(const query& query);
901 
907  void add_answer(const resource& resource);
908 
914  void add_authority(const resource& resource);
915 
921  void add_additional(const resource& resource);
922 
928  queries_type queries() const;
929 
935  resources_type answers() const;
936 
942  resources_type authority() const;
943 
949  resources_type additional() const;
950 
966  static std::string encode_domain_name(const std::string& domain_name);
967 
980  static std::string decode_domain_name(const std::string& domain_name);
981 
989  bool matches_response(const uint8_t* ptr, uint32_t total_sz) const;
990 
994  DNS* clone() const {
995  return new DNS(*this);
996  }
997 private:
998  friend class soa_record;
999 
1000  TINS_BEGIN_PACK
1001  struct dns_header {
1002  uint16_t id;
1003  #if TINS_IS_LITTLE_ENDIAN
1004  uint16_t
1005  rd:1,
1006  tc:1,
1007  aa:1,
1008  opcode:4,
1009  qr:1,
1010  rcode:4,
1011  cd:1,
1012  ad:1,
1013  z:1,
1014  ra:1;
1015  #elif TINS_IS_BIG_ENDIAN
1016  uint16_t
1017  qr:1,
1018  opcode:4,
1019  aa:1,
1020  tc:1,
1021  rd:1,
1022  ra:1,
1023  z:1,
1024  ad:1,
1025  cd:1,
1026  rcode:4;
1027  #endif
1028  uint16_t questions, answers,
1029  authority, additional;
1030  } TINS_END_PACK;
1031 
1032  typedef std::vector<std::pair<uint32_t*, uint32_t> > sections_type;
1033 
1034  uint32_t compose_name(const uint8_t* ptr, char* out_ptr) const;
1035  void convert_records(const uint8_t* ptr,
1036  const uint8_t* end,
1037  resources_type& res) const;
1038  void skip_to_section_end(Memory::InputMemoryStream& stream,
1039  const uint32_t num_records) const;
1040  void skip_to_dname_end(Memory::InputMemoryStream& stream) const;
1041  void update_records(uint32_t& section_start,
1042  uint32_t num_records,
1043  uint32_t threshold,
1044  uint32_t offset);
1045  uint8_t* update_dname(uint8_t* ptr, uint32_t threshold, uint32_t offset);
1046  static void inline_convert_v4(uint32_t value, char* output);
1047  static bool contains_dname(uint16_t type);
1048  void write_serialization(uint8_t* buffer, uint32_t total_sz);
1049  void add_record(const resource& resource, const sections_type& sections);
1050 
1051  dns_header header_;
1052  byte_array records_data_;
1053  uint32_t answers_idx_, authority_idx_, additional_idx_;
1054 };
1055 
1056 } // Tins
1057 
1058 #endif // TINS_DNS_H
uint8_t authoritative_answer() const
Setter for the authoritative answer field.
Definition: dns.h:688
uint8_t rcode() const
Setter for the rcode field.
Definition: dns.h:755
const std::string & dname() const
Getter for the domain name field.
Definition: dns.h:484
uint8_t authenticated_data() const
Setter for the authenticated data field.
Definition: dns.h:736
void preference(uint16_t data)
Setter for the preference field.
Definition: dns.h:607
QRType type() const
Setter for the query response field.
Definition: dns.h:669
PDUType pdu_type() const
Getter for the PDU&#39;s type.
Definition: dns.h:800
uint32_t expire() const
Getter for the expire field.
Definition: dns.h:370
QueryType
Query types enum.
Definition: dns.h:103
TINS_DEPRECATED(QueryType type() const)
Getter for the query type field.
Definition: dns.h:260
std::vector< uint8_t > byte_array
Definition: pdu.h:45
uint32_t ttl() const
Definition: dns.h:524
uint16_t id() const
Setter for the id field.
Definition: dns.h:659
Represents a DNS PDU.
Definition: dns.h:85
PDUType
Enum which identifies each type of PDU.
Definition: pdu.h:127
uint8_t z() const
Setter for the z desired field.
Definition: dns.h:726
void dname(const std::string &nm)
Setter for the name field.
Definition: dns.h:204
TINS_DEPRECATED(void type(QueryType tp))
Setter for the query type field.
Definition: dns.h:225
Definition: hw_address.h:456
QueryType query_type() const
Getter for the query type field.
Definition: dns.h:248
uint8_t truncated() const
Setter for the truncated field.
Definition: dns.h:697
Struct that represent DNS queries.
Definition: dns.h:177
query(std::string nm, QueryType tp, QueryClass cl)
Constructs a DNS query.
Definition: dns.h:187
Class that represents a Start Of Authority record.
Definition: dns.h:281
uint16_t query_type() const
Definition: dns.h:498
query()
Default constructs this Query.
Definition: dns.h:197
void query_class(QueryClass cl)
Setter for the query class field.
Definition: dns.h:234
uint8_t recursion_available() const
Setter for the recursion available field.
Definition: dns.h:717
uint32_t serial() const
Getter for the serial number field.
Definition: dns.h:346
uint16_t preference() const
Getter for the preferece field.
Definition: dns.h:533
DNS * clone() const
Definition: dns.h:994
TINS_DEPRECATED(uint16_t type() const)
Getter for the query type field.
Definition: dns.h:510
const std::string & data() const
Definition: dns.h:491
TINS_DEPRECATED(void type(uint16_t data))
Setter for the query type field.
Definition: dns.h:584
const std::string & mname() const
Getter for the primary source name field.
Definition: dns.h:327
PDU::serialization_type serialize() const
Serialize this SOA record.
Definition: dns.cpp:669
void dname(const std::string &data)
Definition: dns.h:540
QRType
Definition: dns.h:95
uint32_t minimum_ttl() const
Getter for the minimum TTL field.
Definition: dns.h:378
const std::string & dname() const
Getter for the name field.
Definition: dns.h:241
void data(const std::string &data)
Setter for the data field.
Definition: dns.h:556
The Tins namespace.
Definition: address_range.h:38
void query_type(uint16_t data)
Definition: dns.h:572
uint8_t checking_disabled() const
Setter for the checking disabled field.
Definition: dns.h:746
uint16_t answers_count() const
Setter for the answers field.
Definition: dns.h:773
void query_class(uint16_t data)
Definition: dns.h:591
const std::string & rname() const
Getter for the responsible person name field.
Definition: dns.h:338
uint16_t query_class() const
Definition: dns.h:517
resource(std::string dname, std::string data, uint16_t type, uint16_t rclass, uint32_t ttl, uint16_t preference=0)
Definition: dns.h:457
Type used to store a PDU header&#39;s data.
Definition: pdu.h:194
uint32_t refresh() const
Getter for the refresh field.
Definition: dns.h:354
uint8_t recursion_desired() const
Setter for the recursion desired field.
Definition: dns.h:707
Abstraction of an IPv4 address.
Definition: ip_address.h:45
void ttl(uint32_t data)
Definition: dns.h:598
void data(const soa_record &data)
Sets the contents of this resource to the provided SOA record.
Definition: dns.h:564
Definition: ipv6_address.h:45
uint16_t questions_count() const
Setter for the questions field.
Definition: dns.h:764
uint16_t authority_count() const
Setter for the authority field.
Definition: dns.h:782
byte_array serialization_type
Definition: pdu.h:112
QueryClass query_class() const
Getter for the query class field.
Definition: dns.h:267
Base class for protocol data units.
Definition: pdu.h:107
uint8_t opcode() const
Setter for the opcode field.
Definition: dns.h:678
uint32_t retry() const
Getter for the retry field.
Definition: dns.h:362
uint16_t additional_count() const
Setter for the additional field.
Definition: dns.h:791
Class that represent DNS resource records.
Definition: dns.h:444
void query_type(QueryType tp)
Setter for the query type field.
Definition: dns.h:213