2 #include "ext/luawrapper/include/LuaContext.hpp"
6 #include "namespaces.hh"
8 #include "rec-lua-conf.hh"
10 #include "filterpo.hh"
12 #include "rpzloader.hh"
14 #include "remote_logger.hh"
15 #include "validate.hh"
16 #include "validate-recursor.hh"
17 #include "root-dnssec.hh"
19 GlobalStateHolder
<LuaConfigItems
> g_luaconfs
;
21 /* SO HOW DOES THIS WORK! AND PLEASE PAY ATTENTION!
22 This function can be called at any time. It is expected to overwrite all the contents
23 of LuaConfigItems, which is held in a GlobalStateHolder for RCU properties.
25 This function can be called again at a later date, so you must make sure that anything you
26 allow to be configured from here lives in g_luaconfs AND NOWHERE ELSE.
28 If someone loads an empty Lua file, the default LuaConfigItems struct MUST MAKE SENSE.
30 To make this easy on you, here is a LuaConfigItems constructor where you
31 can set sane defaults:
34 LuaConfigItems::LuaConfigItems()
36 DNSName
root("."); // don't use g_rootdnsname here, it might not exist yet
37 for (const auto &dsRecord
: rootDSs
) {
38 auto ds
=std::dynamic_pointer_cast
<DSRecordContent
>(DSRecordContent::make(dsRecord
));
39 dsAnchors
[root
].insert(*ds
);
43 /* DID YOU READ THE STORY ABOVE? */
46 typename
C::value_type::second_type
constGet(const C
& c
, const std::string
& name
)
48 auto iter
= c
.find(name
);
54 typedef std::unordered_map
<std::string
, boost::variant
<bool, uint32_t, std::string
> > rpzOptions_t
;
56 static void parseRPZParameters(rpzOptions_t
& have
, std::string
& polName
, boost::optional
<DNSFilterEngine::Policy
>& defpol
, bool& defpolOverrideLocal
, uint32_t& maxTTL
, size_t& zoneSizeHint
)
58 if(have
.count("policyName")) {
59 polName
= boost::get
<std::string
>(have
["policyName"]);
61 if(have
.count("defpol")) {
62 defpol
=DNSFilterEngine::Policy();
63 defpol
->d_kind
= (DNSFilterEngine::PolicyKind
)boost::get
<uint32_t>(have
["defpol"]);
64 defpol
->d_name
= std::make_shared
<std::string
>(polName
);
65 if(defpol
->d_kind
== DNSFilterEngine::PolicyKind::Custom
) {
66 defpol
->d_custom
.push_back(DNSRecordContent::mastermake(QType::CNAME
, QClass::IN
,
67 boost::get
<string
>(have
["defcontent"])));
69 if(have
.count("defttl"))
70 defpol
->d_ttl
= static_cast<int32_t>(boost::get
<uint32_t>(have
["defttl"]));
72 defpol
->d_ttl
= -1; // get it from the zone
75 if (have
.count("defpolOverrideLocalData")) {
76 defpolOverrideLocal
= boost::get
<bool>(have
["defpolOverrideLocalData"]);
79 if(have
.count("maxTTL")) {
80 maxTTL
= boost::get
<uint32_t>(have
["maxTTL"]);
82 if(have
.count("zoneSizeHint")) {
83 zoneSizeHint
= static_cast<size_t>(boost::get
<uint32_t>(have
["zoneSizeHint"]));
88 typedef std::unordered_map
<std::string
, boost::variant
<bool, uint64_t, std::string
, std::vector
<std::pair
<int,std::string
> > > > protobufOptions_t
;
90 static void parseProtobufOptions(boost::optional
<protobufOptions_t
> vars
, ProtobufExportConfig
& config
)
96 if (vars
->count("timeout")) {
97 config
.timeout
= boost::get
<uint64_t>((*vars
)["timeout"]);
100 if (vars
->count("maxQueuedEntries")) {
101 config
.maxQueuedEntries
= boost::get
<uint64_t>((*vars
)["maxQueuedEntries"]);
104 if (vars
->count("reconnectWaitTime")) {
105 config
.reconnectWaitTime
= boost::get
<uint64_t>((*vars
)["reconnectWaitTime"]);
108 if (vars
->count("asyncConnect")) {
109 config
.asyncConnect
= boost::get
<bool>((*vars
)["asyncConnect"]);
112 if (vars
->count("taggedOnly")) {
113 config
.taggedOnly
= boost::get
<bool>((*vars
)["taggedOnly"]);
116 if (vars
->count("logQueries")) {
117 config
.logQueries
= boost::get
<bool>((*vars
)["logQueries"]);
120 if (vars
->count("logResponses")) {
121 config
.logResponses
= boost::get
<bool>((*vars
)["logResponses"]);
124 if (vars
->count("exportTypes")) {
125 config
.exportTypes
.clear();
127 auto types
= boost::get
<std::vector
<std::pair
<int, std::string
>>>((*vars
)["exportTypes"]);
128 for (const auto& pair
: types
) {
129 const auto type
= pair
.second
;
132 for (const auto& entry
: QType::names
) {
133 if (entry
.first
== type
) {
135 config
.exportTypes
.insert(entry
.second
);
141 throw std::runtime_error("Unknown QType '" + type
+ "' in protobuf's export types");
146 #endif /* HAVE_PROTOBUF */
149 typedef std::unordered_map
<std::string
, boost::variant
<bool, uint64_t, std::string
, std::vector
<std::pair
<int,std::string
> > > > frameStreamOptions_t
;
151 static void parseFrameStreamOptions(boost::optional
<frameStreamOptions_t
> vars
, FrameStreamExportConfig
& config
)
157 if (vars
->count("logQueries")) {
158 config
.logQueries
= boost::get
<bool>((*vars
)["logQueries"]);
160 if (vars
->count("logResponses")) {
161 config
.logResponses
= boost::get
<bool>((*vars
)["logResponses"]);
164 if (vars
->count("bufferHint")) {
165 config
.bufferHint
= boost::get
<uint64_t>((*vars
)["bufferHint"]);
167 if (vars
->count("flushTimeout")) {
168 config
.flushTimeout
= boost::get
<uint64_t>((*vars
)["flushTimeout"]);
170 if (vars
->count("inputQueueSize")) {
171 config
.inputQueueSize
= boost::get
<uint64_t>((*vars
)["inputQueueSize"]);
173 if (vars
->count("outputQueueSize")) {
174 config
.outputQueueSize
= boost::get
<uint64_t>((*vars
)["outputQueueSize"]);
176 if (vars
->count("queueNotifyThreshold")) {
177 config
.queueNotifyThreshold
= boost::get
<uint64_t>((*vars
)["queueNotifyThreshold"]);
179 if (vars
->count("reopenInterval")) {
180 config
.reopenInterval
= boost::get
<uint64_t>((*vars
)["reopenInterval"]);
183 #endif /* HAVE_FSTRM */
185 void loadRecursorLuaConfig(const std::string
& fname
, luaConfigDelayedThreads
& delayedThreads
)
194 throw PDNSException("Cannot open file '"+fname
+"': "+stringerror());
196 auto luaconfsLocal
= g_luaconfs
.getLocal();
197 lci
.generation
= luaconfsLocal
->generation
+ 1;
199 // pdnslog here is compatible with pdnslog in lua-base4.cc.
200 Lua
.writeFunction("pdnslog", [](const std::string
& msg
, boost::optional
<int> loglevel
) { g_log
<< (Logger::Urgency
)loglevel
.get_value_or(Logger::Warning
) << msg
<<endl
; });
201 std::unordered_map
<string
, std::unordered_map
<string
, int>> pdns_table
;
202 pdns_table
["loglevels"] = std::unordered_map
<string
, int>{
203 {"Alert", LOG_ALERT
},
204 {"Critical", LOG_CRIT
},
205 {"Debug", LOG_DEBUG
},
206 {"Emergency", LOG_EMERG
},
208 {"Notice", LOG_NOTICE
},
209 {"Warning", LOG_WARNING
},
212 Lua
.writeVariable("pdns", pdns_table
);
214 Lua
.writeFunction("clearSortlist", [&lci
]() { lci
.sortlist
.clear(); });
216 /* we can get: "1.2.3.4"
217 {"1.2.3.4", "4.5.6.7"}
218 {"1.2.3.4", {"4.5.6.7", "8.9.10.11"}}
221 map
<string
,DNSFilterEngine::PolicyKind
> pmap
{
222 {"NoAction", DNSFilterEngine::PolicyKind::NoAction
},
223 {"Drop", DNSFilterEngine::PolicyKind::Drop
},
224 {"NXDOMAIN", DNSFilterEngine::PolicyKind::NXDOMAIN
},
225 {"NODATA", DNSFilterEngine::PolicyKind::NODATA
},
226 {"Truncate", DNSFilterEngine::PolicyKind::Truncate
},
227 {"Custom", DNSFilterEngine::PolicyKind::Custom
}
229 Lua
.writeVariable("Policy", pmap
);
231 Lua
.writeFunction("rpzFile", [&lci
](const string
& filename
, boost::optional
<rpzOptions_t
> options
) {
233 boost::optional
<DNSFilterEngine::Policy
> defpol
;
234 bool defpolOverrideLocal
= true;
235 std::string
polName("rpzFile");
236 std::shared_ptr
<DNSFilterEngine::Zone
> zone
= std::make_shared
<DNSFilterEngine::Zone
>();
237 uint32_t maxTTL
= std::numeric_limits
<uint32_t>::max();
239 auto& have
= *options
;
240 size_t zoneSizeHint
= 0;
241 parseRPZParameters(have
, polName
, defpol
, defpolOverrideLocal
, maxTTL
, zoneSizeHint
);
242 if (zoneSizeHint
> 0) {
243 zone
->reserve(zoneSizeHint
);
246 g_log
<<Logger::Warning
<<"Loading RPZ from file '"<<filename
<<"'"<<endl
;
247 zone
->setName(polName
);
248 loadRPZFromFile(filename
, zone
, defpol
, defpolOverrideLocal
, maxTTL
);
249 lci
.dfe
.addZone(zone
);
250 g_log
<<Logger::Warning
<<"Done loading RPZ from file '"<<filename
<<"'"<<endl
;
252 catch(const std::exception
& e
) {
253 g_log
<<Logger::Error
<<"Unable to load RPZ zone from '"<<filename
<<"': "<<e
.what()<<endl
;
257 Lua
.writeFunction("rpzMaster", [&lci
, &delayedThreads
](const boost::variant
<string
, std::vector
<std::pair
<int, string
> > >& masters_
, const string
& zoneName
, boost::optional
<rpzOptions_t
> options
) {
259 boost::optional
<DNSFilterEngine::Policy
> defpol
;
260 bool defpolOverrideLocal
= true;
261 std::shared_ptr
<DNSFilterEngine::Zone
> zone
= std::make_shared
<DNSFilterEngine::Zone
>();
264 size_t maxReceivedXFRMBytes
= 0;
265 uint16_t axfrTimeout
= 20;
266 uint32_t maxTTL
= std::numeric_limits
<uint32_t>::max();
267 ComboAddress localAddress
;
268 std::vector
<ComboAddress
> masters
;
269 if (masters_
.type() == typeid(string
)) {
270 masters
.push_back(ComboAddress(boost::get
<std::string
>(masters_
), 53));
273 for (const auto& master
: boost::get
<std::vector
<std::pair
<int, std::string
>>>(masters_
)) {
274 masters
.push_back(ComboAddress(master
.second
, 53));
279 std::string dumpFile
;
280 std::shared_ptr
<SOARecordContent
> sr
= nullptr;
283 std::string seedFile
;
284 std::string
polName(zoneName
);
287 auto& have
= *options
;
288 size_t zoneSizeHint
= 0;
289 parseRPZParameters(have
, polName
, defpol
, defpolOverrideLocal
, maxTTL
, zoneSizeHint
);
290 if (zoneSizeHint
> 0) {
291 zone
->reserve(zoneSizeHint
);
294 if(have
.count("tsigname")) {
295 tt
.name
=DNSName(toLower(boost::get
<string
>(have
["tsigname"])));
296 tt
.algo
=DNSName(toLower(boost::get
<string
>(have
[ "tsigalgo"])));
297 if(B64Decode(boost::get
<string
>(have
[ "tsigsecret"]), tt
.secret
))
298 throw std::runtime_error("TSIG secret is not valid Base-64 encoded");
301 if(have
.count("refresh")) {
302 refresh
= boost::get
<uint32_t>(have
["refresh"]);
305 if(have
.count("maxReceivedMBytes")) {
306 maxReceivedXFRMBytes
= static_cast<size_t>(boost::get
<uint32_t>(have
["maxReceivedMBytes"]));
309 if(have
.count("localAddress")) {
310 localAddress
= ComboAddress(boost::get
<string
>(have
["localAddress"]));
313 if(have
.count("axfrTimeout")) {
314 axfrTimeout
= static_cast<uint16_t>(boost::get
<uint32_t>(have
["axfrTimeout"]));
317 if(have
.count("seedFile")) {
318 seedFile
= boost::get
<std::string
>(have
["seedFile"]);
321 if(have
.count("dumpFile")) {
322 dumpFile
= boost::get
<std::string
>(have
["dumpFile"]);
326 if (localAddress
!= ComboAddress()) {
327 // We were passed a localAddress, check if its AF matches the masters'
328 for (const auto& master
: masters
) {
329 if (localAddress
.sin4
.sin_family
!= master
.sin4
.sin_family
) {
330 throw PDNSException("Master address("+master
.toString()+") is not of the same Address Family as the local address ("+localAddress
.toString()+").");
335 DNSName
domain(zoneName
);
336 zone
->setDomain(domain
);
337 zone
->setName(polName
);
338 zone
->setRefresh(refresh
);
339 zoneIdx
= lci
.dfe
.addZone(zone
);
341 if (!seedFile
.empty()) {
342 g_log
<<Logger::Info
<<"Pre-loading RPZ zone "<<zoneName
<<" from seed file '"<<seedFile
<<"'"<<endl
;
344 sr
= loadRPZFromFile(seedFile
, zone
, defpol
, defpolOverrideLocal
, maxTTL
);
346 if (zone
->getDomain() != domain
) {
347 throw PDNSException("The RPZ zone " + zoneName
+ " loaded from the seed file (" + zone
->getDomain().toString() + ") does not match the one passed in parameter (" + domain
.toString() + ")");
351 throw PDNSException("The RPZ zone " + zoneName
+ " loaded from the seed file (" + zone
->getDomain().toString() + ") has no SOA record");
354 catch(const std::exception
& e
) {
355 g_log
<<Logger::Warning
<<"Unable to pre-load RPZ zone "<<zoneName
<<" from seed file '"<<seedFile
<<"': "<<e
.what()<<endl
;
359 catch(const std::exception
& e
) {
360 g_log
<<Logger::Error
<<"Problem configuring 'rpzMaster': "<<e
.what()<<endl
;
361 exit(1); // FIXME proper exit code?
363 catch(const PDNSException
& e
) {
364 g_log
<<Logger::Error
<<"Problem configuring 'rpzMaster': "<<e
.reason
<<endl
;
365 exit(1); // FIXME proper exit code?
368 delayedThreads
.rpzMasterThreads
.push_back(std::make_tuple(masters
, defpol
, defpolOverrideLocal
, maxTTL
, zoneIdx
, tt
, maxReceivedXFRMBytes
, localAddress
, axfrTimeout
, sr
, dumpFile
));
371 typedef vector
<pair
<int,boost::variant
<string
, vector
<pair
<int, string
> > > > > argvec_t
;
372 Lua
.writeFunction("addSortList",
373 [&lci
](const std::string
& formask_
,
374 const boost::variant
<string
, argvec_t
>& masks
,
375 boost::optional
<int> order_
)
378 Netmask
formask(formask_
);
379 int order
= order_
? (*order_
) : lci
.sortlist
.getMaxOrder(formask
)+1;
380 if(auto str
= boost::get
<string
>(&masks
))
381 lci
.sortlist
.addEntry(formask
, Netmask(*str
), order
);
384 auto vec
= boost::get
<argvec_t
>(&masks
);
385 for(const auto& e
: *vec
) {
386 if(auto s
= boost::get
<string
>(&e
.second
)) {
387 lci
.sortlist
.addEntry(formask
, Netmask(*s
), order
);
390 const auto& v
=boost::get
<vector
<pair
<int, string
> > >(e
.second
);
391 for(const auto& entry
: v
)
392 lci
.sortlist
.addEntry(formask
, Netmask(entry
.second
), order
);
398 catch(std::exception
& e
) {
399 g_log
<<Logger::Error
<<"Error in addSortList: "<<e
.what()<<endl
;
403 Lua
.writeFunction("addTA", [&lci
](const std::string
& who
, const std::string
& what
) {
404 warnIfDNSSECDisabled("Warning: adding Trust Anchor for DNSSEC (addTA), but dnssec is set to 'off'!");
406 auto ds
= std::dynamic_pointer_cast
<DSRecordContent
>(DSRecordContent::make(what
));
407 lci
.dsAnchors
[zone
].insert(*ds
);
410 Lua
.writeFunction("clearTA", [&lci
](boost::optional
<string
> who
) {
411 warnIfDNSSECDisabled("Warning: removing Trust Anchor for DNSSEC (clearTA), but dnssec is set to 'off'!");
413 lci
.dsAnchors
.erase(DNSName(*who
));
415 lci
.dsAnchors
.clear();
419 Lua
.writeFunction("addDS", [&lci
](const std::string
& who
, const std::string
& what
) {
420 warnIfDNSSECDisabled("Warning: adding Trust Anchor for DNSSEC (addDS), but dnssec is set to 'off'!");
421 g_log
<<Logger::Warning
<<"addDS is deprecated and will be removed in the future, switch to addTA"<<endl
;
423 auto ds
= std::dynamic_pointer_cast
<DSRecordContent
>(DSRecordContent::make(what
));
424 lci
.dsAnchors
[zone
].insert(*ds
);
428 Lua
.writeFunction("clearDS", [&lci
](boost::optional
<string
> who
) {
429 g_log
<<Logger::Warning
<<"clearDS is deprecated and will be removed in the future, switch to clearTA"<<endl
;
430 warnIfDNSSECDisabled("Warning: removing Trust Anchor for DNSSEC (clearDS), but dnssec is set to 'off'!");
432 lci
.dsAnchors
.erase(DNSName(*who
));
434 lci
.dsAnchors
.clear();
437 Lua
.writeFunction("addNTA", [&lci
](const std::string
& who
, const boost::optional
<std::string
> why
) {
438 warnIfDNSSECDisabled("Warning: adding Negative Trust Anchor for DNSSEC (addNTA), but dnssec is set to 'off'!");
440 lci
.negAnchors
[DNSName(who
)] = static_cast<string
>(*why
);
442 lci
.negAnchors
[DNSName(who
)] = "";
445 Lua
.writeFunction("clearNTA", [&lci
](boost::optional
<string
> who
) {
446 warnIfDNSSECDisabled("Warning: removing Negative Trust Anchor for DNSSEC (clearNTA), but dnssec is set to 'off'!");
448 lci
.negAnchors
.erase(DNSName(*who
));
450 lci
.negAnchors
.clear();
453 Lua
.writeFunction("readTrustAnchorsFromFile", [&lci
](const std::string
& fnamearg
, const boost::optional
<uint32_t> interval
) {
454 uint32_t realInterval
= 24;
456 realInterval
= static_cast<uint32_t>(*interval
);
458 warnIfDNSSECDisabled("Warning: reading Trust Anchors from file (readTrustAnchorsFromFile), but dnssec is set to 'off'!");
459 lci
.trustAnchorFileInfo
.fname
= fnamearg
;
460 lci
.trustAnchorFileInfo
.interval
= realInterval
;
461 updateTrustAnchorsFromFile(fnamearg
, lci
.dsAnchors
);
465 Lua
.writeFunction("setProtobufMasks", [&lci
](const uint8_t maskV4
, uint8_t maskV6
) {
466 lci
.protobufMaskV4
= maskV4
;
467 lci
.protobufMaskV6
= maskV6
;
470 Lua
.writeFunction("protobufServer", [&lci
](boost::variant
<const std::string
, const std::unordered_map
<int, std::string
>> servers
, boost::optional
<protobufOptions_t
> vars
) {
471 if (!lci
.protobufExportConfig
.enabled
) {
473 lci
.protobufExportConfig
.enabled
= true;
476 if (servers
.type() == typeid(std::string
)) {
477 auto server
= boost::get
<const std::string
>(servers
);
479 lci
.protobufExportConfig
.servers
.emplace_back(server
);
482 auto serversMap
= boost::get
<const std::unordered_map
<int,std::string
>>(servers
);
483 for (const auto& serverPair
: serversMap
) {
484 lci
.protobufExportConfig
.servers
.emplace_back(serverPair
.second
);
488 parseProtobufOptions(vars
, lci
.protobufExportConfig
);
490 catch(std::exception
& e
) {
491 g_log
<<Logger::Error
<<"Error while adding protobuf logger: "<<e
.what()<<endl
;
493 catch(PDNSException
& e
) {
494 g_log
<<Logger::Error
<<"Error while adding protobuf logger: "<<e
.reason
<<endl
;
498 g_log
<<Logger::Error
<<"Only one protobufServer() directive can be configured, we already have "<<lci
.protobufExportConfig
.servers
.at(0).toString()<<endl
;
502 Lua
.writeFunction("outgoingProtobufServer", [&lci
](boost::variant
<const std::string
, const std::unordered_map
<int, std::string
>> servers
, boost::optional
<protobufOptions_t
> vars
) {
503 if (!lci
.outgoingProtobufExportConfig
.enabled
) {
505 lci
.outgoingProtobufExportConfig
.enabled
= true;
508 if (servers
.type() == typeid(std::string
)) {
509 auto server
= boost::get
<const std::string
>(servers
);
511 lci
.outgoingProtobufExportConfig
.servers
.emplace_back(server
);
514 auto serversMap
= boost::get
<const std::unordered_map
<int,std::string
>>(servers
);
515 for (const auto& serverPair
: serversMap
) {
516 lci
.outgoingProtobufExportConfig
.servers
.emplace_back(serverPair
.second
);
520 parseProtobufOptions(vars
, lci
.outgoingProtobufExportConfig
);
522 catch(std::exception
& e
) {
523 g_log
<<Logger::Error
<<"Error while starting outgoing protobuf logger: "<<e
.what()<<endl
;
525 catch(PDNSException
& e
) {
526 g_log
<<Logger::Error
<<"Error while starting outgoing protobuf logger: "<<e
.reason
<<endl
;
530 g_log
<<Logger::Error
<<"Only one outgoingProtobufServer() directive can be configured, we already have "<<lci
.outgoingProtobufExportConfig
.servers
.at(0).toString()<<endl
;
536 Lua
.writeFunction("dnstapFrameStreamServer", [&lci
](boost::variant
<const std::string
, const std::unordered_map
<int, std::string
>> servers
, boost::optional
<frameStreamOptions_t
> vars
) {
537 if (!lci
.frameStreamExportConfig
.enabled
) {
539 lci
.frameStreamExportConfig
.enabled
= true;
542 if (servers
.type() == typeid(std::string
)) {
543 auto server
= boost::get
<const std::string
>(servers
);
544 if (!boost::starts_with(server
, "/")) {
545 ComboAddress
parsecheck(server
);
547 lci
.frameStreamExportConfig
.servers
.emplace_back(server
);
550 auto serversMap
= boost::get
<const std::unordered_map
<int,std::string
>>(servers
);
551 for (const auto& serverPair
: serversMap
) {
552 lci
.frameStreamExportConfig
.servers
.emplace_back(serverPair
.second
);
556 parseFrameStreamOptions(vars
, lci
.frameStreamExportConfig
);
558 catch(std::exception
& e
) {
559 g_log
<<Logger::Error
<<"Error reading config for dnstap framestream logger: "<<e
.what()<<endl
;
561 catch(PDNSException
& e
) {
562 g_log
<<Logger::Error
<<"Error reading config for dnstap framestream logger: "<<e
.reason
<<endl
;
566 g_log
<<Logger::Error
<<"Only one dnstapFrameStreamServer() directive can be configured, we already have "<<lci
.frameStreamExportConfig
.servers
.at(0)<<endl
;
569 #endif /* HAVE_FSTRM */
572 Lua
.executeCode(ifs
);
573 g_luaconfs
.setState(lci
);
575 catch(const LuaContext::ExecutionErrorException
& e
) {
576 g_log
<<Logger::Error
<<"Unable to load Lua script from '"+fname
+"': ";
578 std::rethrow_if_nested(e
);
579 } catch(const std::exception
& exp
) {
580 // exp is the exception that was thrown from inside the lambda
581 g_log
<< exp
.what() << std::endl
;
583 catch(const PDNSException
& exp
) {
584 // exp is the exception that was thrown from inside the lambda
585 g_log
<< exp
.reason
<< std::endl
;
590 catch(std::exception
& err
) {
591 g_log
<<Logger::Error
<<"Unable to load Lua script from '"+fname
+"': "<<err
.what()<<endl
;
597 void startLuaConfigDelayedThreads(const luaConfigDelayedThreads
& delayedThreads
, uint64_t generation
)
599 for (const auto& rpzMaster
: delayedThreads
.rpzMasterThreads
) {
601 std::thread
t(RPZIXFRTracker
, std::get
<0>(rpzMaster
), std::get
<1>(rpzMaster
), std::get
<2>(rpzMaster
), std::get
<3>(rpzMaster
), std::get
<4>(rpzMaster
), std::get
<5>(rpzMaster
), std::get
<6>(rpzMaster
) * 1024 * 1024, std::get
<7>(rpzMaster
), std::get
<8>(rpzMaster
), std::get
<9>(rpzMaster
), std::get
<10>(rpzMaster
), generation
);
604 catch(const std::exception
& e
) {
605 g_log
<<Logger::Error
<<"Problem starting RPZIXFRTracker thread: "<<e
.what()<<endl
;
606 exit(1); // FIXME proper exit code?
608 catch(const PDNSException
& e
) {
609 g_log
<<Logger::Error
<<"Problem starting RPZIXFRTracker thread: "<<e
.reason
<<endl
;
610 exit(1); // FIXME proper exit code?