root/trunk/pdns/pdns/dnsparser.hh @ 2338

Revision 2324, 8.6 KB (checked in by peter, 2 years ago)

Spellcheck. Fixes #296 and a lot more.

Line 
1/*
2    PowerDNS Versatile Database Driven Nameserver
3    Copyright (C) 2005 - 2011 PowerDNS.COM BV
4
5    This program is free software; you can redistribute it and/or modify
6    it under the terms of the GNU General Public License version 2 as
7    published by the Free Software Foundation
8
9    This program is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12    GNU General Public License for more details.
13
14    You should have received a copy of the GNU General Public License
15    along with this program; if not, write to the Free Software
16    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
17*/
18
19#ifndef DNSPARSER_HH
20#define DNSPARSER_HH
21
22#include <map>
23#include <sstream>
24#include <stdexcept>
25#include <iostream>
26#include <vector>
27#include <errno.h>
28// #include <netinet/in.h>
29#include "misc.hh"
30#include <boost/shared_ptr.hpp>
31#include <boost/lexical_cast.hpp>
32#include <boost/tuple/tuple.hpp>
33#include <boost/tuple/tuple_comparison.hpp>
34#include "dns.hh"
35#include "dnswriter.hh"
36
37/** DNS records have three representations:
38    1) in the packet
39    2) parsed in a class, ready for use
40    3) in the zone
41
42    We should implement bidirectional transitions between 1&2 and 2&3.
43    Currently we have: 1 -> 2
44                       2 -> 3
45
46    We can add:        2 -> 1  easily by reversing the packetwriter
47    And we might be able to reverse 2 -> 3 as well
48*/
49   
50#include "namespaces.hh"
51#include "namespaces.hh"
52
53class MOADNSException : public runtime_error
54{
55public:
56  MOADNSException(const string& str) : runtime_error(str)
57  {}
58};
59
60
61class MOADNSParser;
62
63class PacketReader
64{
65public:
66  PacketReader(const vector<uint8_t>& content) 
67    : d_pos(0), d_content(content)
68  {}
69
70  uint32_t get32BitInt();
71  uint16_t get16BitInt();
72  uint8_t get8BitInt();
73 
74  void xfr48BitInt(uint64_t& val);
75
76  void xfr32BitInt(uint32_t& val)
77  {
78    val=get32BitInt();
79  }
80
81  void xfrIP(uint32_t& val)
82  {
83    xfr32BitInt(val);
84    val=htonl(val);
85  }
86
87  void xfrTime(uint32_t& val)
88  {
89    xfr32BitInt(val);
90  }
91
92
93  void xfr16BitInt(uint16_t& val)
94  {
95    val=get16BitInt();
96  }
97
98  void xfrType(uint16_t& val)
99  {
100    xfr16BitInt(val);
101  }
102
103
104  void xfr8BitInt(uint8_t& val)
105  {
106    val=get8BitInt();
107  }
108
109
110  void xfrLabel(string &label, bool compress=false)
111  {
112    label=getLabel();
113  }
114
115  void xfrText(string &text, bool multi=false)
116  {
117    text=getText(multi);
118  }
119
120  void xfrBlob(string& blob);
121  void xfrBlob(string& blob, int length);
122  void xfrHexBlob(string& blob, bool keepReading=false);
123
124  static uint16_t get16BitInt(const vector<unsigned char>&content, uint16_t& pos);
125  static void getLabelFromContent(const vector<uint8_t>& content, uint16_t& frompos, string& ret, int recurs);
126
127  void getDnsrecordheader(struct dnsrecordheader &ah);
128  void copyRecord(vector<unsigned char>& dest, uint16_t len);
129  void copyRecord(unsigned char* dest, uint16_t len);
130
131  string getLabel(unsigned int recurs=0);
132  string getText(bool multi);
133
134  uint16_t d_pos;
135
136private:
137  uint16_t d_startrecordpos; // needed for getBlob later on
138  uint16_t d_recordlen;      // ditto
139  const vector<uint8_t>& d_content;
140};
141
142struct DNSRecord;
143
144class DNSRecordContent
145{
146public:
147  static DNSRecordContent* mastermake(const DNSRecord &dr, PacketReader& pr);
148  static DNSRecordContent* mastermake(uint16_t qtype, uint16_t qclass, const string& zone);
149
150  virtual std::string getZoneRepresentation() const = 0;
151  virtual ~DNSRecordContent() {}
152  virtual void toPacket(DNSPacketWriter& pw)=0;
153  virtual string serialize(const string& qname, bool canonic=false, bool lowerCase=false) // it would rock if this were const, but it is too hard
154  {
155    vector<uint8_t> packet;
156    string empty;
157    DNSPacketWriter pw(packet, empty, 1);
158    if(canonic)
159      pw.setCanonic(true);
160
161    if(lowerCase)
162      pw.setLowercase(true);
163
164    pw.startRecord(qname, d_qtype);
165    this->toPacket(pw);
166    pw.commit();
167   
168    string record;
169    pw.getRecords(record);
170    return record;
171  }
172
173  static shared_ptr<DNSRecordContent> unserialize(const string& qname, uint16_t qtype, const string& serialized);
174
175  void doRecordCheck(const struct DNSRecord&){}
176
177  std::string label;
178  struct dnsrecordheader header;
179
180  typedef DNSRecordContent* makerfunc_t(const struct DNSRecord& dr, PacketReader& pr); 
181  typedef DNSRecordContent* zmakerfunc_t(const string& str); 
182
183  static void regist(uint16_t cl, uint16_t ty, makerfunc_t* f, zmakerfunc_t* z, const char* name)
184  {
185    if(f)
186      getTypemap()[make_pair(cl,ty)]=f;
187    if(z)
188      getZmakermap()[make_pair(cl,ty)]=z;
189
190    getT2Namemap().insert(make_pair(make_pair(cl,ty), name));
191    getN2Typemap().insert(make_pair(name, make_pair(cl,ty)));
192  }
193
194  static void unregist(uint16_t cl, uint16_t ty) 
195  {
196    pair<uint16_t, uint16_t> key=make_pair(cl, ty);
197    getTypemap().erase(key);
198    getZmakermap().erase(key);
199  }
200
201  static uint16_t TypeToNumber(const string& name)
202  {
203    n2typemap_t::const_iterator iter = getN2Typemap().find(name);
204    if(iter != getN2Typemap().end())
205      return iter->second.second;
206   
207    if(boost::starts_with(name, "TYPE"))
208        return atoi(name.c_str()+4);
209   
210    throw runtime_error("Unknown DNS type '"+name+"'");
211  }
212
213  static const string NumberToType(uint16_t num, uint16_t classnum=1)
214  {
215    t2namemap_t::const_iterator iter = getT2Namemap().find(make_pair(classnum, num));
216    if(iter == getT2Namemap().end()) 
217      return "TYPE" + lexical_cast<string>(num);
218      //      throw runtime_error("Unknown DNS type with numerical id "+lexical_cast<string>(num));
219    return iter->second;
220  }
221
222  explicit DNSRecordContent(uint16_t type) : d_qtype(type)
223  {}
224 
225 
226  DNSRecordContent& operator=(const DNSRecordContent& orig) 
227  {
228    const_cast<uint16_t&>(d_qtype) = orig.d_qtype; // **COUGH**
229    label = orig.label;
230    header = orig.header;
231    return *this;
232  }
233
234 
235  const uint16_t d_qtype;
236
237protected:
238  typedef std::map<std::pair<uint16_t, uint16_t>, makerfunc_t* > typemap_t;
239  typedef std::map<std::pair<uint16_t, uint16_t>, zmakerfunc_t* > zmakermap_t;
240  typedef std::map<std::pair<uint16_t, uint16_t>, string > t2namemap_t;
241  typedef std::map<string, std::pair<uint16_t, uint16_t> > n2typemap_t;
242  static typemap_t& getTypemap();
243  static t2namemap_t& getT2Namemap();
244  static n2typemap_t& getN2Typemap();
245  static zmakermap_t& getZmakermap();
246};
247
248struct DNSRecord
249{
250  std::string d_label;
251  uint16_t d_type;
252  uint16_t d_class;
253  uint32_t d_ttl;
254  uint16_t d_clen;
255  enum {Answer=1, Nameserver, Additional} d_place;
256  boost::shared_ptr<DNSRecordContent> d_content;
257
258  bool operator<(const DNSRecord& rhs) const
259  {
260    string lzrp, rzrp;
261    if(d_content)
262      lzrp=toLower(d_content->getZoneRepresentation());
263    if(rhs.d_content)
264      rzrp=toLower(rhs.d_content->getZoneRepresentation());
265   
266    string llabel=toLower(d_label);
267    string rlabel=toLower(rhs.d_label);
268
269    return 
270      tie(llabel,     d_type,     d_class, lzrp) <
271      tie(rlabel, rhs.d_type, rhs.d_class, rzrp);
272  }
273
274  bool operator==(const DNSRecord& rhs) const
275  {
276    string lzrp, rzrp;
277    if(d_content)
278      lzrp=toLower(d_content->getZoneRepresentation());
279    if(rhs.d_content)
280      rzrp=toLower(rhs.d_content->getZoneRepresentation());
281   
282    string llabel=toLower(d_label);
283    string rlabel=toLower(rhs.d_label);
284   
285    return 
286      tie(llabel,     d_type,     d_class, lzrp) ==
287      tie(rlabel, rhs.d_type, rhs.d_class, rzrp);
288  }
289};
290
291//! This class can be used to parse incoming packets, and is copyable
292class MOADNSParser : public boost::noncopyable
293{
294public:
295  //! Parse from a string
296  MOADNSParser(const string& buffer)  : d_tsigPos(0)
297  {
298    init(buffer.c_str(), (unsigned int)buffer.size());
299  }
300
301  //! Parse from a pointer and length
302  MOADNSParser(const char *packet, unsigned int len) : d_tsigPos(0)
303  {
304    init(packet, len);
305  }
306
307  dnsheader d_header;
308  string d_qname;
309  uint16_t d_qclass, d_qtype;
310  //uint8_t d_rcode;
311
312  typedef vector<pair<DNSRecord, uint16_t > > answers_t;
313 
314  //! All answers contained in this packet
315  answers_t d_answers;
316
317  shared_ptr<PacketReader> getPacketReader(uint16_t offset)
318  {
319    shared_ptr<PacketReader> pr(new PacketReader(d_content));
320    pr->d_pos=offset;
321    return pr;
322  }
323
324  uint16_t getTSIGPos()
325  {
326    return d_tsigPos;
327  }
328private:
329  void getDnsrecordheader(struct dnsrecordheader &ah);
330  void init(const char *packet, unsigned int len);
331  vector<uint8_t> d_content;
332  uint16_t d_tsigPos;
333};
334
335string simpleCompress(const string& label, const string& root="");
336void simpleExpandTo(const string& label, unsigned int frompos, string& ret);
337void ageDNSPacket(std::string& packet, uint32_t seconds);
338#endif
Note: See TracBrowser for help on using the browser.