]>
Commit | Line | Data |
---|---|---|
f814d7c8 | 1 | /* |
6edbf68a PL |
2 | * This file is part of PowerDNS or dnsdist. |
3 | * Copyright -- PowerDNS.COM B.V. and its contributors | |
4 | * | |
5 | * This program is free software; you can redistribute it and/or modify | |
6 | * it under the terms of version 2 of the GNU General Public License as | |
7 | * published by the Free Software Foundation. | |
8 | * | |
9 | * In addition, for the avoidance of any doubt, permission is granted to | |
10 | * link this program with OpenSSL and to (re)distribute the binaries | |
11 | * produced as the result of such linking. | |
12 | * | |
13 | * This program is distributed in the hope that it will be useful, | |
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
16 | * GNU General Public License for more details. | |
17 | * | |
18 | * You should have received a copy of the GNU General Public License | |
19 | * along with this program; if not, write to the Free Software | |
20 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | |
21 | */ | |
870a0fe4 AT |
22 | #ifdef HAVE_CONFIG_H |
23 | #include "config.h" | |
24 | #endif | |
a416d398 | 25 | #include "ascii.hh" |
f814d7c8 BH |
26 | #include "dnsparser.hh" |
27 | #include "sstuff.hh" | |
28 | #include "misc.hh" | |
29 | #include "dnswriter.hh" | |
30 | #include "dnsrecords.hh" | |
f814d7c8 BH |
31 | #include "misc.hh" |
32 | #include <fstream> | |
33 | #include "dns.hh" | |
34 | #include "zoneparser-tng.hh" | |
125e4840 BH |
35 | #include <deque> |
36 | #include <boost/algorithm/string.hpp> | |
e0e48a7a | 37 | #include <system_error> |
f814d7c8 | 38 | |
3108d502 | 39 | static string g_INstr("IN"); |
40 | ||
675fa24c | 41 | ZoneParserTNG::ZoneParserTNG(const string& fname, const DNSName& zname, const string& reldir) : d_reldir(reldir), |
232f0877 | 42 | d_zonename(zname), d_defaultttl(3600), |
80ad238a AT |
43 | d_templatecounter(0), d_templatestop(0), |
44 | d_templatestep(0), d_havedollarttl(false){ | |
bf503cc0 BH |
45 | stackFile(fname); |
46 | } | |
47 | ||
675fa24c | 48 | ZoneParserTNG::ZoneParserTNG(const vector<string> zonedata, const DNSName& zname): |
8a70e507 CHB |
49 | d_zonename(zname), d_zonedata(zonedata), d_defaultttl(3600), |
50 | d_templatecounter(0), d_templatestop(0), d_templatestep(0), | |
51 | d_havedollarttl(false), d_fromfile(false) | |
0f0e73fe | 52 | { |
0f0e73fe | 53 | d_zonedataline = d_zonedata.begin(); |
0f0e73fe MS |
54 | } |
55 | ||
bf503cc0 BH |
56 | void ZoneParserTNG::stackFile(const std::string& fname) |
57 | { | |
58 | FILE *fp=fopen(fname.c_str(), "r"); | |
e0e48a7a PL |
59 | if(!fp) { |
60 | std::error_code ec (errno,std::generic_category()); | |
61 | throw std::system_error(ec, "Unable to open file '"+fname+"': "+stringerror()); | |
62 | } | |
cfe397d5 BH |
63 | |
64 | filestate fs(fp, fname); | |
65 | d_filestates.push(fs); | |
0f0e73fe | 66 | d_fromfile = true; |
f814d7c8 BH |
67 | } |
68 | ||
69 | ZoneParserTNG::~ZoneParserTNG() | |
70 | { | |
cfe397d5 BH |
71 | while(!d_filestates.empty()) { |
72 | fclose(d_filestates.top().d_fp); | |
73 | d_filestates.pop(); | |
bf503cc0 | 74 | } |
f814d7c8 BH |
75 | } |
76 | ||
125e4840 BH |
77 | static string makeString(const string& line, const pair<string::size_type, string::size_type>& range) |
78 | { | |
79 | return string(line.c_str() + range.first, range.second - range.first); | |
80 | } | |
81 | ||
cfe397d5 BH |
82 | static bool isTimeSpec(const string& nextpart) |
83 | { | |
84 | if(nextpart.empty()) | |
85 | return false; | |
86 | for(string::const_iterator iter = nextpart.begin(); iter != nextpart.end(); ++iter) { | |
87 | if(isdigit(*iter)) | |
88 | continue; | |
89 | if(iter+1 != nextpart.end()) | |
90 | return false; | |
91 | char c=tolower(*iter); | |
2326ec3f | 92 | return (c=='s' || c=='m' || c=='h' || c=='d' || c=='w' || c=='y'); |
cfe397d5 BH |
93 | } |
94 | return true; | |
95 | } | |
96 | ||
97 | ||
98 | unsigned int ZoneParserTNG::makeTTLFromZone(const string& str) | |
125e4840 BH |
99 | { |
100 | if(str.empty()) | |
101 | return 0; | |
102 | ||
97ce13be RG |
103 | unsigned int val; |
104 | try { | |
105 | val=pdns_stou(str); | |
106 | } | |
107 | catch (const std::out_of_range& oor) { | |
108 | throw PDNSException("Unable to parse time specification '"+str+"' "+getLineOfFile()); | |
109 | } | |
110 | ||
3108d502 | 111 | char lc=dns_tolower(str[str.length()-1]); |
125e4840 BH |
112 | if(!isdigit(lc)) |
113 | switch(lc) { | |
3108d502 | 114 | case 's': |
2326ec3f | 115 | break; |
3108d502 | 116 | case 'm': |
38e655b6 BH |
117 | val*=60; // minutes, not months! |
118 | break; | |
3108d502 | 119 | case 'h': |
125e4840 BH |
120 | val*=3600; |
121 | break; | |
3108d502 | 122 | case 'd': |
125e4840 BH |
123 | val*=3600*24; |
124 | break; | |
3108d502 | 125 | case 'w': |
125e4840 BH |
126 | val*=3600*24*7; |
127 | break; | |
3108d502 | 128 | case 'y': // ? :-) |
125e4840 BH |
129 | val*=3600*24*365; |
130 | break; | |
cfe397d5 | 131 | |
125e4840 | 132 | default: |
3fed7dbd | 133 | throw PDNSException("Unable to parse time specification '"+str+"' "+getLineOfFile()); |
125e4840 BH |
134 | } |
135 | return val; | |
136 | } | |
137 | ||
2e83ba09 BH |
138 | bool ZoneParserTNG::getTemplateLine() |
139 | { | |
b8c3ea84 | 140 | if(d_templateparts.empty() || d_templatecounter > d_templatestop) // no template, or done with |
2e83ba09 BH |
141 | return false; |
142 | ||
143 | string retline; | |
144 | for(parts_t::const_iterator iter = d_templateparts.begin() ; iter != d_templateparts.end(); ++iter) { | |
145 | if(iter != d_templateparts.begin()) | |
146 | retline+=" "; | |
147 | ||
148 | string part=makeString(d_templateline, *iter); | |
149 | ||
150 | /* a part can contain a 'naked' $, an escaped $ (\$), or ${offset,width,radix}, with width defaulting to 0, | |
f1f15cb2 | 151 | and radix being 'd', 'o', 'x' or 'X', defaulting to 'd'. |
2e83ba09 BH |
152 | |
153 | The width is zero-padded, so if the counter is at 1, the offset is 15, with is 3, and the radix is 'x', | |
154 | output will be '010', from the input of ${15,3,x} | |
155 | */ | |
156 | ||
157 | string outpart; | |
158 | outpart.reserve(part.size()+5); | |
159 | bool inescape=false; | |
160 | ||
161 | for(string::size_type pos = 0; pos < part.size() ; ++pos) { | |
162 | char c=part[pos]; | |
163 | if(inescape) { | |
4957a608 BH |
164 | outpart.append(1, c); |
165 | inescape=false; | |
166 | continue; | |
2e83ba09 | 167 | } |
4957a608 | 168 | |
2e83ba09 | 169 | if(part[pos]=='\\') { |
4957a608 BH |
170 | inescape=true; |
171 | continue; | |
2e83ba09 BH |
172 | } |
173 | if(c=='$') { | |
4957a608 | 174 | if(pos + 1 == part.size() || part[pos+1]!='{') { // a trailing $, or not followed by { |
335da0ba | 175 | outpart.append(std::to_string(d_templatecounter)); |
4957a608 BH |
176 | continue; |
177 | } | |
178 | ||
179 | // need to deal with { case | |
180 | ||
181 | pos+=2; | |
182 | string::size_type startPos=pos; | |
183 | for(; pos < part.size() && part[pos]!='}' ; ++pos) | |
184 | ; | |
185 | ||
186 | if(pos == part.size()) // partial spec | |
187 | break; | |
188 | ||
189 | // we are on the '}' | |
190 | ||
191 | string spec(part.c_str() + startPos, part.c_str() + pos); | |
192 | int offset=0, width=0; | |
193 | char radix='d'; | |
194 | sscanf(spec.c_str(), "%d,%d,%c", &offset, &width, &radix); // parse format specifier | |
195 | ||
4957a608 | 196 | char tmp[80]; |
4338e69f OM |
197 | switch (radix) { |
198 | case 'o': | |
199 | snprintf(tmp, sizeof(tmp), "%0*o", width, d_templatecounter + offset); | |
200 | break; | |
201 | case 'x': | |
202 | snprintf(tmp, sizeof(tmp), "%0*x", width, d_templatecounter + offset); | |
203 | break; | |
204 | case 'X': | |
205 | snprintf(tmp, sizeof(tmp), "%0*X", width, d_templatecounter + offset); | |
206 | break; | |
207 | case 'd': | |
208 | default: | |
209 | snprintf(tmp, sizeof(tmp), "%0*d", width, d_templatecounter + offset); | |
210 | break; | |
211 | } | |
4957a608 | 212 | outpart+=tmp; |
2e83ba09 BH |
213 | } |
214 | else | |
4957a608 | 215 | outpart.append(1, c); |
2e83ba09 BH |
216 | } |
217 | retline+=outpart; | |
218 | } | |
219 | d_templatecounter+=d_templatestep; | |
220 | ||
221 | d_line = retline; | |
222 | return true; | |
223 | } | |
224 | ||
050e6877 | 225 | static void chopComment(string& line) |
a09683af | 226 | { |
3108d502 | 227 | if(line.find(';')==string::npos) |
228 | return; | |
a09683af BH |
229 | string::size_type pos, len = line.length(); |
230 | bool inQuote=false; | |
231 | for(pos = 0 ; pos < len; ++pos) { | |
232 | if(line[pos]=='\\') | |
233 | pos++; | |
234 | else if(line[pos]=='"') | |
235 | inQuote=!inQuote; | |
236 | else if(line[pos]==';' && !inQuote) | |
237 | break; | |
238 | } | |
239 | if(pos != len) | |
240 | line.resize(pos); | |
241 | } | |
242 | ||
050e6877 | 243 | static bool findAndElide(string& line, char c) |
9f0076d7 BH |
244 | { |
245 | string::size_type pos, len = line.length(); | |
246 | bool inQuote=false; | |
247 | for(pos = 0 ; pos < len; ++pos) { | |
248 | if(line[pos]=='\\') | |
249 | pos++; | |
250 | else if(line[pos]=='"') | |
251 | inQuote=!inQuote; | |
252 | else if(line[pos]==c && !inQuote) | |
253 | break; | |
254 | } | |
255 | if(pos != len) { | |
256 | line.erase(pos, 1); | |
257 | return true; | |
258 | } | |
259 | return false; | |
260 | } | |
261 | ||
d16a2ccf PL |
262 | DNSName ZoneParserTNG::getZoneName() |
263 | { | |
264 | return d_zonename; | |
265 | } | |
266 | ||
d27ea394 BH |
267 | string ZoneParserTNG::getLineOfFile() |
268 | { | |
0f0e73fe | 269 | if (d_zonedata.size() > 0) |
335da0ba | 270 | return "on line "+std::to_string(std::distance(d_zonedata.begin(), d_zonedataline))+" of given string"; |
0f0e73fe | 271 | |
a1239f65 RG |
272 | if (d_filestates.empty()) |
273 | return ""; | |
274 | ||
335da0ba | 275 | return "on line "+std::to_string(d_filestates.top().d_lineno)+" of file '"+d_filestates.top().d_filename+"'"; |
d27ea394 | 276 | } |
cfe397d5 | 277 | |
c91effc8 | 278 | pair<string,int> ZoneParserTNG::getLineNumAndFile() |
279 | { | |
9923fc22 PD |
280 | if (d_filestates.empty()) |
281 | return {"", 0}; | |
282 | else | |
283 | return {d_filestates.top().d_filename, d_filestates.top().d_lineno}; | |
c91effc8 | 284 | } |
285 | ||
4950b140 | 286 | bool ZoneParserTNG::get(DNSResourceRecord& rr, std::string* comment) |
f814d7c8 BH |
287 | { |
288 | retry:; | |
2e83ba09 | 289 | if(!getTemplateLine() && !getLine()) |
f814d7c8 | 290 | return false; |
125e4840 | 291 | |
1e01f0f5 | 292 | boost::trim_right_if(d_line, is_any_of(" \t\r\n\x1a")); |
a5a1f447 | 293 | if(comment) |
294 | comment->clear(); | |
295 | if(comment && d_line.find(';') != string::npos) | |
296 | *comment = d_line.substr(d_line.find(';')); | |
125e4840 | 297 | |
9bbcf03a RG |
298 | d_parts.clear(); |
299 | vstringtok(d_parts, d_line); | |
300 | ||
301 | if(d_parts.empty()) | |
125e4840 BH |
302 | goto retry; |
303 | ||
9bbcf03a | 304 | if(d_parts[0].first != d_parts[0].second && d_line[d_parts[0].first]==';') // line consisting of nothing but comments |
4d2c97aa BH |
305 | goto retry; |
306 | ||
125e4840 | 307 | if(d_line[0]=='$') { |
9bbcf03a RG |
308 | string command=makeString(d_line, d_parts[0]); |
309 | if(pdns_iequals(command,"$TTL") && d_parts.size() > 1) { | |
310 | d_defaultttl=makeTTLFromZone(trim_right_copy_if(makeString(d_line, d_parts[1]), is_any_of(";"))); | |
df1d406a BH |
311 | d_havedollarttl=true; |
312 | } | |
9bbcf03a RG |
313 | else if(pdns_iequals(command,"$INCLUDE") && d_parts.size() > 1 && d_fromfile) { |
314 | string fname=unquotify(makeString(d_line, d_parts[1])); | |
da042e6e | 315 | if(!fname.empty() && fname[0]!='/' && !d_reldir.empty()) |
4957a608 | 316 | fname=d_reldir+"/"+fname; |
da042e6e | 317 | stackFile(fname); |
bf503cc0 | 318 | } |
9bbcf03a RG |
319 | else if(pdns_iequals(command, "$ORIGIN") && d_parts.size() > 1) { |
320 | d_zonename = DNSName(makeString(d_line, d_parts[1])); | |
2e83ba09 | 321 | } |
9bbcf03a | 322 | else if(pdns_iequals(command, "$GENERATE") && d_parts.size() > 2) { |
91a862bf RG |
323 | if (!d_generateEnabled) { |
324 | throw exception("$GENERATE is not allowed in this zone"); | |
325 | } | |
bf503cc0 | 326 | // $GENERATE 1-127 $ CNAME $.0 |
9bbcf03a | 327 | string range=makeString(d_line, d_parts[1]); |
2e83ba09 BH |
328 | d_templatestep=1; |
329 | d_templatestop=0; | |
bfce2f57 | 330 | sscanf(range.c_str(),"%u-%u/%u", &d_templatecounter, &d_templatestop, &d_templatestep); |
775a673a OM |
331 | if (d_templatestep < 1 || |
332 | d_templatestop < d_templatecounter) { | |
b4ab09cd | 333 | throw exception("Invalid $GENERATE parameters"); |
775a673a | 334 | } |
ba3d53d1 RG |
335 | if (d_maxGenerateSteps != 0) { |
336 | size_t numberOfSteps = (d_templatestop - d_templatecounter) / d_templatestep; | |
337 | if (numberOfSteps > d_maxGenerateSteps) { | |
338 | throw exception("The number of $GENERATE steps (" + std::to_string(numberOfSteps) + ") is too high, the maximum is set to " + std::to_string(d_maxGenerateSteps)); | |
339 | } | |
340 | } | |
2e83ba09 | 341 | d_templateline=d_line; |
9bbcf03a RG |
342 | d_parts.pop_front(); |
343 | d_parts.pop_front(); | |
2e83ba09 | 344 | |
9bbcf03a | 345 | d_templateparts=d_parts; |
2e83ba09 | 346 | goto retry; |
bf503cc0 | 347 | } |
125e4840 | 348 | else |
d27ea394 | 349 | throw exception("Can't parse zone line '"+d_line+"' "+getLineOfFile()); |
f814d7c8 | 350 | goto retry; |
f814d7c8 | 351 | } |
125e4840 | 352 | |
e720f311 | 353 | bool prevqname=false; |
9bbcf03a | 354 | string qname = makeString(d_line, d_parts[0]); // Don't use DNSName here! |
3108d502 | 355 | if(dns_isspace(d_line[0])) { |
125e4840 | 356 | rr.qname=d_prevqname; |
e720f311 KM |
357 | prevqname=true; |
358 | }else { | |
8171ab83 | 359 | rr.qname=DNSName(qname); |
9bbcf03a | 360 | d_parts.pop_front(); |
e720f311 | 361 | if(qname.empty() || qname[0]==';') |
125e4840 BH |
362 | goto retry; |
363 | } | |
d66269ef | 364 | if(qname=="@") |
125e4840 | 365 | rr.qname=d_zonename; |
e720f311 | 366 | else if(!prevqname && !isCanonical(qname)) |
675fa24c | 367 | rr.qname += d_zonename; |
125e4840 BH |
368 | d_prevqname=rr.qname; |
369 | ||
9bbcf03a | 370 | if(d_parts.empty()) |
d27ea394 | 371 | throw exception("Line with too little parts "+getLineOfFile()); |
125e4840 | 372 | |
125e4840 | 373 | string nextpart; |
f814d7c8 | 374 | |
125e4840 BH |
375 | rr.ttl=d_defaultttl; |
376 | bool haveTTL=0, haveQTYPE=0; | |
377 | pair<string::size_type, string::size_type> range; | |
378 | ||
9bbcf03a RG |
379 | while(!d_parts.empty()) { |
380 | range=d_parts.front(); | |
381 | d_parts.pop_front(); | |
125e4840 BH |
382 | nextpart=makeString(d_line, range); |
383 | if(nextpart.empty()) | |
384 | break; | |
385 | ||
a5a1f447 | 386 | if(nextpart.find(';')!=string::npos) { |
125e4840 | 387 | break; |
a5a1f447 | 388 | } |
125e4840 BH |
389 | |
390 | // cout<<"Next part: '"<<nextpart<<"'"<<endl; | |
3108d502 | 391 | |
392 | if(pdns_iequals(nextpart, g_INstr)) { | |
125e4840 BH |
393 | // cout<<"Ignoring 'IN'\n"; |
394 | continue; | |
395 | } | |
cfe397d5 | 396 | if(!haveTTL && !haveQTYPE && isTimeSpec(nextpart)) { |
125e4840 | 397 | rr.ttl=makeTTLFromZone(nextpart); |
7fd6c67e | 398 | if(!d_havedollarttl) |
399 | d_defaultttl = rr.ttl; | |
125e4840 BH |
400 | haveTTL=true; |
401 | // cout<<"ttl is probably: "<<rr.ttl<<endl; | |
402 | continue; | |
403 | } | |
404 | if(haveQTYPE) | |
405 | break; | |
406 | ||
407 | try { | |
408 | rr.qtype=DNSRecordContent::TypeToNumber(nextpart); | |
409 | // cout<<"Got qtype ("<<rr.qtype.getCode()<<")\n"; | |
410 | haveQTYPE=1; | |
411 | continue; | |
412 | } | |
413 | catch(...) { | |
d27ea394 | 414 | throw runtime_error("Parsing zone content "+getLineOfFile()+ |
232f0877 CH |
415 | ": '"+nextpart+ |
416 | "' doesn't look like a qtype, stopping loop"); | |
125e4840 BH |
417 | } |
418 | } | |
419 | if(!haveQTYPE) | |
d27ea394 | 420 | throw exception("Malformed line "+getLineOfFile()+": '"+d_line+"'"); |
125e4840 | 421 | |
3108d502 | 422 | // rr.content=d_line.substr(range.first); |
423 | rr.content.assign(d_line, range.first, string::npos); | |
a09683af | 424 | chopComment(rr.content); |
1e01f0f5 | 425 | trim_if(rr.content, is_any_of(" \r\n\t\x1a")); |
849fde0b | 426 | |
3108d502 | 427 | if(rr.content.size()==1 && rr.content[0]=='@') |
90c3521b | 428 | rr.content=d_zonename.toString(); |
b33702d5 | 429 | |
9f0076d7 BH |
430 | if(findAndElide(rr.content, '(')) { // have found a ( and elided it |
431 | if(!findAndElide(rr.content, ')')) { | |
432 | while(getLine()) { | |
4957a608 BH |
433 | trim_right(d_line); |
434 | chopComment(d_line); | |
435 | trim(d_line); | |
436 | ||
437 | bool ended = findAndElide(d_line, ')'); | |
438 | rr.content+=" "+d_line; | |
439 | if(ended) | |
440 | break; | |
125e4840 | 441 | } |
125e4840 BH |
442 | } |
443 | } | |
1e01f0f5 | 444 | trim_if(rr.content, is_any_of(" \r\n\t\x1a")); |
9f0076d7 | 445 | |
43f40013 | 446 | vector<string> recparts; |
125e4840 BH |
447 | switch(rr.qtype.getCode()) { |
448 | case QType::MX: | |
43f40013 BH |
449 | stringtok(recparts, rr.content); |
450 | if(recparts.size()==2) { | |
1293f91e PL |
451 | if (recparts[1]!=".") { |
452 | try { | |
453 | recparts[1] = toCanonic(d_zonename, recparts[1]).toStringRootDot(); | |
454 | } catch (std::exception &e) { | |
86f1af1c | 455 | throw PDNSException("Error in record '" + rr.qname.toLogString() + " " + rr.qtype.getName() + "': " + e.what()); |
1293f91e PL |
456 | } |
457 | } | |
43f40013 BH |
458 | rr.content=recparts[0]+" "+recparts[1]; |
459 | } | |
460 | break; | |
25e0cd7f | 461 | |
6348d406 PD |
462 | case QType::RP: |
463 | stringtok(recparts, rr.content); | |
464 | if(recparts.size()==2) { | |
0c0e717c PD |
465 | recparts[0] = toCanonic(d_zonename, recparts[0]).toStringRootDot(); |
466 | recparts[1] = toCanonic(d_zonename, recparts[1]).toStringRootDot(); | |
6348d406 PD |
467 | rr.content=recparts[0]+" "+recparts[1]; |
468 | } | |
469 | break; | |
470 | ||
25e0cd7f BH |
471 | case QType::SRV: |
472 | stringtok(recparts, rr.content); | |
473 | if(recparts.size()==4) { | |
1293f91e PL |
474 | if(recparts[3]!=".") { |
475 | try { | |
476 | recparts[3] = toCanonic(d_zonename, recparts[3]).toStringRootDot(); | |
477 | } catch (std::exception &e) { | |
86f1af1c | 478 | throw PDNSException("Error in record '" + rr.qname.toLogString() + " " + rr.qtype.getName() + "': " + e.what()); |
1293f91e PL |
479 | } |
480 | } | |
25e0cd7f BH |
481 | rr.content=recparts[0]+" "+recparts[1]+" "+recparts[2]+" "+recparts[3]; |
482 | } | |
483 | break; | |
484 | ||
43f40013 | 485 | |
125e4840 BH |
486 | case QType::NS: |
487 | case QType::CNAME: | |
8dee0750 | 488 | case QType::DNAME: |
125e4840 | 489 | case QType::PTR: |
1293f91e PL |
490 | try { |
491 | rr.content = toCanonic(d_zonename, rr.content).toStringRootDot(); | |
492 | } catch (std::exception &e) { | |
86f1af1c | 493 | throw PDNSException("Error in record '" + rr.qname.toLogString() + " " + rr.qtype.getName() + "': " + e.what()); |
1293f91e | 494 | } |
125e4840 | 495 | break; |
319d6e47 | 496 | case QType::AFSDB: |
9f067a15 JJ |
497 | stringtok(recparts, rr.content); |
498 | if(recparts.size() == 2) { | |
499 | try { | |
319d6e47 | 500 | recparts[1]=toCanonic(d_zonename, recparts[1]).toStringRootDot(); |
9f067a15 | 501 | } catch (std::exception &e) { |
86f1af1c | 502 | throw PDNSException("Error in record '" + rr.qname.toLogString() + " " + rr.qtype.getName() + "': " + e.what()); |
319d6e47 | 503 | } |
9f067a15 | 504 | } else { |
86f1af1c | 505 | throw PDNSException("AFSDB record for "+rr.qname.toLogString()+" invalid"); |
9f067a15 JJ |
506 | } |
507 | rr.content.clear(); | |
508 | for(string::size_type n = 0; n < recparts.size(); ++n) { | |
509 | if(n) | |
510 | rr.content.append(1,' '); | |
125e4840 | 511 | |
9f067a15 | 512 | rr.content+=recparts[n]; |
319d6e47 JJ |
513 | } |
514 | break; | |
125e4840 | 515 | case QType::SOA: |
43f40013 | 516 | stringtok(recparts, rr.content); |
0c306c7c | 517 | if(recparts.size() > 7) |
86f1af1c | 518 | throw PDNSException("SOA record contents for "+rr.qname.toLogString()+" contains too many parts"); |
43f40013 | 519 | if(recparts.size() > 1) { |
562c0b13 PL |
520 | try { |
521 | recparts[0]=toCanonic(d_zonename, recparts[0]).toStringRootDot(); | |
522 | recparts[1]=toCanonic(d_zonename, recparts[1]).toStringRootDot(); | |
1293f91e | 523 | } catch (std::exception &e) { |
86f1af1c | 524 | throw PDNSException("Error in record '" + rr.qname.toLogString() + " " + rr.qtype.getName() + "': " + e.what()); |
562c0b13 | 525 | } |
125e4840 BH |
526 | } |
527 | rr.content.clear(); | |
43f40013 | 528 | for(string::size_type n = 0; n < recparts.size(); ++n) { |
125e4840 | 529 | if(n) |
4957a608 | 530 | rr.content.append(1,' '); |
c9f935fa | 531 | |
82cc6877 | 532 | if(n > 1) |
335da0ba | 533 | rr.content+=std::to_string(makeTTLFromZone(recparts[n])); |
82cc6877 | 534 | else |
43f40013 | 535 | rr.content+=recparts[n]; |
125e4840 | 536 | } |
38e655b6 | 537 | break; |
125e4840 BH |
538 | default:; |
539 | } | |
f814d7c8 BH |
540 | return true; |
541 | } | |
542 | ||
834942f1 | 543 | |
f814d7c8 BH |
544 | bool ZoneParserTNG::getLine() |
545 | { | |
0f0e73fe MS |
546 | if (d_zonedata.size() > 0) { |
547 | if (d_zonedataline != d_zonedata.end()) { | |
548 | d_line = *d_zonedataline; | |
cb6655e7 | 549 | ++d_zonedataline; |
0f0e73fe MS |
550 | return true; |
551 | } | |
552 | return false; | |
553 | } | |
cfe397d5 | 554 | while(!d_filestates.empty()) { |
834942f1 | 555 | if(stringfgets(d_filestates.top().d_fp, d_line)) { |
cfe397d5 | 556 | d_filestates.top().d_lineno++; |
bf503cc0 BH |
557 | return true; |
558 | } | |
cfe397d5 BH |
559 | fclose(d_filestates.top().d_fp); |
560 | d_filestates.pop(); | |
f814d7c8 BH |
561 | } |
562 | return false; | |
563 | } |