tdns
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
dns-storage.hh
Go to the documentation of this file.
1 #pragma once
2 #include <strings.h>
3 #include <string>
4 #include <set>
5 #include <map>
6 #include <vector>
7 #include <deque>
8 #include <iostream>
9 #include <cstdint>
10 #include <functional>
11 #include <memory>
12 #include "nenum.hh"
13 #include "comboaddress.hh"
14 
20 // note - some platforms are confused over these #defines. Specifically, BYTE_ORDER without __ is a false prophet and may lie!
21 
23 struct dnsheader {
24  uint16_t id; /* query identification number */
25 #if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
26  /* fields in third byte */
27  unsigned qr: 1; /* response flag */
28  unsigned opcode: 4; /* purpose of message */
29  unsigned aa: 1; /* authoritative answer */
30  unsigned tc: 1; /* truncated message */
31  unsigned rd: 1; /* recursion desired */
32  /* fields in fourth byte */
33  unsigned ra: 1; /* recursion available */
34  unsigned unused :1; /* unused bits (MBZ as of 4.9.3a3) */
35  unsigned ad: 1; /* authentic data from named */
36  unsigned cd: 1; /* checking disabled by resolver */
37  unsigned rcode :4; /* response code */
38 #elif __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
39  /* fields in third byte */
40  unsigned rd :1; /* recursion desired */
41  unsigned tc :1; /* truncated message */
42  unsigned aa :1; /* authoritative answer */
43  unsigned opcode :4; /* purpose of message */
44  unsigned qr :1; /* response flag */
45  /* fields in fourth byte */
46  unsigned rcode :4; /* response code */
47  unsigned cd: 1; /* checking disabled by resolver */
48  unsigned ad: 1; /* authentic data from named */
49  unsigned unused :1; /* unused bits (MBZ as of 4.9.3a3) */
50  unsigned ra :1; /* recursion available */
51 #endif
52  /* remaining bytes */
53  uint16_t qdcount; /* number of question entries */
54  uint16_t ancount; /* number of answer entries */
55  uint16_t nscount; /* number of authority entries */
56  uint16_t arcount; /* number of resource entries */
57 };
58 
59 static_assert(sizeof(dnsheader) == 12, "dnsheader size must be 12");
60 
61 // enums
62 enum class RCode
63 {
64  Noerror = 0, Formerr = 1, Servfail = 2, Nxdomain = 3, Notimp = 4, Refused = 5, Notauth = 9, Badvers=16
65 };
66 
67 // this makes enums printable, which is nice
69 SENUM8(RCode, Noerror, Formerr, Servfail, Nxdomain, Notimp, Refused, Notauth, Badvers)
70 SMARTENUMEND(RCode);
71 
73 enum class DNSType : uint16_t
74 {
75  A = 1, NS = 2, CNAME = 5, SOA=6, PTR=12, MX=15, TXT=16, AAAA = 28, SRV=33, NAPTR=35, DS=43, RRSIG=46,
76  NSEC=47, DNSKEY=48, NSEC3=50, OPT=41, IXFR = 251, AXFR = 252, ANY = 255, CAA = 257
77 };
78 
80 SENUM13(DNSType, A, NS, CNAME, SOA, PTR, MX, TXT, AAAA, SRV, NAPTR, DS, RRSIG, NSEC)
81 SENUM7(DNSType, DNSKEY, NSEC3, OPT, IXFR, AXFR, ANY, CAA)
82 SMARTENUMEND(DNSType);
83 
85 enum class DNSClass : uint16_t
86 {
87  IN=1, CH=3
88 };
90 
91 COMBOENUM4(DNSSection, Question, 0, Answer, 1, Authority, 2, Additional, 3);
92 // this semicolon makes Doxygen happy
93 
95 class DNSLabel
96 {
97 public:
98  DNSLabel() {}
99  DNSLabel(const char* s) : DNSLabel(std::string(s)) {}
100  DNSLabel(const std::string& s) : d_s(s)
101  {
102  if(d_s.size() > 63)
103  throw std::out_of_range("label too long");
104  }
106  bool operator<(const DNSLabel& rhs) const
107  {
108  return std::lexicographical_compare(d_s.begin(), d_s.end(), rhs.d_s.begin(), rhs.d_s.end(), charcomp);
109  }
110 
111  bool operator==(const DNSLabel &rhs) const
112  {
113  return !(*this < rhs) && !(rhs<*this);
114  }
115  auto size() const { return d_s.size(); }
116  auto empty() const { return d_s.empty(); }
117 
118  std::string d_s;
119 private:
120  static bool charcomp(char a, char b)
121  {
122  if(a >= 0x61 && a <= 0x7A)
123  a -= 0x20;
124  if(b >= 0x61 && b <= 0x7A)
125  b -= 0x20;
126  return a < b;
127  }
128 };
129 std::ostream & operator<<(std::ostream &os, const DNSLabel& d);
130 
131 
133 struct DNSName
134 {
135  DNSName() {}
136  DNSName(std::initializer_list<DNSLabel> dls) : d_name(dls) {}
137  void push_back(const DNSLabel& l) { d_name.push_back(l); }
138  auto back() const { return d_name.back(); }
139  auto begin() const { return d_name.begin(); }
140  bool empty() const { return d_name.empty(); }
141  auto end() const { return d_name.end(); }
142  auto front() const { return d_name.front(); }
143  void pop_back() { d_name.pop_back(); }
144  void pop_front() { d_name.pop_front(); }
145  auto push_front(const DNSLabel& dn) { return d_name.push_front(dn); }
146  auto size() { return d_name.size(); }
147  void clear() { d_name.clear(); }
148  bool makeRelative(const DNSName& root);
149  bool isPartOf(const DNSName& root) const;
150  std::string toString() const;
151  bool operator==(const DNSName& rhs) const
152  {
153  return std::lexicographical_compare(begin(), end(), rhs.begin(), rhs.end())==0 &&
154  std::lexicographical_compare(rhs.begin(), rhs.end(), begin(), end())==0;
155  }
156  bool operator!=(const DNSName& rhs) const
157  {
158  return !operator==(rhs);
159  }
160 
161  bool operator<(const DNSName& rhs) const
162  {
163  return std::lexicographical_compare(begin(), end(), rhs.begin(), rhs.end());
164  }
165 
166  std::deque<DNSLabel> d_name;
167 };
168 
169 // printing, concatenation
170 std::ostream & operator<<(std::ostream &os, const DNSName& d);
171 DNSName operator+(const DNSName& a, const DNSName& b);
172 DNSName makeDNSName(const std::string& str);
173 
174 class DNSMessageWriter;
175 
177 
180 struct RRGen
181 {
182  virtual void toMessage(DNSMessageWriter& dpw) = 0;
183  virtual std::string toString() const = 0;
184  virtual DNSType getType() const = 0;
185  virtual ~RRGen();
186 };
187 
189 struct RRSet
190 {
191  std::vector<std::unique_ptr<RRGen>> contents;
192  std::vector<std::unique_ptr<RRGen>> signatures;
193  void add(std::unique_ptr<RRGen>&& rr)
194  {
195  if(rr->getType() != DNSType::RRSIG)
196  contents.emplace_back(std::move(rr));
197  else
198  signatures.emplace_back(std::move(rr));
199  }
200  uint32_t ttl{3600};
201 };
202 
204 struct DNSNode
205 {
209  DNSNode(const DNSLabel& lab, DNSNode* parent) : d_name(lab), d_parent(parent) {}
210  ~DNSNode();
212  const DNSNode* find(DNSName& name, DNSName& last, bool wildcards=false, const DNSNode** passedZonecut=0, const DNSNode** passedWcard=0) const;
213 
215  DNSNode* add(DNSName name);
216 
217  const DNSNode* next() const;
218  const DNSNode* prev() const;
219  DNSName getName() const
220  {
221  DNSName ret;
222  auto us = this;
223 
224  while(us) {
225  if(!us->d_name.empty())
226  ret.push_back(us->d_name);
227  us = us->d_parent;
228  }
229  return ret;
230  }
232  void addRRs(std::unique_ptr<RRGen>&&a);
234  template<typename... Types>
235  void addRRs(std::unique_ptr<RRGen>&&a, Types&&... args)
236  {
237  addRRs(std::move(a));
238  addRRs(std::forward<Types>(args)...);
239  }
240 
241  struct DNSNodeCmp
242  {
243  bool operator()(const DNSNode& a, const DNSNode& b) const
244  {
245  return a.d_name < b.d_name;
246  }
247  bool operator()(const DNSNode& a, const DNSLabel& b) const
248  {
249  return a.d_name < b;
250  }
251  bool operator()(const DNSLabel& a, const DNSNode& b) const
252  {
253  return a < b.d_name;
254  }
255  using is_transparent = void;
256  };
257 
259  std::set<DNSNode, DNSNodeCmp> children;
260 
261  // !the RRSets, grouped by type
262  std::map<DNSType, RRSet > rrsets;
263  std::unique_ptr<DNSNode> zone;
264  uint16_t namepos{0};
265 };
266 
268 void loadZones(DNSNode& zones);
269 
270 std::unique_ptr<DNSNode> retrieveZone(const ComboAddress& remote, const DNSName& zone);
std::unique_ptr< DNSNode > retrieveZone(const ComboAddress &remote, const DNSName &zone)
connects to an authoritative server, retrieves a zone, returns it as a smart pointer ...
Definition: tauth.cc:492
uint16_t id
Definition: dns-storage.hh:24
bool empty() const
Definition: dns-storage.hh:140
Resource records are treated as a set and have one TTL for the whole set.
Definition: dns-storage.hh:189
uint32_t ttl
Definition: dns-storage.hh:200
uint16_t ancount
Definition: dns-storage.hh:54
bool makeRelative(const DNSName &root)
Makes us relative to 'root', returns false if we weren't part of root.
Definition: dns-storage.cc:7
unsigned opcode
Definition: dns-storage.hh:28
auto size() const
Definition: dns-storage.hh:115
std::vector< std::unique_ptr< RRGen > > signatures
Definition: dns-storage.hh:192
std::vector< std::unique_ptr< RRGen > > contents
Definition: dns-storage.hh:191
#define SENUM8(x, a1,...)
Definition: nenum.hh:17
unsigned ad
Definition: dns-storage.hh:35
unsigned rcode
Definition: dns-storage.hh:37
Definition: dns-storage.hh:241
uint16_t qdcount
Definition: dns-storage.hh:53
DNSLabel()
Definition: dns-storage.hh:98
DNSLabel(const char *s)
Definition: dns-storage.hh:99
DNSClass
Stores the class of a DNS query or resource record.
Definition: dns-storage.hh:85
bool operator==(const DNSLabel &rhs) const
Definition: dns-storage.hh:111
bool operator!=(const DNSName &rhs) const
Definition: dns-storage.hh:156
DNS header struct.
Definition: dns-storage.hh:23
std::deque< DNSLabel > d_name
Definition: dns-storage.hh:166
DNSName makeDNSName(const std::string &str)
This function is plain wrong and does unescape its input XXX.
Definition: dns-storage.cc:55
unsigned qr
Definition: dns-storage.hh:27
auto end() const
Definition: dns-storage.hh:141
CH Question
Definition: dns-storage.hh:91
CH Authority
Definition: dns-storage.hh:91
unsigned unused
Definition: dns-storage.hh:34
auto empty() const
Definition: dns-storage.hh:116
virtual std::string toString() const =0
uint16_t arcount
Definition: dns-storage.hh:56
bool isPartOf(const DNSName &root) const
Checks is this DNSName is part of root.
Definition: dns-storage.cc:25
const DNSNode * next() const
Definition: dns-storage.cc:123
std::string toString() const
Definition: dns-storage.cc:221
SMARTENUMEND(RCode)
std::unique_ptr< DNSNode > zone
if this is set, this node is a zone
Definition: dns-storage.hh:263
DNSLabel(const std::string &s)
Definition: dns-storage.hh:100
DNSNode * d_parent
Definition: dns-storage.hh:207
bool operator()(const DNSNode &a, const DNSNode &b) const
Definition: dns-storage.hh:243
DNSNode()
Definition: dns-storage.hh:208
void addRRs(std::unique_ptr< RRGen > &&a, Types &&...args)
add multiple RRGen to this node
Definition: dns-storage.hh:235
void push_back(const DNSLabel &l)
Definition: dns-storage.hh:137
DNSNode(const DNSLabel &lab, DNSNode *parent)
Definition: dns-storage.hh:209
bool operator<(const DNSName &rhs) const
Definition: dns-storage.hh:161
DNSName(std::initializer_list< DNSLabel > dls)
Definition: dns-storage.hh:136
Represents the contents of a resource record.
Definition: dns-storage.hh:180
DNSNode * add(DNSName name)
This is an idempotent way to add a node to a DNS tree.
Definition: dns-storage.cc:114
A DNS Message writer.
Definition: dnsmessages.hh:111
std::string d_s
Definition: dns-storage.hh:118
auto back() const
Definition: dns-storage.hh:138
bool operator==(const DNSName &rhs) const
Definition: dns-storage.hh:151
#define SENUM7(x, a1,...)
Definition: nenum.hh:16
bool operator()(const DNSLabel &a, const DNSNode &b) const
Definition: dns-storage.hh:251
CH Additional
Definition: dns-storage.hh:91
DNSName()
Definition: dns-storage.hh:135
DNSName operator+(const DNSName &a, const DNSName &b)
Append two DNSNames.
Definition: dns-storage.cc:46
unsigned ra
Definition: dns-storage.hh:33
A node in the DNS tree.
Definition: dns-storage.hh:204
auto push_front(const DNSLabel &dn)
Definition: dns-storage.hh:145
std::ostream & operator<<(std::ostream &os, const DNSLabel &d)
Definition: dns-storage.cc:195
void loadZones(DNSNode &zones)
Called by main() to load zone information.
Definition: contents.cc:12
virtual DNSType getType() const =0
RCode
Definition: dns-storage.hh:62
#define SENUM2(x, a1,...)
Definition: nenum.hh:11
void addRRs(std::unique_ptr< RRGen > &&a)
add one RRGen to this node
Definition: dns-storage.cc:180
const DNSNode * prev() const
Definition: dns-storage.cc:158
uint16_t namepos
for label compression, we also use DNSNodes
Definition: dns-storage.hh:264
bool operator()(const DNSNode &a, const DNSLabel &b) const
Definition: dns-storage.hh:247
void clear()
Definition: dns-storage.hh:147
IN
Definition: dns-storage.hh:89
virtual ~RRGen()
unsigned tc
Definition: dns-storage.hh:30
unsigned rd
Definition: dns-storage.hh:31
Represents a DNS label, which is part of a DNS Name.
Definition: dns-storage.hh:95
auto front() const
Definition: dns-storage.hh:142
void pop_back()
Definition: dns-storage.hh:143
auto begin() const
Definition: dns-storage.hh:139
A DNS Name with helpful methods. Inherits case insensitivity from DNSLabel.
Definition: dns-storage.hh:133
CH Answer
Definition: dns-storage.hh:91
#define SENUM13(x, a1,...)
Definition: nenum.hh:22
std::set< DNSNode, DNSNodeCmp > children
children, found by DNSLabel
Definition: dns-storage.hh:259
bool operator<(const DNSLabel &rhs) const
Equality and comparison are case insensitive.
Definition: dns-storage.hh:106
unsigned aa
Definition: dns-storage.hh:29
unsigned cd
Definition: dns-storage.hh:36
auto size()
Definition: dns-storage.hh:146
std::map< DNSType, RRSet > rrsets
Definition: dns-storage.hh:262
uint16_t nscount
Definition: dns-storage.hh:55
DNSLabel d_name
Definition: dns-storage.hh:206
SMARTENUMSTART(DNSClass) SENUM2(DNSClass
void pop_front()
Definition: dns-storage.hh:144
void is_transparent
Definition: dns-storage.hh:255
DNSName getName() const
Definition: dns-storage.hh:219
virtual void toMessage(DNSMessageWriter &dpw)=0
DNSType
Stores the type of a DNS query or resource record.
Definition: dns-storage.hh:73
#define COMBOENUM4(x, a1, b1, a2, b2, a3, b3, a4, b4)
Definition: nenum.hh:41
void add(std::unique_ptr< RRGen > &&rr)
Definition: dns-storage.hh:193
const DNSNode * find(DNSName &name, DNSName &last, bool wildcards=false, const DNSNode **passedZonecut=0, const DNSNode **passedWcard=0) const
This is the key function that finds names, returns where it found them and if any zonecuts were passs...
Definition: dns-storage.cc:79