root/trunk/pdns/pdns/zoneparser-tng.cc @ 802

Revision 802, 5.6 KB (checked in by ahu, 7 years ago)

Big bag of VC++ fixes, mostly by Michel 'Wimpie' Stol

Line 
1/*
2    PowerDNS Versatile Database Driven Nameserver
3    Copyright (C) 2005 - 2006  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
7    as 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
17*/
18
19#include "dnsparser.hh"
20#include "sstuff.hh"
21#include "misc.hh"
22#include "dnswriter.hh"
23#include "dnsrecords.hh"
24#include "misc.hh"
25#include <fstream>
26#include "dns.hh"
27#include "zoneparser-tng.hh"
28#include <deque>
29#include <boost/algorithm/string.hpp>
30#include <boost/lexical_cast.hpp>
31
32ZoneParserTNG::ZoneParserTNG(const string& fname, const string& zname) : d_zonename(zname), d_defaultttl(3600)
33{
34  d_fp=fopen(fname.c_str(), "r");
35  if(!d_fp)
36    throw runtime_error("Unable to open file '"+fname+"': "+stringerror());
37}
38
39ZoneParserTNG::~ZoneParserTNG()
40{
41  fclose(d_fp);
42}
43
44static string makeString(const string& line, const pair<string::size_type, string::size_type>& range)
45{
46  return string(line.c_str() + range.first, range.second - range.first);
47}
48
49static unsigned int makeTTLFromZone(const string& str)
50{
51  if(str.empty())
52    return 0;
53
54  unsigned int val=atoi(str.c_str());
55  char lc=toupper(str[str.length()-1]);
56  if(!isdigit(lc))
57    switch(lc) {
58    case 'H':
59      val*=3600;
60      break;
61    case 'D':
62      val*=3600*24;
63      break;
64    case 'W':
65      val*=3600*24*7;
66      break;
67    case 'M':
68      val*=3600*24*7*4;
69      break;
70    case 'Y': // ? :-)
71      val*=3600*24*365;
72      break;
73    default:
74      throw ZoneParserTNG::exception("Unable to parse time specification '"+str+"'");
75    }
76  return val;
77}
78
79bool ZoneParserTNG::get(DNSResourceRecord& rr) 
80{
81 retry:;
82  if(!getLine())
83    return false;
84
85  chomp(d_line, " \r\n\x1a");
86  deque<pair<string::size_type, string::size_type> > parts;
87  vstringtok(parts, d_line);
88
89  if(parts.empty())
90    goto retry;
91
92  if(d_line[0]=='$') { 
93    if(makeString(d_line, parts[0])=="$TTL" && parts.size() > 1)
94      d_defaultttl=makeTTLFromZone(makeString(d_line,parts[1]));
95    else
96      throw exception("Can't parse zone line '"+d_line+"'");
97    goto retry;
98  }
99
100
101  if(isspace(d_line[0])) 
102    rr.qname=d_prevqname;
103  else {
104    rr.qname=makeString(d_line, parts[0]); 
105    parts.pop_front();
106    if(rr.qname.empty() || rr.qname[0]==';')
107      goto retry;
108  }
109  if(rr.qname=="@")
110    rr.qname=d_zonename;
111  else if(!isCanonical(rr.qname)) {
112    rr.qname.append(1,'.');
113    rr.qname.append(d_zonename);
114  }
115  d_prevqname=rr.qname;
116
117  if(parts.empty()) 
118    throw exception("Line with too little parts");
119
120  // cout<<"Have qname: '"<<rr.qname<<"'\n";
121
122  string nextpart;
123 
124  rr.ttl=d_defaultttl;
125  bool haveTTL=0, haveQTYPE=0;
126  pair<string::size_type, string::size_type> range;
127
128  while(!parts.empty()) {
129    range=parts.front();
130    parts.pop_front();
131    nextpart=makeString(d_line, range);
132    if(nextpart.empty())
133      break;
134
135    if(nextpart.find(';')!=string::npos)
136      break;
137
138    // cout<<"Next part: '"<<nextpart<<"'"<<endl;
139   
140    if(!Utility::strcasecmp(nextpart.c_str(), "IN")) {
141      // cout<<"Ignoring 'IN'\n";
142      continue;
143    }
144    if(!haveTTL && !haveQTYPE && all(nextpart, is_digit())) {
145      rr.ttl=makeTTLFromZone(nextpart);
146      haveTTL=true;
147      // cout<<"ttl is probably: "<<rr.ttl<<endl;
148      continue;
149    }
150    if(haveQTYPE) 
151      break;
152
153    try {
154      rr.qtype=DNSRecordContent::TypeToNumber(nextpart);
155      // cout<<"Got qtype ("<<rr.qtype.getCode()<<")\n";
156      haveQTYPE=1;
157      continue;
158    }
159    catch(...) {
160      cerr<<"Oops, this doesn't look like a qtype, stopping loop\n";
161      break;
162    }
163  }
164  if(!haveQTYPE) 
165    throw exception("Malformed line '"+d_line+"'");
166
167  rr.content=d_line.substr(range.first);
168
169  string::size_type pos=rr.content.rfind(';');
170  if(pos!=string::npos)
171    rr.content.resize(pos);
172
173  if(rr.qtype.getCode()!=QType::TXT && (pos=rr.content.find('('))!=string::npos) {
174    rr.content.resize(pos); // chop off (
175    trim(rr.content);
176    while(getLine()) {
177      chomp(d_line,"\r\n ");
178      pos=d_line.rfind(';');
179      if(pos!=string::npos)
180        d_line.resize(pos);
181
182      trim(d_line);
183     
184      pos=d_line.find(')');
185      if(pos!=string::npos) {
186        d_line.resize(pos);
187        trim(d_line);
188        rr.content+=" "+d_line;
189        break;
190      }
191      rr.content+=" "+d_line;
192    }
193  }
194  vector<string> soaparts;
195  switch(rr.qtype.getCode()) {
196  case QType::MX:
197  case QType::NS:
198  case QType::CNAME:
199  case QType::PTR:
200  case QType::SRV:
201    rr.content=toCanonic(d_zonename, rr.content);
202    break;
203
204  case QType::SOA:
205    stringtok(soaparts, rr.content);
206    if(soaparts.size() > 1) {
207      soaparts[0]=toCanonic(d_zonename, soaparts[0]);
208      soaparts[1]=toCanonic(d_zonename, soaparts[1]);
209    }
210    rr.content.clear();
211    for(string::size_type n = 0; n < soaparts.size(); ++n) {
212      if(n)
213        rr.content.append(1,' ');
214      rr.content+=soaparts[n];
215    }
216  default:;
217  }
218
219  rr.d_place=DNSResourceRecord::ANSWER;
220  return true;
221}
222
223bool ZoneParserTNG::getLine()
224{
225  char buffer[1024];
226  if(fgets(buffer, 1024, d_fp)) {
227    d_line=buffer;
228    return true;
229  }
230  return false;
231}
232
233
234#if 0
235int main(int argc, char** argv)
236try
237{
238  reportAllTypes();
239  ZoneParserTNG zpt(argv[1]);
240  DNSResourceRecord rr;
241  while(zpt.get(rr)) {
242  }
243 
244
245}
246catch(...)
247{}
248#endif
Note: See TracBrowser for help on using the browser.