root/trunk/pdns/pdns/rcpgenerator.cc @ 510

Revision 510, 6.9 KB (checked in by ahu, 8 years ago)

fix double-srv regression test error
add label compression to dnswriter, make parser, string parser, sting generator ignore that
make mx, cname, ptr, ns, soa do label compression
fix string parser to not add a trailing . when no zone is configured for expansion
add some comments to DNSPacketWriter
add dnspbench to benchmark and test the new infrastructure away from sdig

new infra appears to generate 100.000 simple packets/s on 1.4GHz

remove a warning in misc.cc

Line 
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
16    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17*/
18
19#include "rcpgenerator.hh"
20#include "dnsparser.hh"
21#include "misc.hh"
22#include <boost/lexical_cast.hpp>
23#include <iostream>
24#include "base64.hh"
25using namespace boost;
26
27RecordTextReader::RecordTextReader(const string& str, const string& zone) : d_string(str), d_zone(zone), d_pos(0), d_end(str.size())
28{
29}
30
31void RecordTextReader::xfr32BitInt(uint32_t &val)
32{
33  skipSpaces();
34
35  if(!isdigit(d_string.at(d_pos)))
36    throw RecordTextException("expected digits at position "+lexical_cast<string>(d_pos)+" in '"+d_string+"'");
37
38  char *endptr;
39  unsigned long ret=strtoul(d_string.c_str() + d_pos, &endptr, 10);
40  val=ret;
41 
42  d_pos = endptr - d_string.c_str();
43}
44
45void RecordTextReader::xfrTime(uint32_t &val)
46{
47  struct tm tm;
48  memset(&tm, 0, sizeof(tm));
49 
50  string tmp;
51  xfrLabel(tmp); // ends on number, so this works
52
53  sscanf(tmp.c_str(), "%04d%02d%02d" "%02d%02d%02d", 
54         &tm.tm_year, &tm.tm_mon, &tm.tm_mday, 
55         &tm.tm_hour, &tm.tm_min, &tm.tm_sec);
56
57  tm.tm_year-=1900;
58  tm.tm_min-=1;
59 
60  val=mktime(&tm);
61}
62
63void RecordTextReader::xfrIP(uint32_t &val)
64{
65  skipSpaces();
66
67  if(!isdigit(d_string.at(d_pos)))
68    throw RecordTextException("expected digits at position "+lexical_cast<string>(d_pos)+" in '"+d_string+"'");
69 
70  string ip;
71  xfrLabel(ip);
72 
73  if(!IpToU32(ip, &val))
74    throw RecordTextException("unable to parse IP address '"+ip+"'");
75}
76
77
78bool RecordTextReader::eof()
79{
80  return d_pos==d_end;
81}
82
83void RecordTextReader::xfr16BitInt(uint16_t &val)
84{
85  uint32_t tmp;
86  xfr32BitInt(tmp);
87  val=tmp;
88  if(val!=tmp)
89    throw RecordTextException("Overflow reading 16 bit integer from record content"); // fixme improve
90}
91
92void RecordTextReader::xfr8BitInt(uint8_t &val)
93{
94  uint32_t tmp;
95  xfr32BitInt(tmp);
96  val=tmp;
97  if(val!=tmp)
98    throw RecordTextException("Overflow reading 8 bit integer from record content"); // fixme improve
99}
100
101
102void RecordTextReader::xfrLabel(string& val, bool)
103{
104  skipSpaces();
105  int pos=d_pos;
106  while(d_pos < d_end && !isspace(d_string[d_pos]))
107    d_pos++;
108
109  val.assign(d_string.c_str()+pos, d_string.c_str() + d_pos);
110  if(val.empty())
111    val=d_zone;
112  else if(!d_zone.empty()) {
113    char last=val[val.size()-1];
114   
115    if(last != '.' && !isdigit(last)) // don't add zone to IP address
116      val+="."+d_zone;
117  }
118}
119
120void RecordTextReader::xfrBlob(string& val)
121{
122  skipSpaces();
123  int pos=d_pos;
124  while(d_pos < d_end && !isspace(d_string[d_pos]))
125    d_pos++;
126
127  string tmp;
128  tmp.assign(d_string.c_str()+pos, d_string.c_str() + d_pos);
129  val.clear();
130  B64Decode(tmp, val);
131}
132
133void RecordTextReader::xfrText(string& val)
134{
135  skipSpaces();
136  if(d_string[d_pos]!='"')
137    throw RecordTextException("Data field in DNS should start with quote (\") at position "+lexical_cast<string>(d_pos)+" of '"+d_string+"'");
138
139  val.clear();
140  val.reserve(d_end - d_pos);
141 
142  while(++d_pos < d_end && d_string[d_pos]!='"') {
143    if(d_string[d_pos]=='\\' && d_pos+1!=d_end) {
144      ++d_pos;
145    }
146    val.append(1, d_string[d_pos]);
147  }
148  if(d_pos == d_end)
149    throw RecordTextException("Data field in DNS should end on a quote (\") in '"+d_string+"'");
150  d_pos++;
151}
152
153void RecordTextReader::xfrType(uint16_t& val)
154{
155  skipSpaces();
156  int pos=d_pos;
157  while(d_pos < d_end && !isspace(d_string[d_pos]))
158    d_pos++;
159
160  string tmp;
161  tmp.assign(d_string.c_str()+pos, d_string.c_str() + d_pos);
162
163  val=DNSRecordContent::TypeToNumber(tmp);
164}
165
166
167void RecordTextReader::skipSpaces()
168{
169  while(d_pos < d_end && isspace(d_string[d_pos]))
170    d_pos++;
171
172  if(d_pos == d_end)
173    throw RecordTextException("missing field at the end of record content '"+d_string+"'");
174}
175
176
177RecordTextWriter::RecordTextWriter(string& str) : d_string(str)
178{
179  d_string.clear();
180}
181
182void RecordTextWriter::xfr32BitInt(const uint32_t& val)
183{
184  if(!d_string.empty())
185    d_string.append(1,' ');
186  d_string+=lexical_cast<string>(val);
187}
188
189
190
191void RecordTextWriter::xfrType(const uint16_t& val)
192{
193  if(!d_string.empty())
194    d_string.append(1,' ');
195  d_string+=DNSRecordContent::NumberToType(val);
196}
197
198void RecordTextWriter::xfrIP(const uint32_t& val)
199{
200  if(!d_string.empty())
201    d_string.append(1,' ');
202
203  ostringstream str;
204 
205  str<< ((val >> 24)&0xff) << ".";
206  str<< ((val >> 16)&0xff) << ".";
207  str<< ((val >>  8)&0xff) << ".";
208  str<< ((val      )&0xff);
209
210  d_string+=str.str();
211}
212
213
214void RecordTextWriter::xfrTime(const uint32_t& val)
215{
216  if(!d_string.empty())
217    d_string.append(1,' ');
218 
219  struct tm tm;
220  time_t time=val; // Y2038 bug!
221  gmtime_r(&time, &tm);
222 
223  char tmp[16];
224  snprintf(tmp,sizeof(tmp)-1, "%04d%02d%02d" "%02d%02d%02d", 
225           tm.tm_year+1900, tm.tm_mon+1, tm.tm_mday, 
226           tm.tm_hour, tm.tm_min, tm.tm_sec);
227 
228  d_string += tmp;
229}
230
231
232void RecordTextWriter::xfr16BitInt(const uint16_t& val)
233{
234  xfr32BitInt(val);
235}
236
237void RecordTextWriter::xfr8BitInt(const uint8_t& val)
238{
239  xfr32BitInt(val);
240}
241
242
243void RecordTextWriter::xfrLabel(const string& val, bool)
244{
245  if(!d_string.empty())
246    d_string.append(1,' ');
247  d_string+=val;
248}
249
250void RecordTextWriter::xfrBlob(const string& val)
251{
252  if(!d_string.empty())
253    d_string.append(1,' ');
254
255  d_string+=Base64Encode(val);
256}
257
258void RecordTextWriter::xfrText(const string& val)
259{
260  if(!d_string.empty())
261    d_string.append(1,' ');
262  d_string.append(1,'"');
263
264  if(val.find_first_of("\\\"") == string::npos)
265    d_string+=val;
266  else {
267    string::size_type end=val.size();
268   
269    for(string::size_type pos=0; pos < end; ++pos) {
270      if(val[pos]=='\'' || val[pos]=='"')
271        d_string.append(1,'\\');
272      d_string.append(1, val[pos]);
273    }
274  }
275
276  d_string.append(1,'"');
277}
278
279
280#ifdef TESTING
281
282int main(int argc, char**argv)
283try
284{
285  RecordTextReader rtr(argv[1], argv[2]);
286 
287  unsigned int order, pref;
288  string flags, services, regexp, replacement;
289  string mx;
290
291  rtr.xfrInt(order);
292  rtr.xfrInt(pref);
293  rtr.xfrText(flags);
294  rtr.xfrText(services);
295  rtr.xfrText(regexp);
296  rtr.xfrLabel(replacement);
297
298  cout<<"order: "<<order<<", pref: "<<pref<<"\n";
299  cout<<"flags: \""<<flags<<"\", services: \""<<services<<"\", regexp: \""<<regexp<<"\", replacement: "<<replacement<<"\n";
300
301  string out;
302  RecordTextWriter rtw(out);
303
304  rtw.xfrInt(order);
305  rtw.xfrInt(pref);
306  rtw.xfrText(flags);
307  rtw.xfrText(services);
308  rtw.xfrText(regexp);
309  rtw.xfrLabel(replacement);
310
311  cout<<"Regenerated: '"<<out<<"'\n";
312 
313}
314catch(exception& e)
315{
316  cerr<<"Fatal: "<<e.what()<<endl;
317}
318
319#endif
Note: See TracBrowser for help on using the browser.