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