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

Revision 513, 4.9 KB (checked in by ahu, 8 years ago)

expose dnsheader
shave off one call to random() on construction - go add your own random

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
31DNSPacketWriter::dnsheader* DNSPacketWriter::getHeader()
32{
33  return (dnsheader*)&*d_content.begin();
34}
35
36void DNSPacketWriter::setRD(bool rd)
37{
38  dnsheader* dh=reinterpret_cast<dnsheader*>( &*d_content.begin());
39  dh->rd=rd;
40}
41
42void DNSPacketWriter::startRecord(const string& name, uint16_t qtype, uint32_t ttl, uint16_t qclass, Place place)
43{
44  if(!d_record.empty()) 
45    commit();
46
47  d_recordqname=name;
48  d_recordqtype=qtype;
49  d_recordqclass=qclass;
50  d_recordttl=ttl;
51
52  d_stuff = 0; 
53
54  xfrLabel(d_recordqname, true);
55  d_content.insert(d_content.end(), d_record.begin(), d_record.end());
56  d_record.clear();
57
58  d_stuff = sizeof(dnsrecordheader); // this is needed to get compressed label offsets right, the dnsrecordheader will be interspersed
59
60  dnsheader* dh=reinterpret_cast<dnsheader*>( &*d_content.begin());
61  switch(place) {
62  case ANSWER:
63    dh->ancount = htons(ntohs(dh->ancount) + 1);
64    break;
65  case AUTHORITY:
66    dh->nscount = htons(ntohs(dh->nscount) + 1);
67    break;
68  case ADDITIONAL:
69    dh->arcount = htons(ntohs(dh->arcount) + 1);
70    break;
71  }
72}
73
74void DNSPacketWriter::addOpt(int udpsize, int extRCode, int Z)
75{
76  uint32_t ttl=0;
77  struct Stuff {
78    uint8_t extRCode, version;
79    uint16_t Z;
80  } __attribute__((packed));
81
82  Stuff stuff;
83
84  stuff.extRCode=extRCode;
85  stuff.version=0;
86  stuff.Z=htons(Z);
87 
88  memcpy(&ttl, &stuff, sizeof(stuff));
89  cout<<sizeof(stuff)<<endl;
90  ttl=ntohl(ttl); // will be reversed later on
91 
92  startRecord("", ns_t_opt, ttl, udpsize, ADDITIONAL);
93}
94
95void DNSPacketWriter::xfr32BitInt(uint32_t val)
96{
97  uint8_t* ptr=reinterpret_cast<uint8_t*>(&val);
98  d_record.insert(d_record.end(), ptr, ptr+4);
99}
100
101void DNSPacketWriter::xfr16BitInt(uint16_t val)
102{
103  uint8_t* ptr=reinterpret_cast<uint8_t*>(&val);
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
162
163void DNSPacketWriter::commit()
164{
165  // build dnsrecordheader
166  struct dnsrecordheader drh;
167  drh.d_type=htons(d_recordqtype);
168  drh.d_class=htons(d_recordqclass);
169  drh.d_ttl=htonl(d_recordttl);
170  drh.d_clen=htons(d_record.size());
171
172  // and write out the header
173  const uint8_t* ptr=(const uint8_t*)&drh;
174  d_content.insert(d_content.end(), ptr, ptr+sizeof(drh));
175
176  // write out d_record
177  d_content.insert(d_content.end(), d_record.begin(), d_record.end());
178
179  d_record.clear();   // clear d_record, ready for next record
180}
181
182
183
184
185
186
Note: See TracBrowser for help on using the browser.