root/trunk/pdns/pdns/dnswriter.cc @ 514

Revision 514, 5.2 KB (checked in by ahu, 8 years ago)

the gist is: move pdns_recursor over to new {zone,packet}-{parser,generator} stuff
this means the pdns_recursor does not use DNSPacket anymore (yay)
Commit adds:

d_qtype storage to all DNSRecordContent classes
infrastructure to extract *only* the record for a packet, assuming it came with a qname
add reportAllTypes() if you want to be able to parse all types,

reportBasicTypes() for the pdns_recursor
reportOtherTypes() if you want the rest too

updates Makefile.am so everything compiles again
fix endian issues in packetwriter/parser

remove virtualness/inheritance from the pdns_recursor storage cache (teeny speedup)

Things might be a bit scary in the recursor now.

Line 
1#include "dnswriter.hh"
2#include "misc.hh"
3#include "dnsparser.hh"
4
5DNSPacketWriter::DNSPacketWriter(vector<uint8_t>& content, const string& qname, uint16_t  qtype, uint16_t qclass)
6  : d_pos(0), d_content(content), d_qname(qname), d_qtype(qtype), d_qclass(qclass)
7{
8  d_content.clear();
9  dnsheader dnsheader;
10 
11  memset(&dnsheader, 0, sizeof(dnsheader));
12  dnsheader.id=0;
13  dnsheader.qdcount=htons(1);
14 
15  const uint8_t* ptr=(const uint8_t*)&dnsheader;
16  d_content.insert(d_content.end(), ptr, ptr + sizeof(dnsheader));   
17 
18  xfrLabel(qname, false);
19  d_content.insert(d_content.end(), d_record.begin(), d_record.end());
20  d_record.clear();
21
22  qtype=htons(qtype);
23  ptr=(const uint8_t*)&qtype;
24  d_content.insert(d_content.end(), ptr, ptr+2);
25 
26  qclass=htons(qclass);
27  ptr=(const uint8_t*)&qclass;
28  d_content.insert(d_content.end(), ptr, ptr+2);
29
30  d_stuff=0xffff;
31}
32
33DNSPacketWriter::dnsheader* DNSPacketWriter::getHeader()
34{
35  return (dnsheader*)&*d_content.begin();
36}
37
38
39void DNSPacketWriter::startRecord(const string& name, uint16_t qtype, uint32_t ttl, uint16_t qclass, Place place)
40{
41  if(!d_record.empty()) 
42    commit();
43
44  d_recordqname=name;
45  d_recordqtype=qtype;
46  d_recordqclass=qclass;
47  d_recordttl=ttl;
48
49  d_stuff = 0; 
50
51  xfrLabel(d_recordqname, true);
52  d_content.insert(d_content.end(), d_record.begin(), d_record.end());
53  d_record.clear();
54
55  d_stuff = sizeof(dnsrecordheader); // this is needed to get compressed label offsets right, the dnsrecordheader will be interspersed
56  d_sor=d_content.size() + d_stuff; // start of real record
57
58  dnsheader* dh=reinterpret_cast<dnsheader*>( &*d_content.begin());
59  switch(place) {
60  case ANSWER:
61    dh->ancount = htons(ntohs(dh->ancount) + 1);
62    break;
63  case AUTHORITY:
64    dh->nscount = htons(ntohs(dh->nscount) + 1);
65    break;
66  case ADDITIONAL:
67    dh->arcount = htons(ntohs(dh->arcount) + 1);
68    break;
69  }
70}
71
72void DNSPacketWriter::addOpt(int udpsize, int extRCode, int Z)
73{
74  uint32_t ttl=0;
75  struct Stuff {
76    uint8_t extRCode, version;
77    uint16_t Z;
78  } __attribute__((packed));
79
80  Stuff stuff;
81
82  stuff.extRCode=extRCode;
83  stuff.version=0;
84  stuff.Z=htons(Z);
85 
86  memcpy(&ttl, &stuff, sizeof(stuff));
87  cout<<sizeof(stuff)<<endl;
88  ttl=ntohl(ttl); // will be reversed later on
89 
90  startRecord("", ns_t_opt, ttl, udpsize, ADDITIONAL);
91}
92
93void DNSPacketWriter::xfr32BitInt(uint32_t val)
94{
95  int rval=htonl(val);
96  uint8_t* ptr=reinterpret_cast<uint8_t*>(&rval);
97  d_record.insert(d_record.end(), ptr, ptr+4);
98}
99
100void DNSPacketWriter::xfr16BitInt(uint16_t val)
101{
102  int rval=htons(val);
103  uint8_t* ptr=reinterpret_cast<uint8_t*>(&rval);
104  d_record.insert(d_record.end(), ptr, ptr+2);
105}
106
107void DNSPacketWriter::xfr8BitInt(uint8_t val)
108{
109  d_record.push_back(val);
110}
111
112void DNSPacketWriter::xfrText(const string& text)
113{
114  d_record.push_back(text.length());
115  const uint8_t* ptr=(uint8_t*)(text.c_str());
116  d_record.insert(d_record.end(), ptr, ptr+text.size());
117}
118
119
120void DNSPacketWriter::xfrLabel(const string& label, bool compress)
121{
122  typedef vector<string> parts_t;
123  parts_t parts;
124  stringtok(parts, label, ".");
125 
126  string enc;
127  unsigned int pos=d_content.size() + d_record.size() + d_stuff; // d_stuff is amount of stuff that is yet to be written out - the dnsrecordheader for example
128  string chopped(label);
129 
130  for(parts_t::const_iterator i=parts.begin(); i!=parts.end(); ++i) {
131    map<string, uint16_t>::iterator li;
132    if(compress && (li=d_labelmap.find(chopped))!=d_labelmap.end()) {   // see if we've written out this domain before
133      uint16_t offset=li->second;
134      offset|=0xc000;
135      enc.append(1, (char)(offset >> 8));
136      enc.append(1, (char)(offset & 0xff));
137      goto out;                                 // skip trailing 0 in case of compression
138    }
139    else if(compress || d_labelmap.count(chopped)) { // if 'compress' is true, li will be equal to d_labelmap.end()
140      d_labelmap[chopped]=pos;                       //  if untrue, we need to count
141    }
142    enc.append(1, (char)i->length());
143    enc.append(*i);
144    pos+=i->length()+1;
145    chopOff(chopped);                   // www.powerdns.com -> powerdns.com -> com
146  }
147  enc.append(1,(char)0);
148
149 out:;
150
151  const uint8_t* ptr=reinterpret_cast<const uint8_t*>(enc.c_str());
152  d_record.insert(d_record.end(), ptr, ptr+enc.size());
153}
154
155void DNSPacketWriter::xfrBlob(const string& blob)
156{
157  const uint8_t* ptr=reinterpret_cast<const uint8_t*>(blob.c_str());
158
159  d_record.insert(d_record.end(), ptr, ptr+blob.size());
160}
161
162void DNSPacketWriter::getRecords(string& records)
163{
164  records.assign(d_content.begin() + d_sor, d_content.end());
165}
166
167void DNSPacketWriter::commit()
168{
169  if(d_stuff==0xffff && (d_content.size()!=d_sor || !d_record.empty()))
170    throw MOADNSException("DNSPacketWriter::commit() called without startRecord ever having been called, but a record was added");
171  // build dnsrecordheader
172  struct dnsrecordheader drh;
173  drh.d_type=htons(d_recordqtype);
174  drh.d_class=htons(d_recordqclass);
175  drh.d_ttl=htonl(d_recordttl);
176  drh.d_clen=htons(d_record.size());
177
178  // and write out the header
179  const uint8_t* ptr=(const uint8_t*)&drh;
180  d_content.insert(d_content.end(), ptr, ptr+sizeof(drh));
181
182  // write out d_record
183  d_content.insert(d_content.end(), d_record.begin(), d_record.end());
184
185  d_record.clear();   // clear d_record, ready for next record
186}
187
188
189
190
191
192
Note: See TracBrowser for help on using the browser.