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

Revision 1369, 7.8 KB (checked in by ahu, 4 years ago)

we had some htonls in a twist for xfrIP.. hopefully this is the right fix

RevLine 
[501]1/*
2    PowerDNS Versatile Database Driven Nameserver
3    Copyright (C) 2005  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
[680]16    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
[501]17*/
18
[303]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>
[792]28// #include <netinet/in.h>
[426]29#include "misc.hh"
[303]30#include <boost/shared_ptr.hpp>
[308]31#include <boost/lexical_cast.hpp>
[424]32#include <boost/tuple/tuple.hpp>
33#include <boost/tuple/tuple_comparison.hpp>
[792]34#include "dns.hh"
[514]35#include "dnswriter.hh"
[498]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   
[303]50using namespace std;
51using namespace boost;
52
[683]53class MOADNSException : public runtime_error
54{
55public:
56  MOADNSException(const string& str) : runtime_error(str)
57  {}
58};
59
[303]60
61class MOADNSParser;
62
63class PacketReader
64{
65public:
[477]66  PacketReader(const vector<uint8_t>& content) 
[303]67    : d_pos(0), d_content(content)
68  {}
69
[477]70  uint32_t get32BitInt();
71  uint16_t get16BitInt();
[498]72  uint8_t get8BitInt();
[1095]73 
74  void xfr48BitInt(uint64_t& val);
[498]75
76  void xfr32BitInt(uint32_t& val)
77  {
78    val=get32BitInt();
79  }
80
[502]81  void xfrIP(uint32_t& val)
82  {
83    xfr32BitInt(val);
[1369]84    val=htonl(val);
[502]85  }
86
[507]87  void xfrTime(uint32_t& val)
88  {
89    xfr32BitInt(val);
90  }
91
92
[498]93  void xfr16BitInt(uint16_t& val)
94  {
95    val=get16BitInt();
96  }
97
[507]98  void xfrType(uint16_t& val)
99  {
100    xfr16BitInt(val);
101  }
102
103
[505]104  void xfr8BitInt(uint8_t& val)
105  {
106    val=get8BitInt();
107  }
108
109
[510]110  void xfrLabel(string &label, bool compress=false)
[498]111  {
112    label=getLabel();
113  }
114
[996]115  void xfrText(string &text, bool multi=false)
[498]116  {
[996]117    text=getText(multi);
[498]118  }
119
[505]120  void xfrBlob(string& blob);
[1100]121  void xfrBlob(string& blob, int length);
[650]122  void xfrHexBlob(string& blob);
[505]123
[477]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);
[498]126
[303]127  void getDnsrecordheader(struct dnsrecordheader &ah);
[477]128  void copyRecord(vector<unsigned char>& dest, uint16_t len);
129  void copyRecord(unsigned char* dest, uint16_t len);
[491]130
[303]131  string getLabel(unsigned int recurs=0);
[996]132  string getText(bool multi);
[303]133
[477]134  uint16_t d_pos;
[498]135
[303]136private:
[505]137  uint16_t d_startrecordpos; // needed for getBlob later on
138  uint16_t d_recordlen;      // dito
[477]139  const vector<uint8_t>& d_content;
[303]140};
141
[514]142struct DNSRecord;
[308]143
[303]144class DNSRecordContent
145{
146public:
[308]147  static DNSRecordContent* mastermake(const DNSRecord &dr, PacketReader& pr);
[511]148  static DNSRecordContent* mastermake(uint16_t qtype, uint16_t qclass, const string& zone);
[498]149
[303]150  virtual std::string getZoneRepresentation() const = 0;
151  virtual ~DNSRecordContent() {}
[511]152  virtual void toPacket(DNSPacketWriter& pw)=0;
[1369]153  virtual string serialize(const string& qname) // it would rock if this were const, but it is too hard
[514]154  {
155    vector<uint8_t> packet;
[1050]156    string empty;
157    DNSPacketWriter pw(packet, empty, 1);
[514]158   
159    pw.startRecord(qname, d_qtype);
160    this->toPacket(pw);
161    pw.commit();
162   
163    string record;
164    pw.getRecords(record);
165    return record;
166  }
[303]167
[514]168  static shared_ptr<DNSRecordContent> unserialize(const string& qname, uint16_t qtype, const string& serialized);
169
[499]170  void doRecordCheck(const struct DNSRecord&){}
171
[303]172  std::string label;
173  struct dnsrecordheader header;
[308]174
175  typedef DNSRecordContent* makerfunc_t(const struct DNSRecord& dr, PacketReader& pr); 
[511]176  typedef DNSRecordContent* zmakerfunc_t(const string& str); 
177
178  static void regist(uint16_t cl, uint16_t ty, makerfunc_t* f, zmakerfunc_t* z, const char* name)
[308]179  {
[518]180    if(f)
[612]181      getTypemap()[make_pair(cl,ty)]=f;
[518]182    if(z)
[612]183      getZmakermap()[make_pair(cl,ty)]=z;
[518]184
[612]185    getNamemap()[make_pair(cl,ty)]=name;
[308]186  }
187
[823]188  static void unregist(uint16_t cl, uint16_t ty) 
189  {
190    pair<uint16_t, uint16_t> key=make_pair(cl, ty);
191    getTypemap().erase(key);
192    getZmakermap().erase(key);
193  }
194
[308]195  static uint16_t TypeToNumber(const string& name)
196  {
[612]197    for(namemap_t::const_iterator i=getNamemap().begin(); i!=getNamemap().end();++i)
[802]198      if(!Utility::strcasecmp(i->second.c_str(), name.c_str()))
[308]199        return i->first.second;
200
201    throw runtime_error("Unknown DNS type '"+name+"'");
202  }
203
[1359]204  static const string NumberToType(uint16_t num, uint16_t classnum=1)
[308]205  {
[1359]206    if(!getNamemap().count(make_pair(classnum,num)))
[420]207      return "#" + lexical_cast<string>(num);
208      //      throw runtime_error("Unknown DNS type with numerical id "+lexical_cast<string>(num));
[1359]209    return getNamemap()[make_pair(classnum,num)];
[308]210  }
211
[514]212  explicit DNSRecordContent(uint16_t type) : d_qtype(type)
213  {}
214  const uint16_t d_qtype;
215
[303]216protected:
[477]217  typedef std::map<std::pair<uint16_t, uint16_t>, makerfunc_t* > typemap_t;
[511]218  typedef std::map<std::pair<uint16_t, uint16_t>, zmakerfunc_t* > zmakermap_t;
[477]219  typedef std::map<std::pair<uint16_t, uint16_t>, string > namemap_t;
[612]220
221  static typemap_t& getTypemap();
222  static namemap_t& getNamemap();
223  static zmakermap_t& getZmakermap();
[303]224};
225
226struct DNSRecord
227{
228  std::string d_label;
[477]229  uint16_t d_type;
230  uint16_t d_class;
231  uint32_t d_ttl;
232  uint16_t d_clen;
[511]233  enum {Answer=1, Nameserver, Additional} d_place;
[303]234  boost::shared_ptr<DNSRecordContent> d_content;
[424]235
236  bool operator<(const DNSRecord& rhs) const
237  {
238    string lzrp, rzrp;
239    if(d_content)
[426]240      lzrp=toLower(d_content->getZoneRepresentation());
[424]241    if(rhs.d_content)
[426]242      rzrp=toLower(rhs.d_content->getZoneRepresentation());
[424]243   
[426]244    string llabel=toLower(d_label);
245    string rlabel=toLower(rhs.d_label);
246
[424]247    return 
[426]248      tie(llabel,     d_type,     d_class, lzrp) <
249      tie(rlabel, rhs.d_type, rhs.d_class, rzrp);
[424]250  }
251
252  bool operator==(const DNSRecord& rhs) const
253  {
254    string lzrp, rzrp;
255    if(d_content)
[426]256      lzrp=toLower(d_content->getZoneRepresentation());
[424]257    if(rhs.d_content)
[426]258      rzrp=toLower(rhs.d_content->getZoneRepresentation());
[424]259   
[426]260    string llabel=toLower(d_label);
261    string rlabel=toLower(rhs.d_label);
262   
[424]263    return 
[426]264      tie(llabel,     d_type,     d_class, lzrp) ==
265      tie(rlabel, rhs.d_type, rhs.d_class, rzrp);
[424]266  }
[303]267};
268
[511]269//! This class can be used to parse incoming packets, and is copyable
[1359]270class MOADNSParser : public boost::noncopyable
[303]271{
272public:
[511]273  //! Parse from a string
[1359]274  MOADNSParser(const string& buffer)  : d_tsigPos(0)
[303]275  {
[802]276    init(buffer.c_str(), (unsigned int)buffer.size());
[303]277  }
278
[511]279  //! Parse from a pointer and length
[1359]280  MOADNSParser(const char *packet, unsigned int len) : d_tsigPos(0)
[303]281  {
282    init(packet, len);
283  }
[511]284
[303]285  dnsheader d_header;
286  string d_qname;
[477]287  uint16_t d_qclass, d_qtype;
[308]288  uint8_t d_rcode;
[303]289
290  typedef vector<pair<DNSRecord, uint16_t > > answers_t;
[511]291 
292  //! All answers contained in this packet
[303]293  answers_t d_answers;
294
295  shared_ptr<PacketReader> getPacketReader(uint16_t offset)
296  {
297    shared_ptr<PacketReader> pr(new PacketReader(d_content));
298    pr->d_pos=offset;
299    return pr;
300  }
[511]301
[1359]302  uint16_t getTSIGPos()
303  {
304    return d_tsigPos;
305  }
[303]306private:
307  void getDnsrecordheader(struct dnsrecordheader &ah);
308  void init(const char *packet, unsigned int len);
309  vector<uint8_t> d_content;
[1359]310  uint16_t d_tsigPos;
[303]311};
312
[1050]313string simpleCompress(const string& label, const string& root="");
[972]314void simpleExpandTo(const string& label, unsigned int frompos, string& ret);
[303]315
316#endif
Note: See TracBrowser for help on using the browser.