]> git.ipfire.org Git - thirdparty/pdns.git/blame - pdns/recursordist/reczones.cc
rec: Switch to `pdns::UniqueFilePtr`
[thirdparty/pdns.git] / pdns / recursordist / 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 */
84d4747e 22
870a0fe4
AT
23#ifdef HAVE_CONFIG_H
24#include "config.h"
25#endif
84d4747e 26
9883d3f9
OM
27#include <sys/stat.h>
28
23855ca0 29#include "reczones-helpers.hh"
49a699c4 30#include "arguments.hh"
49a699c4 31#include "dnsrecords.hh"
c6d82407
OM
32#include "logger.hh"
33#include "syncres.hh"
34#include "zoneparser-tng.hh"
9883d3f9 35#include "settings/cxxsettings.hh"
302df819
AT
36
37extern int g_argc;
38extern char** g_argv;
49a699c4 39
5c7e7d48
OM
40bool primeHints(time_t now)
41{
42 const string hintfile = ::arg()["hint-file"];
43 vector<DNSRecord> nsvec;
44 bool ret = true;
3e5afd94 45
0908f757 46 if (hintfile == "no" || hintfile == "no-refresh") {
5c7e7d48 47 auto log = g_slog->withName("config");
0908f757
OM
48 SLOG(g_log << Logger::Debug << "Priming root disabled by hint-file setting" << endl,
49 log->info(Logr::Debug, "Priming root disabled by hint-file setting"));
5c7e7d48
OM
50 return ret;
51 }
52
53 if (hintfile.empty()) {
54 putDefaultHintsIntoCache(now, nsvec);
55 }
56 else {
57 ret = readHintsIntoCache(now, hintfile, nsvec);
49a699c4 58 }
7d021373 59
ccfadb6c 60 g_recCache->doWipeCache(g_rootdnsname, false, QType::NS);
5c7e7d48
OM
61 g_recCache->replace(now, g_rootdnsname, QType::NS, nsvec, {}, {}, false, g_rootdnsname, boost::none, boost::none, vState::Insecure, ComboAddress("255.255.255.255")); // and stuff in the cache
62 return ret;
1b4e0ae0
OM
63}
64
199e75c7 65static void convertServersForAD(const std::string& zone, const std::string& input, SyncRes::AuthDomain& authDomain, const char* sepa, Logr::log_t log, bool verbose = true)
49a699c4
BH
66{
67 vector<string> servers;
68 stringtok(servers, input, sepa);
199e75c7 69 authDomain.d_servers.clear();
49a699c4 70
d8d1d955 71 vector<string> addresses;
199e75c7
OM
72 for (auto& server : servers) {
73 ComboAddress addr = parseIPAndPort(server, 53);
74 authDomain.d_servers.push_back(addr);
d8d1d955
OM
75 if (verbose) {
76 addresses.push_back(addr.toStringWithPort());
77 }
78 }
79 if (verbose) {
80 if (!g_slogStructured) {
81 g_log << Logger::Info << "Redirecting queries for zone '" << zone << "' ";
199e75c7 82 if (authDomain.d_rdForward) {
d8d1d955
OM
83 g_log << "with recursion ";
84 }
85 g_log << "to: ";
86 bool first = true;
199e75c7 87 for (const auto& address : addresses) {
6cb5db59 88 if (!first) {
d8d1d955 89 g_log << ", ";
6cb5db59
OM
90 }
91 else {
d8d1d955
OM
92 first = false;
93 }
199e75c7 94 g_log << address;
d8d1d955
OM
95 }
96 g_log << endl;
97 }
98 else {
199e75c7 99 log->info(Logr::Info, "Redirecting queries", "zone", Logging::Loggable(zone), "recursion", Logging::Loggable(authDomain.d_rdForward), "addresses", Logging::IterLoggable(addresses.begin(), addresses.end()));
d8d1d955 100 }
49a699c4 101 }
49a699c4
BH
102}
103
050e6877 104static void* pleaseUseNewSDomainsMap(std::shared_ptr<SyncRes::domainmap_t> newmap)
49a699c4 105{
645b217b 106 SyncRes::setDomainMap(std::move(newmap));
199e75c7 107 return nullptr;
49a699c4
BH
108}
109
9883d3f9 110string reloadZoneConfiguration(bool yaml)
49a699c4 111{
fa9fb323 112 std::shared_ptr<SyncRes::domainmap_t> original = SyncRes::getDomainMap();
d8d1d955 113 auto log = g_slog->withName("config");
6cb5db59 114
9883d3f9
OM
115 string configname = ::arg()["config-dir"] + "/recursor";
116 if (!::arg()["config-name"].empty()) {
117 configname = ::arg()["config-dir"] + "/recursor-" + ::arg()["config-name"];
118 }
119 cleanSlashes(configname);
120
49a699c4 121 try {
d8d1d955 122 SLOG(g_log << Logger::Warning << "Reloading zones, purging data from cache" << endl,
d197c31c 123 log->info(Logr::Notice, "Reloading zones, purging data from cache"));
a712cb56 124
9883d3f9
OM
125 if (yaml) {
126 configname += ".yml";
127 string msg;
128 pdns::rust::settings::rec::Recursorsettings settings;
129 // XXX Does ::arg()["include-dir"] have the right value, i.e. potentially overriden by command line?
130 auto yamlstatus = pdns::settings::rec::readYamlSettings(configname, ::arg()["include-dir"], settings, msg, log);
131
132 switch (yamlstatus) {
133 case pdns::settings::rec::YamlSettingsStatus::CannotOpen:
134 throw runtime_error("Unable to open '" + configname + "': " + msg);
135 break;
136 case pdns::settings::rec::YamlSettingsStatus::PresentButFailed:
137 throw runtime_error("Error processing '" + configname + "': " + msg);
138 break;
139 case pdns::settings::rec::YamlSettingsStatus::OK:
140 // Does *not* set include-dir
141 pdns::settings::rec::setArgsForZoneRelatedSettings(settings);
142 break;
143 }
302df819 144 }
9883d3f9
OM
145 else {
146 configname += ".conf";
49a699c4 147
9883d3f9
OM
148 if (!::arg().preParseFile(configname, "forward-zones")) {
149 throw runtime_error("Unable to re-parse configuration file '" + configname + "'");
150 }
151 ::arg().preParseFile(configname, "forward-zones-file");
152 ::arg().preParseFile(configname, "forward-zones-recurse");
153 ::arg().preParseFile(configname, "auth-zones");
154 ::arg().preParseFile(configname, "allow-notify-for");
155 ::arg().preParseFile(configname, "allow-notify-for-file");
156 ::arg().preParseFile(configname, "export-etc-hosts", "off");
157 ::arg().preParseFile(configname, "serve-rfc1918");
158 ::arg().preParseFile(configname, "include-dir");
159 ::arg().preParse(g_argc, g_argv, "include-dir");
160
161 // then process includes
162 std::vector<std::string> extraConfigs;
163 ::arg().gatherIncludes(::arg()["include-dir"], ".conf", extraConfigs);
164
165 for (const std::string& filename : extraConfigs) {
166 if (!::arg().preParseFile(filename, "forward-zones", ::arg()["forward-zones"])) {
167 throw runtime_error("Unable to re-parse configuration file include '" + filename + "'");
168 }
169 ::arg().preParseFile(filename, "forward-zones-file", ::arg()["forward-zones-file"]);
170 ::arg().preParseFile(filename, "forward-zones-recurse", ::arg()["forward-zones-recurse"]);
171 ::arg().preParseFile(filename, "auth-zones", ::arg()["auth-zones"]);
172 ::arg().preParseFile(filename, "allow-notify-for", ::arg()["allow-notify-for"]);
173 ::arg().preParseFile(filename, "allow-notify-for-file", ::arg()["allow-notify-for-file"]);
174 ::arg().preParseFile(filename, "export-etc-hosts", ::arg()["export-etc-hosts"]);
175 ::arg().preParseFile(filename, "serve-rfc1918", ::arg()["serve-rfc1918"]);
176 }
177 }
178 // Process command line args potentially overriding what we read from config files
452d5116
AT
179 ::arg().preParse(g_argc, g_argv, "forward-zones");
180 ::arg().preParse(g_argc, g_argv, "forward-zones-file");
4b6d1ba4 181 ::arg().preParse(g_argc, g_argv, "forward-zones-recurse");
452d5116 182 ::arg().preParse(g_argc, g_argv, "auth-zones");
35189b7d
KF
183 ::arg().preParse(g_argc, g_argv, "allow-notify-for");
184 ::arg().preParse(g_argc, g_argv, "allow-notify-for-file");
452d5116
AT
185 ::arg().preParse(g_argc, g_argv, "export-etc-hosts");
186 ::arg().preParse(g_argc, g_argv, "serve-rfc1918");
187
9883d3f9 188 auto [newDomainMap, newNotifySet] = parseZoneConfiguration(yaml);
b68af3ee 189
190 // purge both original and new names
191 std::set<DNSName> oldAndNewDomains;
9883d3f9
OM
192 for (const auto& entry : *newDomainMap) {
193 oldAndNewDomains.insert(entry.first);
b68af3ee 194 }
195
fa9fb323 196 if (original) {
9883d3f9
OM
197 for (const auto& entry : *original) {
198 oldAndNewDomains.insert(entry.first);
b68af3ee 199 }
200 }
201
35189b7d
KF
202 // these explicitly-named captures should not be necessary, as lambda
203 // capture of tuple-like structured bindings is permitted, but some
204 // compilers still don't allow it
9883d3f9
OM
205 broadcastFunction([dmap = newDomainMap] { return pleaseUseNewSDomainsMap(dmap); });
206 broadcastFunction([nsset = newNotifySet] { return pleaseSupplantAllowNotifyFor(nsset); });
79911452
OM
207
208 // Wipe the caches *after* the new auth domain info has been set
209 // up, as a query during setting up might fill the caches
210 // again. Old code did the clear before, exposing a race.
9883d3f9
OM
211 for (const auto& entry : oldAndNewDomains) {
212 wipeCaches(entry, true, 0xffff);
79911452 213 }
49a699c4
BH
214 return "ok\n";
215 }
d8d1d955
OM
216 catch (const std::exception& e) {
217 SLOG(g_log << Logger::Error << "Encountered error reloading zones, keeping original data: " << e.what() << endl,
218 log->error(Logr::Error, e.what(), "Encountered error reloading zones, keeping original data"));
49a699c4 219 }
d8d1d955
OM
220 catch (const PDNSException& ae) {
221 SLOG(g_log << Logger::Error << "Encountered error reloading zones, keeping original data: " << ae.reason << endl,
222 log->error(Logr::Error, ae.reason, "Encountered error reloading zones, keeping original data"));
49a699c4 223 }
fa9fb323 224 catch (...) {
d8d1d955 225 SLOG(g_log << Logger::Error << "Encountered unknown error reloading zones, keeping original data" << endl,
6cb5db59 226 log->error(Logr::Error, "Exception", "Encountered error reloading zones, keeping original data"));
49a699c4
BH
227 }
228 return "reloading failed, see log\n";
229}
230
9883d3f9 231static void readAuthZoneData(SyncRes::AuthDomain& authDomain, const pair<string, string>& headers, Logr::log_t log)
49a699c4 232{
9883d3f9
OM
233 SLOG(g_log << Logger::Notice << "Parsing authoritative data for zone '" << headers.first << "' from file '" << headers.second << "'" << endl,
234 log->info(Logr::Notice, "Parsing authoritative data from file", "zone", Logging::Loggable(headers.first), "file", Logging::Loggable(headers.second)));
235 ZoneParserTNG zpt(headers.second, DNSName(headers.first));
236 zpt.setMaxGenerateSteps(::arg().asNum("max-generate-steps"));
237 zpt.setMaxIncludes(::arg().asNum("max-include-depth"));
238 DNSResourceRecord resourceRecord;
239 DNSRecord dnsrecord;
240 while (zpt.get(resourceRecord)) {
241 try {
242 dnsrecord = DNSRecord(resourceRecord);
243 dnsrecord.d_place = DNSResourceRecord::ANSWER;
244 }
245 catch (std::exception& e) {
246 throw PDNSException("Error parsing record '" + resourceRecord.qname.toLogString() + "' of type " + resourceRecord.qtype.toString() + " in zone '" + headers.first + "' from file '" + headers.second + "': " + e.what());
247 }
248 catch (...) {
249 throw PDNSException("Error parsing record '" + resourceRecord.qname.toLogString() + "' of type " + resourceRecord.qtype.toString() + " in zone '" + headers.first + "' from file '" + headers.second + "'");
250 }
49a699c4 251
9883d3f9
OM
252 authDomain.d_records.insert(dnsrecord);
253 }
254}
49a699c4 255
9883d3f9
OM
256static void processForwardZones(shared_ptr<SyncRes::domainmap_t>& newMap, Logr::log_t log)
257{
258 const std::array<string, 3> option_names = {"auth-zones", "forward-zones", "forward-zones-recurse"};
259
260 for (size_t option = 0; option < option_names.size(); ++option) {
261 vector<string> parts;
262 stringtok(parts, ::arg()[option_names.at(option)], " ,\t\n\r");
263 for (const auto& part : parts) {
264 SyncRes::AuthDomain authDomain;
265 if (part.find('=') == string::npos) {
266 throw PDNSException("Error parsing '" + part + "', missing =");
267 }
268 pair<string, string> headers = splitField(part, '=');
dc593046
OM
269 boost::trim(headers.first);
270 boost::trim(headers.second);
9883d3f9
OM
271
272 if (option == 0) {
273 authDomain.d_rdForward = false;
274 readAuthZoneData(authDomain, headers, log);
49a699c4
BH
275 }
276 else {
9883d3f9
OM
277 authDomain.d_rdForward = (option == 2);
278 convertServersForAD(headers.first, headers.second, authDomain, ";", log);
49a699c4 279 }
3337c2f7 280
9883d3f9
OM
281 authDomain.d_name = DNSName(headers.first);
282 (*newMap)[authDomain.d_name] = authDomain;
49a699c4
BH
283 }
284 }
9883d3f9
OM
285}
286
287static void processApiZonesFile(shared_ptr<SyncRes::domainmap_t>& newMap, shared_ptr<notifyset_t>& newSet, Logr::log_t log)
288{
289 if (::arg()["api-config-dir"].empty()) {
290 return;
291 }
292 const auto filename = ::arg()["api-config-dir"] + "/apizones";
293 struct stat statStruct
294 {
295 };
296 // It's a TOCTU, but a harmless one
297 if (stat(filename.c_str(), &statStruct) != 0) {
298 return;
299 }
300
301 SLOG(g_log << Logger::Notice << "Processing ApiZones YAML settings from " << filename << endl,
302 log->info(Logr::Notice, "Processing ApiZones YAML settings", "path", Logging::Loggable(filename)));
303
304 const uint64_t before = newMap->size();
fa9fb323 305
9883d3f9
OM
306 std::unique_ptr<pdns::rust::settings::rec::ApiZones> zones = pdns::rust::settings::rec::api_read_zones(filename);
307 zones->validate("apizones");
308
309 for (const auto& forward : zones->forward_zones) {
310 SyncRes::AuthDomain authDomain;
311 authDomain.d_name = DNSName(string(forward.zone));
312 authDomain.d_rdForward = forward.recurse;
313 for (const auto& forwarder : forward.forwarders) {
314 ComboAddress addr = parseIPAndPort(string(forwarder), 53);
315 authDomain.d_servers.emplace_back(addr);
316 }
317 (*newMap)[authDomain.d_name] = authDomain;
318 if (forward.notify_allowed) {
319 newSet->insert(authDomain.d_name);
320 }
321 }
322 for (const auto& auth : zones->auth_zones) {
323 SyncRes::AuthDomain authDomain;
324 authDomain.d_name = DNSName(string(auth.zone));
325 readAuthZoneData(authDomain, {string(auth.zone), string(auth.file)}, log);
326 (*newMap)[authDomain.d_name] = authDomain;
327 }
328 SLOG(g_log << Logger::Warning << "Done parsing " << newMap->size() - before
329 << " ApiZones YAML settings from file '"
330 << filename << "'" << endl,
331 log->info(Logr::Notice, "Done parsing ApiZones YAML from file", "file",
332 Logging::Loggable(filename), "count",
333 Logging::Loggable(newMap->size() - before)));
334}
335
336static void processForwardZonesFile(shared_ptr<SyncRes::domainmap_t>& newMap, shared_ptr<notifyset_t>& newSet, Logr::log_t log)
337{
17417d54 338 const auto& filename = ::arg()["forward-zones-file"];
9883d3f9
OM
339 if (filename.empty()) {
340 return;
341 }
342 const uint64_t before = newMap->size();
343
344 if (boost::ends_with(filename, ".yml")) {
345 ::rust::Vec<pdns::rust::settings::rec::ForwardZone> vec;
346 pdns::settings::rec::readYamlForwardZonesFile(filename, vec, log);
347 for (const auto& forward : vec) {
348 SyncRes::AuthDomain authDomain;
349 authDomain.d_name = DNSName(string(forward.zone));
350 authDomain.d_rdForward = forward.recurse;
351 for (const auto& forwarder : forward.forwarders) {
352 ComboAddress addr = parseIPAndPort(string(forwarder), 53);
353 authDomain.d_servers.emplace_back(addr);
354 }
355 (*newMap)[authDomain.d_name] = authDomain;
356 if (forward.notify_allowed) {
357 newSet->insert(authDomain.d_name);
358 }
359 }
360 }
361 else {
362 SLOG(g_log << Logger::Warning << "Reading zone forwarding information from '" << filename << "'" << endl,
363 log->info(Logr::Notice, "Reading zone forwarding information", "file", Logging::Loggable(filename)));
01807c64 364 auto filePtr = pdns::UniqueFilePtr(fopen(filename.c_str(), "r"));
9883d3f9
OM
365 if (!filePtr) {
366 int err = errno;
367 throw PDNSException("Error opening forward-zones-file '" + filename + "': " + stringerror(err));
49a699c4
BH
368 }
369
834942f1 370 string line;
fa9fb323 371 int linenum = 0;
9883d3f9
OM
372 while (linenum++, stringfgets(filePtr.get(), line)) {
373 SyncRes::AuthDomain authDomain;
dc593046 374 boost::trim(line);
f904c51c 375 if (line[0] == '#') { // Comment line, skip to the next line
fa2909dc 376 continue;
f904c51c
FM
377 }
378 string domain;
379 string instructions;
1a09e47b 380 std::tie(domain, instructions) = splitField(line, '=');
fa2909dc 381 instructions = splitField(instructions, '#').first; // Remove EOL comments
dc593046
OM
382 boost::trim(domain);
383 boost::trim(instructions);
35189b7d
KF
384 if (domain.empty()) {
385 if (instructions.empty()) { // empty line
386 continue;
387 }
9883d3f9 388 throw PDNSException("Error parsing line " + std::to_string(linenum) + " of " + filename);
e58483cc 389 }
35189b7d
KF
390
391 bool allowNotifyFor = false;
392
393 for (; !domain.empty(); domain.erase(0, 1)) {
394 switch (domain[0]) {
395 case '+':
9883d3f9 396 authDomain.d_rdForward = true;
35189b7d
KF
397 continue;
398 case '^':
399 allowNotifyFor = true;
400 continue;
401 }
402 break;
49a699c4 403 }
35189b7d 404
fa9fb323 405 if (domain.empty()) {
9883d3f9 406 throw PDNSException("Error parsing line " + std::to_string(linenum) + " of " + filename);
49a699c4
BH
407 }
408
409 try {
9883d3f9 410 convertServersForAD(domain, instructions, authDomain, ",; ", log, false);
49a699c4 411 }
fa9fb323 412 catch (...) {
9883d3f9 413 throw PDNSException("Conversion error parsing line " + std::to_string(linenum) + " of " + filename);
49a699c4
BH
414 }
415
9883d3f9
OM
416 authDomain.d_name = DNSName(domain);
417 (*newMap)[authDomain.d_name] = authDomain;
35189b7d 418 if (allowNotifyFor) {
9883d3f9 419 newSet->insert(authDomain.d_name);
35189b7d 420 }
49a699c4 421 }
49a699c4 422 }
9883d3f9
OM
423 SLOG(g_log << Logger::Warning << "Done parsing " << newMap->size() - before
424 << " forwarding instructions from file '"
425 << filename << "'" << endl,
426 log->info(Logr::Notice, "Done parsing forwarding instructions from file", "file",
427 Logging::Loggable(filename), "count",
428 Logging::Loggable(newMap->size() - before)));
429}
49a699c4 430
9883d3f9
OM
431static void processExportEtcHosts(std::shared_ptr<SyncRes::domainmap_t>& newMap, Logr::log_t log)
432{
433 if (!::arg().mustDo("export-etc-hosts")) {
434 return;
435 }
436 string fname = ::arg()["etc-hosts-file"];
437 ifstream ifs(fname);
438 if (!ifs) {
439 SLOG(g_log << Logger::Warning << "Could not open " << fname << " for reading" << endl,
440 log->error(Logr::Warning, "Could not open file for reading", "file", Logging::Loggable(fname)));
441 return;
442 }
443 vector<string> parts;
444 std::string line{};
445 while (getline(ifs, line)) {
446 if (!parseEtcHostsLine(parts, line)) {
447 continue;
49a699c4 448 }
fa9fb323 449
9883d3f9
OM
450 try {
451 string searchSuffix = ::arg()["export-etc-hosts-search-suffix"];
452 addForwardAndReverseLookupEntries(*newMap, searchSuffix, parts, log);
453 }
454 catch (const PDNSException& ex) {
455 SLOG(g_log << Logger::Warning
456 << "The line `" << line << "` "
457 << "in the provided etc-hosts file `" << fname << "` "
458 << "could not be added: " << ex.reason << ". Going to skip it."
459 << endl,
460 log->info(Logr::Notice, "Skipping line in etc-hosts file",
461 "line", Logging::Loggable(line),
462 "hosts-file", Logging::Loggable(fname),
463 "reason", Logging::Loggable(ex.reason)));
49a699c4
BH
464 }
465 }
9883d3f9 466}
35189b7d 467
9883d3f9
OM
468static void processServeRFC1918(std::shared_ptr<SyncRes::domainmap_t>& newMap, Logr::log_t log)
469{
470 if (!::arg().mustDo("serve-rfc1918")) {
471 return;
472 }
473 SLOG(g_log << Logger::Warning << "Inserting rfc 1918 private space zones" << endl,
474 log->info(Logr::Notice, "Inserting rfc 1918 private space zones"));
49a699c4 475
9883d3f9
OM
476 makePartialIPZone(*newMap, {"127"}, log);
477 makePartialIPZone(*newMap, {"10"}, log);
478 makePartialIPZone(*newMap, {"192", "168"}, log);
9452c5e6 479
9883d3f9
OM
480 for (int count = 16; count < 32; count++) {
481 makePartialIPZone(*newMap, {"172", std::to_string(count).c_str()}, log);
49a699c4 482 }
9883d3f9 483}
35189b7d 484
9883d3f9
OM
485static void processAllowNotifyFor(shared_ptr<notifyset_t>& newSet)
486{
487 vector<string> parts;
35189b7d 488 stringtok(parts, ::arg()["allow-notify-for"], " ,\t\n\r");
84d4747e
FM
489 for (auto& part : parts) {
490 newSet->insert(DNSName(part));
35189b7d 491 }
9883d3f9 492}
35189b7d 493
9883d3f9
OM
494static void processAllowNotifyForFile(shared_ptr<notifyset_t>& newSet, Logr::log_t log)
495{
17417d54 496 const auto& filename = ::arg()["allow-notify-for-file"];
9883d3f9
OM
497 if (filename.empty()) {
498 return;
499 }
500 const uint64_t before = newSet->size();
501 if (boost::ends_with(filename, ".yml")) {
502 ::rust::Vec<::rust::String> vec;
503 pdns::settings::rec::readYamlAllowNotifyForFile(filename, vec, log);
504 for (const auto& name : vec) {
505 newSet->insert(DNSName(string(name)));
506 }
507 }
508 else {
509 SLOG(g_log << Logger::Warning << "Reading NOTIFY-allowed zones from '" << filename << "'" << endl,
510 log->info(Logr::Notice, "Reading NOTIFY-allowed zones from file", "file", Logging::Loggable(filename)));
01807c64 511 auto filePtr = pdns::UniqueFilePtr(fopen(filename.c_str(), "r"));
9883d3f9
OM
512 if (!filePtr) {
513 throw PDNSException("Error opening allow-notify-for-file '" + filename + "': " + stringerror());
35189b7d
KF
514 }
515
516 string line;
9883d3f9 517 while (stringfgets(filePtr.get(), line)) {
35189b7d 518 boost::trim(line);
9883d3f9 519 if (line[0] == '#') { // Comment line, skip to the next line
35189b7d 520 continue;
9883d3f9 521 }
35189b7d
KF
522 newSet->insert(DNSName(line));
523 }
35189b7d 524 }
9883d3f9
OM
525 SLOG(g_log << Logger::Warning << "Done parsing " << newSet->size() - before << " NOTIFY-allowed zones from file '" << filename << "'" << endl,
526 log->info(Logr::Notice, "Done parsing NOTIFY-allowed zones from file", "file", Logging::Loggable(filename), "count", Logging::Loggable(newSet->size() - before)));
527}
528
529std::tuple<std::shared_ptr<SyncRes::domainmap_t>, std::shared_ptr<notifyset_t>> parseZoneConfiguration(bool yaml)
530{
531 auto log = g_slog->withName("config");
532
533 TXTRecordContent::report();
534 OPTRecordContent::report();
535
536 auto newMap = std::make_shared<SyncRes::domainmap_t>();
537 auto newSet = std::make_shared<notifyset_t>();
538
539 processForwardZones(newMap, log);
540 processForwardZonesFile(newMap, newSet, log);
541 if (yaml) {
542 processApiZonesFile(newMap, newSet, log);
543 }
544 processExportEtcHosts(newMap, log);
545 processServeRFC1918(newMap, log);
546 processAllowNotifyFor(newSet);
547 processAllowNotifyForFile(newSet, log);
35189b7d
KF
548
549 return {newMap, newSet};
49a699c4 550}