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

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

create more xfrType
create xfrTime for DNSSEC timestamps (with our own y2038 bug!)
hook up xfrTime - our output is now equivalent to that of the latest bind dig I for all queries I can try

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)
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 {
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)
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.