]> git.ipfire.org Git - thirdparty/pdns.git/blame - pdns/reczones.cc
Make the constructors taking a pthread_rwlock_t * private.
[thirdparty/pdns.git] / pdns / reczones.cc
CommitLineData
49a699c4 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
49a699c4
BH
25#include "syncres.hh"
26#include "arguments.hh"
27#include "zoneparser-tng.hh"
28#include "logger.hh"
29#include "dnsrecords.hh"
10c96475 30#include "root-addresses.hh"
302df819
AT
31
32extern int g_argc;
33extern char** g_argv;
49a699c4 34
1b4e0ae0
OM
35static thread_local set<DNSName> t_rootNSZones;
36
feb47aed
OM
37static void insertIntoRootNSZones(const DNSName &name) {
38 // do not insert dot, wiping dot's NS records from the cache in primeRootNSZones()
39 // will cause infinite recursion
40 if (!name.isRoot()) {
41 t_rootNSZones.insert(name);
42 }
43}
44
49a699c4
BH
45void primeHints(void)
46{
47 // prime root cache
fb17a52f 48 const vState validationState = Insecure;
e325f20c 49 vector<DNSRecord> nsset;
1b4e0ae0 50 t_rootNSZones.clear();
49a699c4
BH
51
52 if(::arg()["hint-file"].empty()) {
e325f20c 53 DNSRecord arr, aaaarr, nsrr;
12c06211 54 nsrr.d_name=g_rootdnsname;
e325f20c 55 arr.d_type=QType::A;
56 aaaarr.d_type=QType::AAAA;
57 nsrr.d_type=QType::NS;
58 arr.d_ttl=aaaarr.d_ttl=nsrr.d_ttl=time(0)+3600000;
49a699c4
BH
59
60 for(char c='a';c<='m';++c) {
e863a05a 61 char templ[40];
49a699c4 62 strncpy(templ,"a.root-servers.net.", sizeof(templ) - 1);
a683e8bd 63 templ[sizeof(templ)-1] = '\0';
49a699c4 64 *templ=c;
e325f20c 65 aaaarr.d_name=arr.d_name=DNSName(templ);
feb47aed 66 insertIntoRootNSZones(arr.d_name.getLastLabel());
e325f20c 67 nsrr.d_content=std::make_shared<NSRecordContent>(DNSName(templ));
10c96475 68 arr.d_content=std::make_shared<ARecordContent>(ComboAddress(rootIps4[c-'a']));
e325f20c 69 vector<DNSRecord> aset;
70 aset.push_back(arr);
d6fd3cb8 71 s_RC->replace(time(0), DNSName(templ), QType(QType::A), aset, vector<std::shared_ptr<RRSIGRecordContent>>(), vector<std::shared_ptr<DNSRecord>>(), true, boost::none, boost::none, validationState); // auth, nuke it all
10c96475
PL
72 if (rootIps6[c-'a'] != NULL) {
73 aaaarr.d_content=std::make_shared<AAAARecordContent>(ComboAddress(rootIps6[c-'a']));
49a699c4 74
e325f20c 75 vector<DNSRecord> aaaaset;
76 aaaaset.push_back(aaaarr);
d6fd3cb8 77 s_RC->replace(time(0), DNSName(templ), QType(QType::AAAA), aaaaset, vector<std::shared_ptr<RRSIGRecordContent>>(), vector<std::shared_ptr<DNSRecord>>(), true, boost::none, boost::none, validationState);
49a699c4
BH
78 }
79
e325f20c 80 nsset.push_back(nsrr);
49a699c4
BH
81 }
82 }
83 else {
84 ZoneParserTNG zpt(::arg()["hint-file"]);
ba3d53d1 85 zpt.setMaxGenerateSteps(::arg().asNum("max-generate-steps"));
49a699c4
BH
86 DNSResourceRecord rr;
87
88 while(zpt.get(rr)) {
89 rr.ttl+=time(0);
90 if(rr.qtype.getCode()==QType::A) {
e325f20c 91 vector<DNSRecord> aset;
92 aset.push_back(DNSRecord(rr));
d6fd3cb8 93 s_RC->replace(time(0), rr.qname, QType(QType::A), aset, vector<std::shared_ptr<RRSIGRecordContent>>(), vector<std::shared_ptr<DNSRecord>>(), true, boost::none, boost::none, validationState); // auth, etc see above
49a699c4 94 } else if(rr.qtype.getCode()==QType::AAAA) {
e325f20c 95 vector<DNSRecord> aaaaset;
96 aaaaset.push_back(DNSRecord(rr));
d6fd3cb8 97 s_RC->replace(time(0), rr.qname, QType(QType::AAAA), aaaaset, vector<std::shared_ptr<RRSIGRecordContent>>(), vector<std::shared_ptr<DNSRecord>>(), true, boost::none, boost::none, validationState);
49a699c4
BH
98 } else if(rr.qtype.getCode()==QType::NS) {
99 rr.content=toLower(rr.content);
e325f20c 100 nsset.push_back(DNSRecord(rr));
49a699c4 101 }
feb47aed 102 insertIntoRootNSZones(rr.qname.getLastLabel());
49a699c4
BH
103 }
104 }
a7956123 105 s_RC->doWipeCache(g_rootdnsname, false, QType::NS);
d6fd3cb8 106 s_RC->replace(time(0), g_rootdnsname, QType(QType::NS), nsset, vector<std::shared_ptr<RRSIGRecordContent>>(), vector<std::shared_ptr<DNSRecord>>(), false, boost::none, boost::none, validationState); // and stuff in the cache
1b4e0ae0
OM
107}
108
c16c8fe5
OM
109
110// Do not only put the root hints into the cache, but also make sure
111// the NS records of the top level domains of the names of the root
112// servers are in the cache. We need these to correctly determine the
113// security status of that specific domain (normally
114// root-servers.net). This is caused by the accident that the root
115// servers are authoritative for root-servers.net, and some
116// implementations reply not with a delegation on a root-servers.net
117// DS query, but with a NODATA response (the domain is unsigned).
1b4e0ae0
OM
118void primeRootNSZones(bool dnssecmode)
119{
120 struct timeval now;
121 gettimeofday(&now, 0);
122 SyncRes sr(now);
123
124 if (dnssecmode) {
125 sr.setDoDNSSEC(true);
126 sr.setDNSSECValidationRequested(true);
127 }
17b71b05
OM
128
129 // beginResolve() can yield to another mthread that could trigger t_rootNSZones updates,
130 // so make a local copy
131 set<DNSName> copy(t_rootNSZones);
132 for (const auto & qname: copy) {
a7956123 133 s_RC->doWipeCache(qname, false, QType::NS);
1b4e0ae0
OM
134 vector<DNSRecord> ret;
135 sr.beginResolve(qname, QType(QType::NS), QClass::IN, ret);
136 }
49a699c4
BH
137}
138
9065eb05 139static void makeNameToIPZone(std::shared_ptr<SyncRes::domainmap_t> newMap, const DNSName& hostname, const string& ip)
49a699c4
BH
140{
141 SyncRes::AuthDomain ad;
687fe166
CH
142 ad.d_rdForward=false;
143
e325f20c 144 DNSRecord dr;
145 dr.d_name=hostname;
e693ff5a 146 dr.d_place=DNSResourceRecord::ANSWER;
e325f20c 147 dr.d_ttl=86400;
148 dr.d_type=QType::SOA;
149 dr.d_class = 1;
6177a176 150 dr.d_content = DNSRecordContent::mastermake(QType::SOA, 1, "localhost. root 1 604800 86400 2419200 604800");
49a699c4 151
e325f20c 152 ad.d_records.insert(dr);
49a699c4 153
e325f20c 154 dr.d_type=QType::NS;
155 dr.d_content=std::make_shared<NSRecordContent>("localhost.");
49a699c4 156
e325f20c 157 ad.d_records.insert(dr);
49a699c4 158
e325f20c 159 dr.d_type=QType::A;
6177a176 160 dr.d_content = DNSRecordContent::mastermake(QType::A, 1, ip);
e325f20c 161 ad.d_records.insert(dr);
49a699c4 162
e325f20c 163 if(newMap->count(dr.d_name)) {
e6a9dde5 164 g_log<<Logger::Warning<<"Hosts file will not overwrite zone '"<<dr.d_name<<"' already loaded"<<endl;
49a699c4
BH
165 }
166 else {
e6a9dde5 167 g_log<<Logger::Warning<<"Inserting forward zone '"<<dr.d_name<<"' based on hosts file"<<endl;
3337c2f7
RG
168 ad.d_name=dr.d_name;
169 (*newMap)[ad.d_name]=ad;
49a699c4
BH
170 }
171}
172
173//! parts[0] must be an IP address, the rest must be host names
9065eb05 174static void makeIPToNamesZone(std::shared_ptr<SyncRes::domainmap_t> newMap, const vector<string>& parts)
49a699c4
BH
175{
176 string address=parts[0];
177 vector<string> ipparts;
178 stringtok(ipparts, address,".");
179
180 SyncRes::AuthDomain ad;
687fe166
CH
181 ad.d_rdForward=false;
182
e325f20c 183 DNSRecord dr;
49a699c4 184 for(int n=ipparts.size()-1; n>=0 ; --n) {
e325f20c 185 dr.d_name.appendRawLabel(ipparts[n]);
49a699c4 186 }
e325f20c 187 dr.d_name.appendRawLabel("in-addr");
188 dr.d_name.appendRawLabel("arpa");
189 dr.d_class = 1;
e693ff5a 190 dr.d_place=DNSResourceRecord::ANSWER;
e325f20c 191 dr.d_ttl=86400;
192 dr.d_type=QType::SOA;
6177a176 193 dr.d_content=DNSRecordContent::mastermake(QType::SOA, 1, "localhost. root 1 604800 86400 2419200 604800");
49a699c4 194
e325f20c 195 ad.d_records.insert(dr);
49a699c4 196
e325f20c 197 dr.d_type=QType::NS;
198 dr.d_content=std::make_shared<NSRecordContent>(DNSName("localhost."));
49a699c4 199
e325f20c 200 ad.d_records.insert(dr);
201 dr.d_type=QType::PTR;
49a699c4
BH
202
203 if(ipparts.size()==4) // otherwise this is a partial zone
204 for(unsigned int n=1; n < parts.size(); ++n) {
6177a176 205 dr.d_content=DNSRecordContent::mastermake(QType::PTR, 1, DNSName(parts[n]).toString()); // XXX FIXME DNSNAME PAIN CAN THIS BE RIGHT?
e325f20c 206 ad.d_records.insert(dr);
49a699c4
BH
207 }
208
e325f20c 209 if(newMap->count(dr.d_name)) {
e6a9dde5 210 g_log<<Logger::Warning<<"Will not overwrite zone '"<<dr.d_name<<"' already loaded"<<endl;
49a699c4
BH
211 }
212 else {
213 if(ipparts.size()==4)
e6a9dde5 214 g_log<<Logger::Warning<<"Inserting reverse zone '"<<dr.d_name<<"' based on hosts file"<<endl;
3337c2f7
RG
215 ad.d_name = dr.d_name;
216 (*newMap)[ad.d_name]=ad;
49a699c4
BH
217 }
218}
219
220
221
222/* mission in life: parse three cases
223 1) 1.2.3.4
224 2) 1.2.3.4:5300
225 3) 2001::1
226 4) [2002::1]:53
227*/
228
229ComboAddress parseIPAndPort(const std::string& input, uint16_t port)
230{
231 if(input.find(':') == string::npos || input.empty()) // common case
232 return ComboAddress(input, port);
233
234 pair<string,string> both;
235
236 try { // case 2
237 both=splitField(input,':');
335da0ba 238 uint16_t newport=static_cast<uint16_t>(pdns_stou(both.second));
49a699c4
BH
239 return ComboAddress(both.first, newport);
240 }
241 catch(...){}
242
243 if(input[0]=='[') { // case 4
244 both=splitField(input.substr(1),']');
335da0ba 245 return ComboAddress(both.first, both.second.empty() ? port : static_cast<uint16_t>(pdns_stou(both.second.substr(1))));
49a699c4
BH
246 }
247
248 return ComboAddress(input, port); // case 3
249}
250
251
050e6877 252static void convertServersForAD(const std::string& input, SyncRes::AuthDomain& ad, const char* sepa, bool verbose=true)
49a699c4
BH
253{
254 vector<string> servers;
255 stringtok(servers, input, sepa);
256 ad.d_servers.clear();
257
258 for(vector<string>::const_iterator iter = servers.begin(); iter != servers.end(); ++iter) {
259 if(verbose && iter != servers.begin())
e6a9dde5 260 g_log<<", ";
49a699c4
BH
261
262 ComboAddress addr=parseIPAndPort(*iter, 53);
263 if(verbose)
e6a9dde5 264 g_log<<addr.toStringWithPort();
49a699c4
BH
265 ad.d_servers.push_back(addr);
266 }
267 if(verbose)
e6a9dde5 268 g_log<<endl;
49a699c4
BH
269}
270
050e6877 271static void* pleaseUseNewSDomainsMap(std::shared_ptr<SyncRes::domainmap_t> newmap)
49a699c4 272{
a712cb56 273 SyncRes::setDomainMap(newmap);
3427fa8a 274 return 0;
49a699c4
BH
275}
276
277string reloadAuthAndForwards()
278{
a712cb56 279 std::shared_ptr<SyncRes::domainmap_t> original=SyncRes::getDomainMap();
49a699c4
BH
280
281 try {
e6a9dde5 282 g_log<<Logger::Warning<<"Reloading zones, purging data from cache"<<endl;
a712cb56 283
49a699c4 284 string configname=::arg()["config-dir"]+"/recursor.conf";
3e63da83
JR
285 if(::arg()["config-name"]!="") {
286 configname=::arg()["config-dir"]+"/recursor-"+::arg()["config-name"]+".conf";
287 }
49a699c4
BH
288 cleanSlashes(configname);
289
49e3ed87
PL
290 if(!::arg().preParseFile(configname.c_str(), "forward-zones"))
291 throw runtime_error("Unable to re-parse configuration file '"+configname+"'");
49a699c4 292 ::arg().preParseFile(configname.c_str(), "forward-zones-file");
4b6d1ba4 293 ::arg().preParseFile(configname.c_str(), "forward-zones-recurse");
49a699c4
BH
294 ::arg().preParseFile(configname.c_str(), "auth-zones");
295 ::arg().preParseFile(configname.c_str(), "export-etc-hosts", "off");
296 ::arg().preParseFile(configname.c_str(), "serve-rfc1918");
302df819
AT
297 ::arg().preParseFile(configname.c_str(), "include-dir");
298 ::arg().preParse(g_argc, g_argv, "include-dir");
299
300 // then process includes
301 std::vector<std::string> extraConfigs;
302 ::arg().gatherIncludes(extraConfigs);
303
ef7cd021 304 for(const std::string& fn : extraConfigs) {
49e3ed87
PL
305 if(!::arg().preParseFile(fn.c_str(), "forward-zones", ::arg()["forward-zones"]))
306 throw runtime_error("Unable to re-parse configuration file include '"+fn+"'");
302df819 307 ::arg().preParseFile(fn.c_str(), "forward-zones-file", ::arg()["forward-zones-file"]);
4b6d1ba4 308 ::arg().preParseFile(fn.c_str(), "forward-zones-recurse", ::arg()["forward-zones-recurse"]);
302df819
AT
309 ::arg().preParseFile(fn.c_str(), "auth-zones",::arg()["auth-zones"]);
310 ::arg().preParseFile(fn.c_str(), "export-etc-hosts",::arg()["export-etc-hosts"]);
311 ::arg().preParseFile(fn.c_str(), "serve-rfc1918",::arg()["serve-rfc1918"]);
312 }
49a699c4 313
452d5116
AT
314 ::arg().preParse(g_argc, g_argv, "forward-zones");
315 ::arg().preParse(g_argc, g_argv, "forward-zones-file");
4b6d1ba4 316 ::arg().preParse(g_argc, g_argv, "forward-zones-recurse");
452d5116
AT
317 ::arg().preParse(g_argc, g_argv, "auth-zones");
318 ::arg().preParse(g_argc, g_argv, "export-etc-hosts");
319 ::arg().preParse(g_argc, g_argv, "serve-rfc1918");
320
9065eb05 321 std::shared_ptr<SyncRes::domainmap_t> newDomainMap = parseAuthAndForwards();
b68af3ee 322
323 // purge both original and new names
324 std::set<DNSName> oldAndNewDomains;
9065eb05 325 for(const auto& i : *newDomainMap) {
b68af3ee 326 oldAndNewDomains.insert(i.first);
327 }
328
329 if(original) {
330 for(const auto& i : *original) {
331 oldAndNewDomains.insert(i.first);
332 }
333 }
334
7af99dff 335 for(const auto& i : oldAndNewDomains) {
2087df40
OM
336 broadcastAccFunction<uint64_t>(boost::bind(pleaseWipeCache, i, true, 0xffff));
337 broadcastAccFunction<uint64_t>(boost::bind(pleaseWipePacketCache, i, true, 0xffff));
338 broadcastAccFunction<uint64_t>(boost::bind(pleaseWipeAndCountNegCache, i, true));
49a699c4
BH
339 }
340
9065eb05 341 broadcastFunction(boost::bind(pleaseUseNewSDomainsMap, newDomainMap));
49a699c4
BH
342 return "ok\n";
343 }
344 catch(std::exception& e) {
e6a9dde5 345 g_log<<Logger::Error<<"Encountered error reloading zones, keeping original data: "<<e.what()<<endl;
49a699c4 346 }
3f81d239 347 catch(PDNSException& ae) {
e6a9dde5 348 g_log<<Logger::Error<<"Encountered error reloading zones, keeping original data: "<<ae.reason<<endl;
49a699c4
BH
349 }
350 catch(...) {
e6a9dde5 351 g_log<<Logger::Error<<"Encountered unknown error reloading zones, keeping original data"<<endl;
49a699c4
BH
352 }
353 return "reloading failed, see log\n";
354}
355
9065eb05 356std::shared_ptr<SyncRes::domainmap_t> parseAuthAndForwards()
49a699c4
BH
357{
358 TXTRecordContent::report();
359 OPTRecordContent::report();
360
9065eb05 361 auto newMap = std::make_shared<SyncRes::domainmap_t>();
49a699c4
BH
362
363 typedef vector<string> parts_t;
364 parts_t parts;
365 const char *option_names[3]={"auth-zones", "forward-zones", "forward-zones-recurse"};
366 for(int n=0; n < 3 ; ++n ) {
367 parts.clear();
39588f55 368 stringtok(parts, ::arg()[option_names[n]], " ,\t\n\r");
49a699c4
BH
369 for(parts_t::const_iterator iter = parts.begin(); iter != parts.end(); ++iter) {
370 SyncRes::AuthDomain ad;
71925546
AT
371 if ((*iter).find('=') == string::npos)
372 throw PDNSException("Error parsing '" + *iter + "', missing =");
49a699c4
BH
373 pair<string,string> headers=splitField(*iter, '=');
374 trim(headers.first);
375 trim(headers.second);
c5c066bf 376 // headers.first=toCanonic("", headers.first);
49a699c4 377 if(n==0) {
687fe166 378 ad.d_rdForward = false;
e6a9dde5 379 g_log<<Logger::Error<<"Parsing authoritative data for zone '"<<headers.first<<"' from file '"<<headers.second<<"'"<<endl;
c5c066bf 380 ZoneParserTNG zpt(headers.second, DNSName(headers.first));
ba3d53d1 381 zpt.setMaxGenerateSteps(::arg().asNum("max-generate-steps"));
49a699c4 382 DNSResourceRecord rr;
e325f20c 383 DNSRecord dr;
49a699c4
BH
384 while(zpt.get(rr)) {
385 try {
e325f20c 386 dr=DNSRecord(rr);
e693ff5a 387 dr.d_place=DNSResourceRecord::ANSWER;
49a699c4
BH
388 }
389 catch(std::exception &e) {
86f1af1c 390 throw PDNSException("Error parsing record '"+rr.qname.toLogString()+"' of type "+rr.qtype.getName()+" in zone '"+headers.first+"' from file '"+headers.second+"': "+e.what());
49a699c4
BH
391 }
392 catch(...) {
86f1af1c 393 throw PDNSException("Error parsing record '"+rr.qname.toLogString()+"' of type "+rr.qtype.getName()+" in zone '"+headers.first+"' from file '"+headers.second+"'");
49a699c4
BH
394 }
395
e325f20c 396 ad.d_records.insert(dr);
49a699c4
BH
397 }
398 }
399 else {
e6a9dde5 400 g_log<<Logger::Error<<"Redirecting queries for zone '"<<headers.first<<"' ";
49a699c4 401 if(n == 2) {
e6a9dde5 402 g_log<<"with recursion ";
687fe166 403 ad.d_rdForward = true;
49a699c4 404 }
687fe166 405 else ad.d_rdForward = false;
e6a9dde5 406 g_log<<"to: ";
49a699c4
BH
407
408 convertServersForAD(headers.second, ad, ";");
409 if(n == 2) {
687fe166 410 ad.d_rdForward = true;
49a699c4
BH
411 }
412 }
3337c2f7
RG
413
414 ad.d_name = DNSName(headers.first);
415 (*newMap)[ad.d_name]=ad;
49a699c4
BH
416 }
417 }
418
419 if(!::arg()["forward-zones-file"].empty()) {
e6a9dde5 420 g_log<<Logger::Warning<<"Reading zone forwarding information from '"<<::arg()["forward-zones-file"]<<"'"<<endl;
49a699c4 421 SyncRes::AuthDomain ad;
5e1f23ca
RG
422 auto fp = std::unique_ptr<FILE, int(*)(FILE*)>(fopen(::arg()["forward-zones-file"].c_str(), "r"), fclose);
423 if(!fp) {
3f81d239 424 throw PDNSException("Error opening forward-zones-file '"+::arg()["forward-zones-file"]+"': "+stringerror());
49a699c4
BH
425 }
426
834942f1 427 string line;
49a699c4
BH
428 int linenum=0;
429 uint64_t before = newMap->size();
834942f1 430 while(linenum++, stringfgets(fp.get(), line)) {
fa2909dc
PL
431 trim(line);
432 if (line[0] == '#') // Comment line, skip to the next line
433 continue;
49a699c4
BH
434 string domain, instructions;
435 tie(domain, instructions)=splitField(line, '=');
fa2909dc 436 instructions = splitField(instructions, '#').first; // Remove EOL comments
49a699c4
BH
437 trim(domain);
438 trim(instructions);
e58483cc
BH
439 if(domain.empty() && instructions.empty()) { // empty line
440 continue;
441 }
49a699c4
BH
442 if(boost::starts_with(domain,"+")) {
443 domain=domain.c_str()+1;
444 ad.d_rdForward = true;
445 }
446 else
447 ad.d_rdForward = false;
448 if(domain.empty()) {
335da0ba 449 throw PDNSException("Error parsing line "+std::to_string(linenum)+" of " +::arg()["forward-zones-file"]);
49a699c4
BH
450 }
451
452 try {
453 convertServersForAD(instructions, ad, ",; ", false);
454 }
455 catch(...) {
335da0ba 456 throw PDNSException("Conversion error parsing line "+std::to_string(linenum)+" of " +::arg()["forward-zones-file"]);
49a699c4
BH
457 }
458
3337c2f7
RG
459 ad.d_name = DNSName(domain);
460 (*newMap)[ad.d_name]=ad;
49a699c4 461 }
e6a9dde5 462 g_log<<Logger::Warning<<"Done parsing " << newMap->size() - before<<" forwarding instructions from file '"<<::arg()["forward-zones-file"]<<"'"<<endl;
49a699c4
BH
463 }
464
465 if(::arg().mustDo("export-etc-hosts")) {
466 string line;
467 string fname=::arg()["etc-hosts-file"];
468
469 ifstream ifs(fname.c_str());
470 if(!ifs) {
8c0128ef 471 g_log<<Logger::Warning<<"Could not open "<<fname<<" for reading"<<endl;
49a699c4
BH
472 }
473 else {
ac0b4eb3 474 string searchSuffix = ::arg()["export-etc-hosts-search-suffix"];
49a699c4
BH
475 string::size_type pos;
476 while(getline(ifs,line)) {
232f0877
CH
477 pos=line.find('#');
478 if(pos!=string::npos)
479 line.resize(pos);
480 trim(line);
481 if(line.empty())
482 continue;
483 parts.clear();
484 stringtok(parts, line, "\t\r\n ");
485 if(parts[0].find(':')!=string::npos)
486 continue;
487
488 for(unsigned int n=1; n < parts.size(); ++n) {
489 if(searchSuffix.empty() || parts[n].find('.') != string::npos)
8171ab83 490 makeNameToIPZone(newMap, DNSName(parts[n]), parts[0]);
232f0877 491 else {
8171ab83 492 DNSName canonic=toCanonic(DNSName(searchSuffix), parts[n]); /// XXXX DNSName pain
493 if(canonic != DNSName(parts[n])) { // XXX further DNSName pain
232f0877 494 makeNameToIPZone(newMap, canonic, parts[0]);
ac0b4eb3
BH
495 }
496 }
497 }
232f0877 498 makeIPToNamesZone(newMap, parts);
49a699c4
BH
499 }
500 }
501 }
502 if(::arg().mustDo("serve-rfc1918")) {
e6a9dde5 503 g_log<<Logger::Warning<<"Inserting rfc 1918 private space zones"<<endl;
49a699c4
BH
504 parts.clear();
505 parts.push_back("127");
506 makeIPToNamesZone(newMap, parts);
507 parts[0]="10";
508 makeIPToNamesZone(newMap, parts);
509
510 parts[0]="192.168";
511 makeIPToNamesZone(newMap, parts);
512 for(int n=16; n < 32; n++) {
335da0ba 513 parts[0]="172."+std::to_string(n);
49a699c4
BH
514 makeIPToNamesZone(newMap,parts);
515 }
516 }
517 return newMap;
518}